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

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