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

Revision 864, 57.0 kB (checked in by ppalmers, 15 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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 };
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                 *processor,
842                 portname.str(),
843                 direction,
844                 channelInfo->streamPosition,
845                 channelInfo->streamLocation,
846                 Streaming::AmdtpPortInfo::E_MBLA
847         );
848         break;
849
850     case ePT_MIDI:
851         p=new Streaming::AmdtpMidiPort(
852                 *processor,
853                 portname.str(),
854                 direction,
855                 channelInfo->streamPosition,
856                 channelInfo->streamLocation,
857                 Streaming::AmdtpPortInfo::E_Midi
858         );
859
860         break;
861     default:
862     // unsupported
863         break;
864     }
865
866     if (!p) {
867         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str());
868     }
869
870     return true;
871 }
872
873 bool
874 DiceAvDevice::lock() {
875     fb_octlet_t result;
876
877     debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n",
878         m_model->vendor_name, m_model->model_name, getNodeId());
879
880     // get a notifier to handle device notifications
881     nodeaddr_t notify_address;
882     notify_address = get1394Service().findFreeARMBlock(
883                         DICE_NOTIFIER_BASE_ADDRESS,
884                         DICE_NOTIFIER_BLOCK_LENGTH,
885                         DICE_NOTIFIER_BLOCK_LENGTH);
886
887     if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) {
888         debugError("Could not find free ARM block for notification\n");
889         return false;
890     }
891
892     m_notifier=new DiceAvDevice::DiceNotifier(this, notify_address);
893
894     if(!m_notifier) {
895         debugError("Could not allocate notifier\n");
896         return false;
897     }
898
899     if (!get1394Service().registerARMHandler(m_notifier)) {
900         debugError("Could not register notifier\n");
901         delete m_notifier;
902         m_notifier=NULL;
903         return false;
904     }
905
906     // register this notifier
907     fb_nodeaddr_t addr = DICE_REGISTER_BASE
908                        + m_global_reg_offset
909                        + DICE_REGISTER_GLOBAL_OWNER;
910
911     // registry offsets should always be smaller than 0x7FFFFFFF
912     // because otherwise base + offset > 64bit
913     if(m_global_reg_offset & 0x80000000) {
914         debugError("register offset not initialized yet\n");
915         return false;
916     }
917
918     fb_nodeaddr_t swap_value = ((0xFFC0) | get1394Service().getLocalNodeId());
919     swap_value = swap_value << 48;
920     swap_value |= m_notifier->getStart();
921
922     if (!get1394Service().lockCompareSwap64(  getNodeId() | 0xFFC0, addr, DICE_OWNER_NO_OWNER,
923                                        swap_value, &result )) {
924         debugWarning("Could not register ourselves as device owner\n");
925         return false;
926     }
927
928     if (result != DICE_OWNER_NO_OWNER) {
929         debugWarning("Could not register ourselves as device owner, unexpected register value: 0x%016llX\n", result);
930         return false;
931     }
932
933     return true;
934 }
935
936
937 bool
938 DiceAvDevice::unlock() {
939     fb_octlet_t result;
940
941     if(!m_notifier) {
942         debugWarning("Request to unlock, but no notifier present!\n");
943         return false;
944     }
945
946     fb_nodeaddr_t addr = DICE_REGISTER_BASE
947                        + m_global_reg_offset
948                        + DICE_REGISTER_GLOBAL_OWNER;
949
950     // registry offsets should always be smaller than 0x7FFFFFFF
951     // because otherwise base + offset > 64bit
952     if(m_global_reg_offset & 0x80000000) {
953         debugError("register offset not initialized yet\n");
954         return false;
955     }
956
957     fb_nodeaddr_t compare_value = ((0xFFC0) | get1394Service().getLocalNodeId());
958     compare_value <<= 48;
959     compare_value |= m_notifier->getStart();
960
961     if (!get1394Service().lockCompareSwap64(  getNodeId() | 0xFFC0, addr, compare_value,
962                                        DICE_OWNER_NO_OWNER, &result )) {
963         debugWarning("Could not unregister ourselves as device owner\n");
964         return false;
965     }
966
967     get1394Service().unregisterARMHandler(m_notifier);
968     delete m_notifier;
969     m_notifier=NULL;
970
971     return true;
972 }
973
974 bool
975 DiceAvDevice::enableStreaming() {
976     return enableIsoStreaming();
977 }
978
979 bool
980 DiceAvDevice::disableStreaming() {
981     return disableIsoStreaming();
982 }
983
984 int
985 DiceAvDevice::getStreamCount() {
986     return m_receiveProcessors.size() + m_transmitProcessors.size();
987 }
988
989 Streaming::StreamProcessor *
990 DiceAvDevice::getStreamProcessorByIndex(int i) {
991
992     if (i<(int)m_receiveProcessors.size()) {
993         return m_receiveProcessors.at(i);
994     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
995         return m_transmitProcessors.at(i-m_receiveProcessors.size());
996     }
997
998     return NULL;
999 }
1000
1001 bool
1002 DiceAvDevice::startStreamByIndex(int i) {
1003
1004     if (isIsoStreamingEnabled()) {
1005         debugError("Cannot start streams while streaming is enabled\n");
1006         return false;
1007     }
1008
1009     if (i<(int)m_receiveProcessors.size()) {
1010         int n=i;
1011         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1012
1013         // allocate ISO channel
1014         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
1015         if(isochannel<0) {
1016             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
1017             return false;
1018         }
1019         p->setChannel(isochannel);
1020
1021         fb_quadlet_t reg_isoch;
1022         // check value of ISO_CHANNEL register
1023         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
1024             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
1025             p->setChannel(-1);
1026             deallocateIsoChannel(isochannel);
1027             return false;
1028         }
1029         if(reg_isoch != 0xFFFFFFFFUL) {
1030             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ATX %d\n", reg_isoch, n);
1031             p->setChannel(-1);
1032             deallocateIsoChannel(isochannel);
1033             return false;
1034         }
1035
1036         // write value of ISO_CHANNEL register
1037         reg_isoch=isochannel;
1038         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
1039             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
1040             p->setChannel(-1);
1041             deallocateIsoChannel(isochannel);
1042             return false;
1043         }
1044
1045         return true;
1046
1047     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1048         int n=i-m_receiveProcessors.size();
1049         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1050
1051         // allocate ISO channel
1052         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
1053         if(isochannel<0) {
1054             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
1055             return false;
1056         }
1057         p->setChannel(isochannel);
1058
1059         fb_quadlet_t reg_isoch;
1060         // check value of ISO_CHANNEL register
1061         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
1062             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
1063             p->setChannel(-1);
1064             deallocateIsoChannel(isochannel);
1065             return false;
1066         }
1067         if(reg_isoch != 0xFFFFFFFFUL) {
1068             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ARX %d\n", reg_isoch, n);
1069             p->setChannel(-1);
1070             deallocateIsoChannel(isochannel);
1071             return false;
1072         }
1073
1074         // write value of ISO_CHANNEL register
1075         reg_isoch=isochannel;
1076         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
1077             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
1078             p->setChannel(-1);
1079             deallocateIsoChannel(isochannel);
1080             return false;
1081         }
1082
1083         return true;
1084     }
1085
1086     debugError("SP index %d out of range!\n",i);
1087
1088     return false;
1089 }
1090
1091 bool
1092 DiceAvDevice::stopStreamByIndex(int i) {
1093
1094     if (isIsoStreamingEnabled()) {
1095         debugError("Cannot stop streams while streaming is enabled\n");
1096         return false;
1097     }
1098
1099     if (i<(int)m_receiveProcessors.size()) {
1100         int n=i;
1101         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1102         unsigned int isochannel=p->getChannel();
1103
1104         fb_quadlet_t reg_isoch;
1105         // check value of ISO_CHANNEL register
1106         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
1107             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
1108             return false;
1109         }
1110         if(reg_isoch != isochannel) {
1111             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ATX %d\n", isochannel, reg_isoch, n);
1112             return false;
1113         }
1114
1115         // write value of ISO_CHANNEL register
1116         reg_isoch=0xFFFFFFFFUL;
1117         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
1118             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
1119             return false;
1120         }
1121
1122         // deallocate ISO channel
1123         if(!deallocateIsoChannel(isochannel)) {
1124             debugError("Could not deallocate iso channel for SP %d (ATX %d)\n",i,n);
1125             return false;
1126         }
1127
1128         p->setChannel(-1);
1129         return true;
1130
1131     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1132         int n=i-m_receiveProcessors.size();
1133         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1134
1135         unsigned int isochannel=p->getChannel();
1136
1137         fb_quadlet_t reg_isoch;
1138         // check value of ISO_CHANNEL register
1139         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
1140             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
1141             return false;
1142         }
1143         if(reg_isoch != isochannel) {
1144             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ARX %d\n", isochannel, reg_isoch, n);
1145             return false;
1146         }
1147
1148         // write value of ISO_CHANNEL register
1149         reg_isoch=0xFFFFFFFFUL;
1150         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
1151             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
1152             return false;
1153         }
1154
1155         // deallocate ISO channel
1156         if(!deallocateIsoChannel(isochannel)) {
1157             debugError("Could not deallocate iso channel for SP %d (ARX %d)\n",i,n);
1158             return false;
1159         }
1160
1161         p->setChannel(-1);
1162         return true;
1163     }
1164
1165     debugError("SP index %d out of range!\n",i);
1166
1167     return false;
1168 }
1169
1170 // helper routines
1171
1172 // allocate ISO resources for the SP's
1173 int DiceAvDevice::allocateIsoChannel(unsigned int packet_size) {
1174     unsigned int bandwidth=8+packet_size;
1175
1176     int ch=get1394Service().allocateIsoChannelGeneric(bandwidth);
1177
1178     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
1179         ch, bandwidth);
1180
1181     return ch;
1182 }
1183 // deallocate ISO resources
1184 bool DiceAvDevice::deallocateIsoChannel(int channel) {
1185     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
1186     return get1394Service().freeIsoChannel(channel);
1187 }
1188
1189 bool
1190 DiceAvDevice::enableIsoStreaming() {
1191     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_ENABLE);
1192 }
1193
1194 bool
1195 DiceAvDevice::disableIsoStreaming() {
1196     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_DISABLE);
1197 }
1198
1199 bool
1200 DiceAvDevice::isIsoStreamingEnabled() {
1201     fb_quadlet_t result;
1202     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &result);
1203     // I don't know what exactly is 'enable',
1204     // but disable is definately == 0
1205     return (result != DICE_ISOSTREAMING_DISABLE);
1206 }
1207
1208 /**
1209  * @brief performs a masked bit register equals 0 check on the global parameter space
1210  * @return true if readGlobalReg(offset) & mask == 0
1211  */
1212 bool
1213 DiceAvDevice::maskedCheckZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1214     fb_quadlet_t result;
1215     readGlobalReg(offset, &result);
1216     return ((result & mask) == 0);
1217 }
1218 /**
1219  * @brief performs a masked bit register not equal to 0 check on the global parameter space
1220  * @return true if readGlobalReg(offset) & mask != 0
1221  */
1222 bool
1223 DiceAvDevice::maskedCheckNotZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1224     return !maskedCheckZeroGlobalReg(offset, mask);
1225 }
1226
1227 DiceAvDevice::diceNameVector
1228 DiceAvDevice::getTxNameString(unsigned int i) {
1229     diceNameVector names;
1230     char namestring[DICE_TX_NAMES_SIZE+1];
1231
1232     if (!readTxRegBlock(i, DICE_REGISTER_TX_NAMES_BASE,
1233                         (fb_quadlet_t *)namestring, DICE_TX_NAMES_SIZE)) {
1234         debugError("Could not read TX name string \n");
1235         return names;
1236     }
1237
1238     namestring[DICE_TX_NAMES_SIZE]='\0';
1239     return splitNameString(std::string(namestring));
1240 }
1241
1242 DiceAvDevice::diceNameVector
1243 DiceAvDevice::getRxNameString(unsigned int i) {
1244     diceNameVector names;
1245     char namestring[DICE_RX_NAMES_SIZE+1];
1246
1247     if (!readRxRegBlock(i, DICE_REGISTER_RX_NAMES_BASE,
1248                         (fb_quadlet_t *)namestring, DICE_RX_NAMES_SIZE)) {
1249         debugError("Could not read RX name string \n");
1250         return names;
1251     }
1252
1253     namestring[DICE_RX_NAMES_SIZE]='\0';
1254     return splitNameString(std::string(namestring));
1255 }
1256
1257 DiceAvDevice::diceNameVector
1258 DiceAvDevice::getClockSourceNameString() {
1259     diceNameVector names;
1260     char namestring[DICE_CLOCKSOURCENAMES_SIZE+1];
1261
1262     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_CLOCKSOURCENAMES,
1263                         (fb_quadlet_t *)namestring, DICE_CLOCKSOURCENAMES_SIZE)) {
1264         debugError("Could not read CLOCKSOURCE name string \n");
1265         return names;
1266     }
1267
1268     namestring[DICE_CLOCKSOURCENAMES_SIZE]='\0';
1269     return splitNameString(std::string(namestring));
1270 }
1271
1272 std::string
1273 DiceAvDevice::getDeviceNickName() {
1274     char namestring[DICE_NICK_NAME_SIZE+1];
1275
1276     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_NICK_NAME,
1277                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1278         debugError("Could not read nickname string \n");
1279         return std::string("(unknown)");
1280     }
1281
1282     namestring[DICE_NICK_NAME_SIZE]='\0';
1283     return std::string(namestring);
1284 }
1285
1286 DiceAvDevice::diceNameVector
1287 DiceAvDevice::splitNameString(std::string in) {
1288     diceNameVector names;
1289
1290     // find the end of the string
1291     unsigned int end=in.find(string("\\\\"));
1292     // cut the end
1293     in=in.substr(0,end);
1294
1295     unsigned int cut;
1296     while( (cut = in.find(string("\\"))) != in.npos ) {
1297         if(cut > 0) {
1298             names.push_back(in.substr(0,cut));
1299         }
1300         in = in.substr(cut+1);
1301     }
1302     if(in.length() > 0) {
1303         names.push_back(in);
1304     }
1305     return names;
1306 }
1307
1308
1309 // I/O routines
1310 bool
1311 DiceAvDevice::initIoFunctions() {
1312
1313     // offsets and sizes are returned in quadlets, but we use byte values
1314
1315     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_OFF, &m_global_reg_offset)) {
1316         debugError("Could not initialize m_global_reg_offset\n");
1317         return false;
1318     }
1319     m_global_reg_offset*=4;
1320
1321     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_SZ, &m_global_reg_size)) {
1322         debugError("Could not initialize m_global_reg_size\n");
1323         return false;
1324     }
1325     m_global_reg_size*=4;
1326
1327     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_OFF, &m_tx_reg_offset)) {
1328         debugError("Could not initialize m_tx_reg_offset\n");
1329         return false;
1330     }
1331     m_tx_reg_offset*=4;
1332
1333     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_SZ, &m_tx_reg_size)) {
1334         debugError("Could not initialize m_tx_reg_size\n");
1335         return false;
1336     }
1337     m_tx_reg_size*=4;
1338
1339     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_OFF, &m_rx_reg_offset)) {
1340         debugError("Could not initialize m_rx_reg_offset\n");
1341         return false;
1342     }
1343     m_rx_reg_offset*=4;
1344
1345     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_SZ, &m_rx_reg_size)) {
1346         debugError("Could not initialize m_rx_reg_size\n");
1347         return false;
1348     }
1349     m_rx_reg_size*=4;
1350
1351     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_OFF, &m_unused1_reg_offset)) {
1352         debugError("Could not initialize m_unused1_reg_offset\n");
1353         return false;
1354     }
1355     m_unused1_reg_offset*=4;
1356
1357     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_SZ, &m_unused1_reg_size)) {
1358         debugError("Could not initialize m_unused1_reg_size\n");
1359         return false;
1360     }
1361     m_unused1_reg_size*=4;
1362
1363     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_OFF, &m_unused2_reg_offset)) {
1364         debugError("Could not initialize m_unused2_reg_offset\n");
1365         return false;
1366     }
1367     m_unused2_reg_offset*=4;
1368
1369     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_SZ, &m_unused2_reg_size)) {
1370         debugError("Could not initialize m_unused2_reg_size\n");
1371         return false;
1372     }
1373     m_unused2_reg_size*=4;
1374
1375     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_NB_TX, &m_nb_tx)) {
1376         debugError("Could not initialize m_nb_tx\n");
1377         return false;
1378     }
1379     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_SZ_TX, &m_tx_size)) {
1380         debugError("Could not initialize m_tx_size\n");
1381         return false;
1382     }
1383     m_tx_size*=4;
1384
1385     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_NB_RX, &m_nb_rx)) {
1386         debugError("Could not initialize m_nb_rx\n");
1387         return false;
1388     }
1389     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
1390         debugError("Could not initialize m_rx_size\n");
1391         return false;
1392     }
1393     m_rx_size*=4;
1394
1395     debugOutput(DEBUG_LEVEL_VERBOSE,"DICE Parameter Space info:\n");
1396     debugOutput(DEBUG_LEVEL_VERBOSE," Global  : offset=%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
1397     debugOutput(DEBUG_LEVEL_VERBOSE," TX      : offset=%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
1398     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
1399     debugOutput(DEBUG_LEVEL_VERBOSE," RX      : offset=%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
1400     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
1401     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED1 : offset=%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
1402     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED2 : offset=%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
1403
1404     return true;
1405 }
1406
1407 bool
1408 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1409     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
1410
1411     if(offset >= DICE_INVALID_OFFSET) {
1412         debugError("invalid offset: 0x%016llX\n", offset);
1413         return false;
1414     }
1415
1416     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1417     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1418
1419     if(!get1394Service().read_quadlet( nodeId, addr, result ) ) {
1420         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1421         return false;
1422     }
1423
1424     *result=ntohl(*result);
1425
1426     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1427
1428     return true;
1429 }
1430
1431 bool
1432 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1433     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
1434         offset, data);
1435
1436     if(offset >= DICE_INVALID_OFFSET) {
1437         debugError("invalid offset: 0x%016llX\n", offset);
1438         return false;
1439     }
1440
1441     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1442     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1443
1444     if(!get1394Service().write_quadlet( nodeId, addr, htonl(data) ) ) {
1445         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1446         return false;
1447     }
1448     return true;
1449 }
1450
1451 bool
1452 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1453     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1454         offset, length);
1455
1456     if(offset >= DICE_INVALID_OFFSET) {
1457         debugError("invalid offset: 0x%016llX\n", offset);
1458         return false;
1459     }
1460
1461     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1462     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1463
1464     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1465         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1466         return false;
1467     }
1468
1469     for(unsigned int i=0;i<length/4;i++) {
1470         *(data+i)=ntohl(*(data+i));
1471     }
1472
1473     return true;
1474 }
1475
1476 bool
1477 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1478     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1479         offset, length);
1480
1481     if(offset >= DICE_INVALID_OFFSET) {
1482         debugError("invalid offset: 0x%016llX\n", offset);
1483         return false;
1484     }
1485
1486     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1487     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1488
1489     fb_quadlet_t data_out[length/4];
1490
1491     for(unsigned int i=0;i<length/4;i++) {
1492         data_out[i]=ntohl(*(data+i));
1493     }
1494
1495     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1496         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1497         return false;
1498     }
1499
1500     return true;
1501 }
1502
1503 bool
1504 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1505     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1506
1507     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1508     return readReg(m_global_reg_offset + offset_gl, result);
1509 }
1510
1511 bool
1512 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1513     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n",
1514         offset, data);
1515
1516     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1517     return writeReg(m_global_reg_offset + offset_gl, data);
1518 }
1519
1520 bool
1521 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1522     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1523         offset, length);
1524
1525     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1526     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1527 }
1528
1529 bool
1530 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1531     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1532         offset, length);
1533
1534     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1535     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1536 }
1537
1538 fb_nodeaddr_t
1539 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1540
1541     // registry offsets should always be smaller than 0x7FFFFFFF
1542     // because otherwise base + offset > 64bit
1543     if(m_global_reg_offset & 0x80000000) {
1544         debugError("register offset not initialized yet\n");
1545         return DICE_INVALID_OFFSET;
1546     }
1547     // out-of-range check
1548     if(offset+length > m_global_reg_offset+m_global_reg_size) {
1549         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1550         return DICE_INVALID_OFFSET;
1551     }
1552
1553     return offset;
1554 }
1555
1556 bool
1557 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1558     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1559
1560     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1561     return readReg(m_tx_reg_offset + offset_tx, result);
1562 }
1563
1564 bool
1565 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1566     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1567         i, offset, data);
1568
1569     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1570     return writeReg(m_tx_reg_offset + offset_tx, data);
1571 }
1572
1573 bool
1574 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1575     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1576         offset, length);
1577
1578     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1579     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1580 }
1581
1582 bool
1583 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1584     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1585         offset, length);
1586
1587     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1588     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1589 }
1590
1591 fb_nodeaddr_t
1592 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1593     // registry offsets should always be smaller than 0x7FFFFFFF
1594     // because otherwise base + offset > 64bit
1595     if(m_tx_reg_offset & 0x80000000) {
1596         debugError("register offset not initialized yet\n");
1597         return DICE_INVALID_OFFSET;
1598     }
1599     if(m_nb_tx & 0x80000000) {
1600         debugError("m_nb_tx not initialized yet\n");
1601         return DICE_INVALID_OFFSET;
1602     }
1603     if(m_tx_size & 0x80000000) {
1604         debugError("m_tx_size not initialized yet\n");
1605         return DICE_INVALID_OFFSET;
1606     }
1607     if(i >= m_nb_tx) {
1608         debugError("TX index out of range\n");
1609         return DICE_INVALID_OFFSET;
1610     }
1611
1612     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1613
1614     // out-of-range check
1615     if(offset_tx + length > m_tx_reg_offset+4+m_tx_reg_size*m_nb_tx) {
1616         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1617         return DICE_INVALID_OFFSET;
1618     }
1619
1620     return offset_tx;
1621 }
1622
1623 bool
1624 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1625     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1626
1627     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1628     return readReg(m_rx_reg_offset + offset_rx, result);
1629 }
1630
1631 bool
1632 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1633     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n",
1634         offset, data);
1635
1636     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1637     return writeReg(m_rx_reg_offset + offset_rx, data);
1638 }
1639
1640 bool
1641 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1642     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1643         offset, length);
1644
1645     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1646     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1647 }
1648
1649 bool
1650 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1651     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1652         offset, length);
1653
1654     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1655     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1656 }
1657
1658 fb_nodeaddr_t
1659 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1660     // registry offsets should always be smaller than 0x7FFFFFFF
1661     // because otherwise base + offset > 64bit
1662     if(m_rx_reg_offset & 0x80000000) {
1663         debugError("register offset not initialized yet\n");
1664         return DICE_INVALID_OFFSET;
1665     }
1666     if(m_nb_rx & 0x80000000) {
1667         debugError("m_nb_rx not initialized yet\n");
1668         return DICE_INVALID_OFFSET;
1669     }
1670     if(m_rx_size & 0x80000000) {
1671         debugError("m_rx_size not initialized yet\n");
1672         return DICE_INVALID_OFFSET;
1673     }
1674     if(i >= m_nb_rx) {
1675         debugError("RX index out of range\n");
1676         return DICE_INVALID_OFFSET;
1677     }
1678
1679     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1680
1681     // out-of-range check
1682     if(offset_rx + length > m_rx_reg_offset+4+m_rx_reg_size*m_nb_rx) {
1683         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1684         return DICE_INVALID_OFFSET;
1685     }
1686     return offset_rx;
1687 }
1688
1689
1690 // the notifier
1691
1692 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1693  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1694               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1695               RAW1394_ARM_WRITE, 0)
1696  , m_dicedevice(d)
1697 {
1698
1699 }
1700
1701 DiceAvDevice::DiceNotifier::~DiceNotifier()
1702 {
1703
1704 }
1705
1706 }
Note: See TracBrowser for help on using the browser.