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

Revision 1630, 72.0 kB (checked in by ppalmers, 13 years ago)

add base level support for the DICE EAP based mixers (incomplete)

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