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

Revision 1332, 61.9 kB (checked in by ppalmers, 15 years ago)

re #152: applied the patch.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "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         /* Vendor-specific hacks */
769
770         /* Alesis io14 RX0 claims to have six audio channels. Ignore it, just
771          * use 8 for Bus1-L+R .. Bus4-L+R.
772          */
773         if ((FW_VENDORID_ALESIS == getConfigRom().getNodeVendorId()) &&
774             (0x00000001 == getConfigRom().getModelId())) {
775             nb_audio=8;
776         }
777
778         // request the channel names
779         diceNameVector names_audio=getRxNameString(i);
780
781         if (names_audio.size() != nb_audio) {
782             debugWarning("The audio channel name vector is incorrect, using default names\n");
783             names_audio.clear();
784
785             for (unsigned int j=0;j<nb_audio;j++) {
786                 std::ostringstream newname;
787                 newname << "output_" << j;
788                 names_audio.push_back(newname.str());
789             }
790         }
791
792         nb_channels=nb_audio;
793         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
794
795         // construct the MIDI names
796         diceNameVector names_midi;
797         for (unsigned int j=0;j<nb_midi;j++) {
798             std::ostringstream newname;
799             newname << "midi_out_" << j;
800             names_midi.push_back(newname.str());
801         }
802
803         // construct the streamprocessor
804         Streaming::AmdtpTransmitStreamProcessor *p;
805         p=new Streaming::AmdtpTransmitStreamProcessor(*this,
806                              nb_channels);
807
808         if(!p->init()) {
809             debugFatal("Could not initialize transmit processor!\n");
810             delete p;
811             continue;
812         }
813
814 #if AMDTP_ALLOW_PAYLOAD_IN_NODATA_XMIT
815         // the DICE-II cannot handle payload in the NO-DATA packets.
816         // the other DICE chips don't need payload. Therefore
817         // we disable it.
818         p->sendPayloadForNoDataPackets(false);
819 #endif
820
821         // add audio ports to the processor
822         for (unsigned int j=0;j<nb_audio;j++) {
823             diceChannelInfo channelInfo;
824             channelInfo.name=names_audio.at(j);
825             channelInfo.portType=ePT_Analog;
826             channelInfo.streamPosition=j;
827             channelInfo.streamLocation=0;
828
829             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
830                 debugError("Could not add channel %s to StreamProcessor\n",
831                     channelInfo.name.c_str());
832                 continue;
833             }
834         }
835
836         // add midi ports to the processor
837         for (unsigned int j=0;j<nb_midi;j++) {
838             diceChannelInfo channelInfo;
839             channelInfo.name=names_midi.at(j);
840             channelInfo.portType=ePT_MIDI;
841             channelInfo.streamPosition=nb_audio;
842             channelInfo.streamLocation=j;
843
844             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
845                 debugError("Could not add channel %s to StreamProcessor\n",
846                     channelInfo.name.c_str());
847                 continue;
848             }
849         }
850
851         m_transmitProcessors.push_back(p);
852     }
853     return true;
854 }
855
856 bool
857 DiceAvDevice::addChannelToProcessor(
858     diceChannelInfo *channelInfo,
859     Streaming::StreamProcessor *processor,
860     Streaming::Port::E_Direction direction) {
861
862     std::string id=std::string("dev?");
863     if(!getOption("id", id)) {
864         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
865     }
866
867     std::ostringstream portname;
868     portname << id;
869     if(direction == Streaming::Port::E_Playback) {
870         portname << "p";
871     } else {
872         portname << "c";
873     }
874
875     portname << "_" << channelInfo->name;
876
877     Streaming::Port *p=NULL;
878     switch(channelInfo->portType) {
879     case ePT_Analog:
880         p=new Streaming::AmdtpAudioPort(
881                 *processor,
882                 portname.str(),
883                 direction,
884                 channelInfo->streamPosition,
885                 channelInfo->streamLocation,
886                 Streaming::AmdtpPortInfo::E_MBLA
887         );
888         break;
889
890     case ePT_MIDI:
891         p=new Streaming::AmdtpMidiPort(
892                 *processor,
893                 portname.str(),
894                 direction,
895                 channelInfo->streamPosition,
896                 channelInfo->streamLocation,
897                 Streaming::AmdtpPortInfo::E_Midi
898         );
899
900         break;
901     default:
902     // unsupported
903         break;
904     }
905
906     if (!p) {
907         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str());
908     }
909
910     return true;
911 }
912
913 bool
914 DiceAvDevice::lock() {
915     fb_octlet_t result;
916
917     debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n",
918         m_model->vendor_name, m_model->model_name, getNodeId());
919
920     // get a notifier to handle device notifications
921     nodeaddr_t notify_address;
922     notify_address = get1394Service().findFreeARMBlock(
923                         DICE_NOTIFIER_BASE_ADDRESS,
924                         DICE_NOTIFIER_BLOCK_LENGTH,
925                         DICE_NOTIFIER_BLOCK_LENGTH);
926
927     if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) {
928         debugError("Could not find free ARM block for notification\n");
929         return false;
930     }
931
932     m_notifier=new DiceAvDevice::DiceNotifier(this, notify_address);
933
934     if(!m_notifier) {
935         debugError("Could not allocate notifier\n");
936         return false;
937     }
938
939     if (!get1394Service().registerARMHandler(m_notifier)) {
940         debugError("Could not register notifier\n");
941         delete m_notifier;
942         m_notifier=NULL;
943         return false;
944     }
945
946     // register this notifier
947     fb_nodeaddr_t addr = DICE_REGISTER_BASE
948                        + m_global_reg_offset
949                        + DICE_REGISTER_GLOBAL_OWNER;
950
951     // registry offsets should always be smaller than 0x7FFFFFFF
952     // because otherwise base + offset > 64bit
953     if(m_global_reg_offset & 0x80000000) {
954         debugError("register offset not initialized yet\n");
955         return false;
956     }
957
958     fb_nodeaddr_t swap_value = ((0xFFC0) | get1394Service().getLocalNodeId());
959     swap_value = swap_value << 48;
960     swap_value |= m_notifier->getStart();
961
962     if (!get1394Service().lockCompareSwap64(getNodeId() | 0xFFC0,
963                                             addr, DICE_OWNER_NO_OWNER,
964                                             swap_value, &result )) {
965         debugWarning("Could not register ourselves as device owner\n");
966         return false;
967     }
968
969     if (result != DICE_OWNER_NO_OWNER) {
970         debugWarning("Could not register ourselves as device owner, unexpected register value: 0x%016llX\n", result);
971         return false;
972     }
973
974     return true;
975 }
976
977
978 bool
979 DiceAvDevice::unlock() {
980     fb_octlet_t result;
981
982     if(!m_notifier) {
983         debugWarning("Request to unlock, but no notifier present!\n");
984         return false;
985     }
986
987     fb_nodeaddr_t addr = DICE_REGISTER_BASE
988                        + m_global_reg_offset
989                        + DICE_REGISTER_GLOBAL_OWNER;
990
991     // registry offsets should always be smaller than 0x7FFFFFFF
992     // because otherwise base + offset > 64bit
993     if(m_global_reg_offset & 0x80000000) {
994         debugError("register offset not initialized yet\n");
995         return false;
996     }
997
998     fb_nodeaddr_t compare_value = ((0xFFC0) | get1394Service().getLocalNodeId());
999     compare_value <<= 48;
1000     compare_value |= m_notifier->getStart();
1001
1002     if (!get1394Service().lockCompareSwap64(  getNodeId() | 0xFFC0, addr, compare_value,
1003                                        DICE_OWNER_NO_OWNER, &result )) {
1004         debugWarning("Could not unregister ourselves as device owner\n");
1005         return false;
1006     }
1007
1008     get1394Service().unregisterARMHandler(m_notifier);
1009     delete m_notifier;
1010     m_notifier=NULL;
1011
1012     return true;
1013 }
1014
1015 bool
1016 DiceAvDevice::enableStreaming() {
1017     return enableIsoStreaming();
1018 }
1019
1020 bool
1021 DiceAvDevice::disableStreaming() {
1022     return disableIsoStreaming();
1023 }
1024
1025 int
1026 DiceAvDevice::getStreamCount() {
1027     return m_receiveProcessors.size() + m_transmitProcessors.size();
1028 }
1029
1030 Streaming::StreamProcessor *
1031 DiceAvDevice::getStreamProcessorByIndex(int i) {
1032
1033     if (i<(int)m_receiveProcessors.size()) {
1034         return m_receiveProcessors.at(i);
1035     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1036         return m_transmitProcessors.at(i-m_receiveProcessors.size());
1037     }
1038
1039     return NULL;
1040 }
1041
1042 bool
1043 DiceAvDevice::startStreamByIndex(int i) {
1044
1045     if (isIsoStreamingEnabled()) {
1046         debugError("Cannot start streams while streaming is enabled\n");
1047         return false;
1048     }
1049
1050     if (i<(int)m_receiveProcessors.size()) {
1051         int n=i;
1052         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1053
1054         // allocate ISO channel
1055         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
1056         if(isochannel<0) {
1057             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
1058             return false;
1059         }
1060         p->setChannel(isochannel);
1061
1062         fb_quadlet_t reg_isoch;
1063         // check value of ISO_CHANNEL register
1064         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
1065             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
1066             p->setChannel(-1);
1067             deallocateIsoChannel(isochannel);
1068             return false;
1069         }
1070         if(reg_isoch != 0xFFFFFFFFUL) {
1071             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ATX %d\n", reg_isoch, n);
1072             p->setChannel(-1);
1073             deallocateIsoChannel(isochannel);
1074             return false;
1075         }
1076
1077         // write value of ISO_CHANNEL register
1078         reg_isoch=isochannel;
1079         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
1080             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
1081             p->setChannel(-1);
1082             deallocateIsoChannel(isochannel);
1083             return false;
1084         }
1085
1086         return true;
1087
1088     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1089         int n=i-m_receiveProcessors.size();
1090         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1091
1092         // allocate ISO channel
1093         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
1094         if(isochannel<0) {
1095             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
1096             return false;
1097         }
1098         p->setChannel(isochannel);
1099
1100         fb_quadlet_t reg_isoch;
1101         // check value of ISO_CHANNEL register
1102         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
1103             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
1104             p->setChannel(-1);
1105             deallocateIsoChannel(isochannel);
1106             return false;
1107         }
1108         if(reg_isoch != 0xFFFFFFFFUL) {
1109             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ARX %d\n", reg_isoch, n);
1110             p->setChannel(-1);
1111             deallocateIsoChannel(isochannel);
1112             return false;
1113         }
1114
1115         // write value of ISO_CHANNEL register
1116         reg_isoch=isochannel;
1117         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
1118             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
1119             p->setChannel(-1);
1120             deallocateIsoChannel(isochannel);
1121             return false;
1122         }
1123
1124         return true;
1125     }
1126
1127     debugError("SP index %d out of range!\n",i);
1128
1129     return false;
1130 }
1131
1132 bool
1133 DiceAvDevice::stopStreamByIndex(int i) {
1134
1135     if (isIsoStreamingEnabled()) {
1136         debugError("Cannot stop streams while streaming is enabled\n");
1137         return false;
1138     }
1139
1140     if (i<(int)m_receiveProcessors.size()) {
1141         int n=i;
1142         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1143         unsigned int isochannel=p->getChannel();
1144
1145         fb_quadlet_t reg_isoch;
1146         // check value of ISO_CHANNEL register
1147         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
1148             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
1149             return false;
1150         }
1151         if(reg_isoch != isochannel) {
1152             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ATX %d\n", isochannel, reg_isoch, n);
1153             return false;
1154         }
1155
1156         // write value of ISO_CHANNEL register
1157         reg_isoch=0xFFFFFFFFUL;
1158         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
1159             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
1160             return false;
1161         }
1162
1163         // deallocate ISO channel
1164         if(!deallocateIsoChannel(isochannel)) {
1165             debugError("Could not deallocate iso channel for SP %d (ATX %d)\n",i,n);
1166             return false;
1167         }
1168
1169         p->setChannel(-1);
1170         return true;
1171
1172     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1173         int n=i-m_receiveProcessors.size();
1174         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1175
1176         unsigned int isochannel=p->getChannel();
1177
1178         fb_quadlet_t reg_isoch;
1179         // check value of ISO_CHANNEL register
1180         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
1181             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
1182             return false;
1183         }
1184         if(reg_isoch != isochannel) {
1185             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ARX %d\n", isochannel, reg_isoch, n);
1186             return false;
1187         }
1188
1189         // write value of ISO_CHANNEL register
1190         reg_isoch=0xFFFFFFFFUL;
1191         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
1192             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
1193             return false;
1194         }
1195
1196         // deallocate ISO channel
1197         if(!deallocateIsoChannel(isochannel)) {
1198             debugError("Could not deallocate iso channel for SP %d (ARX %d)\n",i,n);
1199             return false;
1200         }
1201
1202         p->setChannel(-1);
1203         return true;
1204     }
1205
1206     debugError("SP index %d out of range!\n",i);
1207
1208     return false;
1209 }
1210
1211 // helper routines
1212
1213 // allocate ISO resources for the SP's
1214 int DiceAvDevice::allocateIsoChannel(unsigned int packet_size) {
1215     unsigned int bandwidth=8+packet_size;
1216
1217     int ch=get1394Service().allocateIsoChannelGeneric(bandwidth);
1218
1219     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
1220         ch, bandwidth);
1221
1222     return ch;
1223 }
1224 // deallocate ISO resources
1225 bool DiceAvDevice::deallocateIsoChannel(int channel) {
1226     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
1227     return get1394Service().freeIsoChannel(channel);
1228 }
1229
1230 bool
1231 DiceAvDevice::enableIsoStreaming() {
1232     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_ENABLE);
1233 }
1234
1235 bool
1236 DiceAvDevice::disableIsoStreaming() {
1237     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_DISABLE);
1238 }
1239
1240 bool
1241 DiceAvDevice::isIsoStreamingEnabled() {
1242     fb_quadlet_t result;
1243     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &result);
1244     // I don't know what exactly is 'enable',
1245     // but disable is definately == 0
1246     return (result != DICE_ISOSTREAMING_DISABLE);
1247 }
1248
1249 /**
1250  * @brief performs a masked bit register equals 0 check on the global parameter space
1251  * @return true if readGlobalReg(offset) & mask == 0
1252  */
1253 bool
1254 DiceAvDevice::maskedCheckZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1255     fb_quadlet_t result;
1256     readGlobalReg(offset, &result);
1257     return ((result & mask) == 0);
1258 }
1259 /**
1260  * @brief performs a masked bit register not equal to 0 check on the global parameter space
1261  * @return true if readGlobalReg(offset) & mask != 0
1262  */
1263 bool
1264 DiceAvDevice::maskedCheckNotZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1265     return !maskedCheckZeroGlobalReg(offset, mask);
1266 }
1267
1268 DiceAvDevice::diceNameVector
1269 DiceAvDevice::getTxNameString(unsigned int i) {
1270     diceNameVector names;
1271     char namestring[DICE_TX_NAMES_SIZE+1];
1272
1273     if (!readTxRegBlockSwapped(i, DICE_REGISTER_TX_NAMES_BASE,
1274                         (fb_quadlet_t *)namestring, DICE_TX_NAMES_SIZE)) {
1275         debugError("Could not read TX name string \n");
1276         return names;
1277     }
1278
1279     namestring[DICE_TX_NAMES_SIZE]='\0';
1280     return splitNameString(std::string(namestring));
1281 }
1282
1283 DiceAvDevice::diceNameVector
1284 DiceAvDevice::getRxNameString(unsigned int i) {
1285     diceNameVector names;
1286     char namestring[DICE_RX_NAMES_SIZE+1];
1287
1288     if (!readRxRegBlockSwapped(i, DICE_REGISTER_RX_NAMES_BASE,
1289                         (fb_quadlet_t *)namestring, DICE_RX_NAMES_SIZE)) {
1290         debugError("Could not read RX name string \n");
1291         return names;
1292     }
1293
1294     namestring[DICE_RX_NAMES_SIZE]='\0';
1295     return splitNameString(std::string(namestring));
1296 }
1297
1298 DiceAvDevice::diceNameVector
1299 DiceAvDevice::getClockSourceNameString() {
1300     diceNameVector names;
1301     char namestring[DICE_CLOCKSOURCENAMES_SIZE+1];
1302
1303     if (!readGlobalRegBlockSwapped(DICE_REGISTER_GLOBAL_CLOCKSOURCENAMES,
1304                       (fb_quadlet_t *)namestring, DICE_CLOCKSOURCENAMES_SIZE)) {
1305         debugError("Could not read CLOCKSOURCE name string \n");
1306         return names;
1307     }
1308
1309     namestring[DICE_CLOCKSOURCENAMES_SIZE]='\0';
1310     return splitNameString(std::string(namestring));
1311 }
1312
1313 std::string
1314 DiceAvDevice::getDeviceNickName() {
1315     char namestring[DICE_NICK_NAME_SIZE+1];
1316
1317     if (!readGlobalRegBlockSwapped(DICE_REGISTER_GLOBAL_NICK_NAME,
1318                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1319         debugError("Could not read nickname string \n");
1320         return std::string("(unknown)");
1321     }
1322
1323     namestring[DICE_NICK_NAME_SIZE]='\0';
1324     return std::string(namestring);
1325 }
1326
1327 bool
1328 DiceAvDevice::setDeviceNickName(std::string name) {
1329     char namestring[DICE_NICK_NAME_SIZE+1];
1330     strncpy(namestring, name.c_str(), DICE_NICK_NAME_SIZE);
1331
1332     if (!writeGlobalRegBlockSwapped(DICE_REGISTER_GLOBAL_NICK_NAME,
1333                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1334         debugError("Could not write nickname string \n");
1335         return false;
1336     }
1337     return true;
1338 }
1339
1340 DiceAvDevice::diceNameVector
1341 DiceAvDevice::splitNameString(std::string in) {
1342     diceNameVector names;
1343
1344     // find the end of the string
1345     string::size_type end=in.find(string("\\\\"));
1346     // cut the end
1347     in=in.substr(0,end);
1348
1349     string::size_type cut;
1350     while( (cut = in.find(string("\\"))) != in.npos ) {
1351         if(cut > 0) {
1352             names.push_back(in.substr(0,cut));
1353         }
1354         in = in.substr(cut+1);
1355     }
1356     if(in.length() > 0) {
1357         names.push_back(in);
1358     }
1359     return names;
1360 }
1361
1362
1363 // I/O routines
1364 bool
1365 DiceAvDevice::initIoFunctions() {
1366
1367     // offsets and sizes are returned in quadlets, but we use byte values
1368
1369     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_OFF, &m_global_reg_offset)) {
1370         debugError("Could not initialize m_global_reg_offset\n");
1371         return false;
1372     }
1373     m_global_reg_offset*=4;
1374
1375     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_SZ, &m_global_reg_size)) {
1376         debugError("Could not initialize m_global_reg_size\n");
1377         return false;
1378     }
1379     m_global_reg_size*=4;
1380
1381     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_OFF, &m_tx_reg_offset)) {
1382         debugError("Could not initialize m_tx_reg_offset\n");
1383         return false;
1384     }
1385     m_tx_reg_offset*=4;
1386
1387     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_SZ, &m_tx_reg_size)) {
1388         debugError("Could not initialize m_tx_reg_size\n");
1389         return false;
1390     }
1391     m_tx_reg_size*=4;
1392
1393     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_OFF, &m_rx_reg_offset)) {
1394         debugError("Could not initialize m_rx_reg_offset\n");
1395         return false;
1396     }
1397     m_rx_reg_offset*=4;
1398
1399     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_SZ, &m_rx_reg_size)) {
1400         debugError("Could not initialize m_rx_reg_size\n");
1401         return false;
1402     }
1403     m_rx_reg_size*=4;
1404
1405     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_OFF, &m_unused1_reg_offset)) {
1406         debugError("Could not initialize m_unused1_reg_offset\n");
1407         return false;
1408     }
1409     m_unused1_reg_offset*=4;
1410
1411     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_SZ, &m_unused1_reg_size)) {
1412         debugError("Could not initialize m_unused1_reg_size\n");
1413         return false;
1414     }
1415     m_unused1_reg_size*=4;
1416
1417     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_OFF, &m_unused2_reg_offset)) {
1418         debugError("Could not initialize m_unused2_reg_offset\n");
1419         return false;
1420     }
1421     m_unused2_reg_offset*=4;
1422
1423     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_SZ, &m_unused2_reg_size)) {
1424         debugError("Could not initialize m_unused2_reg_size\n");
1425         return false;
1426     }
1427     m_unused2_reg_size*=4;
1428
1429     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_NB_TX, &m_nb_tx)) {
1430         debugError("Could not initialize m_nb_tx\n");
1431         return false;
1432     }
1433     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_SZ_TX, &m_tx_size)) {
1434         debugError("Could not initialize m_tx_size\n");
1435         return false;
1436     }
1437     m_tx_size*=4;
1438
1439     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_NB_RX, &m_nb_rx)) {
1440         debugError("Could not initialize m_nb_rx\n");
1441         return false;
1442     }
1443
1444     // FIXME: verify this and clean it up.
1445     /* special case for io14, which announces two receive transmitters,
1446      * but only has one
1447      */
1448     if ((FW_VENDORID_ALESIS == getConfigRom().getNodeVendorId()) &&
1449             (0x00000001 == getConfigRom().getModelId())) {
1450         m_nb_rx = 1;
1451     }
1452
1453     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
1454         debugError("Could not initialize m_rx_size\n");
1455         return false;
1456     }
1457     m_rx_size*=4;
1458
1459     debugOutput(DEBUG_LEVEL_VERBOSE,"DICE Parameter Space info:\n");
1460     debugOutput(DEBUG_LEVEL_VERBOSE," Global  : offset=%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
1461     debugOutput(DEBUG_LEVEL_VERBOSE," TX      : offset=%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
1462     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
1463     debugOutput(DEBUG_LEVEL_VERBOSE," RX      : offset=%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
1464     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
1465     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED1 : offset=%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
1466     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED2 : offset=%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
1467
1468     return true;
1469 }
1470
1471 bool
1472 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1473     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
1474
1475     if(offset >= DICE_INVALID_OFFSET) {
1476         debugError("invalid offset: 0x%016llX\n", offset);
1477         return false;
1478     }
1479
1480     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1481     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1482
1483     if(!get1394Service().read_quadlet( nodeId, addr, result ) ) {
1484         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1485         return false;
1486     }
1487
1488     *result=CondSwapFromBus32(*result);
1489
1490     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1491
1492     return true;
1493 }
1494
1495 bool
1496 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1497     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
1498         offset, data);
1499
1500     if(offset >= DICE_INVALID_OFFSET) {
1501         debugError("invalid offset: 0x%016llX\n", offset);
1502         return false;
1503     }
1504
1505     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1506     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1507
1508     if(!get1394Service().write_quadlet( nodeId, addr, CondSwapToBus32(data) ) ) {
1509         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1510         return false;
1511     }
1512     return true;
1513 }
1514
1515 bool
1516 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1517     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1518         offset, length);
1519
1520     if(offset >= DICE_INVALID_OFFSET) {
1521         debugError("invalid offset: 0x%016llX\n", offset);
1522         return false;
1523     }
1524
1525     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1526     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1527
1528     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1529         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1530         return false;
1531     }
1532
1533     for(unsigned int i=0;i<length/4;i++) {
1534         *(data+i)=CondSwapFromBus32(*(data+i));
1535     }
1536
1537     return true;
1538 }
1539
1540 bool
1541 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1542     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1543         offset, length);
1544
1545     if(offset >= DICE_INVALID_OFFSET) {
1546         debugError("invalid offset: 0x%016llX\n", offset);
1547         return false;
1548     }
1549
1550     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1551     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1552
1553     fb_quadlet_t data_out[length/4];
1554
1555     for(unsigned int i=0;i<length/4;i++) {
1556         data_out[i]=CondSwapFromBus32(*(data+i));
1557     }
1558
1559     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1560         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1561         return false;
1562     }
1563
1564     return true;
1565 }
1566
1567 bool
1568 DiceAvDevice::readRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1569     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1570         offset, length);
1571
1572     if(offset >= DICE_INVALID_OFFSET) {
1573         debugError("invalid offset: 0x%016llX\n", offset);
1574         return false;
1575     }
1576
1577     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1578     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1579
1580     if(!get1394Service().read( nodeId, addr, length/4, data ) ) {
1581         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1582         return false;
1583     }
1584
1585     for(unsigned int i=0;i<length/4;i++) {
1586         *(data+i)=ByteSwap32(*(data+i));
1587     }
1588
1589     return true;
1590 }
1591
1592 bool
1593 DiceAvDevice::writeRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1594     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1595         offset, length);
1596
1597     if(offset >= DICE_INVALID_OFFSET) {
1598         debugError("invalid offset: 0x%016llX\n", offset);
1599         return false;
1600     }
1601
1602     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1603     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1604
1605     fb_quadlet_t data_out[length/4];
1606
1607     for(unsigned int i=0;i<length/4;i++) {
1608         data_out[i]=ByteSwap32(*(data+i));
1609     }
1610
1611     if(!get1394Service().write( nodeId, addr, length/4, data_out ) ) {
1612         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1613         return false;
1614     }
1615
1616     return true;
1617 }
1618
1619 bool
1620 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1621     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1622
1623     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1624     return readReg(m_global_reg_offset + offset_gl, result);
1625 }
1626
1627 bool
1628 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1629     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n",
1630         offset, data);
1631
1632     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1633     return writeReg(m_global_reg_offset + offset_gl, data);
1634 }
1635
1636 bool
1637 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1638     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1639         offset, length);
1640
1641     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1642     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1643 }
1644
1645 bool
1646 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1647     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1648         offset, length);
1649
1650     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1651     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1652 }
1653
1654 bool
1655 DiceAvDevice::readGlobalRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1656     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1657         offset, length);
1658
1659     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1660     return readRegBlockSwapped(m_global_reg_offset + offset_gl, data, length);
1661 }
1662
1663 bool
1664 DiceAvDevice::writeGlobalRegBlockSwapped(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1665     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1666         offset, length);
1667
1668     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1669     return writeRegBlockSwapped(m_global_reg_offset + offset_gl, data, length);
1670 }
1671
1672 fb_nodeaddr_t
1673 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1674
1675     // registry offsets should always be smaller than 0x7FFFFFFF
1676     // because otherwise base + offset > 64bit
1677     if(m_global_reg_offset & 0x80000000) {
1678         debugError("register offset not initialized yet\n");
1679         return DICE_INVALID_OFFSET;
1680     }
1681     // out-of-range check
1682     if(offset+length > m_global_reg_offset+m_global_reg_size) {
1683         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1684         return DICE_INVALID_OFFSET;
1685     }
1686
1687     return offset;
1688 }
1689
1690 bool
1691 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1692     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1693
1694     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1695     return readReg(m_tx_reg_offset + offset_tx, result);
1696 }
1697
1698 bool
1699 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1700     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1701         i, offset, data);
1702
1703     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1704     return writeReg(m_tx_reg_offset + offset_tx, data);
1705 }
1706
1707 bool
1708 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1709     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1710         offset, length);
1711
1712     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1713     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1714 }
1715
1716 bool
1717 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1718     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1719         offset, length);
1720
1721     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1722     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1723 }
1724
1725 bool
1726 DiceAvDevice::readTxRegBlockSwapped(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1727     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1728         offset, length);
1729
1730     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1731     return readRegBlockSwapped(m_tx_reg_offset + offset_tx, data, length);
1732 }
1733
1734 fb_nodeaddr_t
1735 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1736     // registry offsets should always be smaller than 0x7FFFFFFF
1737     // because otherwise base + offset > 64bit
1738     if(m_tx_reg_offset & 0x80000000) {
1739         debugError("register offset not initialized yet\n");
1740         return DICE_INVALID_OFFSET;
1741     }
1742     if(m_nb_tx & 0x80000000) {
1743         debugError("m_nb_tx not initialized yet\n");
1744         return DICE_INVALID_OFFSET;
1745     }
1746     if(m_tx_size & 0x80000000) {
1747         debugError("m_tx_size not initialized yet\n");
1748         return DICE_INVALID_OFFSET;
1749     }
1750     if(i >= m_nb_tx) {
1751         debugError("TX index out of range\n");
1752         return DICE_INVALID_OFFSET;
1753     }
1754
1755     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1756
1757     // out-of-range check
1758     if(offset_tx + length > m_tx_reg_offset+4+m_tx_reg_size*m_nb_tx) {
1759         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1760         return DICE_INVALID_OFFSET;
1761     }
1762
1763     return offset_tx;
1764 }
1765
1766 bool
1767 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1768     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1769
1770     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1771     return readReg(m_rx_reg_offset + offset_rx, result);
1772 }
1773
1774 bool
1775 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1776     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n",
1777         offset, data);
1778
1779     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1780     return writeReg(m_rx_reg_offset + offset_rx, data);
1781 }
1782
1783 bool
1784 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1785     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1786         offset, length);
1787
1788     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1789     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1790 }
1791
1792 bool
1793 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1794     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1795         offset, length);
1796
1797     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1798     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1799 }
1800
1801 bool
1802 DiceAvDevice::readRxRegBlockSwapped(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1803     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1804         offset, length);
1805
1806     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1807     return readRegBlockSwapped(m_rx_reg_offset + offset_rx, data, length);
1808 }
1809
1810 fb_nodeaddr_t
1811 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1812     // registry offsets should always be smaller than 0x7FFFFFFF
1813     // because otherwise base + offset > 64bit
1814     if(m_rx_reg_offset & 0x80000000) {
1815         debugError("register offset not initialized yet\n");
1816         return DICE_INVALID_OFFSET;
1817     }
1818     if(m_nb_rx & 0x80000000) {
1819         debugError("m_nb_rx not initialized yet\n");
1820         return DICE_INVALID_OFFSET;
1821     }
1822     if(m_rx_size & 0x80000000) {
1823         debugError("m_rx_size not initialized yet\n");
1824         return DICE_INVALID_OFFSET;
1825     }
1826     if(i >= m_nb_rx) {
1827         debugError("RX index out of range\n");
1828         return DICE_INVALID_OFFSET;
1829     }
1830
1831     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1832
1833     // out-of-range check
1834     if(offset_rx + length > m_rx_reg_offset+4+m_rx_reg_size*m_nb_rx) {
1835         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1836         return DICE_INVALID_OFFSET;
1837     }
1838     return offset_rx;
1839 }
1840
1841
1842 // the notifier
1843
1844 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1845  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1846               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1847               RAW1394_ARM_WRITE, 0)
1848  , m_dicedevice(d)
1849 {
1850
1851 }
1852
1853 DiceAvDevice::DiceNotifier::~DiceNotifier()
1854 {
1855
1856 }
1857
1858 }
Note: See TracBrowser for help on using the browser.