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

Revision 742, 49.1 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

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