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

Revision 1347, 62.7 kB (checked in by ppalmers, 15 years ago)

re #152: apply patch

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