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

Revision 1218, 61.6 kB (checked in by ppalmers, 13 years ago)

add Alesis io|14 quirk (thx Adrian Knoth)

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