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

Revision 433, 40.9 kB (checked in by pieterpalmers, 17 years ago)

- dice support

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 #warning DICE support is currently untested
21
22 #include "dice/dice_avdevice.h"
23 #include "dice/dice_defines.h"
24
25 #include "libieee1394/configrom.h"
26 #include "libieee1394/ieee1394service.h"
27
28 #include "libstreaming/AmdtpStreamProcessor.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
42 namespace Dice {
43
44 // to define the supported devices
45 static VendorModelEntry supportedDeviceList[] =
46 {
47     {0x00000000, 0x0000, "DICE VENDOR", "XXX"},
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_configRom->getNodeVendorId();
110     unsigned int modelId = m_configRom->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     bool supported=false;
174     fb_quadlet_t select=0x0;
175    
176     switch ( samplingFrequency ) {
177     default:
178     case eSF_22050Hz:
179     case eSF_24000Hz:
180         supported=false;
181         break;
182     case eSF_32000Hz:
183         supported=maskedCheckNotZeroGlobalReg(
184                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
185                     DICE_CLOCKCAP_RATE_32K);
186         select=DICE_RATE_32K;
187         break;
188     case eSF_44100Hz:
189         supported=maskedCheckNotZeroGlobalReg(
190                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
191                     DICE_CLOCKCAP_RATE_44K1);
192         select=DICE_RATE_44K1;
193         break;
194     case eSF_48000Hz:
195         supported=maskedCheckNotZeroGlobalReg(
196                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
197                     DICE_CLOCKCAP_RATE_48K);
198         select=DICE_RATE_48K;
199         break;
200     case eSF_88200Hz:
201         supported=maskedCheckNotZeroGlobalReg(
202                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
203                     DICE_CLOCKCAP_RATE_88K2);
204         select=DICE_RATE_88K2;
205         break;
206     case eSF_96000Hz:
207         supported=maskedCheckNotZeroGlobalReg(
208                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
209                     DICE_CLOCKCAP_RATE_96K);
210         select=DICE_RATE_96K;
211         break;
212     case eSF_176400Hz:
213         supported=maskedCheckNotZeroGlobalReg(
214                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
215                     DICE_CLOCKCAP_RATE_176K4);
216         select=DICE_RATE_176K4;
217         break;
218     case eSF_192000Hz:
219         supported=maskedCheckNotZeroGlobalReg(
220                     DICE_REGISTER_GLOBAL_CLOCKCAPABILITIES,
221                     DICE_CLOCKCAP_RATE_192K);
222         select=DICE_RATE_192K;
223         break;
224     }
225
226     if (!supported) {
227         debugWarning("Unsupported sample rate: %d\n", convertESamplingFrequency(samplingFrequency));
228         return false;
229     }
230
231     if (isIsoStreamingEnabled()) {
232         debugError("Cannot change samplerate while streaming is enabled\n");
233         return false;
234     }
235    
236     fb_quadlet_t clockreg;
237     if (!readGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, &clockreg)) {
238         debugError("Could not read CLOCK_SELECT register\n");
239         return false;
240     }
241    
242     clockreg = DICE_SET_RATE(clockreg, select);
243    
244     if (!writeGlobalReg(DICE_REGISTER_GLOBAL_CLOCK_SELECT, clockreg)) {
245         debugError("Could not write CLOCK_SELECT register\n");
246         return false;
247     }
248
249     return true;
250 }
251
252 void
253 DiceAvDevice::showDevice() const
254 {
255     debugOutput(DEBUG_LEVEL_VERBOSE,
256         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
257         m_nodeId);
258 }
259
260 // NOTE on bandwidth calculation
261 // FIXME: The bandwidth allocation calculation can probably be
262 // refined somewhat since this is currently based on a rudimentary
263 // understanding of the iso protocol.
264 // Currently we assume the following.
265 //   * Ack/iso gap = 0.05 us
266 //   * DATA_PREFIX = 0.16 us
267 //   * DATA_END    = 0.26 us
268 // These numbers are the worst-case figures given in the ieee1394
269 // standard.  This gives approximately 0.5 us of overheads per
270 // packet - around 25 bandwidth allocation units (from the ieee1394
271 // standard 1 bandwidth allocation unit is 125/6144 us).  We further
272 // assume the device is running at S400 (which it should be) so one
273 // allocation unit is equivalent to 1 transmitted byte; thus the
274 // bandwidth allocation required for the packets themselves is just
275 // the size of the packet.
276 bool
277 DiceAvDevice::prepare() {
278     int samplerate=getSamplingFrequency();
279
280     // prepare receive SP's
281     for (unsigned int i=0;i<m_nb_tx;i++) {
282         fb_quadlet_t nb_audio;
283         fb_quadlet_t nb_midi;
284         unsigned int nb_channels=0;
285        
286         if(!readTxReg(i, DICE_REGISTER_TX_NB_AUDIO_BASE, &nb_audio)) {
287             debugError("Could not read DICE_REGISTER_TX_NB_AUDIO_BASE register for ATX%u",i);
288             continue;
289         }
290         if(!readTxReg(i, DICE_REGISTER_TX_MIDI_BASE, &nb_midi)) {
291             debugError("Could not read DICE_REGISTER_TX_MIDI_BASE register for ATX%u",i);
292             continue;
293         }
294        
295         // request the channel names
296         diceNameVector names_audio=getTxNameString(i);
297        
298         if (names_audio.size() != nb_audio) {
299             debugWarning("The audio channel name vector is incorrect, using default names\n");
300             names_audio.clear();
301            
302             for (unsigned int j=0;j<nb_audio;j++) {
303                 std::ostringstream newname;
304                 newname << "input_" << j;
305                 names_audio.push_back(newname.str());
306             }
307         }
308        
309         nb_channels=nb_audio;
310         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
311        
312         // construct the MIDI names
313         diceNameVector names_midi;
314         for (unsigned int j=0;j<nb_midi;j++) {
315             std::ostringstream newname;
316             newname << "midi_in_" << j;
317             names_midi.push_back(newname.str());
318         }
319        
320         // construct the streamprocessor
321         Streaming::AmdtpReceiveStreamProcessor *p;
322         p=new Streaming::AmdtpReceiveStreamProcessor(
323                              m_p1394Service->getPort(),
324                              samplerate,
325                              nb_channels);
326
327         if(!p->init()) {
328             debugFatal("Could not initialize receive processor!\n");
329             delete p;
330             continue;
331         }
332
333         // add audio ports to the processor
334         for (unsigned int j=0;j<nb_audio;j++) {
335             diceChannelInfo channelInfo;
336             channelInfo.name=names_audio.at(i);
337             channelInfo.portType=ePT_Analog;
338             channelInfo.streamPosition=j;
339             channelInfo.streamLocation=0;
340
341             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
342                 debugError("Could not add channel %s to StreamProcessor\n",
343                     channelInfo.name.c_str());
344                 continue;
345             }
346         }
347        
348         // add midi ports to the processor
349         for (unsigned int j=0;j<nb_midi;j++) {
350             diceChannelInfo channelInfo;
351             channelInfo.name=names_midi.at(i);
352             channelInfo.portType=ePT_MIDI;
353             channelInfo.streamPosition=nb_audio;
354             channelInfo.streamLocation=j;
355
356             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Capture)) {
357                 debugError("Could not add channel %s to StreamProcessor\n",
358                     channelInfo.name.c_str());
359                 continue;
360             }
361         }
362        
363         // add the SP to the vector
364         m_receiveProcessors.push_back(p);
365     }
366    
367     // prepare transmit SP's
368     for (unsigned int i=0;i<m_nb_rx;i++) {
369         fb_quadlet_t nb_audio;
370         fb_quadlet_t nb_midi;
371         unsigned int nb_channels=0;
372        
373         if(!readTxReg(i, DICE_REGISTER_RX_NB_AUDIO_BASE, &nb_audio)) {
374             debugError("Could not read DICE_REGISTER_RX_NB_AUDIO_BASE register for ARX%u",i);
375             continue;
376         }
377         if(!readTxReg(i, DICE_REGISTER_RX_MIDI_BASE, &nb_midi)) {
378             debugError("Could not read DICE_REGISTER_RX_MIDI_BASE register for ARX%u",i);
379             continue;
380         }
381        
382         // request the channel names
383         diceNameVector names_audio=getRxNameString(i);
384        
385         if (names_audio.size() != nb_audio) {
386             debugWarning("The audio channel name vector is incorrect, using default names\n");
387             names_audio.clear();
388            
389             for (unsigned int j=0;j<nb_audio;j++) {
390                 std::ostringstream newname;
391                 newname << "output_" << j;
392                 names_audio.push_back(newname.str());
393             }
394         }
395        
396         nb_channels=nb_audio;
397         if(nb_midi) nb_channels += 1; // midi-muxed counts as one
398        
399         // construct the MIDI names
400         diceNameVector names_midi;
401         for (unsigned int j=0;j<nb_midi;j++) {
402             std::ostringstream newname;
403             newname << "midi_out_" << j;
404             names_midi.push_back(newname.str());
405         }
406        
407         // construct the streamprocessor
408         Streaming::AmdtpTransmitStreamProcessor *p;
409         p=new Streaming::AmdtpTransmitStreamProcessor(
410                              m_p1394Service->getPort(),
411                              samplerate,
412                              nb_channels);
413
414         if(!p->init()) {
415             debugFatal("Could not initialize transmit processor!\n");
416             delete p;
417             continue;
418         }
419
420         // add audio ports to the processor
421         for (unsigned int j=0;j<nb_audio;j++) {
422             diceChannelInfo channelInfo;
423             channelInfo.name=names_audio.at(i);
424             channelInfo.portType=ePT_Analog;
425             channelInfo.streamPosition=j;
426             channelInfo.streamLocation=0;
427
428             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
429                 debugError("Could not add channel %s to StreamProcessor\n",
430                     channelInfo.name.c_str());
431                 continue;
432             }
433         }
434        
435         // add midi ports to the processor
436         for (unsigned int j=0;j<nb_midi;j++) {
437             diceChannelInfo channelInfo;
438             channelInfo.name=names_midi.at(i);
439             channelInfo.portType=ePT_MIDI;
440             channelInfo.streamPosition=nb_audio;
441             channelInfo.streamLocation=j;
442
443             if (!addChannelToProcessor(&channelInfo, p, Streaming::Port::E_Playback)) {
444                 debugError("Could not add channel %s to StreamProcessor\n",
445                     channelInfo.name.c_str());
446                 continue;
447             }
448         }
449        
450         m_transmitProcessors.push_back(p);
451     }
452     return true;
453 }
454
455 bool
456 DiceAvDevice::addChannelToProcessor(
457     diceChannelInfo *channelInfo,
458     Streaming::StreamProcessor *processor,
459     Streaming::Port::E_Direction direction) {
460    
461     std::string id=std::string("dev?");
462     if(!getOption("id", id)) {
463         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
464     }
465
466     std::ostringstream portname;
467     portname << id << "_" << channelInfo->name;
468
469     Streaming::Port *p=NULL;
470     switch(channelInfo->portType) {
471     case ePT_Analog:
472         p=new Streaming::AmdtpAudioPort(
473                 portname.str(),
474                 direction,
475                 channelInfo->streamPosition,
476                 channelInfo->streamLocation,
477                 Streaming::AmdtpPortInfo::E_MBLA
478         );
479         break;
480
481     case ePT_MIDI:
482         p=new Streaming::AmdtpMidiPort(
483                 portname.str(),
484                 direction,
485                 channelInfo->streamPosition,
486                 channelInfo->streamLocation,
487                 Streaming::AmdtpPortInfo::E_Midi
488         );
489
490         break;
491     default:
492     // unsupported
493         break;
494     }
495
496     if (!p) {
497         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str());
498     } else {
499
500         if (!processor->addPort(p)) {
501             debugWarning("Could not register port with stream processor\n");
502             return false;
503         }
504     }
505
506     return true;
507 }
508
509 bool
510 DiceAvDevice::lock() {
511     fb_octlet_t result;
512    
513     debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n",
514         m_model->vendor_name, m_model->model_name, m_nodeId);
515        
516     // get a notifier to handle device notifications
517     nodeaddr_t notify_address;
518     notify_address = m_p1394Service->findFreeARMBlock(
519                         DICE_NOTIFIER_BASE_ADDRESS,
520                         DICE_NOTIFIER_BLOCK_LENGTH,
521                         DICE_NOTIFIER_BLOCK_LENGTH);
522    
523     if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) {
524         debugError("Could not find free ARM block for notification\n");
525         return false;
526     }
527    
528     m_notifier=new DiceAvDevice::DiceNotifier(this, notify_address);
529    
530     if(!m_notifier) {
531         debugError("Could not allocate notifier\n");
532         return false;
533     }
534    
535     if (!m_p1394Service->registerARMHandler(m_notifier)) {
536         debugError("Could not register notifier\n");
537         delete m_notifier;
538         m_notifier=NULL;
539         return false;
540     }
541
542     // register this notifier
543     fb_nodeaddr_t addr = DICE_REGISTER_BASE
544                        + m_global_reg_offset
545                        + DICE_REGISTER_GLOBAL_OWNER;
546
547     // registry offsets should always be smaller than 0x7FFFFFFF
548     // because otherwise base + offset > 64bit
549     if(m_global_reg_offset & 0x80000000) {
550         debugError("register offset not initialized yet\n");
551         return false;
552     }
553    
554     fb_nodeaddr_t swap_value = ((0xFFC0) | m_p1394Service->getLocalNodeId()) << 24;
555     swap_value |= m_notifier->getStart();
556    
557     if (!m_p1394Service->lockCompareSwap64(  m_nodeId, addr, DICE_OWNER_NO_OWNER,
558                                        swap_value, &result )) {
559         debugWarning("Could not register ourselves as device owner\n");
560     }
561
562     return true;
563 }
564
565
566 bool
567 DiceAvDevice::unlock() {
568     fb_octlet_t result;
569    
570     if(!m_notifier) {
571         debugWarning("Request to unlock, but no notifier present!\n");
572         return false;
573     }
574    
575     fb_nodeaddr_t addr = DICE_REGISTER_BASE
576                        + m_global_reg_offset
577                        + DICE_REGISTER_GLOBAL_OWNER;
578
579     // registry offsets should always be smaller than 0x7FFFFFFF
580     // because otherwise base + offset > 64bit
581     if(m_global_reg_offset & 0x80000000) {
582         debugError("register offset not initialized yet\n");
583         return false;
584     }
585    
586     fb_nodeaddr_t compare_value = ((0xFFC0) | m_p1394Service->getLocalNodeId()) << 24;
587     compare_value |= m_notifier->getStart();
588    
589     if (!m_p1394Service->lockCompareSwap64(  m_nodeId, addr, compare_value,
590                                        DICE_OWNER_NO_OWNER, &result )) {
591         debugWarning("Could not unregister ourselves as device owner\n");
592     }
593    
594     m_p1394Service->unregisterARMHandler(m_notifier);
595     delete m_notifier;
596     m_notifier=NULL;
597
598     return true;
599 }
600
601 int
602 DiceAvDevice::getStreamCount() {
603     return m_receiveProcessors.size() + m_transmitProcessors.size();
604 }
605
606 Streaming::StreamProcessor *
607 DiceAvDevice::getStreamProcessorByIndex(int i) {
608
609     if (i<(int)m_receiveProcessors.size()) {
610         return m_receiveProcessors.at(i);
611     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
612         return m_transmitProcessors.at(i-m_receiveProcessors.size());
613     }
614
615     return NULL;
616 }
617
618 bool
619 DiceAvDevice::startStreamByIndex(int i) {
620
621     if (isIsoStreamingEnabled()) {
622         debugError("Cannot start streams while streaming is enabled\n");
623         return false;
624     }
625
626     if (i<(int)m_receiveProcessors.size()) {
627         int n=i;
628         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
629        
630         // allocate ISO channel
631         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
632         if(isochannel<0) {
633             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
634             return false;
635         }
636         p->setChannel(isochannel);
637        
638         fb_quadlet_t reg_isoch;
639         // check value of ISO_CHANNEL register
640         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
641             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
642             p->setChannel(-1);
643             deallocateIsoChannel(isochannel);
644             return false;
645         }
646         if(reg_isoch != 0xFFFFFFFFUL) {
647             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ATX %d\n", reg_isoch, n);
648             p->setChannel(-1);
649             deallocateIsoChannel(isochannel);
650             return false;
651         }
652        
653         // write value of ISO_CHANNEL register
654         reg_isoch=isochannel;
655         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
656             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
657             p->setChannel(-1);
658             deallocateIsoChannel(isochannel);
659             return false;
660         }
661        
662         return true;
663        
664     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
665         int n=i-m_receiveProcessors.size();
666         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
667        
668         // allocate ISO channel
669         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
670         if(isochannel<0) {
671             debugError("Could not allocate iso channel for SP %d (ATX %d)\n",i,n);
672             return false;
673         }
674         p->setChannel(isochannel);
675        
676         fb_quadlet_t reg_isoch;
677         // check value of ISO_CHANNEL register
678         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
679             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
680             p->setChannel(-1);
681             deallocateIsoChannel(isochannel);
682             return false;
683         }
684         if(reg_isoch != 0xFFFFFFFFUL) {
685             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X) for ARX %d\n", reg_isoch, n);
686             p->setChannel(-1);
687             deallocateIsoChannel(isochannel);
688             return false;
689         }
690        
691         // write value of ISO_CHANNEL register
692         reg_isoch=isochannel;
693         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
694             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
695             p->setChannel(-1);
696             deallocateIsoChannel(isochannel);
697             return false;
698         }
699        
700         return true;
701     }
702    
703     debugError("SP index %d out of range!\n",i);
704    
705     return false;
706 }
707
708 bool
709 DiceAvDevice::stopStreamByIndex(int i) {
710
711     if (isIsoStreamingEnabled()) {
712         debugError("Cannot stop streams while streaming is enabled\n");
713         return false;
714     }
715
716     if (i<(int)m_receiveProcessors.size()) {
717         int n=i;
718         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
719         unsigned int isochannel=p->getChannel();
720        
721         fb_quadlet_t reg_isoch;
722         // check value of ISO_CHANNEL register
723         if(!readTxReg(n, DICE_REGISTER_TX_ISOC_BASE, &reg_isoch)) {
724             debugError("Could not read ISO_CHANNEL register for ATX %d\n", n);
725             return false;
726         }
727         if(reg_isoch != isochannel) {
728             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ATX %d\n", isochannel, reg_isoch, n);
729             return false;
730         }
731        
732         // write value of ISO_CHANNEL register
733         reg_isoch=0xFFFFFFFFUL;
734         if(!writeTxReg(n, DICE_REGISTER_TX_ISOC_BASE, reg_isoch)) {
735             debugError("Could not write ISO_CHANNEL register for ATX %d\n", n);
736             return false;
737         }
738        
739         // deallocate ISO channel
740         if(!deallocateIsoChannel(isochannel)) {
741             debugError("Could not deallocate iso channel for SP %d (ATX %d)\n",i,n);
742             return false;
743         }
744        
745         p->setChannel(-1);
746         return true;
747        
748     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
749         int n=i-m_receiveProcessors.size();
750         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
751        
752         unsigned int isochannel=p->getChannel();
753        
754         fb_quadlet_t reg_isoch;
755         // check value of ISO_CHANNEL register
756         if(!readRxReg(n, DICE_REGISTER_RX_ISOC_BASE, &reg_isoch)) {
757             debugError("Could not read ISO_CHANNEL register for ARX %d\n", n);
758             return false;
759         }
760         if(reg_isoch != isochannel) {
761             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X) for ARX %d\n", isochannel, reg_isoch, n);
762             return false;
763         }
764        
765         // write value of ISO_CHANNEL register
766         reg_isoch=0xFFFFFFFFUL;
767         if(!writeRxReg(n, DICE_REGISTER_RX_ISOC_BASE, reg_isoch)) {
768             debugError("Could not write ISO_CHANNEL register for ARX %d\n", n);
769             return false;
770         }
771        
772         // deallocate ISO channel
773         if(!deallocateIsoChannel(isochannel)) {
774             debugError("Could not deallocate iso channel for SP %d (ARX %d)\n",i,n);
775             return false;
776         }
777        
778         p->setChannel(-1);
779         return true;
780     }
781    
782     debugError("SP index %d out of range!\n",i);
783    
784     return false;
785 }
786
787 // helper routines
788
789 // allocate ISO resources for the SP's
790 int DiceAvDevice::allocateIsoChannel(unsigned int packet_size) {
791     unsigned int bandwidth=8+packet_size;
792    
793     int ch=m_p1394Service->allocateIsoChannelGeneric(bandwidth);
794        
795     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
796         ch, bandwidth);
797    
798     return ch;
799 }
800 // deallocate ISO resources
801 bool DiceAvDevice::deallocateIsoChannel(int channel) {
802     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
803     return m_p1394Service->freeIsoChannel(channel);
804 }
805
806 bool
807 DiceAvDevice::enableIsoStreaming() {
808     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_ENABLE);
809 }
810
811 bool
812 DiceAvDevice::disableIsoStreaming() {
813     return writeGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, DICE_ISOSTREAMING_DISABLE);
814 }
815
816 bool
817 DiceAvDevice::isIsoStreamingEnabled() {
818     fb_quadlet_t result;
819     readGlobalReg(DICE_REGISTER_GLOBAL_ENABLE, &result);
820     // I don't know what exactly is 'enable',
821     // but disable is definately == 0
822     return (result != DICE_ISOSTREAMING_DISABLE);
823 }
824
825 /**
826  * @brief performs a masked bit register equals 0 check on the global parameter space
827  * @return true if readGlobalReg(offset) & mask == 0
828  */
829 bool
830 DiceAvDevice::maskedCheckZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
831     fb_quadlet_t result;
832     readGlobalReg(offset, &result);
833     return ((result & mask) == 0);
834 }
835 /**
836  * @brief performs a masked bit register not equal to 0 check on the global parameter space
837  * @return true if readGlobalReg(offset) & mask != 0
838  */
839 bool
840 DiceAvDevice::maskedCheckNotZeroGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t mask) {
841     return !maskedCheckZeroGlobalReg(offset, mask);
842 }
843
844 DiceAvDevice::diceNameVector
845 DiceAvDevice::getTxNameString(unsigned int i) {
846     diceNameVector names;
847     char namestring[DICE_TX_NAMES_SIZE*4+1];
848    
849     if (!readTxRegBlock(i, DICE_REGISTER_TX_NAMES_BASE,
850                         (fb_quadlet_t *)namestring, DICE_TX_NAMES_SIZE*4)) {
851         debugError("Could not read TX name string \n");
852         return names;
853     }
854    
855     namestring[DICE_TX_NAMES_SIZE*4]='\0';
856     return splitNameString(std::string(namestring));
857 }
858
859 DiceAvDevice::diceNameVector
860 DiceAvDevice::getRxNameString(unsigned int i) {
861     diceNameVector names;
862     char namestring[DICE_RX_NAMES_SIZE*4+1];
863    
864     if (!readRxRegBlock(i, DICE_REGISTER_RX_NAMES_BASE,
865                         (fb_quadlet_t *)namestring, DICE_RX_NAMES_SIZE*4)) {
866         debugError("Could not read RX name string \n");
867         return names;
868     }
869    
870     namestring[DICE_RX_NAMES_SIZE*4]='\0';
871     return splitNameString(std::string(namestring));
872 }
873
874 DiceAvDevice::diceNameVector
875 DiceAvDevice::getClockSourceNameString() {
876     diceNameVector names;
877     char namestring[DICE_CLOCKSOURCENAMES_SIZE*4+1];
878    
879     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_CLOCKSOURCENAMES,
880                         (fb_quadlet_t *)namestring, DICE_CLOCKSOURCENAMES_SIZE*4)) {
881         debugError("Could not read CLOCKSOURCE name string \n");
882         return names;
883     }
884    
885     namestring[DICE_CLOCKSOURCENAMES_SIZE*4]='\0';
886     return splitNameString(std::string(namestring));
887 }
888
889 std::string
890 DiceAvDevice::getDeviceNickName() {
891     char namestring[DICE_NICK_NAME_SIZE*4+1];
892    
893     if (!readGlobalRegBlock(DICE_REGISTER_GLOBAL_NICK_NAME,
894                         (fb_quadlet_t *)namestring, DICE_NICK_NAME_SIZE*4)) {
895         debugError("Could not read nickname string \n");
896         return std::string("(unknown)");
897     }
898    
899     namestring[DICE_NICK_NAME_SIZE*4]='\0';
900     return std::string(namestring);
901 }
902
903 DiceAvDevice::diceNameVector
904 DiceAvDevice::splitNameString(std::string in) {
905     diceNameVector names;
906
907     // find the end of the string
908     unsigned int end=in.find_first_of("\\\\");
909     // cut the end
910     in=in.substr(0,end-2);
911
912     unsigned int cut;
913     while( (cut = in.find_first_of("\\")) != in.npos ) {
914         if(cut > 0) {
915             names.push_back(in.substr(0,cut));
916         }
917         in = in.substr(cut+1);
918     }
919     if(in.length() > 0) {
920         names.push_back(in);
921     }
922     return names;
923 }
924
925
926 // I/O routines
927 bool
928 DiceAvDevice::initIoFunctions() {
929
930     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_OFF, &m_global_reg_offset)) {
931         debugError("Could not initialize m_global_reg_offset\n");
932         return false;
933     }
934     if(!readReg(DICE_REGISTER_GLOBAL_PAR_SPACE_SZ, &m_global_reg_size)) {
935         debugError("Could not initialize m_global_reg_size\n");
936         return false;
937     }
938     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_OFF, &m_tx_reg_offset)) {
939         debugError("Could not initialize m_tx_reg_offset\n");
940         return false;
941     }
942     if(!readReg(DICE_REGISTER_TX_PAR_SPACE_SZ, &m_tx_reg_size)) {
943         debugError("Could not initialize m_tx_reg_size\n");
944         return false;
945     }
946     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_OFF, &m_rx_reg_offset)) {
947         debugError("Could not initialize m_rx_reg_offset\n");
948         return false;
949     }
950     if(!readReg(DICE_REGISTER_RX_PAR_SPACE_SZ, &m_rx_reg_size)) {
951         debugError("Could not initialize m_rx_reg_size\n");
952         return false;
953     }
954     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_OFF, &m_unused1_reg_offset)) {
955         debugError("Could not initialize m_unused1_reg_offset\n");
956         return false;
957     }
958     if(!readReg(DICE_REGISTER_UNUSED1_SPACE_SZ, &m_unused1_reg_size)) {
959         debugError("Could not initialize m_unused1_reg_size\n");
960         return false;
961     }
962     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_OFF, &m_unused2_reg_offset)) {
963         debugError("Could not initialize m_unused2_reg_offset\n");
964         return false;
965     }
966     if(!readReg(DICE_REGISTER_UNUSED2_SPACE_SZ, &m_unused2_reg_size)) {
967         debugError("Could not initialize m_unused2_reg_size\n");
968         return false;
969     }
970
971     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_NB_TX, &m_nb_tx)) {
972         debugError("Could not initialize m_nb_tx\n");
973         return false;
974     }
975     if(!readReg(m_tx_reg_offset + DICE_REGISTER_TX_SZ_TX, &m_tx_size)) {
976         debugError("Could not initialize m_tx_size\n");
977         return false;
978     }
979     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_NB_RX, &m_nb_rx)) {
980         debugError("Could not initialize m_nb_rx\n");
981         return false;
982     }
983     if(!readReg(m_tx_reg_offset + DICE_REGISTER_RX_SZ_RX, &m_rx_size)) {
984         debugError("Could not initialize m_rx_size\n");
985         return false;
986     }
987    
988     return true;
989 }
990
991 bool
992 DiceAvDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
993     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
994    
995     if(offset >= DICE_INVALID_OFFSET) {
996         debugError("invalid offset: 0x%016llX\n", offset);
997         return false;
998     }
999    
1000     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1001     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
1002    
1003     if(!m_p1394Service->read_quadlet( nodeId, addr, result ) ) {
1004         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
1005         return false;
1006     }
1007     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
1008    
1009     return true;
1010 }
1011
1012 bool
1013 DiceAvDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1014     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n", 
1015         offset, data);
1016    
1017     if(offset >= DICE_INVALID_OFFSET) {
1018         debugError("invalid offset: 0x%016llX\n", offset);
1019         return false;
1020     }
1021    
1022     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1023     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
1024    
1025     if(!m_p1394Service->write_quadlet( nodeId, addr, data ) ) {
1026         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
1027         return false;
1028     }
1029     return true;
1030 }
1031
1032 bool
1033 DiceAvDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1034     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
1035         offset, length);
1036    
1037     if(offset >= DICE_INVALID_OFFSET) {
1038         debugError("invalid offset: 0x%016llX\n", offset);
1039         return false;
1040     }
1041    
1042     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1043     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
1044    
1045     if(!m_p1394Service->read( nodeId, addr, length, data ) ) {
1046         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
1047         return false;
1048     }
1049     return true;
1050 }
1051
1052 bool
1053 DiceAvDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1054     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n", 
1055         offset, length);
1056    
1057     if(offset >= DICE_INVALID_OFFSET) {
1058         debugError("invalid offset: 0x%016llX\n", offset);
1059         return false;
1060     }
1061    
1062     fb_nodeaddr_t addr=DICE_REGISTER_BASE + offset;
1063     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
1064
1065     if(!m_p1394Service->write( nodeId, addr, length, data ) ) {
1066         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
1067         return false;
1068     }
1069     return true;
1070 }
1071
1072 bool
1073 DiceAvDevice::readGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
1074     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register offset 0x%04llX\n", offset);
1075
1076     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1077     return readReg(m_global_reg_offset + offset_gl, result);
1078 }
1079
1080 bool
1081 DiceAvDevice::writeGlobalReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
1082     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register offset 0x%08llX, data: 0x%08X\n", 
1083         offset, data);
1084
1085     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, sizeof(fb_quadlet_t));
1086     return writeReg(m_global_reg_offset + offset_gl, data);
1087 }
1088
1089 bool
1090 DiceAvDevice::readGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1091     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading global register block offset 0x%04llX, length %u bytes\n",
1092         offset, length);
1093
1094     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1095     return readRegBlock(m_global_reg_offset + offset_gl, data, length);
1096 }
1097
1098 bool
1099 DiceAvDevice::writeGlobalRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1100     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing global register block offset 0x%04llX, length %u bytes\n",
1101         offset, length);
1102
1103     fb_nodeaddr_t offset_gl=globalOffsetGen(offset, length);
1104     return writeRegBlock(m_global_reg_offset + offset_gl, data, length);
1105 }
1106
1107 fb_nodeaddr_t
1108 DiceAvDevice::globalOffsetGen(fb_nodeaddr_t offset, size_t length) {
1109
1110     // registry offsets should always be smaller than 0x7FFFFFFF
1111     // because otherwise base + offset > 64bit
1112     if(m_global_reg_offset & 0x80000000) {
1113         debugError("register offset not initialized yet\n");
1114         return DICE_INVALID_OFFSET;
1115     }
1116     // out-of-range check
1117     if(offset + length > m_global_reg_size) {
1118         debugError("register offset+length too large: 0x%0llX\n", offset + length);
1119         return DICE_INVALID_OFFSET;
1120     }
1121    
1122     return offset;
1123 }
1124
1125 bool
1126 DiceAvDevice::readTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1127     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading tx %d register offset 0x%04llX\n", i, offset);
1128    
1129     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1130     return readReg(m_tx_reg_offset + offset_tx, result);
1131 }
1132
1133 bool
1134 DiceAvDevice::writeTxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1135     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing tx %d register offset 0x%08llX, data: 0x%08X\n",
1136         i, offset, data);
1137
1138     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, sizeof(fb_quadlet_t));
1139     return writeReg(m_tx_reg_offset + offset_tx, data);
1140 }
1141
1142 bool
1143 DiceAvDevice::readTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1144     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1145         offset, length);
1146    
1147     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1148     return readRegBlock(m_tx_reg_offset + offset_tx, data, length);
1149 }
1150
1151 bool
1152 DiceAvDevice::writeTxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1153     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1154         offset, length);
1155
1156     fb_nodeaddr_t offset_tx=txOffsetGen(i, offset, length);
1157     return writeRegBlock(m_tx_reg_offset + offset_tx, data, length);
1158 }
1159
1160 fb_nodeaddr_t
1161 DiceAvDevice::txOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1162     // registry offsets should always be smaller than 0x7FFFFFFF
1163     // because otherwise base + offset > 64bit
1164     if(m_tx_reg_offset & 0x80000000) {
1165         debugError("register offset not initialized yet\n");
1166         return DICE_INVALID_OFFSET;
1167     }
1168     if(m_nb_tx & 0x80000000) {
1169         debugError("m_nb_tx not initialized yet\n");
1170         return DICE_INVALID_OFFSET;
1171     }
1172     if(m_tx_size & 0x80000000) {
1173         debugError("m_tx_size not initialized yet\n");
1174         return DICE_INVALID_OFFSET;
1175     }
1176     if(i >= m_nb_rx) {
1177         debugError("TX index out of range\n");
1178         return DICE_INVALID_OFFSET;
1179     }
1180
1181     fb_nodeaddr_t offset_tx = DICE_REGISTER_TX_PARAM(m_tx_size, i, offset);
1182
1183     // out-of-range check
1184     if(offset_tx + length > m_tx_reg_size) {
1185         debugError("register offset+length too large: 0x%0llX\n", offset_tx + length);
1186         return DICE_INVALID_OFFSET;
1187     }
1188
1189     return offset_tx;
1190 }
1191
1192 bool
1193 DiceAvDevice::readRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *result) {
1194     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx %d register offset 0x%04llX\n", i, offset);
1195    
1196     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1197     return readReg(m_rx_reg_offset + offset_rx, result);
1198 }
1199
1200 bool
1201 DiceAvDevice::writeRxReg(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t data) {
1202     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register offset 0x%08llX, data: 0x%08X\n", 
1203         offset, data);
1204        
1205     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, sizeof(fb_quadlet_t));
1206     return writeReg(m_rx_reg_offset + offset_rx, data);
1207 }
1208
1209 bool
1210 DiceAvDevice::readRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1211     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading rx register block offset 0x%04llX, length %u bytes\n",
1212         offset, length);
1213    
1214     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1215     return readRegBlock(m_rx_reg_offset + offset_rx, data, length);
1216 }
1217
1218 bool
1219 DiceAvDevice::writeRxRegBlock(unsigned int i, fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
1220     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing rx register block offset 0x%04llX, length %u bytes\n",
1221         offset, length);
1222
1223     fb_nodeaddr_t offset_rx=rxOffsetGen(i, offset, length);
1224     return writeRegBlock(m_rx_reg_offset + offset_rx, data, length);
1225 }
1226
1227 fb_nodeaddr_t
1228 DiceAvDevice::rxOffsetGen(unsigned int i, fb_nodeaddr_t offset, size_t length) {
1229     // registry offsets should always be smaller than 0x7FFFFFFF
1230     // because otherwise base + offset > 64bit
1231     if(m_rx_reg_offset & 0x80000000) {
1232         debugError("register offset not initialized yet\n");
1233         return DICE_INVALID_OFFSET;
1234     }
1235     if(m_nb_rx & 0x80000000) {
1236         debugError("m_nb_rx not initialized yet\n");
1237         return DICE_INVALID_OFFSET;
1238     }
1239     if(m_rx_size & 0x80000000) {
1240         debugError("m_rx_size not initialized yet\n");
1241         return DICE_INVALID_OFFSET;
1242     }
1243     if(i >= m_nb_rx) {
1244         debugError("RX index out of range\n");
1245         return DICE_INVALID_OFFSET;
1246     }
1247
1248     fb_nodeaddr_t offset_rx = DICE_REGISTER_RX_PARAM(m_rx_size, i, offset);
1249
1250     // out-of-range check
1251     if(offset_rx + length > m_rx_reg_size) {
1252         debugError("register offset+length too large: 0x%0llX\n", offset_rx + length);
1253         return DICE_INVALID_OFFSET;
1254     }
1255     return offset_rx;
1256 }
1257
1258
1259 // the notifier
1260
1261 DiceAvDevice::DiceNotifier::DiceNotifier(DiceAvDevice *d, nodeaddr_t start)
1262  : ARMHandler(start, DICE_NOTIFIER_BLOCK_LENGTH,
1263               RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
1264               RAW1394_ARM_WRITE, 0)
1265  , m_dicedevice(d)
1266 {
1267
1268 }
1269
1270 DiceAvDevice::DiceNotifier::~DiceNotifier()
1271 {
1272
1273 }
1274
1275 }
Note: See TracBrowser for help on using the browser.