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

Revision 587, 49.0 kB (checked in by ppalmers, 16 years ago)

- moved all vendor id's to one include file
- introduced the framework for the ECHO FireWorks? platform

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