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

Revision 1539, 72.1 kB (checked in by ppalmers, 14 years ago)

- Fix bug in dice transmit channel detection
- Implement snoop mode for DICE

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