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

Revision 436, 49.7 kB (checked in by pieterpalmers, 16 years ago)

- fixed verbose level setting
- debugged DICE code, works with EVM

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