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

Revision 969, 57.0 kB (checked in by ppalmers, 16 years ago)

fixes #85

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\n",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\n",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\n",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\n",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.