root/trunk/libffado/src/dice/dice_avdevice.cpp

Revision 1336, 62.7 kB (checked in by ppalmers, 15 years ago)

Bring trunk up to date with branches/libffado-2.0:

"""
svn merge -r 1254:1299 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1301:1320 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1322:1323 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1329:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
"""

Add getSupportedSamplingFrequencies() to DICE, RME and Metric Halo AvDevices?

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "dice/dice_avdevice.h"
25 #include "dice/dice_defines.h"
26
27 #include "libieee1394/configrom.h"
28 #include "libieee1394/ieee1394service.h"
29
30 #include "debugmodule/debugmodule.h"
31
32 #include "libutil/ByteSwap.h"
33 #include <libraw1394/csr.h>
34
35 #include <stdint.h>
36 #include <iostream>
37 #include <sstream>
38
39 #include <string>
40 #include <cstring>
41 #include <assert.h>
42
43 using namespace std;
44
45 namespace Dice {
46
47 // to define the supported devices
48 static VendorModelEntry supportedDeviceList[] =
49 {
50     // vendor id, model id, vendor name, model name
51     {FW_VENDORID_TCAT,   0x00000002, "TCAT", "DiceII EVM"},
52     {FW_VENDORID_TCAT,   0x00000004, "TCAT", "DiceII EVM (vxx)"},
53     {FW_VENDORID_TCAT,   0x00000021, "TC Electronic", "Konnekt 8"},
54     {FW_VENDORID_TCAT,   0x00000023, "TC Electronic", "Konnekt Live"},
55     {FW_VENDORID_ALESIS, 0x00000001, "Alesis", "io|14"},
56 };
57
58 DiceAvDevice::DiceAvDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
59     : FFADODevice( d, configRom )
60     , m_model( NULL )
61     , m_global_reg_offset (0xFFFFFFFFLU)
62     , m_global_reg_size (0xFFFFFFFFLU)
63     , m_tx_reg_offset (0xFFFFFFFFLU)
64     , m_tx_reg_size (0xFFFFFFFFLU)
65     , m_rx_reg_offset (0xFFFFFFFFLU)
66     , m_rx_reg_size (0xFFFFFFFFLU)
67     , m_unused1_reg_offset (0xFFFFFFFFLU)
68     , m_unused1_reg_size (0xFFFFFFFFLU)
69     , m_unused2_reg_offset (0xFFFFFFFFLU)
70     , m_unused2_reg_size (0xFFFFFFFFLU)
71     , m_nb_tx (0xFFFFFFFFLU)
72     , m_tx_size (0xFFFFFFFFLU)
73     , m_nb_rx (0xFFFFFFFFLU)
74     , m_rx_size (0xFFFFFFFFLU)
75     , m_notifier (NULL)
76 {
77     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Dice::DiceAvDevice (NodeID %d)\n",
78                  getConfigRom().getNodeId() );
79
80 }
81
82 DiceAvDevice::~DiceAvDevice()
83 {
84     for ( StreamProcessorVectorIterator it = m_receiveProcessors.begin();
85           it != m_receiveProcessors.end();
86           ++it )
87     {
88         delete *it;
89     }
90     for ( StreamProcessorVectorIterator it = m_transmitProcessors.begin();
91           it != m_transmitProcessors.end();
92           ++it )
93     {
94         delete *it;
95     }
96
97     if (m_notifier) {
98         unlock();
99     }
100 }
101
102 bool
103 DiceAvDevice::probe( ConfigRom& configRom, bool generic )
104 {
105     if (generic) return false;
106     unsigned int vendorId = configRom.getNodeVendorId();
107     unsigned int modelId = configRom.getModelId();
108
109     for ( unsigned int i = 0;
110           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
111           ++i )
112     {
113         if ( ( supportedDeviceList[i].vendor_id == vendorId )
114              && ( supportedDeviceList[i].model_id == modelId )
115            )
116         {
117             return true;
118         }
119     }
120
121     return false;
122 }
123
124 FFADODevice *
125 DiceAvDevice::createDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
126 {
127     return new DiceAvDevice( d, configRom );
128 }
129
130 bool
131 DiceAvDevice::discover()
132 {
133     unsigned int vendorId = getConfigRom().getNodeVendorId();
134     unsigned int modelId = getConfigRom().getModelId();
135
136     for ( unsigned int i = 0;
137           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
138           ++i )
139     {
140         if ( ( supportedDeviceList[i].vendor_id == vendorId )
141              && ( supportedDeviceList[i].model_id == modelId )
142            )
143         {
144             m_model = &(supportedDeviceList[i]);
145         }
146     }
147
148     if (m_model == NULL) {
149         debugWarning("DiceAvDevice::discover() called for a non-dice device");
150         return false;
151     }
152
153     if ( !initIoFunctions() ) {
154         debugError("Could not initialize I/O functions\n");
155         return false;
156     }
157
158     debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s (nick: %s)\n",
159                 m_model->vendor_name, m_model->model_name, getDeviceNickName().c_str());
160
161     return true;
162 }
163
164 int
165 DiceAvDevice::getSamplingFrequency( ) {
166     int samplingFrequency;
167
168     fb_quadlet_t clockreg;
169     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg)) {
170         debugError("Could not read CLOCK_SELECT register\n");
171         return false;
172     }
173
174     clockreg = DICE_GET_RATE(clockreg);
175
176     switch (clockreg) {
177         case DICE_RATE_32K:      samplingFrequency = 32000;  break;
178         case DICE_RATE_44K1:     samplingFrequency = 44100;  break;
179         case DICE_RATE_48K:      samplingFrequency = 48000;  break;
180         case DICE_RATE_88K2:     samplingFrequency = 88200;  break;
181         case DICE_RATE_96K:      samplingFrequency = 96000;  break;
182         case DICE_RATE_176K4:    samplingFrequency = 176400; break;
183         case DICE_RATE_192K:     samplingFrequency = 192000; break;
184         case DICE_RATE_ANY_LOW:  samplingFrequency = 0;   break;
185         case DICE_RATE_ANY_MID:  samplingFrequency = 0;   break;
186         case DICE_RATE_ANY_HIGH: samplingFrequency = 0;  break;
187         case DICE_RATE_NONE:     samplingFrequency = 0;     break;
188         default:                 samplingFrequency = 0; break;
189     }
190
191     return samplingFrequency;
192 }
193
194 #define DICE_CHECK_AND_ADD_SR(v, x, reg) \
195     { if(maskedCheckNotZeroGlobalReg( DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES, reg)) \
196        v.push_back(x); }
197 std::vector<int>
198 DiceAvDevice::getSupportedSamplingFrequencies()
199 {
200     std::vector<int> frequencies;
201     DICE_CHECK_AND_ADD_SR(frequencies, 32000, DICE_CLOCKCAP_RATE_32K);
202     DICE_CHECK_AND_ADD_SR(frequencies, 44100, DICE_CLOCKCAP_RATE_44K1);
203     DICE_CHECK_AND_ADD_SR(frequencies, 48000, DICE_CLOCKCAP_RATE_48K);
204     DICE_CHECK_AND_ADD_SR(frequencies, 88200, DICE_CLOCKCAP_RATE_88K2);
205     DICE_CHECK_AND_ADD_SR(frequencies, 96000, DICE_CLOCKCAP_RATE_96K);
206     DICE_CHECK_AND_ADD_SR(frequencies, 176400, DICE_CLOCKCAP_RATE_176K4);
207     DICE_CHECK_AND_ADD_SR(frequencies, 192000, DICE_CLOCKCAP_RATE_192K);
208     return frequencies;
209 }
210
211 int
212 DiceAvDevice::getConfigurationId()
213 {
214     return 0;
215 }
216
217 bool
218 DiceAvDevice::setSamplingFrequency( int samplingFrequency )
219 {
220     debugOutput(DEBUG_LEVEL_VERBOSE, "Setting sample rate: %d\n",
221         (samplingFrequency));
222
223     bool supported=false;
224     fb_quadlet_t select=0x0;
225
226     switch ( samplingFrequency ) {
227     default:
228     case 22050:
229     case 24000:
230         supported=false;
231         break;
232     case 32000:
233         supported=maskedCheckNotZeroGlobalReg(
234                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
235                     DICE_CLOCKCAP_RATE_32K);
236         select=DICE_RATE_32K;
237         break;
238     case 44100:
239         supported=maskedCheckNotZeroGlobalReg(
240                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
241                     DICE_CLOCKCAP_RATE_44K1);
242         select=DICE_RATE_44K1;
243         break;
244     case 48000:
245         supported=maskedCheckNotZeroGlobalReg(
246                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
247                     DICE_CLOCKCAP_RATE_48K);
248         select=DICE_RATE_48K;
249         break;
250     case 88200:
251         supported=maskedCheckNotZeroGlobalReg(
252                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
253                     DICE_CLOCKCAP_RATE_88K2);
254         select=DICE_RATE_88K2;
255         break;
256     case 96000:
257         supported=maskedCheckNotZeroGlobalReg(
258                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
259                     DICE_CLOCKCAP_RATE_96K);
260         select=DICE_RATE_96K;
261         break;
262     case 176400:
263         supported=maskedCheckNotZeroGlobalReg(
264                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
265                     DICE_CLOCKCAP_RATE_176K4);
266         select=DICE_RATE_176K4;
267         break;
268     case 192000:
269         supported=maskedCheckNotZeroGlobalReg(
270                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
271                     DICE_CLOCKCAP_RATE_192K);
272         select=DICE_RATE_192K;
273         break;
274     }
275
276     if (!supported) {
277         debugWarning("Unsupported sample rate: %d\n", (samplingFrequency));
278         return false;
279     }
280
281     if (isIsoStreamingEnabled()) {
282         debugError("Cannot change samplerate while streaming is enabled\n");
283         return false;
284     }
285
286     fb_quadlet_t clockreg;
287     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg)) {
288         debugError("Could not read CLOCK_SELECT register\n");
289         return false;
290     }
291
292     clockreg = DICE_SET_RATE(clockreg, select);
293
294     if (!writeGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, clockreg)) {
295         debugError("Could not write CLOCK_SELECT register\n");
296         return false;
297     }
298
299     // check if the write succeeded
300     fb_quadlet_t clockreg_verify;
301     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg_verify)) {
302         debugError("Could not read CLOCK_SELECT register\n");
303         return false;
304     }
305
306     if(clockreg != clockreg_verify) {
307         debugError("Samplerate register write failed\n");
308         return false;
309     }
310
311     return true;
312 }
313
314 FFADODevice::ClockSourceVector
315 DiceAvDevice::getSupportedClockSources() {
316     FFADODevice::ClockSourceVector r;
317
318     quadlet_t clock_caps;
319     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES, &clock_caps);
320     uint16_t clocks_supported = (clock_caps >> 16) & 0xFFFF;
321     debugOutput(DEBUG_LEVEL_VERBOSE," Clock caps: 0x%08X, supported=0x%04X\n",
322                                     clock_caps, clocks_supported);
323
324     quadlet_t clock_select;
325     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clock_select);
326     byte_t clock_selected = (clock_select) & 0xFF;
327     debugOutput(DEBUG_LEVEL_VERBOSE," Clock select: 0x%08X, selected=0x%04X\n",
328                                     clock_select, clock_selected);
329     quadlet_t extended_status;
330     readGlobalReg(DICE_REGISTER_GLOBAL_EXTENDED_STATUS, &extended_status);
331     #ifdef DEBUG
332     uint16_t clock_status = (extended_status) & 0xFFFF;
333     uint16_t clock_slipping = (extended_status >> 16) & 0xFFFF;
334     debugOutput(DEBUG_LEVEL_VERBOSE," Clock status: 0x%08X, status=0x%04X, slip=0x%04X\n",
335                                     extended_status, clock_status, clock_slipping);
336     #endif
337
338     diceNameVector names = getClockSourceNameString();
339     if( names.size() < DICE_CLOCKSOURCE_COUNT) {
340         debugError("Not enough clock source names on device\n");
341         return r;
342     }
343     for (unsigned int i=0; i < DICE_CLOCKSOURCE_COUNT; i++) {
344         bool supported = (((clocks_supported >> i) & 0x01) == 1);
345         if (supported) {
346             ClockSource s;
347             s.type = clockIdToType(i);
348             s.id = i;
349             s.valid = true;
350             s.locked = isClockSourceIdLocked(i, extended_status);
351             s.slipping = isClockSourceIdSlipping(i, extended_status);
352             s.active = (clock_selected == i);
353             s.description = names.at(i);
354             r.push_back(s);
355         } else {
356             debugOutput(DEBUG_LEVEL_VERBOSE, "Clock source id %d not supported by device\n", i);
357         }
358     }
359     return r;
360 }
361
362 bool
363 DiceAvDevice::isClockSourceIdLocked(unsigned int id, quadlet_t ext_status_reg) {
364     switch (id) {
365         default: return true;
366         case  DICE_CLOCKSOURCE_AES1:
367                 return ext_status_reg & DICE_EXT_STATUS_AES0_LOCKED;
368         case  DICE_CLOCKSOURCE_AES2:
369                 return ext_status_reg & DICE_EXT_STATUS_AES1_LOCKED;
370         case  DICE_CLOCKSOURCE_AES3:
371                 return ext_status_reg & DICE_EXT_STATUS_AES2_LOCKED;
372         case  DICE_CLOCKSOURCE_AES4:
373                 return ext_status_reg & DICE_EXT_STATUS_AES3_LOCKED;
374         case  DICE_CLOCKSOURCE_AES_ANY:
375                 return ext_status_reg & DICE_EXT_STATUS_AES_ANY_LOCKED;
376         case  DICE_CLOCKSOURCE_ADAT:
377                 return ext_status_reg & DICE_EXT_STATUS_ADAT_LOCKED;
378         case  DICE_CLOCKSOURCE_TDIF:
379                 return ext_status_reg & DICE_EXT_STATUS_TDIF_LOCKED;
380         case  DICE_CLOCKSOURCE_ARX1:
381                 return ext_status_reg & DICE_EXT_STATUS_ARX1_LOCKED;
382         case  DICE_CLOCKSOURCE_ARX2:
383                 return ext_status_reg & DICE_EXT_STATUS_ARX2_LOCKED;
384         case  DICE_CLOCKSOURCE_ARX3:
385                 return ext_status_reg & DICE_EXT_STATUS_ARX3_LOCKED;
386         case  DICE_CLOCKSOURCE_ARX4:
387                 return ext_status_reg & DICE_EXT_STATUS_ARX4_LOCKED;
388         case  DICE_CLOCKSOURCE_WC:
389                 return ext_status_reg & DICE_EXT_STATUS_WC_LOCKED;
390     }
391 }
392 bool
393 DiceAvDevice::isClockSourceIdSlipping(unsigned int id, quadlet_t ext_status_reg) {
394     switch (id) {
395         default: return false;
396         case  DICE_CLOCKSOURCE_AES1:
397                 return ext_status_reg & DICE_EXT_STATUS_AES0_SLIP;
398         case  DICE_CLOCKSOURCE_AES2:
399                 return ext_status_reg & DICE_EXT_STATUS_AES1_SLIP;
400         case  DICE_CLOCKSOURCE_AES3:
401                 return ext_status_reg & DICE_EXT_STATUS_AES2_SLIP;
402         case  DICE_CLOCKSOURCE_AES4:
403                 return ext_status_reg & DICE_EXT_STATUS_AES3_SLIP;
404         case  DICE_CLOCKSOURCE_AES_ANY:
405                 return false;
406         case  DICE_CLOCKSOURCE_ADAT:
407                 return ext_status_reg & DICE_EXT_STATUS_ADAT_SLIP;
408         case  DICE_CLOCKSOURCE_TDIF:
409                 return ext_status_reg & DICE_EXT_STATUS_TDIF_SLIP;
410         case  DICE_CLOCKSOURCE_ARX1:
411                 return ext_status_reg & DICE_EXT_STATUS_ARX1_SLIP;
412         case  DICE_CLOCKSOURCE_ARX2:
413                 return ext_status_reg & DICE_EXT_STATUS_ARX2_SLIP;
414         case  DICE_CLOCKSOURCE_ARX3:
415                 return ext_status_reg & DICE_EXT_STATUS_ARX3_SLIP;
416         case  DICE_CLOCKSOURCE_ARX4:
417                 return ext_status_reg & DICE_EXT_STATUS_ARX4_SLIP;
418         case  DICE_CLOCKSOURCE_WC: // FIXME: not in driver spec, so non-existant
419                 return ext_status_reg & DICE_EXT_STATUS_WC_SLIP;
420     }
421 }
422
423 enum FFADODevice::eClockSourceType
424 DiceAvDevice::clockIdToType(unsigned int id) {
425     switch (id) {
426         default: return eCT_Invalid;
427         case  DICE_CLOCKSOURCE_AES1:
428         case  DICE_CLOCKSOURCE_AES2:
429         case  DICE_CLOCKSOURCE_AES3:
430         case  DICE_CLOCKSOURCE_AES4:
431         case  DICE_CLOCKSOURCE_AES_ANY:
432                 return eCT_AES;
433         case  DICE_CLOCKSOURCE_ADAT:
434                 return eCT_ADAT;
435         case  DICE_CLOCKSOURCE_TDIF:
436                 return eCT_TDIF;
437         case  DICE_CLOCKSOURCE_ARX1:
438         case  DICE_CLOCKSOURCE_ARX2:
439         case  DICE_CLOCKSOURCE_ARX3:
440         case  DICE_CLOCKSOURCE_ARX4:
441                 return eCT_SytMatch;
442         case  DICE_CLOCKSOURCE_WC:
443                 return eCT_WordClock;
444         case DICE_CLOCKSOURCE_INTERNAL:
445                 return eCT_Internal;
446     }
447 }
448
449 bool
450 DiceAvDevice::setActiveClockSource(ClockSource s) {
451     fb_quadlet_t clockreg;
452     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg)) {
453         debugError("Could not read CLOCK_SELECT register\n");
454         return false;
455     }
456
457     clockreg = DICE_SET_CLOCKSOURCE(clockreg, s.id);
458
459     if (!writeGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, clockreg)) {
460         debugError("Could not write CLOCK_SELECT register\n");
461         return false;
462     }
463
464     // check if the write succeeded
465     fb_quadlet_t clockreg_verify;
466     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg_verify)) {
467         debugError("Could not read CLOCK_SELECT register\n");
468         return false;
469     }
470
471     if(clockreg != clockreg_verify) {
472         debugError("CLOCK_SELECT register write failed\n");
473         return false;
474     }
475
476     return DICE_GET_CLOCKSOURCE(clockreg_verify) == s.id;
477 }
478
479 FFADODevice::ClockSource
480 DiceAvDevice::getActiveClockSource() {
481     ClockSource s;
482     quadlet_t clock_caps;
483     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES, &clock_caps);
484     uint16_t clocks_supported = (clock_caps >> 16) & 0xFFFF;
485     debugOutput(DEBUG_LEVEL_VERBOSE," Clock caps: 0x%08X, supported=0x%04X\n",
486                                     clock_caps, clocks_supported);
487
488     quadlet_t clock_select;
489     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clock_select);
490     byte_t id = (clock_select) & 0xFF;
491     debugOutput(DEBUG_LEVEL_VERBOSE," Clock select: 0x%08X, selected=0x%04X\n",
492                                     clock_select, id);
493     quadlet_t extended_status;
494     readGlobalReg(DICE_REGISTER_GLOBAL_EXTENDED_STATUS, &extended_status);
495     #ifdef DEBUG
496     uint16_t clock_status = (extended_status) & 0xFFFF;
497     uint16_t clock_slipping = (extended_status >> 16) & 0xFFFF;
498     debugOutput(DEBUG_LEVEL_VERBOSE," Clock status: 0x%08X, status=0x%04X, slip=0x%04X\n",
499                                     extended_status, clock_status, clock_slipping);
500     #endif
501
502     diceNameVector names = getClockSourceNameString();
503     if( names.size() < DICE_CLOCKSOURCE_COUNT) {
504         debugError("Not enough clock source names on device\n");
505         return s;
506     }
507     bool supported = (((clocks_supported >> id) & 0x01) == 1);
508     if (supported) {
509         s.type = clockIdToType(id);
510         s.id = id;
511         s.valid = true;
512         s.locked = isClockSourceIdLocked(id, extended_status);
513         s.slipping = isClockSourceIdSlipping(id, extended_status);
514         s.active = true;
515         s.description = names.at(id);
516     } else {
517         debugOutput(DEBUG_LEVEL_VERBOSE, "Clock source id %2d not supported by device\n", id);
518     }
519     return s;
520 }
521
522 bool
523 DiceAvDevice::setNickname( std::string name)
524 {
525     return setDeviceNickName(name);
526 }
527
528 std::string
529 DiceAvDevice::getNickname()
530 {
531     return getDeviceNickName();
532 }
533
534 void
535 DiceAvDevice::showDevice()
536 {
537     fb_quadlet_t tmp_quadlet;
538     fb_octlet_t tmp_octlet;
539
540     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a DICE device\n");
541     FFADODevice::showDevice();
542
543     debugOutput(DEBUG_LEVEL_VERBOSE," DICE Parameter Space info:\n");
544     debugOutput(DEBUG_LEVEL_VERBOSE,"  Global  : offset=0x%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
545     debugOutput(DEBUG_LEVEL_VERBOSE,"  TX      : offset=0x%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
546     debugOutput(DEBUG_LEVEL_VERBOSE,"                nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
547     debugOutput(DEBUG_LEVEL_VERBOSE,"  RX      : offset=0x%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
548     debugOutput(DEBUG_LEVEL_VERBOSE,"                nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
549     debugOutput(DEBUG_LEVEL_VERBOSE,"  UNUSED1 : offset=0x%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
550     debugOutput(DEBUG_LEVEL_VERBOSE,"  UNUSED2 : offset=0x%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
551
552     debugOutput(DEBUG_LEVEL_VERBOSE," Global param space:\n");
553
554     readGlobalRegBlock(DICE_REGISTER_GLOBAL_OWNER, reinterpret_cast<fb_quadlet_t *>(&tmp_octlet), sizeof(fb_octlet_t));
555     debugOutput(DEBUG_LEVEL_VERBOSE,"  Owner            : 0x%016X\n",tmp_octlet);
556
557     readGlobalReg(DICE_REGISTER_GLOBAL_NOTIFICATION, &tmp_quadlet);
558     debugOutput(DEBUG_LEVEL_VERBOSE,"  Notification     : 0x%08X\n",tmp_quadlet);
559
560     readGlobalReg(DICE_REGISTER_GLOBAL_NOTIFICATION, &tmp_quadlet);
561     debugOutput(DEBUG_LEVEL_NORMAL,"  Nick name        : %s\n",getDeviceNickName().c_str());
562
563     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &tmp_quadlet);
564     debugOutput(DEBUG_LEVEL_NORMAL,"  Clock Select     : 0x%02X 0x%02X\n",
565         (tmp_quadlet>>8) & 0xFF, tmp_quadlet & 0xFF);
566
567     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &tmp_quadlet);
568     debugOutput(DEBUG_LEVEL_NORMAL,"  Enable           : %s\n",
569         (tmp_quadlet&0x1?"true":"false"));
570
571     readGlobalReg(DICE_REGISTER_GLOBAL_STATUS, &tmp_quadlet);
572     debugOutput(DEBUG_LEVEL_NORMAL,"  Clock Status     : %s 0x%02X\n",
573         (tmp_quadlet&0x1?"locked":"not locked"), (tmp_quadlet>>8) & 0xFF);
574
575     readGlobalReg(DICE_REGISTER_GLOBAL_EXTENDED_STATUS, &tmp_quadlet);
576     debugOutput(DEBUG_LEVEL_VERBOSE,"  Extended Status  : 0x%08X\n",tmp_quadlet);
577
578     readGlobalReg(DICE_REGISTER_GLOBAL_SAMPLE_RATE, &tmp_quadlet);
579     debugOutput(DEBUG_LEVEL_NORMAL,"  Samplerate       : 0x%08X (%lu)\n",tmp_quadlet,tmp_quadlet);
580
581     readGlobalReg(DICE_REGISTER_GLOBAL_VERSION, &tmp_quadlet);
582     debugOutput(DEBUG_LEVEL_NORMAL,"  Version          : 0x%08X (%u.%u.%u.%u)\n",
583         tmp_quadlet,
584         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_A(tmp_quadlet),
585         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_B(tmp_quadlet),
586         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_C(tmp_quadlet),
587         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_D(tmp_quadlet)
588         );
589
590     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES, &tmp_quadlet);
591     debugOutput(DEBUG_LEVEL_VERBOSE,"  Clock caps       : 0x%08X\n",tmp_quadlet);
592
593     diceNameVector names=getClockSourceNameString();
594     debugOutput(DEBUG_LEVEL_VERBOSE,"  Clock sources    :\n");
595
596     for ( diceNameVectorIterator it = names.begin();
597           it != names.end();
598           ++it )
599     {
600         debugOutput(DEBUG_LEVEL_VERBOSE,"    %s\n", (*it).c_str());
601     }
602
603     debugOutput(DEBUG_LEVEL_VERBOSE," TX param space:\n");
604     debugOutput(DEBUG_LEVEL_VERBOSE,"  Nb of xmit        : %1d\n", m_nb_tx);
605     for (unsigned int i=0;i<m_nb_tx;i++) {
606         debugOutput(DEBUG_LEVEL_VERBOSE,"  Transmitter %d:\n",i);
607
608         readTxReg(i, DICE_REGISTER_TX_ISOC_BASE, &tmp_quadlet);
609         debugOutput(DEBUG_LEVEL_VERBOSE,"   ISO channel       : %3d\n", tmp_quadlet);
610         readTxReg(i, DICE_REGISTER_TX_SPEED_BASE, &tmp_quadlet);
611         debugOutput(DEBUG_LEVEL_VERBOSE,"   ISO speed         : %3d\n", tmp_quadlet);
612
613         readTxReg(i, DICE_REGISTER_TX_NB_AUDIO_BASE, &tmp_quadlet);
614         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb audio channels : %3d\n", tmp_quadlet);
615         readTxReg(i, DICE_REGISTER_TX_MIDI_BASE, &tmp_quadlet);
616         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb midi channels  : %3d\n", tmp_quadlet);
617
618         readTxReg(i, DICE_REGISTER_TX_AC3_CAPABILITIES_BASE, &tmp_quadlet);
619         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 caps          : 0x%08X\n", tmp_quadlet);
620         readTxReg(i, DICE_REGISTER_TX_AC3_ENABLE_BASE, &tmp_quadlet);
621         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 enable        : 0x%08X\n", tmp_quadlet);
622
623         diceNameVector channel_names=getTxNameString(i);
624         debugOutput(DEBUG_LEVEL_VERBOSE,"   Channel names     :\n");
625         for ( diceNameVectorIterator it = channel_names.begin();
626             it != channel_names.end();
627             ++it )
628         {
629             debugOutput(DEBUG_LEVEL_VERBOSE,"     %s\n", (*it).c_str());
630         }
631     }
632
633     debugOutput(DEBUG_LEVEL_VERBOSE," RX param space:\n");
634     debugOutput(DEBUG_LEVEL_VERBOSE,"  Nb of recv        : %1d\n", m_nb_tx);
635     for (unsigned int i=0;i<m_nb_rx;i++) {
636         debugOutput(DEBUG_LEVEL_VERBOSE,"  Receiver %d:\n",i);
637
638         readTxReg(i, DICE_REGISTER_RX_ISOC_BASE, &tmp_quadlet);
639         debugOutput(DEBUG_LEVEL_VERBOSE,"   ISO channel       : %3d\n", tmp_quadlet);
640         readTxReg(i, DICE_REGISTER_RX_SEQ_START_BASE, &tmp_quadlet);
641         debugOutput(DEBUG_LEVEL_VERBOSE,"   Sequence start    : %3d\n", tmp_quadlet);
642
643         readTxReg(i, DICE_REGISTER_RX_NB_AUDIO_BASE, &tmp_quadlet);
644         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb audio channels : %3d\n", tmp_quadlet);
645         readTxReg(i, DICE_REGISTER_RX_MIDI_BASE, &tmp_quadlet);
646         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb midi channels  : %3d\n", tmp_quadlet);
647
648         readTxReg(i, DICE_REGISTER_RX_AC3_CAPABILITIES_BASE, &tmp_quadlet);
649         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 caps          : 0x%08X\n", tmp_quadlet);
650         readTxReg(i, DICE_REGISTER_RX_AC3_ENABLE_BASE, &tmp_quadlet);
651         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 enable        : 0x%08X\n", tmp_quadlet);
652
653         diceNameVector channel_names=getRxNameString(i);
654         debugOutput(DEBUG_LEVEL_VERBOSE,"   Channel names     :\n");
655         for ( diceNameVectorIterator it = channel_names.begin();
656             it != channel_names.end();
657             ++it )
658         {
659             debugOutput(DEBUG_LEVEL_VERBOSE,"     %s\n", (*it).c_str());
660         }
661     }
662     flushDebugOutput();
663 }
664
665 // NOTE on bandwidth calculation
666 // FIXME: The bandwidth allocation calculation can probably be
667 // refined somewhat since this is currently based on a rudimentary
668 // understanding of the iso protocol.
669 // Currently we assume the following.
670 //   * Ack/iso gap = 0.05 us
671 //   * DATA_PREFIX = 0.16 us1
672 //   * DATA_END    = 0.26 us
673 // These numbers are the worst-case figures given in the ieee1394
674 // standard.  This gives approximately 0.5 us of overheads per
675 // packet - around 25 bandwidth allocation units (from the ieee1394
676 // standard 1 bandwidth allocation unit is 125/6144 us).  We further
677 // assume the device is running at S400 (which it should be) so one
678 // allocation unit is equivalent to 1 transmitted byte; thus the
679 // bandwidth allocation required for the packets themselves is just
680 // the size of the packet.
681 bool
682 DiceAvDevice::prepare() {
683     // prepare receive SP's
684 //     for (unsigned int i=0;i<1;i++) {
685     for (unsigned int i=0;i<m_nb_tx;i++) {
686         fb_quadlet_t nb_audio;
687         fb_quadlet_t nb_midi;
688         unsigned int nb_channels=0;
689
690         if(!readTxReg(i, DICE_REGISTER_TX_NB_AUDIO_BASE, &nb_audio)) {
691             debugError("Could not read DICE_REGISTER_TX_NB_AUDIO_BASE register for ATX%u\n",i);
692             continue;
693         }
694         if(!readTxReg(i, DICE_REGISTER_TX_MIDI_BASE, &nb_midi)) {
695             debugError("Could not read DICE_REGISTER_TX_MIDI_BASE register for ATX%u\n",i);
696             continue;
697         }
698
699         // request the channel names
700         diceNameVector names_audio=getTxNameString(i);
701
702         if (names_audio.size() != nb_audio) {
703             debugWarning("The audio channel name vector is incorrect, using default names\n");
704             names_audio.clear();
705
706             for (unsigned int j=0;j<nb_audio;j++) {
707                 std::ostringstream newname;
708                 newname << "input_" << j;
709                 names_audio.push_back(newname.str());
710             }
711         }
712
713         nb_channels=nb_audio;
714         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
715
716         // construct the MIDI names
717         diceNameVector names_midi;
718         for (unsigned int j=0;j<nb_midi;j++) {
719             std::ostringstream newname;
720             newname << "midi_in_" << j;
721             names_midi.push_back(newname.str());
722         }
723
724         // construct the streamprocessor
725         Streaming::AmdtpReceiveStreamProcessor *p;
726         p=new Streaming::AmdtpReceiveStreamProcessor(*this,
727                              nb_channels);
728
729         if(!p->init()) {
730             debugFatal("Could not initialize receive processor!\n");
731             delete p;
732             continue;
733         }
734
735         // add audio ports to the processor
736         for (unsigned int j=0;j<nb_audio;j++) {
737             diceChannelInfo channelInfo;
738             channelInfo.name=names_audio.at(j);
739             channelInfo.portType=ePT_Analog;
740             channelInfo.streamPosition=j;
741             channelInfo.streamLocation=0;
742
743             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
744                 debugError("Could not add channel %s to StreamProcessor\n",
745                     channelInfo.name.c_str());
746                 continue;
747             }
748         }
749
750         // add midi ports to the processor
751         for (unsigned int j=0;j<nb_midi;j++) {
752             diceChannelInfo channelInfo;
753             channelInfo.name=names_midi.at(j);
754             channelInfo.portType=ePT_MIDI;
755             channelInfo.streamPosition=nb_audio;
756             channelInfo.streamLocation=j;
757
758             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
759                 debugError("Could not add channel %s to StreamProcessor\n",
760                     channelInfo.name.c_str());
761                 continue;
762             }
763         }
764
765         // add the SP to the vector
766         m_receiveProcessors.push_back(p);
767     }
768
769     // prepare transmit SP's
770     //for (unsigned int i=0;i<1;i++) {
771     for (unsigned int i=0;i<m_nb_rx;i++) {
772         fb_quadlet_t nb_audio;
773         fb_quadlet_t nb_midi;
774         unsigned int nb_channels=0;
775
776         if(!readTxReg(i, DICE_REGISTER_RX_NB_AUDIO_BASE, &nb_audio)) {
777             debugError("Could not read DICE_REGISTER_RX_NB_AUDIO_BASE register for ARX%u\n",i);
778             continue;
779         }
780         if(!readTxReg(i, DICE_REGISTER_RX_MIDI_BASE, &nb_midi)) {
781             debugError("Could not read DICE_REGISTER_RX_MIDI_BASE register for ARX%u\n",i);
782             continue;
783         }
784
785         /* Vendor-specific hacks */
786
787         /* Alesis io14 RX0 claims to have six audio channels. Ignore it, just
788          * use 8 for Bus1-L+R .. Bus4-L+R.
789          */
790         if ((FW_VENDORID_ALESIS == getConfigRom().getNodeVendorId()) &&
791             (0x00000001 == getConfigRom().getModelId())) {
792             nb_audio=8;
793         }
794
795         // request the channel names
796         diceNameVector names_audio=getRxNameString(i);
797
798         if (names_audio.size() != nb_audio) {
799             debugWarning("The audio channel name vector is incorrect, using default names\n");
800             names_audio.clear();
801
802             for (unsigned int j=0;j<nb_audio;j++) {
803                 std::ostringstream newname;
804                 newname << "output_" << j;
805                 names_audio.push_back(newname.str());
806             }
807         }
808
809         nb_channels=nb_audio;
810         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
811
812         // construct the MIDI names
813         diceNameVector names_midi;
814         for (unsigned int j=0;j<nb_midi;j++) {
815             std::ostringstream newname;
816             newname << "midi_out_" << j;
817             names_midi.push_back(newname.str());
818         }
819
820         // construct the streamprocessor
821         Streaming::AmdtpTransmitStreamProcessor *p;
822         p=new Streaming::AmdtpTransmitStreamProcessor(*this,
823                              nb_channels);
824
825         if(!p->init()) {
826             debugFatal("Could not initialize transmit processor!\n");
827             delete p;
828             continue;
829         }
830
831 #if AMDTP_ALLOW_PAYLOAD_IN_NODATA_XMIT
832         // the DICE-II cannot handle payload in the NO-DATA packets.
833         // the other DICE chips don't need payload. Therefore
834         // we disable it.
835         p->sendPayloadForNoDataPackets(false);
836 #endif
837
838         // add audio ports to the processor
839         for (unsigned int j=0;j<nb_audio;j++) {
840             diceChannelInfo channelInfo;
841             channelInfo.name=names_audio.at(j);
842             channelInfo.portType=ePT_Analog;
843             channelInfo.streamPosition=j;
844             channelInfo.streamLocation=0;
845
846             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
847                 debugError("Could not add channel %s to StreamProcessor\n",
848                     channelInfo.name.c_str());
849                 continue;
850             }
851         }
852
853         // add midi ports to the processor
854         for (unsigned int j=0;j<nb_midi;j++) {
855             diceChannelInfo channelInfo;
856             channelInfo.name=names_midi.at(j);
857             channelInfo.portType=ePT_MIDI;
858             channelInfo.streamPosition=nb_audio;
859             channelInfo.streamLocation=j;
860
861             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
862                 debugError("Could not add channel %s to StreamProcessor\n",
863                     channelInfo.name.c_str());
864                 continue;
865             }
866         }
867
868         m_transmitProcessors.push_back(p);
869     }
870     return true;
871 }
872
873 bool
874 DiceAvDevice::addChannelToProcessor(
875     diceChannelInfo *channelInfo,
876     Streaming::StreamProcessor *processor,
877     Streaming::Port::E_Direction direction) {
878
879     std::string id=std::string("dev?");
880     if(!getOption("id", id)) {
881         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
882     }
883
884     std::ostringstream portname;
885     portname << id;
886     if(direction == Streaming::Port::E_Playback) {
887         portname << "p";
888     } else {
889         portname << "c";
890     }
891
892     portname << "_" << channelInfo->name;
893
894     Streaming::Port *p=NULL;
895     switch(channelInfo->portType) {
896     case ePT_Analog:
897         p=new Streaming::AmdtpAudioPort(
898                 *processor,
899                 portname.str(),
900                 direction,
901                 channelInfo->streamPosition,
902                 channelInfo->streamLocation,
903                 Streaming::AmdtpPortInfo::E_MBLA
904         );
905         break;
906
907     case ePT_MIDI:
908         p=new Streaming::AmdtpMidiPort(
909                 *processor,
910                 portname.str(),
911                 direction,
912                 channelInfo->streamPosition,
913                 channelInfo->streamLocation,
914                 Streaming::AmdtpPortInfo::E_Midi
915         );
916
917         break;
918     default:
919     // unsupported
920         break;
921     }
922
923     if (!p) {
924         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str());
925     }
926
927     return true;
928 }
929
930 bool
931 DiceAvDevice::lock() {
932     fb_octlet_t result;
933
934     debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n",
935         m_model->vendor_name, m_model->model_name, getNodeId());
936
937     // get a notifier to handle device notifications
938     nodeaddr_t notify_address;
939     notify_address = get1394Service().findFreeARMBlock(
940                         DICE_NOTIFIER_BASE_ADDRESS,
941                         DICE_NOTIFIER_BLOCK_LENGTH,
942                         DICE_NOTIFIER_BLOCK_LENGTH);
943
944     if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) {
945         debugError("Could not find free ARM block for notification\n");
946         return false;
947     }
948
949     m_notifier=new DiceAvDevice::DiceNotifier(this, notify_address);
950
951     if(!m_notifier) {
952         debugError("Could not allocate notifier\n");
953         return false;
954     }
955
956     if (!get1394Service().registerARMHandler(m_notifier)) {
957         debugError("Could not register notifier\n");
958         delete m_notifier;
959         m_notifier=NULL;
960         return false;
961     }
962
963     // register this notifier
964     fb_nodeaddr_t addr = DICE_REGISTER_BASE
965                        + m_global_reg_offset
966                        + DICE_REGISTER_GLOBAL_OWNER;
967
968     // registry offsets should always be smaller than 0x7FFFFFFF
969     // because otherwise base + offset > 64bit
970     if(m_global_reg_offset & 0x80000000) {
971         debugError("register offset not initialized yet\n");
972         return false;
973     }
974
975     fb_nodeaddr_t swap_value = ((0xFFC0) | get1394Service().getLocalNodeId());
976     swap_value = swap_value << 48;
977     swap_value |= m_notifier->getStart();
978
979     if (!get1394Service().lockCompareSwap64(getNodeId() | 0xFFC0,
980                                             addr, DICE_OWNER_NO_OWNER,
981                                             swap_value, &result )) {
982         debugWarning("Could not register ourselves as device owner\n");
983         return false;
984     }
985
986     if (result != DICE_OWNER_NO_OWNER) {
987         debugWarning("Could not register ourselves as device owner, unexpected register value: 0x%016llX\n", result);
988         return false;
989     }
990
991     return true;
992 }
993
994
995 bool
996 DiceAvDevice::unlock() {
997     fb_octlet_t result;
998
999     if(!m_notifier) {
1000         debugWarning("Request to unlock, but no notifier present!\n");
1001         return false;
1002     }
1003
1004     fb_nodeaddr_t addr = DICE_REGISTER_BASE
1005                        + m_global_reg_offset
1006                        + DICE_REGISTER_GLOBAL_OWNER;
1007
1008     // registry offsets should always be smaller than 0x7FFFFFFF
1009     // because otherwise base + offset > 64bit
1010     if(m_global_reg_offset & 0x80000000) {
1011         debugError("register offset not initialized yet\n");
1012         return false;
1013     }
1014
1015     fb_nodeaddr_t compare_value = ((0xFFC0) | get1394Service().getLocalNodeId());
1016     compare_value <<= 48;
1017     compare_value |= m_notifier->getStart();
1018
1019     if (!get1394Service().lockCompareSwap64(  getNodeId() | 0xFFC0, addr, compare_value,
1020                                        DICE_OWNER_NO_OWNER, &result )) {
1021         debugWarning("Could not unregister ourselves as device owner\n");
1022         return false;
1023     }
1024
1025     get1394Service().unregisterARMHandler(m_notifier);
1026     delete m_notifier;
1027     m_notifier=NULL;
1028
1029     return true;
1030 }
1031
1032 bool
1033 DiceAvDevice::enableStreaming() {
1034     return enableIsoStreaming();
1035 }
1036
1037 bool
1038 DiceAvDevice::disableStreaming() {
1039     return disableIsoStreaming();
1040 }
1041
1042 int
1043 DiceAvDevice::getStreamCount() {
1044     return m_receiveProcessors.size() + m_transmitProcessors.size();
1045 }
1046
1047 Streaming::StreamProcessor *
1048 DiceAvDevice::getStreamProcessorByIndex(int i) {
1049
1050     if (i<(int)m_receiveProcessors.size()) {
1051         return m_receiveProcessors.at(i);
1052     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1053         return m_transmitProcessors.at(i-m_receiveProcessors.size());
1054     }
1055
1056     return NULL;
1057 }
1058
1059 bool
1060 DiceAvDevice::startStreamByIndex(int i) {
1061
1062     if (isIsoStreamingEnabled()) {
1063         debugError("Cannot start streams while streaming is enabled\n");
1064         return false;
1065     }
1066
1067     if (i<(int)m_receiveProcessors.size()) {
1068         int n=i;
1069         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1070
1071         // allocate ISO channel
1072         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
1073         if(isochannel<0) {
1074             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
1075             return false;
1076         }
1077         p->setChannel(isochannel);
1078
1079         fb_quadlet_t reg_isoch;
1080         // check value of ISO_CHANNEL register
1081         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
1082             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
1083             p->setChannel(-1);
1084             deallocateIsoChannel(isochannel);
1085             return false;
1086         }
1087         if(reg_isoch != 0xFFFFFFFFUL) {
1088             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ATX %d\n", reg_isoch, n);
1089             p->setChannel(-1);
1090             deallocateIsoChannel(isochannel);
1091             return false;
1092         }
1093
1094         // write value of ISO_CHANNEL register
1095         reg_isoch=isochannel;
1096         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
1097             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
1098             p->setChannel(-1);
1099             deallocateIsoChannel(isochannel);
1100             return false;
1101         }
1102
1103         return true;
1104
1105     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1106         int n=i-m_receiveProcessors.size();
1107         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1108
1109         // allocate ISO channel
1110         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
1111         if(isochannel<0) {
1112             debugError("Could not allocate iso channel for SP %d (ARX %d)\n",i,n);
1113             return false;
1114         }
1115         p->setChannel(isochannel);
1116
1117         fb_quadlet_t reg_isoch;
1118         // check value of ISO_CHANNEL register
1119         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
1120             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
1121             p->setChannel(-1);
1122             deallocateIsoChannel(isochannel);
1123             return false;
1124         }
1125         if(reg_isoch != 0xFFFFFFFFUL) {
1126             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ARX %d\n", reg_isoch, n);
1127             p->setChannel(-1);
1128             deallocateIsoChannel(isochannel);
1129             return false;
1130         }
1131
1132         // write value of ISO_CHANNEL register
1133         reg_isoch=isochannel;
1134         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
1135             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
1136             p->setChannel(-1);
1137             deallocateIsoChannel(isochannel);
1138             return false;
1139         }
1140
1141         return true;
1142     }
1143
1144     debugError("SP index %d out of range!\n",i);
1145
1146     return false;
1147 }
1148
1149 bool
1150 DiceAvDevice::stopStreamByIndex(int i) {
1151
1152     if (isIsoStreamingEnabled()) {
1153         debugError("Cannot stop streams while streaming is enabled\n");
1154         return false;
1155     }
1156
1157     if (i<(int)m_receiveProcessors.size()) {
1158         int n=i;
1159         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1160         unsigned int isochannel=p->getChannel();
1161
1162         fb_quadlet_t reg_isoch;
1163         // check value of ISO_CHANNEL register
1164         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
1165             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
1166             return false;
1167         }
1168         if(reg_isoch != isochannel) {
1169             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ATX %d\n", isochannel, reg_isoch, n);
1170             return false;
1171         }
1172
1173         // write value of ISO_CHANNEL register
1174         reg_isoch=0xFFFFFFFFUL;
1175         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
1176             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
1177             return false;
1178         }
1179
1180         // deallocate ISO channel
1181         if(!deallocateIsoChannel(isochannel)) {
1182             debugError("Could not deallocate iso channel for SP %d (ATX %d)\n",i,n);
1183             return false;
1184         }
1185
1186         p->setChannel(-1);
1187         return true;
1188
1189     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1190         int n=i-m_receiveProcessors.size();
1191         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1192
1193         unsigned int isochannel=p->getChannel();
1194
1195         fb_quadlet_t reg_isoch;
1196         // check value of ISO_CHANNEL register
1197         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
1198             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
1199             return false;
1200         }
1201         if(reg_isoch != isochannel) {
1202             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ARX %d\n", isochannel, reg_isoch, n);
1203             return false;
1204         }
1205
1206         // write value of ISO_CHANNEL register
1207         reg_isoch=0xFFFFFFFFUL;
1208         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
1209             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
1210             return false;
1211         }
1212
1213         // deallocate ISO channel
1214         if(!deallocateIsoChannel(isochannel)) {
1215             debugError("Could not deallocate iso channel for SP %d (ARX %d)\n",i,n);
1216             return false;
1217         }
1218
1219         p->setChannel(-1);
1220         return true;
1221     }
1222
1223     debugError("SP index %d out of range!\n",i);
1224
1225     return false;
1226 }
1227
1228 // helper routines
1229
1230 // allocate ISO resources for the SP's
1231 int DiceAvDevice::allocateIsoChannel(unsigned int packet_size) {
1232     unsigned int bandwidth=8+packet_size;
1233
1234     int ch=get1394Service().allocateIsoChannelGeneric(bandwidth);
1235
1236     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
1237         ch, bandwidth);
1238
1239     return ch;
1240 }
1241 // deallocate ISO resources
1242 bool DiceAvDevice::deallocateIsoChannel(int channel) {
1243     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
1244     return get1394Service().freeIsoChannel(channel);
1245 }
1246
1247 bool
1248 DiceAvDevice::enableIsoStreaming() {
1249     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_ENABLE);
1250 }
1251
1252 bool
1253 DiceAvDevice::disableIsoStreaming() {
1254     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_DISABLE);
1255 }
1256
1257 bool
1258 DiceAvDevice::isIsoStreamingEnabled() {
1259     fb_quadlet_t result;
1260     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &result);
1261     // I don't know what exactly is 'enable',
1262     // but disable is definately == 0
1263     return (result != DICE_ISOSTREAMING_DISABLE);
1264 }
1265
1266 /**
1267  * @brief performs a masked bit register equals 0 check on the global parameter space
1268  * @return true if readGlobalReg(offset) & mask == 0
1269  */
1270 bool
1271 DiceAvDevice::maskedCheckZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1272     fb_quadlet_t result;
1273     readGlobalReg(offset, &result);
1274     return ((result & mask) == 0);
1275 }
1276 /**
1277  * @brief performs a masked bit register not equal to 0 check on the global parameter space
1278  * @return true if readGlobalReg(offset) & mask != 0
1279  */
1280 bool
1281 DiceAvDevice::maskedCheckNotZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1282     return !maskedCheckZeroGlobalReg(offset, mask);
1283 }
1284
1285 DiceAvDevice::diceNameVector
1286 DiceAvDevice::getTxNameString(unsigned int i) {
1287     diceNameVector names;
1288     char namestring[DICE_TX_NAMES_SIZE+1];
1289
1290     if (!readTxRegBlockSwapped(i, DICE_REGISTER_TX_NAMES_BASE,
1291                         (fb_quadlet_t *)namestring, DICE_TX_NAMES_SIZE)) {
1292         debugError("Could not read TX name string \n");
1293         return names;
1294     }
1295
1296     namestring[DICE_TX_NAMES_SIZE]='\0';
1297     return splitNameString(std::string(namestring));
1298 }
1299
1300 DiceAvDevice::diceNameVector
1301 DiceAvDevice::getRxNameString(unsigned int i) {
1302     diceNameVector names;
1303     char namestring[DICE_RX_NAMES_SIZE+1];
1304
1305     if (!readRxRegBlockSwapped(i, DICE_REGISTER_RX_NAMES_BASE,
1306                         (fb_quadlet_t *)namestring, DICE_RX_NAMES_SIZE)) {
1307         debugError("Could not read RX name string \n");
1308         return names;
1309     }
1310
1311     namestring[DICE_RX_NAMES_SIZE]='\0';
1312     return splitNameString(std::string(namestring));
1313 }
1314
1315 DiceAvDevice::diceNameVector
1316 DiceAvDevice::getClockSourceNameString() {
1317     diceNameVector names;
1318     char namestring[DICE_CLOCKSOURCENAMES_SIZE+1];
1319
1320     if (!readGlobalRegBlockSwapped(DICE_REGISTER_GLOBAL_CLOCKSOURCENAMES,
1321                       (fb_quadlet_t *)namestring, DICE_CLOCKSOURCENAMES_SIZE)) {
1322         debugError("Could not read CLOCKSOURCE name string \n");
1323         return names;
1324     }
1325
1326     namestring[DICE_CLOCKSOURCENAMES_SIZE]='\0';
1327     return splitNameString(std::string(namestring));
1328 }
1329
1330 std::string
1331 DiceAvDevice::getDeviceNickName() {
1332     char namestring[DICE_NICK_NAME_SIZE+1];
1333
1334     if (!readGlobalRegBlockSwapped(DICE_REGISTER_GLOBAL_NICK_NAME,
1335                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1336         debugError("Could not read nickname string \n");
1337         return std::string("(unknown)");
1338     }
1339
1340     namestring[DICE_NICK_NAME_SIZE]='\0';
1341     return std::string(namestring);
1342 }
1343
1344 bool
1345 DiceAvDevice::setDeviceNickName(std::string name) {
1346     char namestring[DICE_NICK_NAME_SIZE+1];
1347     strncpy(namestring, name.c_str(), DICE_NICK_NAME_SIZE);
1348
1349     if (!writeGlobalRegBlockSwapped(DICE_REGISTER_GLOBAL_NICK_NAME,
1350                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1351         debugError("Could not write nickname string \n");
1352         return false;
1353     }
1354     return true;
1355 }
1356
1357 DiceAvDevice::diceNameVector
1358 DiceAvDevice::splitNameString(std::string in) {
1359     diceNameVector names;
1360
1361     // find the end of the string
1362     string::size_type end=in.find(string("\\\\"));
1363     // cut the end
1364     in=in.substr(0,end);
1365
1366     string::size_type cut;
1367     while( (cut = in.find(string("\\"))) != in.npos ) {
1368         if(cut > 0) {
1369             names.push_back(in.substr(0,cut));
1370         }
1371         in = in.substr(cut+1);
1372     }
1373     if(in.length() > 0) {
1374         names.push_back(in);
1375     }
1376     return names;
1377 }
1378
1379
1380 // I/O routines
1381 bool
1382 DiceAvDevice::initIoFunctions() {
1383
1384     // offsets and sizes are returned in quadlets, but we use byte values
1385
1386     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_OFF, &m_global_reg_offset)) {
1387         debugError("Could not initialize m_global_reg_offset\n");
1388         return false;
1389     }
1390     m_global_reg_offset*=4;
1391
1392     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_SZ, &m_global_reg_size)) {
1393         debugError("Could not initialize m_global_reg_size\n");
1394         return false;
1395     }
1396     m_global_reg_size*=4;
1397
1398     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_OFF, &m_tx_reg_offset)) {
1399         debugError("Could not initialize m_tx_reg_offset\n");
1400         return false;
1401     }
1402     m_tx_reg_offset*=4;
1403
1404     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_SZ, &m_tx_reg_size)) {
1405         debugError("Could not initialize m_tx_reg_size\n");
1406         return false;
1407     }
1408     m_tx_reg_size*=4;
1409
1410     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_OFF, &m_rx_reg_offset)) {
1411         debugError("Could not initialize m_rx_reg_offset\n");
1412         return false;
1413     }
1414     m_rx_reg_offset*=4;
1415
1416     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_SZ, &m_rx_reg_size)) {
1417         debugError("Could not initialize m_rx_reg_size\n");
1418         return false;
1419     }
1420     m_rx_reg_size*=4;
1421
1422     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_OFF, &m_unused1_reg_offset)) {
1423         debugError("Could not initialize m_unused1_reg_offset\n");
1424         return false;
1425     }
1426     m_unused1_reg_offset*=4;
1427
1428     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_SZ, &m_unused1_reg_size)) {
1429         debugError("Could not initialize m_unused1_reg_size\n");
1430         return false;
1431     }
1432     m_unused1_reg_size*=4;
1433
1434     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_OFF, &m_unused2_reg_offset)) {
1435         debugError("Could not initialize m_unused2_reg_offset\n");
1436         return false;
1437     }
1438     m_unused2_reg_offset*=4;
1439
1440     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_SZ, &m_unused2_reg_size)) {
1441         debugError("Could not initialize m_unused2_reg_size\n");
1442         return false;
1443     }
1444     m_unused2_reg_size*=4;
1445
1446     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_NB_TX, &m_nb_tx)) {
1447         debugError("Could not initialize m_nb_tx\n");
1448         return false;
1449     }
1450     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_SZ_TX, &m_tx_size)) {
1451         debugError("Could not initialize m_tx_size\n");
1452         return false;
1453     }
1454     m_tx_size*=4;
1455
1456     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_NB_RX, &m_nb_rx)) {
1457         debugError("Could not initialize m_nb_rx\n");
1458         return false;
1459     }
1460
1461     // FIXME: verify this and clean it up.
1462     /* special case for io14, which announces two receive transmitters,
1463      * but only has one
1464      */
1465     if ((FW_VENDORID_ALESIS == getConfigRom().getNodeVendorId()) &&
1466             (0x00000001 == getConfigRom().getModelId())) {
1467         m_nb_rx = 1;
1468     }
1469
1470     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
1471         debugError("Could not initialize m_rx_size\n");
1472         return false;
1473     }
1474     m_rx_size*=4;
1475
1476     debugOutput(DEBUG_LEVEL_VERBOSE,"DICE Parameter Space info:\n");
1477     debugOutput(DEBUG_LEVEL_VERBOSE," Global  : offset=%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
1478     debugOutput(DEBUG_LEVEL_VERBOSE," TX      : offset=%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
1479     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
1480     debugOutput(DEBUG_LEVEL_VERBOSE," RX      : offset=%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
1481     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
1482     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED1 : offset=%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
1483     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED2 : offset=%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
1484
1485     return true;
1486 }
1487
1488 bool
1489 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1490     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
1491
1492     if(offset >= DICE_INVALID_OFFSET) {
1493         debugError("invalid offset: 0x%016llX\n", offset);
1494         return false;
1495     }
1496
1497     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1498     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1499
1500     if(!get1394Service().read_quadlet( nodeId, addr, result ) ) {
1501         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1502         return false;
1503     }
1504
1505     *result=CondSwapFromBus32(*result);
1506
1507     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1508
1509     return true;
1510 }
1511
1512 bool
1513 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1514     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
1515         offset, data);
1516
1517     if(offset >= DICE_INVALID_OFFSET) {
1518         debugError("invalid offset: 0x%016llX\n", offset);
1519         return false;
1520     }
1521
1522     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1523     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1524
1525     if(!get1394Service().write_quadlet( nodeId, addr, CondSwapToBus32(data) ) ) {
1526         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1527         return false;
1528     }
1529     return true;
1530 }
1531
1532 bool
1533 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1534     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1535         offset, length);
1536
1537     if(offset >= DICE_INVALID_OFFSET) {
1538         debugError("invalid offset: 0x%016llX\n", offset);
1539         return false;
1540     }
1541
1542     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1543     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1544
1545     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1546         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1547         return false;
1548     }
1549
1550     for(unsigned int i=0;i<length/4;i++) {
1551         *(data+i)=CondSwapFromBus32(*(data+i));
1552     }
1553
1554     return true;
1555 }
1556
1557 bool
1558 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1559     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1560         offset, length);
1561
1562     if(offset >= DICE_INVALID_OFFSET) {
1563         debugError("invalid offset: 0x%016llX\n", offset);
1564         return false;
1565     }
1566
1567     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1568     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1569
1570     fb_quadlet_t data_out[length/4];
1571
1572     for(unsigned int i=0;i<length/4;i++) {
1573         data_out[i]=CondSwapFromBus32(*(data+i));
1574     }
1575
1576     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1577         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1578         return false;
1579     }
1580
1581     return true;
1582 }
1583
1584 bool
1585 DiceAvDevice::readRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1586     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1587         offset, length);
1588
1589     if(offset >= DICE_INVALID_OFFSET) {
1590         debugError("invalid offset: 0x%016llX\n", offset);
1591         return false;
1592     }
1593
1594     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1595     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1596
1597     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1598         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1599         return false;
1600     }
1601
1602     for(unsigned int i=0;i<length/4;i++) {
1603         *(data+i)=ByteSwap32(*(data+i));
1604     }
1605
1606     return true;
1607 }
1608
1609 bool
1610 DiceAvDevice::writeRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1611     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1612         offset, length);
1613
1614     if(offset >= DICE_INVALID_OFFSET) {
1615         debugError("invalid offset: 0x%016llX\n", offset);
1616         return false;
1617     }
1618
1619     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1620     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1621
1622     fb_quadlet_t data_out[length/4];
1623
1624     for(unsigned int i=0;i<length/4;i++) {
1625         data_out[i]=ByteSwap32(*(data+i));
1626     }
1627
1628     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1629         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1630         return false;
1631     }
1632
1633     return true;
1634 }
1635
1636 bool
1637 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1638     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1639
1640     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1641     return readReg(m_global_reg_offset + offset_gl, result);
1642 }
1643
1644 bool
1645 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1646     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n",
1647         offset, data);
1648
1649     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1650     return writeReg(m_global_reg_offset + offset_gl, data);
1651 }
1652
1653 bool
1654 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1655     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1656         offset, length);
1657
1658     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1659     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1660 }
1661
1662 bool
1663 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1664     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1665         offset, length);
1666
1667     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1668     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1669 }
1670
1671 bool
1672 DiceAvDevice::readGlobalRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1673     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1674         offset, length);
1675
1676     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1677     return readRegBlockSwapped(m_global_reg_offset + offset_gl, data, length);
1678 }
1679
1680 bool
1681 DiceAvDevice::writeGlobalRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1682     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1683         offset, length);
1684
1685     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1686     return writeRegBlockSwapped(m_global_reg_offset + offset_gl, data, length);
1687 }
1688
1689 fb_nodeaddr_t
1690 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1691
1692     // registry offsets should always be smaller than 0x7FFFFFFF
1693     // because otherwise base + offset > 64bit
1694     if(m_global_reg_offset & 0x80000000) {
1695         debugError("register offset not initialized yet\n");
1696         return DICE_INVALID_OFFSET;
1697     }
1698     // out-of-range check
1699     if(offset+length > m_global_reg_offset+m_global_reg_size) {
1700         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1701         return DICE_INVALID_OFFSET;
1702     }
1703
1704     return offset;
1705 }
1706
1707 bool
1708 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1709     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1710
1711     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1712     return readReg(m_tx_reg_offset + offset_tx, result);
1713 }
1714
1715 bool
1716 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1717     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1718         i, offset, data);
1719
1720     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1721     return writeReg(m_tx_reg_offset + offset_tx, data);
1722 }
1723
1724 bool
1725 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1726     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1727         offset, length);
1728
1729     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1730     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1731 }
1732
1733 bool
1734 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1735     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1736         offset, length);
1737
1738     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1739     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1740 }
1741
1742 bool
1743 DiceAvDevice::readTxRegBlockSwapped(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1744     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1745         offset, length);
1746
1747     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1748     return readRegBlockSwapped(m_tx_reg_offset + offset_tx, data, length);
1749 }
1750
1751 fb_nodeaddr_t
1752 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1753     // registry offsets should always be smaller than 0x7FFFFFFF
1754     // because otherwise base + offset > 64bit
1755     if(m_tx_reg_offset & 0x80000000) {
1756         debugError("register offset not initialized yet\n");
1757         return DICE_INVALID_OFFSET;
1758     }
1759     if(m_nb_tx & 0x80000000) {
1760         debugError("m_nb_tx not initialized yet\n");
1761         return DICE_INVALID_OFFSET;
1762     }
1763     if(m_tx_size & 0x80000000) {
1764         debugError("m_tx_size not initialized yet\n");
1765         return DICE_INVALID_OFFSET;
1766     }
1767     if(i >= m_nb_tx) {
1768         debugError("TX index out of range\n");
1769         return DICE_INVALID_OFFSET;
1770     }
1771
1772     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1773
1774     // out-of-range check
1775     if(offset_tx + length > m_tx_reg_offset+4+m_tx_reg_size*m_nb_tx) {
1776         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1777         return DICE_INVALID_OFFSET;
1778     }
1779
1780     return offset_tx;
1781 }
1782
1783 bool
1784 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1785     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1786
1787     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1788     return readReg(m_rx_reg_offset + offset_rx, result);
1789 }
1790
1791 bool
1792 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1793     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n",
1794         offset, data);
1795
1796     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1797     return writeReg(m_rx_reg_offset + offset_rx, data);
1798 }
1799
1800 bool
1801 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1802     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1803         offset, length);
1804
1805     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1806     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1807 }
1808
1809 bool
1810 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1811     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1812         offset, length);
1813
1814     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1815     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1816 }
1817
1818 bool
1819 DiceAvDevice::readRxRegBlockSwapped(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1820     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1821         offset, length);
1822
1823     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1824     return readRegBlockSwapped(m_rx_reg_offset + offset_rx, data, length);
1825 }
1826
1827 fb_nodeaddr_t
1828 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1829     // registry offsets should always be smaller than 0x7FFFFFFF
1830     // because otherwise base + offset > 64bit
1831     if(m_rx_reg_offset & 0x80000000) {
1832         debugError("register offset not initialized yet\n");
1833         return DICE_INVALID_OFFSET;
1834     }
1835     if(m_nb_rx & 0x80000000) {
1836         debugError("m_nb_rx not initialized yet\n");
1837         return DICE_INVALID_OFFSET;
1838     }
1839     if(m_rx_size & 0x80000000) {
1840         debugError("m_rx_size not initialized yet\n");
1841         return DICE_INVALID_OFFSET;
1842     }
1843     if(i >= m_nb_rx) {
1844         debugError("RX index out of range\n");
1845         return DICE_INVALID_OFFSET;
1846     }
1847
1848     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1849
1850     // out-of-range check
1851     if(offset_rx + length > m_rx_reg_offset+4+m_rx_reg_size*m_nb_rx) {
1852         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1853         return DICE_INVALID_OFFSET;
1854     }
1855     return offset_rx;
1856 }
1857
1858
1859 // the notifier
1860
1861 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1862  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1863               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1864               RAW1394_ARM_WRITE, 0)
1865  , m_dicedevice(d)
1866 {
1867
1868 }
1869
1870 DiceAvDevice::DiceNotifier::~DiceNotifier()
1871 {
1872
1873 }
1874
1875 }
Note: See TracBrowser for help on using the browser.