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

Revision 1063, 58.1 kB (checked in by ppalmers, 15 years ago)

implement Nickname control element

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