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

Revision 639, 49.3 kB (checked in by ppalmers, 15 years ago)

- Introduce a generic infrastructure for FFADODevices to present the clock sources they support and their state
- Implement this infrastructure for BeBoB devices
- Implement this infrastructure for ECHO Fireworks devices

Line 
1 /*
2  * Copyright (C) 2005-2007 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 library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "dice/dice_avdevice.h"
25 #include "dice/dice_defines.h"
26
27 #include "libieee1394/configrom.h"
28 #include "libieee1394/ieee1394service.h"
29
30 #include "libstreaming/AmdtpStreamProcessor.h"
31
32 #include "debugmodule/debugmodule.h"
33
34 #include <string>
35 #include <stdint.h>
36 #include <assert.h>
37 #include <netinet/in.h>
38 #include <libraw1394/csr.h>
39
40 #include <iostream>
41 #include <sstream>
42
43
44 namespace Dice {
45
46 // to define the supported devices
47 static VendorModelEntry supportedDeviceList[] =
48 {
49     // vendor id, model id, vendor name, model name
50     {FW_VENDORID_TCAT, 0x00000002, "TCAT", "DiceII EVM"},
51 };
52
53 DiceAvDevice::DiceAvDevice( Ieee1394Service& ieee1394Service,
54                             std::auto_ptr<ConfigRom>( configRom ))
55     : FFADODevice( ieee1394Service, configRom )
56     , m_model( 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::DiceAvDevice (NodeID %d)\n",
74                  getConfigRom().getNodeId() );
75
76 }
77
78 DiceAvDevice::~DiceAvDevice()
79 {
80     // FIXME: clean up m_receiveProcessors & xmit
81
82     if (m_notifier) {
83         unlock();
84     }
85 }
86
87 bool
88 DiceAvDevice::probe( ConfigRom& configRom )
89 {
90     unsigned int vendorId = configRom.getNodeVendorId();
91     unsigned int modelId = configRom.getModelId();
92
93     for ( unsigned int i = 0;
94           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
95           ++i )
96     {
97         if ( ( supportedDeviceList[i].vendor_id == vendorId )
98              && ( supportedDeviceList[i].model_id == modelId )
99            )
100         {
101             return true;
102         }
103     }
104
105     return false;
106 }
107
108 FFADODevice *
109 DiceAvDevice::createDevice( Ieee1394Service& ieee1394Service,
110                             std::auto_ptr<ConfigRom>( configRom ))
111 {
112     return new DiceAvDevice(ieee1394Service, configRom );
113 }
114
115 bool
116 DiceAvDevice::discover()
117 {
118     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
119     unsigned int modelId = m_pConfigRom->getModelId();
120
121     for ( unsigned int i = 0;
122           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
123           ++i )
124     {
125         if ( ( supportedDeviceList[i].vendor_id == vendorId )
126              && ( supportedDeviceList[i].model_id == modelId )
127            )
128         {
129             m_model = &(supportedDeviceList[i]);
130         }
131     }
132
133     if (m_model == NULL) {
134         debugWarning("DiceAvDevice::discover() called for a non-dice device");
135         return false;
136     }
137
138     if ( !initIoFunctions() ) {
139         debugError("Could not initialize I/O functions\n");
140         return false;
141     }
142
143     debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s (nick: %s)\n",
144                 m_model->vendor_name, m_model->model_name, getDeviceNickName().c_str());
145
146     return true;
147 }
148
149 int
150 DiceAvDevice::getSamplingFrequency( ) {
151     int samplingFrequency;
152
153     fb_quadlet_t clockreg;
154     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg)) {
155         debugError("Could not read CLOCK_SELECT register\n");
156         return false;
157     }
158
159     clockreg = DICE_GET_RATE(clockreg);
160
161     switch (clockreg) {
162         case DICE_RATE_32K:      samplingFrequency = 32000;  break;
163         case DICE_RATE_44K1:     samplingFrequency = 44100;  break;
164         case DICE_RATE_48K:      samplingFrequency = 48000;  break;
165         case DICE_RATE_88K2:     samplingFrequency = 88200;  break;
166         case DICE_RATE_96K:      samplingFrequency = 96000;  break;
167         case DICE_RATE_176K4:    samplingFrequency = 176400; break;
168         case DICE_RATE_192K:     samplingFrequency = 192000; break;
169         case DICE_RATE_ANY_LOW:  samplingFrequency = 0;   break;
170         case DICE_RATE_ANY_MID:  samplingFrequency = 0;   break;
171         case DICE_RATE_ANY_HIGH: samplingFrequency = 0;  break;
172         case DICE_RATE_NONE:     samplingFrequency = 0;     break;
173         default:                 samplingFrequency = 0; break;
174     }
175
176     return samplingFrequency;
177 }
178
179 int
180 DiceAvDevice::getConfigurationId()
181 {
182     return 0;
183 }
184
185 bool
186 DiceAvDevice::setSamplingFrequency( int samplingFrequency )
187 {
188     debugOutput(DEBUG_LEVEL_VERBOSE, "Setting sample rate: %d\n",
189         (samplingFrequency));
190
191     bool supported=false;
192     fb_quadlet_t select=0x0;
193
194     switch ( samplingFrequency ) {
195     default:
196     case 22050:
197     case 24000:
198         supported=false;
199         break;
200     case 32000:
201         supported=maskedCheckNotZeroGlobalReg(
202                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
203                     DICE_CLOCKCAP_RATE_32K);
204         select=DICE_RATE_32K;
205         break;
206     case 44100:
207         supported=maskedCheckNotZeroGlobalReg(
208                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
209                     DICE_CLOCKCAP_RATE_44K1);
210         select=DICE_RATE_44K1;
211         break;
212     case 48000:
213         supported=maskedCheckNotZeroGlobalReg(
214                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
215                     DICE_CLOCKCAP_RATE_48K);
216         select=DICE_RATE_48K;
217         break;
218     case 88200:
219         supported=maskedCheckNotZeroGlobalReg(
220                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
221                     DICE_CLOCKCAP_RATE_88K2);
222         select=DICE_RATE_88K2;
223         break;
224     case 96000:
225         supported=maskedCheckNotZeroGlobalReg(
226                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
227                     DICE_CLOCKCAP_RATE_96K);
228         select=DICE_RATE_96K;
229         break;
230     case 176400:
231         supported=maskedCheckNotZeroGlobalReg(
232                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
233                     DICE_CLOCKCAP_RATE_176K4);
234         select=DICE_RATE_176K4;
235         break;
236     case 192000:
237         supported=maskedCheckNotZeroGlobalReg(
238                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
239                     DICE_CLOCKCAP_RATE_192K);
240         select=DICE_RATE_192K;
241         break;
242     }
243
244     if (!supported) {
245         debugWarning("Unsupported sample rate: %d\n", (samplingFrequency));
246         return false;
247     }
248
249     if (isIsoStreamingEnabled()) {
250         debugError("Cannot change samplerate while streaming is enabled\n");
251         return false;
252     }
253
254     fb_quadlet_t clockreg;
255     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg)) {
256         debugError("Could not read CLOCK_SELECT register\n");
257         return false;
258     }
259
260     clockreg = DICE_SET_RATE(clockreg, select);
261
262     if (!writeGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, clockreg)) {
263         debugError("Could not write CLOCK_SELECT register\n");
264         return false;
265     }
266
267     // check if the write succeeded
268     fb_quadlet_t clockreg_verify;
269     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg_verify)) {
270         debugError("Could not read CLOCK_SELECT register\n");
271         return false;
272     }
273
274     if(clockreg != clockreg_verify) {
275         debugError("Samplerate register write failed\n");
276         return false;
277     }
278
279     return true;
280 }
281
282 FFADODevice::ClockSourceVector
283 DiceAvDevice::getSupportedClockSources() {
284     FFADODevice::ClockSourceVector r;
285     return r;
286 }
287
288 bool
289 DiceAvDevice::setActiveClockSource(ClockSource s) {
290     return false;
291 }
292
293 FFADODevice::ClockSource
294 DiceAvDevice::getActiveClockSource() {
295     ClockSource s;
296     return s;
297 }
298
299 void
300 DiceAvDevice::showDevice()
301 {
302     fb_quadlet_t tmp_quadlet;
303     fb_octlet_t tmp_octlet;
304
305     debugOutput(DEBUG_LEVEL_VERBOSE,
306         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
307         getNodeId());
308
309     debugOutput(DEBUG_LEVEL_VERBOSE," DICE Parameter Space info:\n");
310     debugOutput(DEBUG_LEVEL_VERBOSE,"  Global  : offset=0x%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
311     debugOutput(DEBUG_LEVEL_VERBOSE,"  TX      : offset=0x%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
312     debugOutput(DEBUG_LEVEL_VERBOSE,"                nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
313     debugOutput(DEBUG_LEVEL_VERBOSE,"  RX      : offset=0x%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
314     debugOutput(DEBUG_LEVEL_VERBOSE,"                nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
315     debugOutput(DEBUG_LEVEL_VERBOSE,"  UNUSED1 : offset=0x%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
316     debugOutput(DEBUG_LEVEL_VERBOSE,"  UNUSED2 : offset=0x%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
317
318     debugOutput(DEBUG_LEVEL_VERBOSE," Global param space:\n");
319
320     readGlobalRegBlock(DICE_REGISTER_GLOBAL_OWNER, (fb_quadlet_t *)&tmp_octlet,sizeof(fb_octlet_t));
321     debugOutput(DEBUG_LEVEL_VERBOSE,"  Owner            : 0x%016X\n",tmp_octlet);
322
323     readGlobalReg(DICE_REGISTER_GLOBAL_NOTIFICATION, &tmp_quadlet);
324     debugOutput(DEBUG_LEVEL_VERBOSE,"  Notification     : 0x%08X\n",tmp_quadlet);
325
326     readGlobalReg(DICE_REGISTER_GLOBAL_NOTIFICATION, &tmp_quadlet);
327     debugOutput(DEBUG_LEVEL_VERBOSE,"  Nick name        : %s\n",getDeviceNickName().c_str());
328
329     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &tmp_quadlet);
330     debugOutput(DEBUG_LEVEL_VERBOSE,"  Clock Select     : 0x%02X 0x%02X\n",
331         (tmp_quadlet>>8) & 0xFF, tmp_quadlet & 0xFF);
332
333     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &tmp_quadlet);
334     debugOutput(DEBUG_LEVEL_VERBOSE,"  Enable           : %s\n",
335         (tmp_quadlet&0x1?"true":"false"));
336
337     readGlobalReg(DICE_REGISTER_GLOBAL_STATUS, &tmp_quadlet);
338     debugOutput(DEBUG_LEVEL_VERBOSE,"  Clock Status     : %s 0x%02X\n",
339         (tmp_quadlet&0x1?"locked":"not locked"), (tmp_quadlet>>8) & 0xFF);
340
341     readGlobalReg(DICE_REGISTER_GLOBAL_EXTENDED_STATUS, &tmp_quadlet);
342     debugOutput(DEBUG_LEVEL_VERBOSE,"  Extended Status  : 0x%08X\n",tmp_quadlet);
343
344     readGlobalReg(DICE_REGISTER_GLOBAL_SAMPLE_RATE, &tmp_quadlet);
345     debugOutput(DEBUG_LEVEL_VERBOSE,"  Samplerate       : 0x%08X (%lu)\n",tmp_quadlet,tmp_quadlet);
346
347     readGlobalReg(DICE_REGISTER_GLOBAL_VERSION, &tmp_quadlet);
348     debugOutput(DEBUG_LEVEL_VERBOSE,"  Version          : 0x%08X (%u.%u.%u.%u)\n",
349         tmp_quadlet,
350         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_A(tmp_quadlet),
351         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_B(tmp_quadlet),
352         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_C(tmp_quadlet),
353         DICE_DRIVER_SPEC_VERSION_NUMBER_GET_D(tmp_quadlet)
354         );
355
356     readGlobalReg(DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES, &tmp_quadlet);
357     debugOutput(DEBUG_LEVEL_VERBOSE,"  Clock caps       : 0x%08X\n",tmp_quadlet & 0x1FFF007F);
358
359     diceNameVector names=getClockSourceNameString();
360     debugOutput(DEBUG_LEVEL_VERBOSE,"  Clock sources    :\n");
361
362     for ( diceNameVectorIterator it = names.begin();
363           it != names.end();
364           ++it )
365     {
366         debugOutput(DEBUG_LEVEL_VERBOSE,"    %s\n", (*it).c_str());
367     }
368
369     debugOutput(DEBUG_LEVEL_VERBOSE," TX param space:\n");
370     debugOutput(DEBUG_LEVEL_VERBOSE,"  Nb of xmit        : %1d\n", m_nb_tx);
371     for (unsigned int i=0;i<m_nb_tx;i++) {
372         debugOutput(DEBUG_LEVEL_VERBOSE,"  Transmitter %d:\n",i);
373
374         readTxReg(i, DICE_REGISTER_TX_ISOC_BASE, &tmp_quadlet);
375         debugOutput(DEBUG_LEVEL_VERBOSE,"   ISO channel       : %3d\n", tmp_quadlet);
376         readTxReg(i, DICE_REGISTER_TX_SPEED_BASE, &tmp_quadlet);
377         debugOutput(DEBUG_LEVEL_VERBOSE,"   ISO speed         : %3d\n", tmp_quadlet);
378
379         readTxReg(i, DICE_REGISTER_TX_NB_AUDIO_BASE, &tmp_quadlet);
380         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb audio channels : %3d\n", tmp_quadlet);
381         readTxReg(i, DICE_REGISTER_TX_MIDI_BASE, &tmp_quadlet);
382         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb midi channels  : %3d\n", tmp_quadlet);
383
384         readTxReg(i, DICE_REGISTER_TX_AC3_CAPABILITIES_BASE, &tmp_quadlet);
385         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 caps          : 0x%08X\n", tmp_quadlet);
386         readTxReg(i, DICE_REGISTER_TX_AC3_ENABLE_BASE, &tmp_quadlet);
387         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 enable        : 0x%08X\n", tmp_quadlet);
388
389         diceNameVector channel_names=getTxNameString(i);
390         debugOutput(DEBUG_LEVEL_VERBOSE,"   Channel names     :\n");
391         for ( diceNameVectorIterator it = channel_names.begin();
392             it != channel_names.end();
393             ++it )
394         {
395             debugOutput(DEBUG_LEVEL_VERBOSE,"     %s\n", (*it).c_str());
396         }
397     }
398
399     debugOutput(DEBUG_LEVEL_VERBOSE," RX param space:\n");
400     debugOutput(DEBUG_LEVEL_VERBOSE,"  Nb of recv        : %1d\n", m_nb_tx);
401     for (unsigned int i=0;i<m_nb_rx;i++) {
402         debugOutput(DEBUG_LEVEL_VERBOSE,"  Receiver %d:\n",i);
403
404         readTxReg(i, DICE_REGISTER_RX_ISOC_BASE, &tmp_quadlet);
405         debugOutput(DEBUG_LEVEL_VERBOSE,"   ISO channel       : %3d\n", tmp_quadlet);
406         readTxReg(i, DICE_REGISTER_RX_SEQ_START_BASE, &tmp_quadlet);
407         debugOutput(DEBUG_LEVEL_VERBOSE,"   Sequence start    : %3d\n", tmp_quadlet);
408
409         readTxReg(i, DICE_REGISTER_RX_NB_AUDIO_BASE, &tmp_quadlet);
410         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb audio channels : %3d\n", tmp_quadlet);
411         readTxReg(i, DICE_REGISTER_RX_MIDI_BASE, &tmp_quadlet);
412         debugOutput(DEBUG_LEVEL_VERBOSE,"   Nb midi channels  : %3d\n", tmp_quadlet);
413
414         readTxReg(i, DICE_REGISTER_RX_AC3_CAPABILITIES_BASE, &tmp_quadlet);
415         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 caps          : 0x%08X\n", tmp_quadlet);
416         readTxReg(i, DICE_REGISTER_RX_AC3_ENABLE_BASE, &tmp_quadlet);
417         debugOutput(DEBUG_LEVEL_VERBOSE,"   AC3 enable        : 0x%08X\n", tmp_quadlet);
418
419         diceNameVector channel_names=getRxNameString(i);
420         debugOutput(DEBUG_LEVEL_VERBOSE,"   Channel names     :\n");
421         for ( diceNameVectorIterator it = channel_names.begin();
422             it != channel_names.end();
423             ++it )
424         {
425             debugOutput(DEBUG_LEVEL_VERBOSE,"     %s\n", (*it).c_str());
426         }
427     }
428 }
429
430 // NOTE on bandwidth calculation
431 // FIXME: The bandwidth allocation calculation can probably be
432 // refined somewhat since this is currently based on a rudimentary
433 // understanding of the iso protocol.
434 // Currently we assume the following.
435 //   * Ack/iso gap = 0.05 us
436 //   * DATA_PREFIX = 0.16 us1
437 //   * DATA_END    = 0.26 us
438 // These numbers are the worst-case figures given in the ieee1394
439 // standard.  This gives approximately 0.5 us of overheads per
440 // packet - around 25 bandwidth allocation units (from the ieee1394
441 // standard 1 bandwidth allocation unit is 125/6144 us).  We further
442 // assume the device is running at S400 (which it should be) so one
443 // allocation unit is equivalent to 1 transmitted byte; thus the
444 // bandwidth allocation required for the packets themselves is just
445 // the size of the packet.
446 bool
447 DiceAvDevice::prepare() {
448     int samplerate=getSamplingFrequency();
449
450     // prepare receive SP's
451     for (unsigned int i=0;i<m_nb_tx;i++) {
452         fb_quadlet_t nb_audio;
453         fb_quadlet_t nb_midi;
454         unsigned int nb_channels=0;
455
456         if(!readTxReg(i, DICE_REGISTER_TX_NB_AUDIO_BASE, &nb_audio)) {
457             debugError("Could not read DICE_REGISTER_TX_NB_AUDIO_BASE register for ATX%u",i);
458             continue;
459         }
460         if(!readTxReg(i, DICE_REGISTER_TX_MIDI_BASE, &nb_midi)) {
461             debugError("Could not read DICE_REGISTER_TX_MIDI_BASE register for ATX%u",i);
462             continue;
463         }
464
465         // request the channel names
466         diceNameVector names_audio=getTxNameString(i);
467
468         if (names_audio.size() != nb_audio) {
469             debugWarning("The audio channel name vector is incorrect, using default names\n");
470             names_audio.clear();
471
472             for (unsigned int j=0;j<nb_audio;j++) {
473                 std::ostringstream newname;
474                 newname << "input_" << j;
475                 names_audio.push_back(newname.str());
476             }
477         }
478
479         nb_channels=nb_audio;
480         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
481
482         // construct the MIDI names
483         diceNameVector names_midi;
484         for (unsigned int j=0;j<nb_midi;j++) {
485             std::ostringstream newname;
486             newname << "midi_in_" << j;
487             names_midi.push_back(newname.str());
488         }
489
490         // construct the streamprocessor
491         Streaming::AmdtpReceiveStreamProcessor *p;
492         p=new Streaming::AmdtpReceiveStreamProcessor(
493                              m_p1394Service->getPort(),
494                              samplerate,
495                              nb_channels);
496
497         if(!p->init()) {
498             debugFatal("Could not initialize receive processor!\n");
499             delete p;
500             continue;
501         }
502
503         // add audio ports to the processor
504         for (unsigned int j=0;j<nb_audio;j++) {
505             diceChannelInfo channelInfo;
506             channelInfo.name=names_audio.at(j);
507             channelInfo.portType=ePT_Analog;
508             channelInfo.streamPosition=j;
509             channelInfo.streamLocation=0;
510
511             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
512                 debugError("Could not add channel %s to StreamProcessor\n",
513                     channelInfo.name.c_str());
514                 continue;
515             }
516         }
517
518         // add midi ports to the processor
519         for (unsigned int j=0;j<nb_midi;j++) {
520             diceChannelInfo channelInfo;
521             channelInfo.name=names_midi.at(j);
522             channelInfo.portType=ePT_MIDI;
523             channelInfo.streamPosition=nb_audio;
524             channelInfo.streamLocation=j;
525
526             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
527                 debugError("Could not add channel %s to StreamProcessor\n",
528                     channelInfo.name.c_str());
529                 continue;
530             }
531         }
532
533         // add the SP to the vector
534         m_receiveProcessors.push_back(p);
535     }
536
537     // prepare transmit SP's
538     for (unsigned int i=0;i<m_nb_rx;i++) {
539         fb_quadlet_t nb_audio;
540         fb_quadlet_t nb_midi;
541         unsigned int nb_channels=0;
542
543         if(!readTxReg(i, DICE_REGISTER_RX_NB_AUDIO_BASE, &nb_audio)) {
544             debugError("Could not read DICE_REGISTER_RX_NB_AUDIO_BASE register for ARX%u",i);
545             continue;
546         }
547         if(!readTxReg(i, DICE_REGISTER_RX_MIDI_BASE, &nb_midi)) {
548             debugError("Could not read DICE_REGISTER_RX_MIDI_BASE register for ARX%u",i);
549             continue;
550         }
551
552         // request the channel names
553         diceNameVector names_audio=getRxNameString(i);
554
555         if (names_audio.size() != nb_audio) {
556             debugWarning("The audio channel name vector is incorrect, using default names\n");
557             names_audio.clear();
558
559             for (unsigned int j=0;j<nb_audio;j++) {
560                 std::ostringstream newname;
561                 newname << "output_" << j;
562                 names_audio.push_back(newname.str());
563             }
564         }
565
566         nb_channels=nb_audio;
567         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
568
569         // construct the MIDI names
570         diceNameVector names_midi;
571         for (unsigned int j=0;j<nb_midi;j++) {
572             std::ostringstream newname;
573             newname << "midi_out_" << j;
574             names_midi.push_back(newname.str());
575         }
576
577         // construct the streamprocessor
578         Streaming::AmdtpTransmitStreamProcessor *p;
579         p=new Streaming::AmdtpTransmitStreamProcessor(
580                              m_p1394Service->getPort(),
581                              samplerate,
582                              nb_channels);
583
584         if(!p->init()) {
585             debugFatal("Could not initialize transmit processor!\n");
586             delete p;
587             continue;
588         }
589
590         // add audio ports to the processor
591         for (unsigned int j=0;j<nb_audio;j++) {
592             diceChannelInfo channelInfo;
593             channelInfo.name=names_audio.at(j);
594             channelInfo.portType=ePT_Analog;
595             channelInfo.streamPosition=j;
596             channelInfo.streamLocation=0;
597
598             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
599                 debugError("Could not add channel %s to StreamProcessor\n",
600                     channelInfo.name.c_str());
601                 continue;
602             }
603         }
604
605         // add midi ports to the processor
606         for (unsigned int j=0;j<nb_midi;j++) {
607             diceChannelInfo channelInfo;
608             channelInfo.name=names_midi.at(j);
609             channelInfo.portType=ePT_MIDI;
610             channelInfo.streamPosition=nb_audio;
611             channelInfo.streamLocation=j;
612
613             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
614                 debugError("Could not add channel %s to StreamProcessor\n",
615                     channelInfo.name.c_str());
616                 continue;
617             }
618         }
619
620         m_transmitProcessors.push_back(p);
621     }
622     return true;
623 }
624
625 bool
626 DiceAvDevice::addChannelToProcessor(
627     diceChannelInfo *channelInfo,
628     Streaming::StreamProcessor *processor,
629     Streaming::Port::E_Direction direction) {
630
631     std::string id=std::string("dev?");
632     if(!getOption("id", id)) {
633         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
634     }
635
636     std::ostringstream portname;
637     portname << id;
638     if(direction == Streaming::Port::E_Playback) {
639         portname << "p";
640     } else {
641         portname << "c";
642     }
643
644     portname << "_" << channelInfo->name;
645
646     Streaming::Port *p=NULL;
647     switch(channelInfo->portType) {
648     case ePT_Analog:
649         p=new Streaming::AmdtpAudioPort(
650                 portname.str(),
651                 direction,
652                 channelInfo->streamPosition,
653                 channelInfo->streamLocation,
654                 Streaming::AmdtpPortInfo::E_MBLA
655         );
656         break;
657
658     case ePT_MIDI:
659         p=new Streaming::AmdtpMidiPort(
660                 portname.str(),
661                 direction,
662                 channelInfo->streamPosition,
663                 channelInfo->streamLocation,
664                 Streaming::AmdtpPortInfo::E_Midi
665         );
666
667         break;
668     default:
669     // unsupported
670         break;
671     }
672
673     if (!p) {
674         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str());
675     } else {
676
677         if (!processor->addPort(p)) {
678             debugWarning("Could not register port with stream processor\n");
679             return false;
680         }
681     }
682
683     return true;
684 }
685
686 bool
687 DiceAvDevice::lock() {
688     fb_octlet_t result;
689
690     debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n",
691         m_model->vendor_name, m_model->model_name, getNodeId());
692
693     // get a notifier to handle device notifications
694     nodeaddr_t notify_address;
695     notify_address = m_p1394Service->findFreeARMBlock(
696                         DICE_NOTIFIER_BASE_ADDRESS,
697                         DICE_NOTIFIER_BLOCK_LENGTH,
698                         DICE_NOTIFIER_BLOCK_LENGTH);
699
700     if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) {
701         debugError("Could not find free ARM block for notification\n");
702         return false;
703     }
704
705     m_notifier=new DiceAvDevice::DiceNotifier(this, notify_address);
706
707     if(!m_notifier) {
708         debugError("Could not allocate notifier\n");
709         return false;
710     }
711
712     if (!m_p1394Service->registerARMHandler(m_notifier)) {
713         debugError("Could not register notifier\n");
714         delete m_notifier;
715         m_notifier=NULL;
716         return false;
717     }
718
719     // register this notifier
720     fb_nodeaddr_t addr = DICE_REGISTER_BASE
721                        + m_global_reg_offset
722                        + DICE_REGISTER_GLOBAL_OWNER;
723
724     // registry offsets should always be smaller than 0x7FFFFFFF
725     // because otherwise base + offset > 64bit
726     if(m_global_reg_offset & 0x80000000) {
727         debugError("register offset not initialized yet\n");
728         return false;
729     }
730
731     fb_nodeaddr_t swap_value = ((0xFFC0) | m_p1394Service->getLocalNodeId());
732     swap_value = swap_value << 48;
733     swap_value |= m_notifier->getStart();
734
735     if (!m_p1394Service->lockCompareSwap64(  getNodeId() | 0xFFC0, addr, DICE_OWNER_NO_OWNER,
736                                        swap_value, &result )) {
737         debugWarning("Could not register ourselves as device owner\n");
738     }
739
740     if (result != DICE_OWNER_NO_OWNER) {
741         debugWarning("Could not register ourselves as device owner, unexpected register value: 0x%016llX\n", result);
742     }
743
744     return true;
745 }
746
747
748 bool
749 DiceAvDevice::unlock() {
750     fb_octlet_t result;
751
752     if(!m_notifier) {
753         debugWarning("Request to unlock, but no notifier present!\n");
754         return false;
755     }
756
757     fb_nodeaddr_t addr = DICE_REGISTER_BASE
758                        + m_global_reg_offset
759                        + DICE_REGISTER_GLOBAL_OWNER;
760
761     // registry offsets should always be smaller than 0x7FFFFFFF
762     // because otherwise base + offset > 64bit
763     if(m_global_reg_offset & 0x80000000) {
764         debugError("register offset not initialized yet\n");
765         return false;
766     }
767
768     fb_nodeaddr_t compare_value = ((0xFFC0) | m_p1394Service->getLocalNodeId());
769     compare_value <<= 48;
770     compare_value |= m_notifier->getStart();
771
772     if (!m_p1394Service->lockCompareSwap64(  getNodeId() | 0xFFC0, addr, compare_value,
773                                        DICE_OWNER_NO_OWNER, &result )) {
774         debugWarning("Could not unregister ourselves as device owner\n");
775     }
776
777     m_p1394Service->unregisterARMHandler(m_notifier);
778     delete m_notifier;
779     m_notifier=NULL;
780
781     return true;
782 }
783
784 bool
785 DiceAvDevice::enableStreaming() {
786     return enableIsoStreaming();
787 }
788
789 bool
790 DiceAvDevice::disableStreaming() {
791     return disableIsoStreaming();
792 }
793
794 int
795 DiceAvDevice::getStreamCount() {
796     return m_receiveProcessors.size() + m_transmitProcessors.size();
797 }
798
799 Streaming::StreamProcessor *
800 DiceAvDevice::getStreamProcessorByIndex(int i) {
801
802     if (i<(int)m_receiveProcessors.size()) {
803         return m_receiveProcessors.at(i);
804     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
805         return m_transmitProcessors.at(i-m_receiveProcessors.size());
806     }
807
808     return NULL;
809 }
810
811 bool
812 DiceAvDevice::startStreamByIndex(int i) {
813
814     if (isIsoStreamingEnabled()) {
815         debugError("Cannot start streams while streaming is enabled\n");
816         return false;
817     }
818
819     if (i<(int)m_receiveProcessors.size()) {
820         int n=i;
821         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
822
823         // allocate ISO channel
824         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
825         if(isochannel<0) {
826             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
827             return false;
828         }
829         p->setChannel(isochannel);
830
831         fb_quadlet_t reg_isoch;
832         // check value of ISO_CHANNEL register
833         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
834             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
835             p->setChannel(-1);
836             deallocateIsoChannel(isochannel);
837             return false;
838         }
839         if(reg_isoch != 0xFFFFFFFFUL) {
840             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ATX %d\n", reg_isoch, n);
841             p->setChannel(-1);
842             deallocateIsoChannel(isochannel);
843             return false;
844         }
845
846         // write value of ISO_CHANNEL register
847         reg_isoch=isochannel;
848         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
849             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
850             p->setChannel(-1);
851             deallocateIsoChannel(isochannel);
852             return false;
853         }
854
855         return true;
856
857     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
858         int n=i-m_receiveProcessors.size();
859         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
860
861         // allocate ISO channel
862         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
863         if(isochannel<0) {
864             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
865             return false;
866         }
867         p->setChannel(isochannel);
868
869         fb_quadlet_t reg_isoch;
870         // check value of ISO_CHANNEL register
871         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
872             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
873             p->setChannel(-1);
874             deallocateIsoChannel(isochannel);
875             return false;
876         }
877         if(reg_isoch != 0xFFFFFFFFUL) {
878             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ARX %d\n", reg_isoch, n);
879             p->setChannel(-1);
880             deallocateIsoChannel(isochannel);
881             return false;
882         }
883
884         // write value of ISO_CHANNEL register
885         reg_isoch=isochannel;
886         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
887             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
888             p->setChannel(-1);
889             deallocateIsoChannel(isochannel);
890             return false;
891         }
892
893         return true;
894     }
895
896     debugError("SP index %d out of range!\n",i);
897
898     return false;
899 }
900
901 bool
902 DiceAvDevice::stopStreamByIndex(int i) {
903
904     if (isIsoStreamingEnabled()) {
905         debugError("Cannot stop streams while streaming is enabled\n");
906         return false;
907     }
908
909     if (i<(int)m_receiveProcessors.size()) {
910         int n=i;
911         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
912         unsigned int isochannel=p->getChannel();
913
914         fb_quadlet_t reg_isoch;
915         // check value of ISO_CHANNEL register
916         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
917             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
918             return false;
919         }
920         if(reg_isoch != isochannel) {
921             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ATX %d\n", isochannel, reg_isoch, n);
922             return false;
923         }
924
925         // write value of ISO_CHANNEL register
926         reg_isoch=0xFFFFFFFFUL;
927         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
928             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
929             return false;
930         }
931
932         // deallocate ISO channel
933         if(!deallocateIsoChannel(isochannel)) {
934             debugError("Could not deallocate iso channel for SP %d (ATX %d)\n",i,n);
935             return false;
936         }
937
938         p->setChannel(-1);
939         return true;
940
941     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
942         int n=i-m_receiveProcessors.size();
943         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
944
945         unsigned int isochannel=p->getChannel();
946
947         fb_quadlet_t reg_isoch;
948         // check value of ISO_CHANNEL register
949         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
950             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
951             return false;
952         }
953         if(reg_isoch != isochannel) {
954             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ARX %d\n", isochannel, reg_isoch, n);
955             return false;
956         }
957
958         // write value of ISO_CHANNEL register
959         reg_isoch=0xFFFFFFFFUL;
960         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
961             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
962             return false;
963         }
964
965         // deallocate ISO channel
966         if(!deallocateIsoChannel(isochannel)) {
967             debugError("Could not deallocate iso channel for SP %d (ARX %d)\n",i,n);
968             return false;
969         }
970
971         p->setChannel(-1);
972         return true;
973     }
974
975     debugError("SP index %d out of range!\n",i);
976
977     return false;
978 }
979
980 // helper routines
981
982 // allocate ISO resources for the SP's
983 int DiceAvDevice::allocateIsoChannel(unsigned int packet_size) {
984     unsigned int bandwidth=8+packet_size;
985
986     int ch=m_p1394Service->allocateIsoChannelGeneric(bandwidth);
987
988     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
989         ch, bandwidth);
990
991     return ch;
992 }
993 // deallocate ISO resources
994 bool DiceAvDevice::deallocateIsoChannel(int channel) {
995     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
996     return m_p1394Service->freeIsoChannel(channel);
997 }
998
999 bool
1000 DiceAvDevice::enableIsoStreaming() {
1001     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_ENABLE);
1002 }
1003
1004 bool
1005 DiceAvDevice::disableIsoStreaming() {
1006     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_DISABLE);
1007 }
1008
1009 bool
1010 DiceAvDevice::isIsoStreamingEnabled() {
1011     fb_quadlet_t result;
1012     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &result);
1013     // I don't know what exactly is 'enable',
1014     // but disable is definately == 0
1015     return (result != DICE_ISOSTREAMING_DISABLE);
1016 }
1017
1018 /**
1019  * @brief performs a masked bit register equals 0 check on the global parameter space
1020  * @return true if readGlobalReg(offset) & mask == 0
1021  */
1022 bool
1023 DiceAvDevice::maskedCheckZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1024     fb_quadlet_t result;
1025     readGlobalReg(offset, &result);
1026     return ((result & mask) == 0);
1027 }
1028 /**
1029  * @brief performs a masked bit register not equal to 0 check on the global parameter space
1030  * @return true if readGlobalReg(offset) & mask != 0
1031  */
1032 bool
1033 DiceAvDevice::maskedCheckNotZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1034     return !maskedCheckZeroGlobalReg(offset, mask);
1035 }
1036
1037 DiceAvDevice::diceNameVector
1038 DiceAvDevice::getTxNameString(unsigned int i) {
1039     diceNameVector names;
1040     char namestring[DICE_TX_NAMES_SIZE+1];
1041
1042     if (!readTxRegBlock(i, DICE_REGISTER_TX_NAMES_BASE,
1043                         (fb_quadlet_t *)namestring, DICE_TX_NAMES_SIZE)) {
1044         debugError("Could not read TX name string \n");
1045         return names;
1046     }
1047
1048     namestring[DICE_TX_NAMES_SIZE]='\0';
1049     return splitNameString(std::string(namestring));
1050 }
1051
1052 DiceAvDevice::diceNameVector
1053 DiceAvDevice::getRxNameString(unsigned int i) {
1054     diceNameVector names;
1055     char namestring[DICE_RX_NAMES_SIZE+1];
1056
1057     if (!readRxRegBlock(i, DICE_REGISTER_RX_NAMES_BASE,
1058                         (fb_quadlet_t *)namestring, DICE_RX_NAMES_SIZE)) {
1059         debugError("Could not read RX name string \n");
1060         return names;
1061     }
1062
1063     namestring[DICE_RX_NAMES_SIZE]='\0';
1064     return splitNameString(std::string(namestring));
1065 }
1066
1067 DiceAvDevice::diceNameVector
1068 DiceAvDevice::getClockSourceNameString() {
1069     diceNameVector names;
1070     char namestring[DICE_CLOCKSOURCENAMES_SIZE+1];
1071
1072     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_CLOCKSOURCENAMES,
1073                         (fb_quadlet_t *)namestring, DICE_CLOCKSOURCENAMES_SIZE)) {
1074         debugError("Could not read CLOCKSOURCE name string \n");
1075         return names;
1076     }
1077
1078     namestring[DICE_CLOCKSOURCENAMES_SIZE]='\0';
1079     return splitNameString(std::string(namestring));
1080 }
1081
1082 std::string
1083 DiceAvDevice::getDeviceNickName() {
1084     char namestring[DICE_NICK_NAME_SIZE+1];
1085
1086     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_NICK_NAME,
1087                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1088         debugError("Could not read nickname string \n");
1089         return std::string("(unknown)");
1090     }
1091
1092     namestring[DICE_NICK_NAME_SIZE]='\0';
1093     return std::string(namestring);
1094 }
1095
1096 DiceAvDevice::diceNameVector
1097 DiceAvDevice::splitNameString(std::string in) {
1098     diceNameVector names;
1099
1100     // find the end of the string
1101     unsigned int end=in.find(string("\\\\"));
1102     // cut the end
1103     in=in.substr(0,end);
1104
1105     unsigned int cut;
1106     while( (cut = in.find(string("\\"))) != in.npos ) {
1107         if(cut > 0) {
1108             names.push_back(in.substr(0,cut));
1109         }
1110         in = in.substr(cut+1);
1111     }
1112     if(in.length() > 0) {
1113         names.push_back(in);
1114     }
1115     return names;
1116 }
1117
1118
1119 // I/O routines
1120 bool
1121 DiceAvDevice::initIoFunctions() {
1122
1123     // offsets and sizes are returned in quadlets, but we use byte values
1124
1125     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_OFF, &m_global_reg_offset)) {
1126         debugError("Could not initialize m_global_reg_offset\n");
1127         return false;
1128     }
1129     m_global_reg_offset*=4;
1130
1131     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_SZ, &m_global_reg_size)) {
1132         debugError("Could not initialize m_global_reg_size\n");
1133         return false;
1134     }
1135     m_global_reg_size*=4;
1136
1137     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_OFF, &m_tx_reg_offset)) {
1138         debugError("Could not initialize m_tx_reg_offset\n");
1139         return false;
1140     }
1141     m_tx_reg_offset*=4;
1142
1143     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_SZ, &m_tx_reg_size)) {
1144         debugError("Could not initialize m_tx_reg_size\n");
1145         return false;
1146     }
1147     m_tx_reg_size*=4;
1148
1149     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_OFF, &m_rx_reg_offset)) {
1150         debugError("Could not initialize m_rx_reg_offset\n");
1151         return false;
1152     }
1153     m_rx_reg_offset*=4;
1154
1155     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_SZ, &m_rx_reg_size)) {
1156         debugError("Could not initialize m_rx_reg_size\n");
1157         return false;
1158     }
1159     m_rx_reg_size*=4;
1160
1161     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_OFF, &m_unused1_reg_offset)) {
1162         debugError("Could not initialize m_unused1_reg_offset\n");
1163         return false;
1164     }
1165     m_unused1_reg_offset*=4;
1166
1167     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_SZ, &m_unused1_reg_size)) {
1168         debugError("Could not initialize m_unused1_reg_size\n");
1169         return false;
1170     }
1171     m_unused1_reg_size*=4;
1172
1173     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_OFF, &m_unused2_reg_offset)) {
1174         debugError("Could not initialize m_unused2_reg_offset\n");
1175         return false;
1176     }
1177     m_unused2_reg_offset*=4;
1178
1179     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_SZ, &m_unused2_reg_size)) {
1180         debugError("Could not initialize m_unused2_reg_size\n");
1181         return false;
1182     }
1183     m_unused2_reg_size*=4;
1184
1185     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_NB_TX, &m_nb_tx)) {
1186         debugError("Could not initialize m_nb_tx\n");
1187         return false;
1188     }
1189     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_SZ_TX, &m_tx_size)) {
1190         debugError("Could not initialize m_tx_size\n");
1191         return false;
1192     }
1193     m_tx_size*=4;
1194
1195     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_NB_RX, &m_nb_rx)) {
1196         debugError("Could not initialize m_nb_rx\n");
1197         return false;
1198     }
1199     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
1200         debugError("Could not initialize m_rx_size\n");
1201         return false;
1202     }
1203     m_rx_size*=4;
1204
1205     debugOutput(DEBUG_LEVEL_VERBOSE,"DICE Parameter Space info:\n");
1206     debugOutput(DEBUG_LEVEL_VERBOSE," Global  : offset=%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
1207     debugOutput(DEBUG_LEVEL_VERBOSE," TX      : offset=%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
1208     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
1209     debugOutput(DEBUG_LEVEL_VERBOSE," RX      : offset=%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
1210     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
1211     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED1 : offset=%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
1212     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED2 : offset=%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
1213
1214     return true;
1215 }
1216
1217 bool
1218 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1219     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
1220
1221     if(offset >= DICE_INVALID_OFFSET) {
1222         debugError("invalid offset: 0x%016llX\n", offset);
1223         return false;
1224     }
1225
1226     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1227     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1228
1229     if(!m_p1394Service->read_quadlet( nodeId, addr, result ) ) {
1230         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1231         return false;
1232     }
1233
1234     *result=ntohl(*result);
1235
1236     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1237
1238     return true;
1239 }
1240
1241 bool
1242 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1243     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
1244         offset, data);
1245
1246     if(offset >= DICE_INVALID_OFFSET) {
1247         debugError("invalid offset: 0x%016llX\n", offset);
1248         return false;
1249     }
1250
1251     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1252     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1253
1254     if(!m_p1394Service->write_quadlet( nodeId, addr, htonl(data) ) ) {
1255         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1256         return false;
1257     }
1258     return true;
1259 }
1260
1261 bool
1262 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1263     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1264         offset, length);
1265
1266     if(offset >= DICE_INVALID_OFFSET) {
1267         debugError("invalid offset: 0x%016llX\n", offset);
1268         return false;
1269     }
1270
1271     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1272     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1273
1274     if(!m_p1394Service->read( nodeId, addr, length/4, data ) ) {
1275         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1276         return false;
1277     }
1278
1279     for(unsigned int i=0;i<length/4;i++) {
1280         *(data+i)=ntohl(*(data+i));
1281     }
1282
1283     return true;
1284 }
1285
1286 bool
1287 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1288     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1289         offset, length);
1290
1291     if(offset >= DICE_INVALID_OFFSET) {
1292         debugError("invalid offset: 0x%016llX\n", offset);
1293         return false;
1294     }
1295
1296     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1297     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1298
1299     fb_quadlet_t data_out[length/4];
1300
1301     for(unsigned int i=0;i<length/4;i++) {
1302         data_out[i]=ntohl(*(data+i));
1303     }
1304
1305     if(!m_p1394Service->write( nodeId, addr, length/4, data_out ) ) {
1306         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1307         return false;
1308     }
1309
1310     return true;
1311 }
1312
1313 bool
1314 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1315     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1316
1317     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1318     return readReg(m_global_reg_offset + offset_gl, result);
1319 }
1320
1321 bool
1322 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1323     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n",
1324         offset, data);
1325
1326     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1327     return writeReg(m_global_reg_offset + offset_gl, data);
1328 }
1329
1330 bool
1331 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1332     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1333         offset, length);
1334
1335     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1336     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1337 }
1338
1339 bool
1340 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1341     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1342         offset, length);
1343
1344     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1345     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1346 }
1347
1348 fb_nodeaddr_t
1349 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1350
1351     // registry offsets should always be smaller than 0x7FFFFFFF
1352     // because otherwise base + offset > 64bit
1353     if(m_global_reg_offset & 0x80000000) {
1354         debugError("register offset not initialized yet\n");
1355         return DICE_INVALID_OFFSET;
1356     }
1357     // out-of-range check
1358     if(offset+length > m_global_reg_offset+m_global_reg_size) {
1359         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1360         return DICE_INVALID_OFFSET;
1361     }
1362
1363     return offset;
1364 }
1365
1366 bool
1367 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1368     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1369
1370     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1371     return readReg(m_tx_reg_offset + offset_tx, result);
1372 }
1373
1374 bool
1375 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1376     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1377         i, offset, data);
1378
1379     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1380     return writeReg(m_tx_reg_offset + offset_tx, data);
1381 }
1382
1383 bool
1384 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1385     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1386         offset, length);
1387
1388     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1389     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1390 }
1391
1392 bool
1393 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1394     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1395         offset, length);
1396
1397     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1398     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1399 }
1400
1401 fb_nodeaddr_t
1402 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1403     // registry offsets should always be smaller than 0x7FFFFFFF
1404     // because otherwise base + offset > 64bit
1405     if(m_tx_reg_offset & 0x80000000) {
1406         debugError("register offset not initialized yet\n");
1407         return DICE_INVALID_OFFSET;
1408     }
1409     if(m_nb_tx & 0x80000000) {
1410         debugError("m_nb_tx not initialized yet\n");
1411         return DICE_INVALID_OFFSET;
1412     }
1413     if(m_tx_size & 0x80000000) {
1414         debugError("m_tx_size not initialized yet\n");
1415         return DICE_INVALID_OFFSET;
1416     }
1417     if(i >= m_nb_tx) {
1418         debugError("TX index out of range\n");
1419         return DICE_INVALID_OFFSET;
1420     }
1421
1422     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1423
1424     // out-of-range check
1425     if(offset_tx + length > m_tx_reg_offset+4+m_tx_reg_size*m_nb_tx) {
1426         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1427         return DICE_INVALID_OFFSET;
1428     }
1429
1430     return offset_tx;
1431 }
1432
1433 bool
1434 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1435     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1436
1437     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1438     return readReg(m_rx_reg_offset + offset_rx, result);
1439 }
1440
1441 bool
1442 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1443     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n",
1444         offset, data);
1445
1446     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1447     return writeReg(m_rx_reg_offset + offset_rx, data);
1448 }
1449
1450 bool
1451 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1452     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1453         offset, length);
1454
1455     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1456     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1457 }
1458
1459 bool
1460 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1461     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1462         offset, length);
1463
1464     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1465     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1466 }
1467
1468 fb_nodeaddr_t
1469 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1470     // registry offsets should always be smaller than 0x7FFFFFFF
1471     // because otherwise base + offset > 64bit
1472     if(m_rx_reg_offset & 0x80000000) {
1473         debugError("register offset not initialized yet\n");
1474         return DICE_INVALID_OFFSET;
1475     }
1476     if(m_nb_rx & 0x80000000) {
1477         debugError("m_nb_rx not initialized yet\n");
1478         return DICE_INVALID_OFFSET;
1479     }
1480     if(m_rx_size & 0x80000000) {
1481         debugError("m_rx_size not initialized yet\n");
1482         return DICE_INVALID_OFFSET;
1483     }
1484     if(i >= m_nb_rx) {
1485         debugError("RX index out of range\n");
1486         return DICE_INVALID_OFFSET;
1487     }
1488
1489     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1490
1491     // out-of-range check
1492     if(offset_rx + length > m_rx_reg_offset+4+m_rx_reg_size*m_nb_rx) {
1493         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1494         return DICE_INVALID_OFFSET;
1495     }
1496     return offset_rx;
1497 }
1498
1499
1500 // the notifier
1501
1502 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1503  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1504               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1505               RAW1394_ARM_WRITE, 0)
1506  , m_dicedevice(d)
1507 {
1508
1509 }
1510
1511 DiceAvDevice::DiceNotifier::~DiceNotifier()
1512 {
1513
1514 }
1515
1516 }
Note: See TracBrowser for help on using the browser.