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

Revision 1047, 57.6 kB (checked in by ppalmers, 15 years ago)

remove compiler warnings. change non-critical warnings to debug messages.

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