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

Revision 1004, 57.1 kB (checked in by ppalmers, 16 years ago)

add konnekt live device id

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