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

Revision 479, 49.0 kB (checked in by wagi, 15 years ago)

- added all missing 'virtual' to function declared in avdevice implementation
- added getConfigurationId function (used for av/c model caching)

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     : IAvDevice( 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     ESamplingFrequency 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 = eSF_32000Hz;  break;
157         case DICE_RATE_44K1:     samplingFrequency = eSF_44100Hz;  break;
158         case DICE_RATE_48K:      samplingFrequency = eSF_48000Hz;  break;
159         case DICE_RATE_88K2:     samplingFrequency = eSF_88200Hz;  break;
160         case DICE_RATE_96K:      samplingFrequency = eSF_96000Hz;  break;
161         case DICE_RATE_176K4:    samplingFrequency = eSF_176400Hz; break;
162         case DICE_RATE_192K:     samplingFrequency = eSF_192000Hz; break;
163         case DICE_RATE_ANY_LOW:  samplingFrequency = eSF_AnyLow;   break;
164         case DICE_RATE_ANY_MID:  samplingFrequency = eSF_AnyMid;   break;
165         case DICE_RATE_ANY_HIGH: samplingFrequency = eSF_AnyHigh;  break;
166         case DICE_RATE_NONE:     samplingFrequency = eSF_None;     break;
167         default:                 samplingFrequency = eSF_DontCare; break;
168     }
169
170     return convertESamplingFrequency(samplingFrequency);
171 }
172
173 int
174 DiceAvDevice::getConfigurationId()
175 {
176     return 0;
177 }
178
179 bool
180 DiceAvDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
181 {
182     debugOutput(DEBUG_LEVEL_VERBOSE, "Setting sample rate: %d\n",
183         convertESamplingFrequency(samplingFrequency));
184
185     bool supported=false;
186     fb_quadlet_t select=0x0;
187
188     switch ( samplingFrequency ) {
189     default:
190     case eSF_22050Hz:
191     case eSF_24000Hz:
192         supported=false;
193         break;
194     case eSF_32000Hz:
195         supported=maskedCheckNotZeroGlobalReg(
196                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
197                     DICE_CLOCKCAP_RATE_32K);
198         select=DICE_RATE_32K;
199         break;
200     case eSF_44100Hz:
201         supported=maskedCheckNotZeroGlobalReg(
202                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
203                     DICE_CLOCKCAP_RATE_44K1);
204         select=DICE_RATE_44K1;
205         break;
206     case eSF_48000Hz:
207         supported=maskedCheckNotZeroGlobalReg(
208                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
209                     DICE_CLOCKCAP_RATE_48K);
210         select=DICE_RATE_48K;
211         break;
212     case eSF_88200Hz:
213         supported=maskedCheckNotZeroGlobalReg(
214                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
215                     DICE_CLOCKCAP_RATE_88K2);
216         select=DICE_RATE_88K2;
217         break;
218     case eSF_96000Hz:
219         supported=maskedCheckNotZeroGlobalReg(
220                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
221                     DICE_CLOCKCAP_RATE_96K);
222         select=DICE_RATE_96K;
223         break;
224     case eSF_176400Hz:
225         supported=maskedCheckNotZeroGlobalReg(
226                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
227                     DICE_CLOCKCAP_RATE_176K4);
228         select=DICE_RATE_176K4;
229         break;
230     case eSF_192000Hz:
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", convertESamplingFrequency(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.