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

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

- fix octlet byteswap bug for non-debug builds
- make Ieee1394Service thread safe

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