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

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

shutdown fix for DICE and MOTU

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