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

Revision 1023, 57.5 kB (checked in by ppalmers, 15 years ago)

add konnek8 id

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