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

Revision 1514, 63.2 kB (checked in by ppalmers, 14 years ago)

add Weiss engineering device ID's

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