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

Revision 1515, 63.6 kB (checked in by holin, 15 years ago)

Alesis Multimix16 support from adi (ticket #196)

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