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

Revision 1131, 61.2 kB (checked in by ppalmers, 16 years ago)

implement endian fixes (thx Heikki Lindholm)
switch from network host order byteswap routines to size based swap routines to remove ambiguity in definition of "long"

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 <byteswap.h>
35 #include <assert.h>
36 #include <byteswap.h>
37 #include <libraw1394/csr.h>
38
39 #include <iostream>
40 #include <sstream>
41
42 #include <string>
43 using namespace std;
44
45 namespace Dice {
46
47 // to define the supported devices
48 static VendorModelEntry supportedDeviceList[] =
49 {
50     // vendor id, model id, vendor name, model name
51     {FW_VENDORID_TCAT, 0x00000002, "TCAT", "DiceII EVM"},
52     {FW_VENDORID_TCAT, 0x00000004, "TCAT", "DiceII EVM (vxx)"},
53     {FW_VENDORID_TCAT, 0x00000021, "TC Electronic", "Konnekt 8"},
54     {FW_VENDORID_TCAT, 0x00000023, "TC Electronic", "Konnekt Live"},
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     unsigned int end=in.find(string("\\\\"));
1334     // cut the end
1335     in=in.substr(0,end);
1336
1337     unsigned int 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     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
1432         debugError("Could not initialize m_rx_size\n");
1433         return false;
1434     }
1435     m_rx_size*=4;
1436
1437     debugOutput(DEBUG_LEVEL_VERBOSE,"DICE Parameter Space info:\n");
1438     debugOutput(DEBUG_LEVEL_VERBOSE," Global  : offset=%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
1439     debugOutput(DEBUG_LEVEL_VERBOSE," TX      : offset=%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
1440     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
1441     debugOutput(DEBUG_LEVEL_VERBOSE," RX      : offset=%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
1442     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
1443     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED1 : offset=%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
1444     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED2 : offset=%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
1445
1446     return true;
1447 }
1448
1449 bool
1450 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1451     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
1452
1453     if(offset >= DICE_INVALID_OFFSET) {
1454         debugError("invalid offset: 0x%016llX\n", offset);
1455         return false;
1456     }
1457
1458     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1459     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1460
1461     if(!get1394Service().read_quadlet( nodeId, addr, result ) ) {
1462         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1463         return false;
1464     }
1465
1466     *result=bswap_32(*result);
1467
1468     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1469
1470     return true;
1471 }
1472
1473 bool
1474 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1475     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
1476         offset, data);
1477
1478     if(offset >= DICE_INVALID_OFFSET) {
1479         debugError("invalid offset: 0x%016llX\n", offset);
1480         return false;
1481     }
1482
1483     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1484     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1485
1486     if(!get1394Service().write_quadlet( nodeId, addr, bswap_32(data) ) ) {
1487         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1488         return false;
1489     }
1490     return true;
1491 }
1492
1493 bool
1494 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1495     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1496         offset, length);
1497
1498     if(offset >= DICE_INVALID_OFFSET) {
1499         debugError("invalid offset: 0x%016llX\n", offset);
1500         return false;
1501     }
1502
1503     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1504     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1505
1506     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1507         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1508         return false;
1509     }
1510
1511     for(unsigned int i=0;i<length/4;i++) {
1512         *(data+i)=bswap_32(*(data+i));
1513     }
1514
1515     return true;
1516 }
1517
1518 bool
1519 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1520     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1521         offset, length);
1522
1523     if(offset >= DICE_INVALID_OFFSET) {
1524         debugError("invalid offset: 0x%016llX\n", offset);
1525         return false;
1526     }
1527
1528     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1529     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1530
1531     fb_quadlet_t data_out[length/4];
1532
1533     for(unsigned int i=0;i<length/4;i++) {
1534         data_out[i]=bswap_32(*(data+i));
1535     }
1536
1537     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1538         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1539         return false;
1540     }
1541
1542     return true;
1543 }
1544
1545 bool
1546 DiceAvDevice::readRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1547     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1548         offset, length);
1549
1550     if(offset >= DICE_INVALID_OFFSET) {
1551         debugError("invalid offset: 0x%016llX\n", offset);
1552         return false;
1553     }
1554
1555     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1556     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1557
1558     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1559         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1560         return false;
1561     }
1562
1563     for(unsigned int i=0;i<length/4;i++) {
1564         *(data+i)=bswap_32(*(data+i));
1565     }
1566
1567     return true;
1568 }
1569
1570 bool
1571 DiceAvDevice::writeRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1572     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1573         offset, length);
1574
1575     if(offset >= DICE_INVALID_OFFSET) {
1576         debugError("invalid offset: 0x%016llX\n", offset);
1577         return false;
1578     }
1579
1580     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1581     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1582
1583     fb_quadlet_t data_out[length/4];
1584
1585     for(unsigned int i=0;i<length/4;i++) {
1586         data_out[i]=bswap_32(*(data+i));
1587     }
1588
1589     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1590         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1591         return false;
1592     }
1593
1594     return true;
1595 }
1596
1597 bool
1598 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1599     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1600
1601     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1602     return readReg(m_global_reg_offset + offset_gl, result);
1603 }
1604
1605 bool
1606 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1607     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n",
1608         offset, data);
1609
1610     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1611     return writeReg(m_global_reg_offset + offset_gl, data);
1612 }
1613
1614 bool
1615 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1616     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1617         offset, length);
1618
1619     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1620     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1621 }
1622
1623 bool
1624 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1625     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1626         offset, length);
1627
1628     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1629     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1630 }
1631
1632 bool
1633 DiceAvDevice::readGlobalRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1634     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1635         offset, length);
1636
1637     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1638     return readRegBlockSwapped(m_global_reg_offset + offset_gl, data, length);
1639 }
1640
1641 bool
1642 DiceAvDevice::writeGlobalRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1643     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1644         offset, length);
1645
1646     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1647     return writeRegBlockSwapped(m_global_reg_offset + offset_gl, data, length);
1648 }
1649
1650 fb_nodeaddr_t
1651 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1652
1653     // registry offsets should always be smaller than 0x7FFFFFFF
1654     // because otherwise base + offset > 64bit
1655     if(m_global_reg_offset & 0x80000000) {
1656         debugError("register offset not initialized yet\n");
1657         return DICE_INVALID_OFFSET;
1658     }
1659     // out-of-range check
1660     if(offset+length > m_global_reg_offset+m_global_reg_size) {
1661         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1662         return DICE_INVALID_OFFSET;
1663     }
1664
1665     return offset;
1666 }
1667
1668 bool
1669 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1670     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1671
1672     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1673     return readReg(m_tx_reg_offset + offset_tx, result);
1674 }
1675
1676 bool
1677 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1678     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1679         i, offset, data);
1680
1681     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1682     return writeReg(m_tx_reg_offset + offset_tx, data);
1683 }
1684
1685 bool
1686 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1687     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1688         offset, length);
1689
1690     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1691     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1692 }
1693
1694 bool
1695 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1696     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1697         offset, length);
1698
1699     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1700     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1701 }
1702
1703 bool
1704 DiceAvDevice::readTxRegBlockSwapped(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1705     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1706         offset, length);
1707
1708     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1709     return readRegBlockSwapped(m_tx_reg_offset + offset_tx, data, length);
1710 }
1711
1712 fb_nodeaddr_t
1713 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1714     // registry offsets should always be smaller than 0x7FFFFFFF
1715     // because otherwise base + offset > 64bit
1716     if(m_tx_reg_offset & 0x80000000) {
1717         debugError("register offset not initialized yet\n");
1718         return DICE_INVALID_OFFSET;
1719     }
1720     if(m_nb_tx & 0x80000000) {
1721         debugError("m_nb_tx not initialized yet\n");
1722         return DICE_INVALID_OFFSET;
1723     }
1724     if(m_tx_size & 0x80000000) {
1725         debugError("m_tx_size not initialized yet\n");
1726         return DICE_INVALID_OFFSET;
1727     }
1728     if(i >= m_nb_tx) {
1729         debugError("TX index out of range\n");
1730         return DICE_INVALID_OFFSET;
1731     }
1732
1733     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1734
1735     // out-of-range check
1736     if(offset_tx + length > m_tx_reg_offset+4+m_tx_reg_size*m_nb_tx) {
1737         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1738         return DICE_INVALID_OFFSET;
1739     }
1740
1741     return offset_tx;
1742 }
1743
1744 bool
1745 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1746     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1747
1748     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1749     return readReg(m_rx_reg_offset + offset_rx, result);
1750 }
1751
1752 bool
1753 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1754     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n",
1755         offset, data);
1756
1757     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1758     return writeReg(m_rx_reg_offset + offset_rx, data);
1759 }
1760
1761 bool
1762 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1763     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1764         offset, length);
1765
1766     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1767     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1768 }
1769
1770 bool
1771 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1772     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1773         offset, length);
1774
1775     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1776     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1777 }
1778
1779 bool
1780 DiceAvDevice::readRxRegBlockSwapped(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1781     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1782         offset, length);
1783
1784     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1785     return readRegBlockSwapped(m_rx_reg_offset + offset_rx, data, length);
1786 }
1787
1788 fb_nodeaddr_t
1789 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1790     // registry offsets should always be smaller than 0x7FFFFFFF
1791     // because otherwise base + offset > 64bit
1792     if(m_rx_reg_offset & 0x80000000) {
1793         debugError("register offset not initialized yet\n");
1794         return DICE_INVALID_OFFSET;
1795     }
1796     if(m_nb_rx & 0x80000000) {
1797         debugError("m_nb_rx not initialized yet\n");
1798         return DICE_INVALID_OFFSET;
1799     }
1800     if(m_rx_size & 0x80000000) {
1801         debugError("m_rx_size not initialized yet\n");
1802         return DICE_INVALID_OFFSET;
1803     }
1804     if(i >= m_nb_rx) {
1805         debugError("RX index out of range\n");
1806         return DICE_INVALID_OFFSET;
1807     }
1808
1809     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1810
1811     // out-of-range check
1812     if(offset_rx + length > m_rx_reg_offset+4+m_rx_reg_size*m_nb_rx) {
1813         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1814         return DICE_INVALID_OFFSET;
1815     }
1816     return offset_rx;
1817 }
1818
1819
1820 // the notifier
1821
1822 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1823  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1824               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1825               RAW1394_ARM_WRITE, 0)
1826  , m_dicedevice(d)
1827 {
1828
1829 }
1830
1831 DiceAvDevice::DiceNotifier::~DiceNotifier()
1832 {
1833
1834 }
1835
1836 }
Note: See TracBrowser for help on using the browser.