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

Revision 1021, 57.4 kB (checked in by ppalmers, 15 years ago)

Allow to disable sending payload on no-data packets though config.h.in. The DICE-II devices cannot cope with them.

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