root/branches/ppalmers-streaming/src/dice/dice_avdevice.cpp

Revision 715, 49.3 kB (checked in by ppalmers, 15 years ago)

some more cleaning

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