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

Revision 554, 48.8 kB (checked in by ppalmers, 15 years ago)

Merge echoaudio branch into trunk.

This adds support for the Echo Audiofire devices to FFADO. Possibly also other devices working with the Apple Class Driver will work with this code. It is not fully complete yet, but the main rework is
done.

First of all the IAvDevice class/interface is renamed to FFADODevice, in order to separate the AV/C code from the FFADO API code. A device supported by FFADO implements a FFADODevice.

The BeBoB device has been split up into three groups:
- libavc/* : all code and commands that are specified by AV/C specs. Note that a lot of the code that used to be in BeBoB::AvDevice? now resides in AVC::Unit
- genericavc/* : a FFADODevice that uses AV/C descriptors & commands for discovery and config
- bebob/* : the bebob FFADODevice that inherits from GenericAVC::AvDevice? but that uses BridgeCo? commands for discovery

Everything has been moved as high as possible in the class hierarchy. If necessary, a subclass that uses device specific commands is introduced (e.g. BeBoB::Plug inherits from AVC::Plug and uses the
BridgeCo? extended plug info command to discover it's properties).

There are some other fixes along the way that have been done too.

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