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

Revision 712, 49.4 kB (checked in by ppalmers, 16 years ago)

almost there...

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     int samplerate=getSamplingFrequency();
450
451     // prepare receive SP's
452     for (unsigned int i=0;i<m_nb_tx;i++) {
453         fb_quadlet_t nb_audio;
454         fb_quadlet_t nb_midi;
455         unsigned int nb_channels=0;
456
457         if(!readTxReg(i, DICE_REGISTER_TX_NB_AUDIO_BASE, &nb_audio)) {
458             debugError("Could not read DICE_REGISTER_TX_NB_AUDIO_BASE register for ATX%u",i);
459             continue;
460         }
461         if(!readTxReg(i, DICE_REGISTER_TX_MIDI_BASE, &nb_midi)) {
462             debugError("Could not read DICE_REGISTER_TX_MIDI_BASE register for ATX%u",i);
463             continue;
464         }
465
466         // request the channel names
467         diceNameVector names_audio=getTxNameString(i);
468
469         if (names_audio.size() != nb_audio) {
470             debugWarning("The audio channel name vector is incorrect, using default names\n");
471             names_audio.clear();
472
473             for (unsigned int j=0;j<nb_audio;j++) {
474                 std::ostringstream newname;
475                 newname << "input_" << j;
476                 names_audio.push_back(newname.str());
477             }
478         }
479
480         nb_channels=nb_audio;
481         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
482
483         // construct the MIDI names
484         diceNameVector names_midi;
485         for (unsigned int j=0;j<nb_midi;j++) {
486             std::ostringstream newname;
487             newname << "midi_in_" << j;
488             names_midi.push_back(newname.str());
489         }
490
491         // construct the streamprocessor
492         Streaming::AmdtpReceiveStreamProcessor *p;
493         p=new Streaming::AmdtpReceiveStreamProcessor(
494                              m_p1394Service->getPort(),
495                              samplerate,
496                              nb_channels);
497
498         if(!p->init()) {
499             debugFatal("Could not initialize receive processor!\n");
500             delete p;
501             continue;
502         }
503
504         // add audio ports to the processor
505         for (unsigned int j=0;j<nb_audio;j++) {
506             diceChannelInfo channelInfo;
507             channelInfo.name=names_audio.at(j);
508             channelInfo.portType=ePT_Analog;
509             channelInfo.streamPosition=j;
510             channelInfo.streamLocation=0;
511
512             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
513                 debugError("Could not add channel %s to StreamProcessor\n",
514                     channelInfo.name.c_str());
515                 continue;
516             }
517         }
518
519         // add midi ports to the processor
520         for (unsigned int j=0;j<nb_midi;j++) {
521             diceChannelInfo channelInfo;
522             channelInfo.name=names_midi.at(j);
523             channelInfo.portType=ePT_MIDI;
524             channelInfo.streamPosition=nb_audio;
525             channelInfo.streamLocation=j;
526
527             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
528                 debugError("Could not add channel %s to StreamProcessor\n",
529                     channelInfo.name.c_str());
530                 continue;
531             }
532         }
533
534         // add the SP to the vector
535         m_receiveProcessors.push_back(p);
536     }
537
538     // prepare transmit SP's
539     for (unsigned int i=0;i<m_nb_rx;i++) {
540         fb_quadlet_t nb_audio;
541         fb_quadlet_t nb_midi;
542         unsigned int nb_channels=0;
543
544         if(!readTxReg(i, DICE_REGISTER_RX_NB_AUDIO_BASE, &nb_audio)) {
545             debugError("Could not read DICE_REGISTER_RX_NB_AUDIO_BASE register for ARX%u",i);
546             continue;
547         }
548         if(!readTxReg(i, DICE_REGISTER_RX_MIDI_BASE, &nb_midi)) {
549             debugError("Could not read DICE_REGISTER_RX_MIDI_BASE register for ARX%u",i);
550             continue;
551         }
552
553         // request the channel names
554         diceNameVector names_audio=getRxNameString(i);
555
556         if (names_audio.size() != nb_audio) {
557             debugWarning("The audio channel name vector is incorrect, using default names\n");
558             names_audio.clear();
559
560             for (unsigned int j=0;j<nb_audio;j++) {
561                 std::ostringstream newname;
562                 newname << "output_" << j;
563                 names_audio.push_back(newname.str());
564             }
565         }
566
567         nb_channels=nb_audio;
568         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
569
570         // construct the MIDI names
571         diceNameVector names_midi;
572         for (unsigned int j=0;j<nb_midi;j++) {
573             std::ostringstream newname;
574             newname << "midi_out_" << j;
575             names_midi.push_back(newname.str());
576         }
577
578         // construct the streamprocessor
579         Streaming::AmdtpTransmitStreamProcessor *p;
580         p=new Streaming::AmdtpTransmitStreamProcessor(
581                              m_p1394Service->getPort(),
582                              samplerate,
583                              nb_channels);
584
585         if(!p->init()) {
586             debugFatal("Could not initialize transmit processor!\n");
587             delete p;
588             continue;
589         }
590
591         // add audio ports to the processor
592         for (unsigned int j=0;j<nb_audio;j++) {
593             diceChannelInfo channelInfo;
594             channelInfo.name=names_audio.at(j);
595             channelInfo.portType=ePT_Analog;
596             channelInfo.streamPosition=j;
597             channelInfo.streamLocation=0;
598
599             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
600                 debugError("Could not add channel %s to StreamProcessor\n",
601                     channelInfo.name.c_str());
602                 continue;
603             }
604         }
605
606         // add midi ports to the processor
607         for (unsigned int j=0;j<nb_midi;j++) {
608             diceChannelInfo channelInfo;
609             channelInfo.name=names_midi.at(j);
610             channelInfo.portType=ePT_MIDI;
611             channelInfo.streamPosition=nb_audio;
612             channelInfo.streamLocation=j;
613
614             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
615                 debugError("Could not add channel %s to StreamProcessor\n",
616                     channelInfo.name.c_str());
617                 continue;
618             }
619         }
620
621         m_transmitProcessors.push_back(p);
622     }
623     return true;
624 }
625
626 bool
627 DiceAvDevice::addChannelToProcessor(
628     diceChannelInfo *channelInfo,
629     Streaming::StreamProcessor *processor,
630     Streaming::Port::E_Direction direction) {
631
632     std::string id=std::string("dev?");
633     if(!getOption("id", id)) {
634         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
635     }
636
637     std::ostringstream portname;
638     portname << id;
639     if(direction == Streaming::Port::E_Playback) {
640         portname << "p";
641     } else {
642         portname << "c";
643     }
644
645     portname << "_" << channelInfo->name;
646
647     Streaming::Port *p=NULL;
648     switch(channelInfo->portType) {
649     case ePT_Analog:
650         p=new Streaming::AmdtpAudioPort(
651                 portname.str(),
652                 direction,
653                 channelInfo->streamPosition,
654                 channelInfo->streamLocation,
655                 Streaming::AmdtpPortInfo::E_MBLA
656         );
657         break;
658
659     case ePT_MIDI:
660         p=new Streaming::AmdtpMidiPort(
661                 portname.str(),
662                 direction,
663                 channelInfo->streamPosition,
664                 channelInfo->streamLocation,
665                 Streaming::AmdtpPortInfo::E_Midi
666         );
667
668         break;
669     default:
670     // unsupported
671         break;
672     }
673
674     if (!p) {
675         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str());
676     } else {
677
678         if (!processor->addPort(p)) {
679             debugWarning("Could not register port with stream processor\n");
680             return false;
681         }
682     }
683
684     return true;
685 }
686
687 bool
688 DiceAvDevice::lock() {
689     fb_octlet_t result;
690
691     debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n",
692         m_model->vendor_name, m_model->model_name, getNodeId());
693
694     // get a notifier to handle device notifications
695     nodeaddr_t notify_address;
696     notify_address = m_p1394Service->findFreeARMBlock(
697                         DICE_NOTIFIER_BASE_ADDRESS,
698                         DICE_NOTIFIER_BLOCK_LENGTH,
699                         DICE_NOTIFIER_BLOCK_LENGTH);
700
701     if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) {
702         debugError("Could not find free ARM block for notification\n");
703         return false;
704     }
705
706     m_notifier=new DiceAvDevice::DiceNotifier(this, notify_address);
707
708     if(!m_notifier) {
709         debugError("Could not allocate notifier\n");
710         return false;
711     }
712
713     if (!m_p1394Service->registerARMHandler(m_notifier)) {
714         debugError("Could not register notifier\n");
715         delete m_notifier;
716         m_notifier=NULL;
717         return false;
718     }
719
720     // register this notifier
721     fb_nodeaddr_t addr = DICE_REGISTER_BASE
722                        + m_global_reg_offset
723                        + DICE_REGISTER_GLOBAL_OWNER;
724
725     // registry offsets should always be smaller than 0x7FFFFFFF
726     // because otherwise base + offset > 64bit
727     if(m_global_reg_offset & 0x80000000) {
728         debugError("register offset not initialized yet\n");
729         return false;
730     }
731
732     fb_nodeaddr_t swap_value = ((0xFFC0) | m_p1394Service->getLocalNodeId());
733     swap_value = swap_value << 48;
734     swap_value |= m_notifier->getStart();
735
736     if (!m_p1394Service->lockCompareSwap64(  getNodeId() | 0xFFC0, addr, DICE_OWNER_NO_OWNER,
737                                        swap_value, &result )) {
738         debugWarning("Could not register ourselves as device owner\n");
739         return false;
740     }
741
742     if (result != DICE_OWNER_NO_OWNER) {
743         debugWarning("Could not register ourselves as device owner, unexpected register value: 0x%016llX\n", result);
744         return false;
745     }
746
747     return true;
748 }
749
750
751 bool
752 DiceAvDevice::unlock() {
753     fb_octlet_t result;
754
755     if(!m_notifier) {
756         debugWarning("Request to unlock, but no notifier present!\n");
757         return false;
758     }
759
760     fb_nodeaddr_t addr = DICE_REGISTER_BASE
761                        + m_global_reg_offset
762                        + DICE_REGISTER_GLOBAL_OWNER;
763
764     // registry offsets should always be smaller than 0x7FFFFFFF
765     // because otherwise base + offset > 64bit
766     if(m_global_reg_offset & 0x80000000) {
767         debugError("register offset not initialized yet\n");
768         return false;
769     }
770
771     fb_nodeaddr_t compare_value = ((0xFFC0) | m_p1394Service->getLocalNodeId());
772     compare_value <<= 48;
773     compare_value |= m_notifier->getStart();
774
775     if (!m_p1394Service->lockCompareSwap64(  getNodeId() | 0xFFC0, addr, compare_value,
776                                        DICE_OWNER_NO_OWNER, &result )) {
777         debugWarning("Could not unregister ourselves as device owner\n");
778         return false;
779     }
780
781     m_p1394Service->unregisterARMHandler(m_notifier);
782     delete m_notifier;
783     m_notifier=NULL;
784
785     return true;
786 }
787
788 bool
789 DiceAvDevice::enableStreaming() {
790     return enableIsoStreaming();
791 }
792
793 bool
794 DiceAvDevice::disableStreaming() {
795     return disableIsoStreaming();
796 }
797
798 int
799 DiceAvDevice::getStreamCount() {
800     return m_receiveProcessors.size() + m_transmitProcessors.size();
801 }
802
803 Streaming::StreamProcessor *
804 DiceAvDevice::getStreamProcessorByIndex(int i) {
805
806     if (i<(int)m_receiveProcessors.size()) {
807         return m_receiveProcessors.at(i);
808     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
809         return m_transmitProcessors.at(i-m_receiveProcessors.size());
810     }
811
812     return NULL;
813 }
814
815 bool
816 DiceAvDevice::startStreamByIndex(int i) {
817
818     if (isIsoStreamingEnabled()) {
819         debugError("Cannot start streams while streaming is enabled\n");
820         return false;
821     }
822
823     if (i<(int)m_receiveProcessors.size()) {
824         int n=i;
825         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
826
827         // allocate ISO channel
828         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
829         if(isochannel<0) {
830             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
831             return false;
832         }
833         p->setChannel(isochannel);
834
835         fb_quadlet_t reg_isoch;
836         // check value of ISO_CHANNEL register
837         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
838             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
839             p->setChannel(-1);
840             deallocateIsoChannel(isochannel);
841             return false;
842         }
843         if(reg_isoch != 0xFFFFFFFFUL) {
844             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ATX %d\n", reg_isoch, n);
845             p->setChannel(-1);
846             deallocateIsoChannel(isochannel);
847             return false;
848         }
849
850         // write value of ISO_CHANNEL register
851         reg_isoch=isochannel;
852         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
853             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
854             p->setChannel(-1);
855             deallocateIsoChannel(isochannel);
856             return false;
857         }
858
859         return true;
860
861     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
862         int n=i-m_receiveProcessors.size();
863         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
864
865         // allocate ISO channel
866         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
867         if(isochannel<0) {
868             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
869             return false;
870         }
871         p->setChannel(isochannel);
872
873         fb_quadlet_t reg_isoch;
874         // check value of ISO_CHANNEL register
875         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
876             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
877             p->setChannel(-1);
878             deallocateIsoChannel(isochannel);
879             return false;
880         }
881         if(reg_isoch != 0xFFFFFFFFUL) {
882             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ARX %d\n", reg_isoch, n);
883             p->setChannel(-1);
884             deallocateIsoChannel(isochannel);
885             return false;
886         }
887
888         // write value of ISO_CHANNEL register
889         reg_isoch=isochannel;
890         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
891             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
892             p->setChannel(-1);
893             deallocateIsoChannel(isochannel);
894             return false;
895         }
896
897         return true;
898     }
899
900     debugError("SP index %d out of range!\n",i);
901
902     return false;
903 }
904
905 bool
906 DiceAvDevice::stopStreamByIndex(int i) {
907
908     if (isIsoStreamingEnabled()) {
909         debugError("Cannot stop streams while streaming is enabled\n");
910         return false;
911     }
912
913     if (i<(int)m_receiveProcessors.size()) {
914         int n=i;
915         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
916         unsigned int isochannel=p->getChannel();
917
918         fb_quadlet_t reg_isoch;
919         // check value of ISO_CHANNEL register
920         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
921             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
922             return false;
923         }
924         if(reg_isoch != isochannel) {
925             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ATX %d\n", isochannel, reg_isoch, n);
926             return false;
927         }
928
929         // write value of ISO_CHANNEL register
930         reg_isoch=0xFFFFFFFFUL;
931         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
932             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
933             return false;
934         }
935
936         // deallocate ISO channel
937         if(!deallocateIsoChannel(isochannel)) {
938             debugError("Could not deallocate iso channel for SP %d (ATX %d)\n",i,n);
939             return false;
940         }
941
942         p->setChannel(-1);
943         return true;
944
945     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
946         int n=i-m_receiveProcessors.size();
947         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
948
949         unsigned int isochannel=p->getChannel();
950
951         fb_quadlet_t reg_isoch;
952         // check value of ISO_CHANNEL register
953         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
954             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
955             return false;
956         }
957         if(reg_isoch != isochannel) {
958             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ARX %d\n", isochannel, reg_isoch, n);
959             return false;
960         }
961
962         // write value of ISO_CHANNEL register
963         reg_isoch=0xFFFFFFFFUL;
964         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
965             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
966             return false;
967         }
968
969         // deallocate ISO channel
970         if(!deallocateIsoChannel(isochannel)) {
971             debugError("Could not deallocate iso channel for SP %d (ARX %d)\n",i,n);
972             return false;
973         }
974
975         p->setChannel(-1);
976         return true;
977     }
978
979     debugError("SP index %d out of range!\n",i);
980
981     return false;
982 }
983
984 // helper routines
985
986 // allocate ISO resources for the SP's
987 int DiceAvDevice::allocateIsoChannel(unsigned int packet_size) {
988     unsigned int bandwidth=8+packet_size;
989
990     int ch=m_p1394Service->allocateIsoChannelGeneric(bandwidth);
991
992     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
993         ch, bandwidth);
994
995     return ch;
996 }
997 // deallocate ISO resources
998 bool DiceAvDevice::deallocateIsoChannel(int channel) {
999     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
1000     return m_p1394Service->freeIsoChannel(channel);
1001 }
1002
1003 bool
1004 DiceAvDevice::enableIsoStreaming() {
1005     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_ENABLE);
1006 }
1007
1008 bool
1009 DiceAvDevice::disableIsoStreaming() {
1010     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_DISABLE);
1011 }
1012
1013 bool
1014 DiceAvDevice::isIsoStreamingEnabled() {
1015     fb_quadlet_t result;
1016     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &result);
1017     // I don't know what exactly is 'enable',
1018     // but disable is definately == 0
1019     return (result != DICE_ISOSTREAMING_DISABLE);
1020 }
1021
1022 /**
1023  * @brief performs a masked bit register equals 0 check on the global parameter space
1024  * @return true if readGlobalReg(offset) & mask == 0
1025  */
1026 bool
1027 DiceAvDevice::maskedCheckZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1028     fb_quadlet_t result;
1029     readGlobalReg(offset, &result);
1030     return ((result & mask) == 0);
1031 }
1032 /**
1033  * @brief performs a masked bit register not equal to 0 check on the global parameter space
1034  * @return true if readGlobalReg(offset) & mask != 0
1035  */
1036 bool
1037 DiceAvDevice::maskedCheckNotZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
1038     return !maskedCheckZeroGlobalReg(offset, mask);
1039 }
1040
1041 DiceAvDevice::diceNameVector
1042 DiceAvDevice::getTxNameString(unsigned int i) {
1043     diceNameVector names;
1044     char namestring[DICE_TX_NAMES_SIZE+1];
1045
1046     if (!readTxRegBlock(i, DICE_REGISTER_TX_NAMES_BASE,
1047                         (fb_quadlet_t *)namestring, DICE_TX_NAMES_SIZE)) {
1048         debugError("Could not read TX name string \n");
1049         return names;
1050     }
1051
1052     namestring[DICE_TX_NAMES_SIZE]='\0';
1053     return splitNameString(std::string(namestring));
1054 }
1055
1056 DiceAvDevice::diceNameVector
1057 DiceAvDevice::getRxNameString(unsigned int i) {
1058     diceNameVector names;
1059     char namestring[DICE_RX_NAMES_SIZE+1];
1060
1061     if (!readRxRegBlock(i, DICE_REGISTER_RX_NAMES_BASE,
1062                         (fb_quadlet_t *)namestring, DICE_RX_NAMES_SIZE)) {
1063         debugError("Could not read RX name string \n");
1064         return names;
1065     }
1066
1067     namestring[DICE_RX_NAMES_SIZE]='\0';
1068     return splitNameString(std::string(namestring));
1069 }
1070
1071 DiceAvDevice::diceNameVector
1072 DiceAvDevice::getClockSourceNameString() {
1073     diceNameVector names;
1074     char namestring[DICE_CLOCKSOURCENAMES_SIZE+1];
1075
1076     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_CLOCKSOURCENAMES,
1077                         (fb_quadlet_t *)namestring, DICE_CLOCKSOURCENAMES_SIZE)) {
1078         debugError("Could not read CLOCKSOURCE name string \n");
1079         return names;
1080     }
1081
1082     namestring[DICE_CLOCKSOURCENAMES_SIZE]='\0';
1083     return splitNameString(std::string(namestring));
1084 }
1085
1086 std::string
1087 DiceAvDevice::getDeviceNickName() {
1088     char namestring[DICE_NICK_NAME_SIZE+1];
1089
1090     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_NICK_NAME,
1091                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE)) {
1092         debugError("Could not read nickname string \n");
1093         return std::string("(unknown)");
1094     }
1095
1096     namestring[DICE_NICK_NAME_SIZE]='\0';
1097     return std::string(namestring);
1098 }
1099
1100 DiceAvDevice::diceNameVector
1101 DiceAvDevice::splitNameString(std::string in) {
1102     diceNameVector names;
1103
1104     // find the end of the string
1105     unsigned int end=in.find(string("\\\\"));
1106     // cut the end
1107     in=in.substr(0,end);
1108
1109     unsigned int cut;
1110     while( (cut = in.find(string("\\"))) != in.npos ) {
1111         if(cut > 0) {
1112             names.push_back(in.substr(0,cut));
1113         }
1114         in = in.substr(cut+1);
1115     }
1116     if(in.length() > 0) {
1117         names.push_back(in);
1118     }
1119     return names;
1120 }
1121
1122
1123 // I/O routines
1124 bool
1125 DiceAvDevice::initIoFunctions() {
1126
1127     // offsets and sizes are returned in quadlets, but we use byte values
1128
1129     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_OFF, &m_global_reg_offset)) {
1130         debugError("Could not initialize m_global_reg_offset\n");
1131         return false;
1132     }
1133     m_global_reg_offset*=4;
1134
1135     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_SZ, &m_global_reg_size)) {
1136         debugError("Could not initialize m_global_reg_size\n");
1137         return false;
1138     }
1139     m_global_reg_size*=4;
1140
1141     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_OFF, &m_tx_reg_offset)) {
1142         debugError("Could not initialize m_tx_reg_offset\n");
1143         return false;
1144     }
1145     m_tx_reg_offset*=4;
1146
1147     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_SZ, &m_tx_reg_size)) {
1148         debugError("Could not initialize m_tx_reg_size\n");
1149         return false;
1150     }
1151     m_tx_reg_size*=4;
1152
1153     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_OFF, &m_rx_reg_offset)) {
1154         debugError("Could not initialize m_rx_reg_offset\n");
1155         return false;
1156     }
1157     m_rx_reg_offset*=4;
1158
1159     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_SZ, &m_rx_reg_size)) {
1160         debugError("Could not initialize m_rx_reg_size\n");
1161         return false;
1162     }
1163     m_rx_reg_size*=4;
1164
1165     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_OFF, &m_unused1_reg_offset)) {
1166         debugError("Could not initialize m_unused1_reg_offset\n");
1167         return false;
1168     }
1169     m_unused1_reg_offset*=4;
1170
1171     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_SZ, &m_unused1_reg_size)) {
1172         debugError("Could not initialize m_unused1_reg_size\n");
1173         return false;
1174     }
1175     m_unused1_reg_size*=4;
1176
1177     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_OFF, &m_unused2_reg_offset)) {
1178         debugError("Could not initialize m_unused2_reg_offset\n");
1179         return false;
1180     }
1181     m_unused2_reg_offset*=4;
1182
1183     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_SZ, &m_unused2_reg_size)) {
1184         debugError("Could not initialize m_unused2_reg_size\n");
1185         return false;
1186     }
1187     m_unused2_reg_size*=4;
1188
1189     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_NB_TX, &m_nb_tx)) {
1190         debugError("Could not initialize m_nb_tx\n");
1191         return false;
1192     }
1193     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_SZ_TX, &m_tx_size)) {
1194         debugError("Could not initialize m_tx_size\n");
1195         return false;
1196     }
1197     m_tx_size*=4;
1198
1199     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_NB_RX, &m_nb_rx)) {
1200         debugError("Could not initialize m_nb_rx\n");
1201         return false;
1202     }
1203     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
1204         debugError("Could not initialize m_rx_size\n");
1205         return false;
1206     }
1207     m_rx_size*=4;
1208
1209     debugOutput(DEBUG_LEVEL_VERBOSE,"DICE Parameter Space info:\n");
1210     debugOutput(DEBUG_LEVEL_VERBOSE," Global  : offset=%04X size=%04d\n", m_global_reg_offset, m_global_reg_size);
1211     debugOutput(DEBUG_LEVEL_VERBOSE," TX      : offset=%04X size=%04d\n", m_tx_reg_offset, m_tx_reg_size);
1212     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_tx, m_tx_size);
1213     debugOutput(DEBUG_LEVEL_VERBOSE," RX      : offset=%04X size=%04d\n", m_rx_reg_offset, m_rx_reg_size);
1214     debugOutput(DEBUG_LEVEL_VERBOSE,"               nb=%4d size=%04d\n", m_nb_rx, m_rx_size);
1215     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED1 : offset=%04X size=%04d\n", m_unused1_reg_offset, m_unused1_reg_size);
1216     debugOutput(DEBUG_LEVEL_VERBOSE," UNUSED2 : offset=%04X size=%04d\n", m_unused2_reg_offset, m_unused2_reg_size);
1217
1218     return true;
1219 }
1220
1221 bool
1222 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1223     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
1224
1225     if(offset >= DICE_INVALID_OFFSET) {
1226         debugError("invalid offset: 0x%016llX\n", offset);
1227         return false;
1228     }
1229
1230     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1231     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1232
1233     if(!m_p1394Service->read_quadlet( nodeId, addr, result ) ) {
1234         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1235         return false;
1236     }
1237
1238     *result=ntohl(*result);
1239
1240     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1241
1242     return true;
1243 }
1244
1245 bool
1246 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1247     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
1248         offset, data);
1249
1250     if(offset >= DICE_INVALID_OFFSET) {
1251         debugError("invalid offset: 0x%016llX\n", offset);
1252         return false;
1253     }
1254
1255     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1256     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1257
1258     if(!m_p1394Service->write_quadlet( nodeId, addr, htonl(data) ) ) {
1259         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1260         return false;
1261     }
1262     return true;
1263 }
1264
1265 bool
1266 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1267     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1268         offset, length);
1269
1270     if(offset >= DICE_INVALID_OFFSET) {
1271         debugError("invalid offset: 0x%016llX\n", offset);
1272         return false;
1273     }
1274
1275     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1276     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1277
1278     if(!m_p1394Service->read( nodeId, addr, length/4, data ) ) {
1279         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1280         return false;
1281     }
1282
1283     for(unsigned int i=0;i<length/4;i++) {
1284         *(data+i)=ntohl(*(data+i));
1285     }
1286
1287     return true;
1288 }
1289
1290 bool
1291 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1292     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
1293         offset, length);
1294
1295     if(offset >= DICE_INVALID_OFFSET) {
1296         debugError("invalid offset: 0x%016llX\n", offset);
1297         return false;
1298     }
1299
1300     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1301     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
1302
1303     fb_quadlet_t data_out[length/4];
1304
1305     for(unsigned int i=0;i<length/4;i++) {
1306         data_out[i]=ntohl(*(data+i));
1307     }
1308
1309     if(!m_p1394Service->write( nodeId, addr, length/4, data_out ) ) {
1310         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1311         return false;
1312     }
1313
1314     return true;
1315 }
1316
1317 bool
1318 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1319     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1320
1321     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1322     return readReg(m_global_reg_offset + offset_gl, result);
1323 }
1324
1325 bool
1326 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1327     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n",
1328         offset, data);
1329
1330     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1331     return writeReg(m_global_reg_offset + offset_gl, data);
1332 }
1333
1334 bool
1335 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1336     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1337         offset, length);
1338
1339     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1340     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1341 }
1342
1343 bool
1344 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1345     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1346         offset, length);
1347
1348     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1349     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1350 }
1351
1352 fb_nodeaddr_t
1353 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1354
1355     // registry offsets should always be smaller than 0x7FFFFFFF
1356     // because otherwise base + offset > 64bit
1357     if(m_global_reg_offset & 0x80000000) {
1358         debugError("register offset not initialized yet\n");
1359         return DICE_INVALID_OFFSET;
1360     }
1361     // out-of-range check
1362     if(offset+length > m_global_reg_offset+m_global_reg_size) {
1363         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1364         return DICE_INVALID_OFFSET;
1365     }
1366
1367     return offset;
1368 }
1369
1370 bool
1371 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1372     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1373
1374     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1375     return readReg(m_tx_reg_offset + offset_tx, result);
1376 }
1377
1378 bool
1379 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1380     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1381         i, offset, data);
1382
1383     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1384     return writeReg(m_tx_reg_offset + offset_tx, data);
1385 }
1386
1387 bool
1388 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1389     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1390         offset, length);
1391
1392     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1393     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1394 }
1395
1396 bool
1397 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1398     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1399         offset, length);
1400
1401     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1402     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1403 }
1404
1405 fb_nodeaddr_t
1406 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1407     // registry offsets should always be smaller than 0x7FFFFFFF
1408     // because otherwise base + offset > 64bit
1409     if(m_tx_reg_offset & 0x80000000) {
1410         debugError("register offset not initialized yet\n");
1411         return DICE_INVALID_OFFSET;
1412     }
1413     if(m_nb_tx & 0x80000000) {
1414         debugError("m_nb_tx not initialized yet\n");
1415         return DICE_INVALID_OFFSET;
1416     }
1417     if(m_tx_size & 0x80000000) {
1418         debugError("m_tx_size not initialized yet\n");
1419         return DICE_INVALID_OFFSET;
1420     }
1421     if(i >= m_nb_tx) {
1422         debugError("TX index out of range\n");
1423         return DICE_INVALID_OFFSET;
1424     }
1425
1426     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1427
1428     // out-of-range check
1429     if(offset_tx + length > m_tx_reg_offset+4+m_tx_reg_size*m_nb_tx) {
1430         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1431         return DICE_INVALID_OFFSET;
1432     }
1433
1434     return offset_tx;
1435 }
1436
1437 bool
1438 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1439     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1440
1441     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1442     return readReg(m_rx_reg_offset + offset_rx, result);
1443 }
1444
1445 bool
1446 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1447     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n",
1448         offset, data);
1449
1450     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1451     return writeReg(m_rx_reg_offset + offset_rx, data);
1452 }
1453
1454 bool
1455 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1456     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1457         offset, length);
1458
1459     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1460     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1461 }
1462
1463 bool
1464 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1465     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1466         offset, length);
1467
1468     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1469     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1470 }
1471
1472 fb_nodeaddr_t
1473 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1474     // registry offsets should always be smaller than 0x7FFFFFFF
1475     // because otherwise base + offset > 64bit
1476     if(m_rx_reg_offset & 0x80000000) {
1477         debugError("register offset not initialized yet\n");
1478         return DICE_INVALID_OFFSET;
1479     }
1480     if(m_nb_rx & 0x80000000) {
1481         debugError("m_nb_rx not initialized yet\n");
1482         return DICE_INVALID_OFFSET;
1483     }
1484     if(m_rx_size & 0x80000000) {
1485         debugError("m_rx_size not initialized yet\n");
1486         return DICE_INVALID_OFFSET;
1487     }
1488     if(i >= m_nb_rx) {
1489         debugError("RX index out of range\n");
1490         return DICE_INVALID_OFFSET;
1491     }
1492
1493     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1494
1495     // out-of-range check
1496     if(offset_rx + length > m_rx_reg_offset+4+m_rx_reg_size*m_nb_rx) {
1497         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1498         return DICE_INVALID_OFFSET;
1499     }
1500     return offset_rx;
1501 }
1502
1503
1504 // the notifier
1505
1506 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1507  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1508               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1509               RAW1394_ARM_WRITE, 0)
1510  , m_dicedevice(d)
1511 {
1512
1513 }
1514
1515 DiceAvDevice::DiceNotifier::~DiceNotifier()
1516 {
1517
1518 }
1519
1520 }
Note: See TracBrowser for help on using the browser.