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

Revision 445, 49.0 kB (checked in by pieterpalmers, 15 years ago)

* name change from FreeBoB to FFADO
* replaced tabs by 4 spaces
* got rid of end-of-line spaces
* made all license and copyrights conform

library becomes LGPL, apps become GPL
explicitly state LGPL v2.1 and GPL v2 (don't like v3 draft)

copyrights are 2005-2007 Daniel & Pieter
except for the MotU stuff (C) Jonathan, Pieter

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