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

Revision 705, 49.4 kB (checked in by ppalmers, 15 years ago)

restructure the streaming directory

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