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

Revision 1234, 61.6 kB (checked in by holin, 16 years ago)

fix gcc 4.3 compile errors and some warnings (largely from Adrian Knoth)

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