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

Revision 723, 49.3 kB (checked in by ppalmers, 14 years ago)

fix problem where receiving multiple streams doesn't work

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