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

Revision 1712, 72.2 kB (checked in by arnonym, 14 years ago)

Start a special class for the saffire24...

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