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

Revision 739, 49.2 kB (checked in by ppalmers, 13 years ago)

- Adapt the ffado external API (upgrade to v3)

NEEDS NEW JACK BACKEND

- simplify FFADODevice constructor even more
- implement first framework support for supporting multiple adapters.

currently all firewire adapters are scanned for supported devices unless specified otherwise
however attaching devices to separate adapters is not supported. using multiple adapters at
that are connected together might work.

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