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

Revision 1510, 62.9 kB (checked in by ppalmers, 12 years ago)

add Focusrite Saffire PRO 40 device id

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