root/branches/libffado-2.0/src/libieee1394/ieee1394service.cpp

Revision 1371, 42.0 kB (checked in by ppalmers, 12 years ago)

* implement our own code to do FCP transactions. the code from libavc had too much side-effects.
* remove libavc1394 as a dependency
* set the SPLIT_TIMEOUT value for the host controller such that late responses by the DM1x00 based devices are not discarded. Should fix the issues with FA-101 discovery. (re:
#155, #162)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "config.h"
26 #include "ieee1394service.h"
27 #include "cycletimer.h"
28 #include "IsoHandlerManager.h"
29 #include "CycleTimerHelper.h"
30
31 #include <libraw1394/csr.h>
32 #include <libiec61883/iec61883.h>
33
34 #include "libutil/SystemTimeSource.h"
35 #include "libutil/Watchdog.h"
36 #include "libutil/PosixMutex.h"
37
38 #include <errno.h>
39 #include "libutil/ByteSwap.h"
40
41 #include <string.h>
42
43 #include <iostream>
44 #include <iomanip>
45
46 using namespace std;
47
48 IMPL_DEBUG_MODULE( Ieee1394Service, Ieee1394Service, DEBUG_LEVEL_NORMAL );
49
50 Ieee1394Service::Ieee1394Service()
51     : m_handle( 0 )
52     , m_handle_lock( new Util::PosixMutex("SRCVHND") )
53     , m_resetHandle( 0 )
54     , m_util_handle( 0 )
55     , m_port( -1 )
56     , m_RHThread_lock( new Util::PosixMutex("SRVCRH") )
57     , m_threadRunning( false )
58     , m_realtime ( false )
59     , m_base_priority ( 0 )
60     , m_pIsoManager( new IsoHandlerManager( *this ) )
61     , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC ) )
62     , m_have_new_ctr_read ( false )
63     , m_pWatchdog ( new Util::Watchdog() )
64 {
65     for (unsigned int i=0; i<64; i++) {
66         m_channels[i].channel=-1;
67         m_channels[i].bandwidth=-1;
68         m_channels[i].alloctype=AllocFree;
69         m_channels[i].xmit_node=0xFFFF;
70         m_channels[i].xmit_plug=-1;
71         m_channels[i].recv_node=0xFFFF;
72         m_channels[i].recv_plug=-1;
73     }
74 }
75
76 Ieee1394Service::Ieee1394Service(bool rt, int prio)
77     : m_handle( 0 )
78     , m_handle_lock( new Util::PosixMutex("SRCVHND") )
79     , m_resetHandle( 0 )
80     , m_util_handle( 0 )
81     , m_port( -1 )
82     , m_RHThread_lock( new Util::PosixMutex("SRVCRH") )
83     , m_threadRunning( false )
84     , m_realtime ( rt )
85     , m_base_priority ( prio )
86     , m_pIsoManager( new IsoHandlerManager( *this, rt, prio ) )
87     , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC,
88                                            rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
89                                            prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) )
90     , m_have_new_ctr_read ( false )
91     , m_pWatchdog ( new Util::Watchdog() )
92 {
93     for (unsigned int i=0; i<64; i++) {
94         m_channels[i].channel=-1;
95         m_channels[i].bandwidth=-1;
96         m_channels[i].alloctype=AllocFree;
97         m_channels[i].xmit_node=0xFFFF;
98         m_channels[i].xmit_plug=-1;
99         m_channels[i].recv_node=0xFFFF;
100         m_channels[i].recv_plug=-1;
101     }
102 }
103
104 Ieee1394Service::~Ieee1394Service()
105 {
106     delete m_pIsoManager;
107     delete m_pCTRHelper;
108     stopRHThread();
109
110     delete m_pWatchdog;
111     if ( m_handle ) {
112         raw1394_destroy_handle( m_handle );
113     }
114     delete m_handle_lock;
115
116     if ( m_resetHandle ) {
117         raw1394_destroy_handle( m_resetHandle );
118     }
119     delete m_RHThread_lock;
120     if ( m_util_handle ) {
121         raw1394_destroy_handle( m_util_handle );
122     }
123 }
124
125 int
126 Ieee1394Service::detectNbPorts()
127 {
128     raw1394handle_t tmp_handle = raw1394_new_handle();
129     if ( tmp_handle == NULL ) {
130         debugError("Could not get libraw1394 handle.\n");
131         return -1;
132     }
133     struct raw1394_portinfo pinf[IEEE1394SERVICE_MAX_FIREWIRE_PORTS];
134     int nb_detected_ports = raw1394_get_port_info(tmp_handle, pinf, IEEE1394SERVICE_MAX_FIREWIRE_PORTS);
135     raw1394_destroy_handle(tmp_handle);
136
137     if (nb_detected_ports < 0) {
138         debugError("Failed to detect number of ports\n");
139         return -1;
140     }
141     return nb_detected_ports;
142 }
143
144 void
145 Ieee1394Service::doBusReset() {
146     debugOutput(DEBUG_LEVEL_VERBOSE, "Issue bus reset on service %p (port %d).\n", this, getPort());
147     raw1394_reset_bus(m_handle);
148 }
149
150 /**
151  * This function waits until there are no bus resets generated in a sleep_time_ms interval
152  * @param nb_tries number of tries to take
153  * @param sleep_time_ms sleep between tries
154  * @return true if the storm passed
155  */
156 bool
157 Ieee1394Service::waitForBusResetStormToEnd( int nb_tries, int sleep_time_ms ) {
158     unsigned int gen_current;
159     do {
160         gen_current = getGeneration();
161         debugOutput(DEBUG_LEVEL_VERBOSE, "Waiting... (gen: %u)\n", gen_current);
162
163         // wait for a while
164         Util::SystemTimeSource::SleepUsecRelative( sleep_time_ms * 1000);
165     } while (gen_current != getGeneration() && --nb_tries);
166
167     if (!nb_tries) {
168         debugError( "Bus reset storm did not stop on time...\n");
169         return false;
170     }
171     return true;
172 }
173
174 bool
175 Ieee1394Service::initialize( int port )
176 {
177     using namespace std;
178
179     int nb_ports = detectNbPorts();
180     if (port + 1 > nb_ports) {
181         debugFatal("Requested port (%d) out of range (# ports: %d)\n", port, nb_ports);
182     }
183
184     if(!m_pWatchdog) {
185         debugError("No valid RT watchdog found.\n");
186         return false;
187     }
188     if(!m_pWatchdog->start()) {
189         debugError("Could not start RT watchdog.\n");
190         return false;
191     }
192
193     m_handle = raw1394_new_handle_on_port( port );
194     if ( !m_handle ) {
195         if ( !errno ) {
196             debugFatal("libraw1394 not compatible\n");
197         } else {
198             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s\n",
199                 strerror(errno) );
200             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
201         }
202         return false;
203     }
204
205     m_resetHandle = raw1394_new_handle_on_port( port );
206     if ( !m_resetHandle ) {
207         if ( !errno ) {
208             debugFatal("libraw1394 not compatible\n");
209         } else {
210             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s",
211                 strerror(errno) );
212             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
213         }
214         return false;
215     }
216
217     m_util_handle = raw1394_new_handle_on_port( port );
218     if ( !m_util_handle ) {
219         if ( !errno ) {
220             debugFatal("libraw1394 not compatible\n");
221         } else {
222             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s",
223                 strerror(errno) );
224             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
225         }
226         return false;
227     }
228
229     // test the cycle timer read function
230     int err;
231     uint32_t cycle_timer;
232     uint64_t local_time;
233     err=raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time);
234     if(err) {
235         debugOutput(DEBUG_LEVEL_VERBOSE, "raw1394_read_cycle_timer failed.\n");
236         debugOutput(DEBUG_LEVEL_VERBOSE, " Error descr: %s\n", strerror(err));
237         debugWarning("==================================================================\n");
238         debugWarning(" This system doesn't support the raw1394_read_cycle_timer call.   \n");
239         debugWarning(" Fallback to indirect CTR read method.                            \n");
240         debugWarning(" FFADO should work, but achieving low-latency might be a problem. \n");
241         debugWarning(" Upgrade the kernel to version 2.6.21 or higher to solve this.    \n");
242         debugWarning("==================================================================\n");
243         m_have_new_ctr_read = false;
244     } else {
245         debugOutput(DEBUG_LEVEL_VERBOSE, "This system supports the raw1394_read_cycle_timer call, using it.\n");
246         m_have_new_ctr_read = true;
247     }
248
249     m_port = port;
250
251     // obtain port name
252     raw1394handle_t tmp_handle = raw1394_new_handle();
253     if ( tmp_handle == NULL ) {
254         debugError("Could not get temporaty libraw1394 handle.\n");
255         return false;
256     }
257     struct raw1394_portinfo pinf[IEEE1394SERVICE_MAX_FIREWIRE_PORTS];
258     int nb_detected_ports = raw1394_get_port_info(tmp_handle, pinf, IEEE1394SERVICE_MAX_FIREWIRE_PORTS);
259     raw1394_destroy_handle(tmp_handle);
260
261     if (nb_detected_ports < 0) {
262         debugError("Failed to detect number of ports\n");
263         return false;
264     }
265
266     if(nb_detected_ports && port < IEEE1394SERVICE_MAX_FIREWIRE_PORTS) {
267         m_portName = pinf[port].name;
268     } else {
269         m_portName = "Unknown";
270     }
271     if (m_portName == "") {
272         m_portName = "Unknown";
273     }
274
275     // set userdata
276     raw1394_set_userdata( m_handle, this );
277     raw1394_set_userdata( m_resetHandle, this );
278     raw1394_set_userdata( m_util_handle, this );
279     raw1394_set_bus_reset_handler( m_resetHandle,
280                                    this->resetHandlerLowLevel );
281
282     // set SPLIT_TIMEOUT to one second to cope with DM1x00 devices that
283     // send responses regardless of the timeout
284     int timeout = getSplitTimeoutUsecs(getLocalNodeId());
285     if (timeout < IEEE1394SERVICE_MIN_SPLIT_TIMEOUT_USECS) {
286         if(!setSplitTimeoutUsecs(getLocalNodeId(), IEEE1394SERVICE_MIN_SPLIT_TIMEOUT_USECS+124)) {
287             debugWarning("Could not set SPLIT_TIMEOUT to min requested\n");
288         }
289         timeout = getSplitTimeoutUsecs(getLocalNodeId());
290         if (timeout < IEEE1394SERVICE_MIN_SPLIT_TIMEOUT_USECS) {
291             debugWarning("Set SPLIT_TIMEOUT to min requested did not succeed\n");
292         }
293     }
294    
295     // check state
296     if(!m_pCTRHelper) {
297         debugFatal("No CycleTimerHelper available, bad!\n");
298         return false;
299     }
300     m_pCTRHelper->setVerboseLevel(getDebugLevel());
301     if(!m_pCTRHelper->Start()) {
302         debugFatal("Could not start CycleTimerHelper\n");
303         return false;
304     }
305
306     if(!m_pIsoManager) {
307         debugFatal("No IsoHandlerManager available, bad!\n");
308         return false;
309     }
310     m_pIsoManager->setVerboseLevel(getDebugLevel());
311     if(!m_pIsoManager->init()) {
312         debugFatal("Could not initialize IsoHandlerManager\n");
313         return false;
314     }
315
316     startRHThread();
317
318     // make sure that the thread parameters of all our helper threads are OK
319     if(!setThreadParameters(m_realtime, m_base_priority)) {
320         debugFatal("Could not set thread parameters\n");
321         return false;
322     }
323     return true;
324 }
325
326 bool
327 Ieee1394Service::setThreadParameters(bool rt, int priority) {
328     bool result = true;
329     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO;
330     m_base_priority = priority;
331     m_realtime = rt;
332     if (m_pIsoManager) {
333         debugOutput(DEBUG_LEVEL_VERBOSE, "Switching IsoManager to (rt=%d, prio=%d)\n",
334                                          rt, priority);
335         result &= m_pIsoManager->setThreadParameters(rt, priority);
336     }
337     if (m_pCTRHelper) {
338         debugOutput(DEBUG_LEVEL_VERBOSE, "Switching CycleTimerHelper to (rt=%d, prio=%d)\n",
339                                          rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
340                                          priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);
341         result &= m_pCTRHelper->setThreadParameters(rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
342                                                     priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);
343     }
344     return result;
345 }
346
347 int
348 Ieee1394Service::getNodeCount()
349 {
350     Util::MutexLockHelper lock(*m_handle_lock);
351     return raw1394_get_nodecount( m_handle );
352 }
353
354 nodeid_t Ieee1394Service::getLocalNodeId() {
355     Util::MutexLockHelper lock(*m_handle_lock);
356     return raw1394_get_local_id(m_handle) & 0x3F;
357 }
358
359 /**
360  * Returns the current value of the cycle timer (in ticks)
361  *
362  * @return the current value of the cycle timer (in ticks)
363  */
364
365 uint32_t
366 Ieee1394Service::getCycleTimerTicks() {
367     return m_pCTRHelper->getCycleTimerTicks();
368 }
369
370 /**
371  * Returns the current value of the cycle timer (as is)
372  *
373  * @return the current value of the cycle timer (as is)
374  */
375 uint32_t
376 Ieee1394Service::getCycleTimer() {
377     return m_pCTRHelper->getCycleTimer();
378 }
379
380 /**
381  * Returns the current value of the cycle timer (in ticks)
382  * for a specific time instant (usecs since epoch)
383  * @return the current value of the cycle timer (in ticks)
384  */
385
386 uint32_t
387 Ieee1394Service::getCycleTimerTicks(uint64_t t) {
388     return m_pCTRHelper->getCycleTimerTicks(t);
389 }
390
391 /**
392  * Returns the current value of the cycle timer (as is)
393  * for a specific time instant (usecs since epoch)
394  * @return the current value of the cycle timer (as is)
395  */
396 uint32_t
397 Ieee1394Service::getCycleTimer(uint64_t t) {
398     return m_pCTRHelper->getCycleTimer(t);
399 }
400
401 uint64_t
402 Ieee1394Service::getSystemTimeForCycleTimerTicks(uint32_t ticks) {
403     return m_pCTRHelper->getSystemTimeForCycleTimerTicks(ticks);
404 }
405
406 uint64_t
407 Ieee1394Service::getSystemTimeForCycleTimer(uint32_t ctr) {
408     return m_pCTRHelper->getSystemTimeForCycleTimer(ctr);
409 }
410
411 bool
412 Ieee1394Service::readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time)
413 {
414     if(m_have_new_ctr_read) {
415         int err;
416         err = raw1394_read_cycle_timer(m_util_handle, cycle_timer, local_time);
417         if(err) {
418             debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err));
419             return false;
420         }
421         return true;
422     } else {
423         // do a normal read of the CTR register
424         // the disadvantage is that local_time and cycle time are not
425         // read at the same time instant (scheduling issues)
426         *local_time = getCurrentTimeAsUsecs();
427         if ( raw1394_read( m_util_handle,
428                 getLocalNodeId() | 0xFFC0,
429                 CSR_REGISTER_BASE | CSR_CYCLE_TIME,
430                 sizeof(uint32_t), cycle_timer ) == 0 ) {
431             *cycle_timer = CondSwapFromBus32(*cycle_timer);
432             return true;
433         } else {
434             return false;
435         }
436     }
437 }
438
439 uint64_t
440 Ieee1394Service::getCurrentTimeAsUsecs() {
441     return Util::SystemTimeSource::getCurrentTimeAsUsecs();
442 }
443
444 bool
445 Ieee1394Service::read( fb_nodeid_t nodeId,
446                        fb_nodeaddr_t addr,
447                        size_t length,
448                        fb_quadlet_t* buffer )
449 {
450     Util::MutexLockHelper lock(*m_handle_lock);
451     return readNoLock(nodeId, addr, length, buffer);
452 }
453
454 bool
455 Ieee1394Service::readNoLock( fb_nodeid_t nodeId,
456                              fb_nodeaddr_t addr,
457                              size_t length,
458                              fb_quadlet_t* buffer )
459 {
460     if (nodeId == INVALID_NODE_ID) {
461         debugWarning("operation on invalid node\n");
462         return false;
463     }
464     if ( raw1394_read( m_handle, nodeId, addr, length*4, buffer ) == 0 ) {
465
466         #ifdef DEBUG
467         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
468             "read: node 0x%hX, addr = 0x%016llX, length = %u\n",
469             nodeId, addr, length);
470         printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, buffer );
471         #endif
472
473         return true;
474     } else {
475         #ifdef DEBUG
476         debugOutput(DEBUG_LEVEL_NORMAL,
477                     "raw1394_read failed: node 0x%hX, addr = 0x%016llX, length = %u\n",
478                     nodeId, addr, length);
479         #endif
480         return false;
481     }
482 }
483
484 bool
485 Ieee1394Service::read_quadlet( fb_nodeid_t nodeId,
486                                fb_nodeaddr_t addr,
487                                fb_quadlet_t* buffer )
488 {
489     return read( nodeId,  addr, sizeof( *buffer )/4, buffer );
490 }
491
492 bool
493 Ieee1394Service::read_octlet( fb_nodeid_t nodeId,
494                               fb_nodeaddr_t addr,
495                               fb_octlet_t* buffer )
496 {
497     return read( nodeId, addr, sizeof( *buffer )/4,
498                  reinterpret_cast<fb_quadlet_t*>( buffer ) );
499 }
500
501 bool
502 Ieee1394Service::write( fb_nodeid_t nodeId,
503                         fb_nodeaddr_t addr,
504                         size_t length,
505                         fb_quadlet_t* data )
506 {
507     Util::MutexLockHelper lock(*m_handle_lock);
508     return writeNoLock(nodeId, addr, length, data);
509 }
510
511 bool
512 Ieee1394Service::writeNoLock( fb_nodeid_t nodeId,
513                               fb_nodeaddr_t addr,
514                               size_t length,
515                               fb_quadlet_t* data )
516 {
517     if (nodeId == INVALID_NODE_ID) {
518         debugWarning("operation on invalid node\n");
519         return false;
520     }
521
522     #ifdef DEBUG
523     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"write: node 0x%hX, addr = 0x%016llX, length = %d\n",
524                 nodeId, addr, length);
525     printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, data );
526     #endif
527
528     return raw1394_write( m_handle, nodeId, addr, length*4, data ) == 0;
529 }
530
531 bool
532 Ieee1394Service::write_quadlet( fb_nodeid_t nodeId,
533                                 fb_nodeaddr_t addr,
534                                 fb_quadlet_t data )
535 {
536     return write( nodeId, addr, sizeof( data )/4, &data );
537 }
538
539 bool
540 Ieee1394Service::write_octlet( fb_nodeid_t nodeId,
541                                fb_nodeaddr_t addr,
542                                fb_octlet_t data )
543 {
544     return write( nodeId, addr, sizeof( data )/4,
545                   reinterpret_cast<fb_quadlet_t*>( &data ) );
546 }
547
548 bool
549 Ieee1394Service::lockCompareSwap64( fb_nodeid_t nodeId,
550                                     fb_nodeaddr_t addr,
551                                     fb_octlet_t compare_value,
552                                     fb_octlet_t swap_value,
553                                     fb_octlet_t* result )
554 {
555     if (nodeId == INVALID_NODE_ID) {
556         debugWarning("operation on invalid node\n");
557         return false;
558     }
559     #ifdef DEBUG
560     debugOutput(DEBUG_LEVEL_VERBOSE,"lockCompareSwap64: node 0x%X, addr = 0x%016llX\n",
561                 nodeId, addr);
562     debugOutput(DEBUG_LEVEL_VERBOSE,"  if (*(addr)==0x%016llX) *(addr)=0x%016llX\n",
563                 compare_value, swap_value);
564     fb_octlet_t buffer;
565     if(!read_octlet( nodeId, addr,&buffer )) {
566         debugWarning("Could not read register\n");
567     } else {
568         debugOutput(DEBUG_LEVEL_VERBOSE,"before = 0x%016llX\n", buffer);
569     }
570     #endif
571
572     // do endiannes swapping
573     compare_value = CondSwapToBus64(compare_value);
574     swap_value    = CondSwapToBus64(swap_value);
575
576     // do separate locking here (no MutexLockHelper) since
577     // we use read_octlet in the DEBUG code in this function
578     m_handle_lock->Lock();
579     int retval=raw1394_lock64(m_handle, nodeId, addr,
580                               RAW1394_EXTCODE_COMPARE_SWAP,
581                               swap_value, compare_value, result);
582     m_handle_lock->Unlock();
583
584     if(retval) {
585         debugError("raw1394_lock64 failed: %s\n", strerror(errno));
586     }
587
588     #ifdef DEBUG
589     if(!read_octlet( nodeId, addr,&buffer )) {
590         debugWarning("Could not read register\n");
591     } else {
592         debugOutput(DEBUG_LEVEL_VERBOSE,"after = 0x%016llX\n", buffer);
593     }
594     #endif
595
596     *result = CondSwapFromBus64(*result);
597
598     return (retval == 0);
599 }
600
601 fb_quadlet_t*
602 Ieee1394Service::transactionBlock( fb_nodeid_t nodeId,
603                                    fb_quadlet_t* buf,
604                                    int len,
605                                    unsigned int* resp_len )
606 {
607     // FIXME: simplify semantics
608     if (nodeId == INVALID_NODE_ID) {
609         debugWarning("operation on invalid node\n");
610         return false;
611     }
612     // NOTE: this expects a call to transactionBlockClose to unlock
613     m_handle_lock->Lock();
614
615     // clear the request & response memory
616     memset(&m_fcp_block, 0, sizeof(m_fcp_block));
617
618     // make a local copy of the request
619     if(len < MAX_FCP_BLOCK_SIZE_QUADS) {
620         memcpy(m_fcp_block.request, buf, len*sizeof(quadlet_t));
621         m_fcp_block.request_length = len;
622     } else {
623         debugWarning("Truncating FCP request\n");
624         memcpy(m_fcp_block.request, buf, MAX_FCP_BLOCK_SIZE_BYTES);
625         m_fcp_block.request_length = MAX_FCP_BLOCK_SIZE_QUADS;
626     }
627     m_fcp_block.target_nodeid = 0xffc0 | nodeId;
628
629     bool success = doFcpTransaction();
630     if(success) {
631         *resp_len = m_fcp_block.response_length;
632         return m_fcp_block.response;
633     } else {
634         debugWarning("FCP transaction failed\n");
635         *resp_len = 0;
636         return NULL;
637     }
638 }
639
640 bool
641 Ieee1394Service::transactionBlockClose()
642 {
643     m_handle_lock->Unlock();
644     return true;
645 }
646
647 // FCP code
648 bool
649 Ieee1394Service::doFcpTransaction()
650 {
651     for(int i=0; i < IEEE1394SERVICE_FCP_MAX_TRIES; i++) {
652         if(doFcpTransactionTry()) {
653             return true;
654         } else {
655             debugOutput(DEBUG_LEVEL_VERBOSE, "FCP transaction try %d failed\n", i);
656             Util::SystemTimeSource::SleepUsecRelative( IEEE1394SERVICE_FCP_SLEEP_BETWEEN_FAILURES_USECS);
657         }
658     }
659     debugError("FCP transaction didn't succeed in %d tries\n", IEEE1394SERVICE_FCP_MAX_TRIES);
660     return false;
661 }
662
663 #define FCP_COMMAND_ADDR   0xFFFFF0000B00ULL
664 #define FCP_RESPONSE_ADDR  0xFFFFF0000D00ULL
665
666 /* AV/C FCP response codes */
667 #define FCP_RESPONSE_NOT_IMPLEMENTED 0x08000000
668 #define FCP_RESPONSE_ACCEPTED 0x09000000
669 #define FCP_RESPONSE_REJECTED 0x0A000000
670 #define FCP_RESPONSE_IN_TRANSITION 0x0B000000
671 #define FCP_RESPONSE_IMPLEMENTED 0x0C000000
672 #define FCP_RESPONSE_STABLE 0x0C000000
673 #define FCP_RESPONSE_CHANGED 0x0D000000
674 #define FCP_RESPONSE_INTERIM 0x0F000000
675
676 /* AV/C FCP mask macros */
677 #define FCP_MASK_START(x) ((x) & 0xF0000000)
678 #define FCP_MASK_CTYPE(x) ((x) & 0x0F000000)
679 #define FCP_MASK_RESPONSE(x) ((x) & 0x0F000000)
680 #define FCP_MASK_SUBUNIT(x) ((x) & 0x00FF0000)
681 #define FCP_MASK_SUBUNIT_TYPE(x) ((x) & 0x00F80000)
682 #define FCP_MASK_SUBUNIT_ID(x) ((x) & 0x00070000)
683 #define FCP_MASK_OPCODE(x) ((x) & 0x0000FF00)
684 #define FCP_MASK_SUBUNIT_AND_OPCODE(x) ((x) & 0x00FFFF00)
685 #define FCP_MASK_OPERAND0(x) ((x) & 0x000000FF)
686 #define FCP_MASK_OPERAND(x, n) ((x) & (0xFF000000 >> ((((n)-1)%4)*8)))
687 #define FCP_MASK_RESPONSE_OPERAND(x, n) ((x) & (0xFF000000 >> (((n)%4)*8)))
688
689 bool
690 Ieee1394Service::doFcpTransactionTry()
691 {
692     // NOTE that access to this is protected by the m_handle lock
693     int err;
694     bool retval = true;
695     uint64_t timeout;
696
697     // prepare an fcp response handler
698     raw1394_set_fcp_handler(m_handle, _avc_fcp_handler);
699
700     // start listening for FCP requests
701     // this fails if some other program is listening for a FCP response
702     err = raw1394_start_fcp_listen(m_handle);
703     if(err) {
704         debugOutput(DEBUG_LEVEL_VERBOSE, "could not start FCP listen (err=%d, errno=%d)\n", err, errno);
705         retval = false;
706         goto out;
707     }
708
709     m_fcp_block.status = eFS_Waiting;
710
711     #ifdef DEBUG
712     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"fcp request: node 0x%hX, length = %d bytes\n",
713                 m_fcp_block.target_nodeid, m_fcp_block.request_length*4);
714     printBuffer(DEBUG_LEVEL_VERY_VERBOSE, m_fcp_block.request_length, m_fcp_block.request );
715     #endif
716
717     // write the FCP request
718     if(!writeNoLock( m_fcp_block.target_nodeid, FCP_COMMAND_ADDR,
719                      m_fcp_block.request_length, m_fcp_block.request)) {
720         debugOutput(DEBUG_LEVEL_VERBOSE, "write of FCP request failed\n");
721         retval = false;
722         goto out;
723     }
724
725     // wait for the response to arrive
726     struct pollfd raw1394_poll;
727     raw1394_poll.fd = raw1394_get_fd(m_handle);
728     raw1394_poll.events = POLLIN;
729
730     timeout = Util::SystemTimeSource::getCurrentTimeAsUsecs() +
731               IEEE1394SERVICE_FCP_RESPONSE_TIMEOUT_USEC;
732
733     while(m_fcp_block.status == eFS_Waiting
734           && Util::SystemTimeSource::getCurrentTimeAsUsecs() < timeout) {
735         if(poll( &raw1394_poll, 1, IEEE1394SERVICE_FCP_POLL_TIMEOUT_MSEC) > 0) {
736             if (raw1394_poll.revents & POLLIN) {
737                 raw1394_loop_iterate(m_handle);
738             }
739         }
740     }
741
742     // stop listening for FCP responses
743     err = raw1394_stop_fcp_listen(m_handle);
744     if(err) {
745         debugOutput(DEBUG_LEVEL_VERBOSE, "could not stop FCP listen (err=%d, errno=%d)\n", err, errno);
746         retval = false;
747         goto out;
748     }
749
750     // check the request and figure out what happened
751     if(m_fcp_block.status == eFS_Waiting) {
752         debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response timed out\n");
753         retval = false;
754         goto out;
755     }
756     if(m_fcp_block.status == eFS_Error) {
757         debugError("FCP request/response error\n");
758         retval = false;
759         goto out;
760     }
761
762 out:
763     m_fcp_block.status = eFS_Empty;
764     return retval;
765 }
766
767 int
768 Ieee1394Service::_avc_fcp_handler(raw1394handle_t handle, nodeid_t nodeid,
769                                   int response, size_t length,
770                                   unsigned char *data)
771 {
772     Ieee1394Service *service = static_cast<Ieee1394Service *>(raw1394_get_userdata(handle));
773     if(service) {
774         return service->handleFcpResponse(nodeid, response, length, data);
775     } else return -1;
776 }
777
778 int
779 Ieee1394Service::handleFcpResponse(nodeid_t nodeid,
780                                    int response, size_t length,
781                                    unsigned char *data)
782 {
783     fb_quadlet_t *data_quads = (fb_quadlet_t *)data;
784     #ifdef DEBUG
785     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"fcp response: node 0x%hX, response = %d, length = %d bytes\n",
786                 nodeid, response, length);
787     printBuffer(DEBUG_LEVEL_VERY_VERBOSE, (length+3)/4, data_quads );
788     #endif
789
790     if (response && length > 3) {
791         if(length > MAX_FCP_BLOCK_SIZE_BYTES) {
792             length = MAX_FCP_BLOCK_SIZE_BYTES;
793             debugWarning("Truncated FCP response\n");
794         }
795
796         // is it an actual response or is it INTERIM?
797         quadlet_t first_quadlet = CondSwapFromBus32(data_quads[0]);
798         if(FCP_MASK_RESPONSE(first_quadlet) == FCP_RESPONSE_INTERIM) {
799             debugOutput(DEBUG_LEVEL_VERBOSE, "INTERIM\n");
800         } else {
801             // it's an actual response, check if it matches our request
802             if(nodeid != m_fcp_block.target_nodeid) {
803                 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response node id's don't match! (%x, %x)\n",
804                                                  m_fcp_block.target_nodeid, nodeid);
805             } else if (first_quadlet == 0) {
806                 debugWarning("Bogus FCP response\n");
807                 printBuffer(DEBUG_LEVEL_WARNING, (length+3)/4, data_quads );
808 #ifdef DEBUG
809             } else if(FCP_MASK_RESPONSE(first_quadlet) < 0x08000000) {
810                 debugWarning("Bogus AV/C FCP response code\n");
811                 printBuffer(DEBUG_LEVEL_WARNING, (length+3)/4, data_quads );
812 #endif
813             } else if(FCP_MASK_SUBUNIT_AND_OPCODE(first_quadlet)
814                       != FCP_MASK_SUBUNIT_AND_OPCODE(CondSwapFromBus32(m_fcp_block.request[0]))) {
815                 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response not for this request: %08lX != %08lX\n",
816                              FCP_MASK_SUBUNIT_AND_OPCODE(first_quadlet),
817                              FCP_MASK_SUBUNIT_AND_OPCODE(CondSwapFromBus32(m_fcp_block.request[0])));
818             } else {
819                 m_fcp_block.response_length = (length + sizeof(quadlet_t) - 1) / sizeof(quadlet_t);
820                 memcpy(m_fcp_block.response, data, length);
821                 m_fcp_block.status = eFS_Responded;
822             }
823        }
824     }
825     return 0;
826 }
827
828 bool
829 Ieee1394Service::setSplitTimeoutUsecs(fb_nodeid_t nodeId, unsigned int timeout)
830 {
831     Util::MutexLockHelper lock(*m_handle_lock);
832     debugOutput(DEBUG_LEVEL_VERBOSE, "setting SPLIT_TIMEOUT on node 0x%X to %uusecs...\n", nodeId, timeout);
833     unsigned int secs = timeout / 1000000;
834     unsigned int usecs = timeout % 1000000;
835
836     quadlet_t split_timeout_hi = CondSwapToBus32(secs & 7);
837     quadlet_t split_timeout_low = CondSwapToBus32(((usecs / 125) & 0x1FFF) << 19);
838
839     // write the CSR registers
840     if(!writeNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_HI, 1,
841                   &split_timeout_hi)) {
842         debugOutput(DEBUG_LEVEL_VERBOSE, "write of CSR_SPLIT_TIMEOUT_HI failed\n");
843         return false;
844     }
845     if(!writeNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_LO, 1,
846                   &split_timeout_low)) {
847         debugOutput(DEBUG_LEVEL_VERBOSE, "write of CSR_SPLIT_TIMEOUT_LO failed\n");
848         return false;
849     }
850     return true;
851 }
852
853 int
854 Ieee1394Service::getSplitTimeoutUsecs(fb_nodeid_t nodeId)
855 {
856     Util::MutexLockHelper lock(*m_handle_lock);
857     quadlet_t split_timeout_hi;
858     quadlet_t split_timeout_low;
859
860     debugOutput(DEBUG_LEVEL_VERBOSE, "reading SPLIT_TIMEOUT on node 0x%X...\n", nodeId);
861
862     if(!readNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_HI, 1,
863                   &split_timeout_hi)) {
864         debugOutput(DEBUG_LEVEL_VERBOSE, "read of CSR_SPLIT_TIMEOUT_HI failed\n");
865         return 0;
866     }
867     debugOutput(DEBUG_LEVEL_VERBOSE, " READ HI: 0x%08lX\n", split_timeout_hi);
868
869     if(!readNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_LO, 1,
870                   &split_timeout_low)) {
871         debugOutput(DEBUG_LEVEL_VERBOSE, "read of CSR_SPLIT_TIMEOUT_LO failed\n");
872         return 0;
873     }
874     debugOutput(DEBUG_LEVEL_VERBOSE, " READ LO: 0x%08lX\n", split_timeout_low);
875
876     split_timeout_hi = CondSwapFromBus32(split_timeout_hi);
877     split_timeout_low = CondSwapFromBus32(split_timeout_low);
878
879     return (split_timeout_hi & 7) * 1000000 + (split_timeout_low >> 19) * 125;
880 }
881
882 int
883 Ieee1394Service::getVerboseLevel()
884 {
885     return getDebugLevel();
886 }
887
888 void
889 Ieee1394Service::printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const
890 {
891
892     for ( unsigned int i=0; i < length; ++i ) {
893         if ( ( i % 4 ) == 0 ) {
894             if ( i > 0 ) {
895                 debugOutputShort(level,"\n");
896             }
897             debugOutputShort(level," %4d: ",i*4);
898         }
899         debugOutputShort(level,"%08X ",buffer[i]);
900     }
901     debugOutputShort(level,"\n");
902 }
903 void
904 Ieee1394Service::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const
905 {
906
907     for ( unsigned int i=0; i < length; ++i ) {
908         if ( ( i % 16 ) == 0 ) {
909             if ( i > 0 ) {
910                 debugOutputShort(level,"\n");
911             }
912             debugOutputShort(level," %4d: ",i*16);
913         }
914         debugOutputShort(level,"%02X ",buffer[i]);
915     }
916     debugOutputShort(level,"\n");
917 }
918
919 int
920 Ieee1394Service::resetHandlerLowLevel( raw1394handle_t handle,
921                                        unsigned int generation )
922 {
923     raw1394_update_generation ( handle, generation );
924     Ieee1394Service* instance
925         = (Ieee1394Service*) raw1394_get_userdata( handle );
926     instance->resetHandler( generation );
927
928     return 0;
929 }
930
931 bool
932 Ieee1394Service::resetHandler( unsigned int generation )
933 {
934     quadlet_t buf=0;
935
936     m_handle_lock->Lock();
937     raw1394_update_generation(m_handle, generation);
938     m_handle_lock->Unlock();
939
940     // do a simple read on ourself in order to update the internal structures
941     // this avoids failures after a bus reset
942     read_quadlet( getLocalNodeId() | 0xFFC0,
943                   CSR_REGISTER_BASE | CSR_CYCLE_TIME,
944                   &buf );
945
946     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
947           it != m_busResetHandlers.end();
948           ++it )
949     {
950         Util::Functor* func = *it;
951         ( *func )();
952     }
953
954     return true;
955 }
956
957 bool
958 Ieee1394Service::startRHThread()
959 {
960     int i;
961
962     if ( m_threadRunning ) {
963         return true;
964     }
965     m_RHThread_lock->Lock();
966     i = pthread_create( &m_thread, 0, rHThread, this );
967     m_RHThread_lock->Unlock();
968     if (i) {
969         debugFatal("Could not start ieee1394 service thread\n");
970         return false;
971     }
972     m_threadRunning = true;
973
974     return true;
975 }
976
977 void
978 Ieee1394Service::stopRHThread()
979 {
980     if ( m_threadRunning ) {
981         // wait for the thread to finish it's work
982         m_RHThread_lock->Lock();
983         pthread_cancel (m_thread);
984         pthread_join (m_thread, 0);
985         m_RHThread_lock->Unlock();
986         m_threadRunning = false;
987     }
988 }
989
990 void*
991 Ieee1394Service::rHThread( void* arg )
992 {
993     Ieee1394Service* pIeee1394Service = (Ieee1394Service*) arg;
994
995     while (true) {
996         // protect ourselves from dying
997         {
998             // use a scoped lock such that it is unlocked
999             // even if we are cancelled while running
1000             // FIXME: check if this is true!
1001 //             Util::MutexLockHelper lock(*(pIeee1394Service->m_RHThread_lock));
1002             raw1394_loop_iterate (pIeee1394Service->m_resetHandle);
1003         }
1004         pthread_testcancel ();
1005     }
1006
1007     return 0;
1008 }
1009
1010 bool
1011 Ieee1394Service::addBusResetHandler( Util::Functor* functor )
1012 {
1013     debugOutput(DEBUG_LEVEL_VERBOSE, "Adding busreset handler (%p)\n", functor);
1014     m_busResetHandlers.push_back( functor );
1015     return true;
1016 }
1017
1018 bool
1019 Ieee1394Service::remBusResetHandler( Util::Functor* functor )
1020 {
1021     debugOutput(DEBUG_LEVEL_VERBOSE, "Removing busreset handler (%p)\n", functor);
1022
1023     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
1024           it != m_busResetHandlers.end();
1025           ++it )
1026     {
1027         if ( *it == functor ) {
1028             debugOutput(DEBUG_LEVEL_VERBOSE, " found\n");
1029             m_busResetHandlers.erase( it );
1030             return true;
1031         }
1032     }
1033     debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n");
1034     return false;
1035 }
1036
1037 /**
1038  * Allocates an iso channel for use by the interface in a similar way to
1039  * libiec61883.  Returns -1 on error (due to there being no free channels)
1040  * or an allocated channel number.
1041  *
1042  * Does not perform anything other than registering the channel and the
1043  * bandwidth at the IRM
1044  *
1045  * Also allocates the necessary bandwidth (in ISO allocation units).
1046  *
1047  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
1048  * bug or it's omitted since that's the channel preferred by video devices.
1049  *
1050  * @param bandwidth the bandwidth to allocate for this channel
1051  * @return the channel number
1052  */
1053 signed int Ieee1394Service::allocateIsoChannelGeneric(unsigned int bandwidth) {
1054     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using generic method...\n" );
1055
1056     Util::MutexLockHelper lock(*m_handle_lock);
1057     struct ChannelInfo cinfo;
1058
1059     int c = -1;
1060     for (c = 0; c < 63; c++) {
1061         if (raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_ALLOC) == 0)
1062             break;
1063     }
1064     if (c < 63) {
1065         if (raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
1066             debugFatal("Could not allocate bandwidth of %d\n", bandwidth);
1067
1068             raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
1069             return -1;
1070         } else {
1071             cinfo.channel=c;
1072             cinfo.bandwidth=bandwidth;
1073             cinfo.alloctype=AllocGeneric;
1074
1075             cinfo.xmit_node=-1;
1076             cinfo.xmit_plug=-1;
1077             cinfo.recv_node=-1;
1078             cinfo.recv_plug=-1;
1079
1080             if (registerIsoChannel(c, cinfo)) {
1081                 return c;
1082             } else {
1083                 raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_FREE);
1084                 raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
1085                 return -1;
1086             }
1087         }
1088     }
1089     return -1;
1090 }
1091
1092 /**
1093  * Allocates an iso channel for use by the interface in a similar way to
1094  * libiec61883.  Returns -1 on error (due to there being no free channels)
1095  * or an allocated channel number.
1096  *
1097  * Uses IEC61883 Connection Management Procedure to establish the connection.
1098  *
1099  * Also allocates the necessary bandwidth (in ISO allocation units).
1100  *
1101  * @param xmit_node  node id of the transmitter
1102  * @param xmit_plug  the output plug to use. If -1, find the first online plug, and
1103  * upon return, contains the plug number used.
1104  * @param recv_node  node id of the receiver
1105  * @param recv_plug the input plug to use. If -1, find the first online plug, and
1106  * upon return, contains the plug number used.
1107  *
1108  * @return the channel number
1109  */
1110
1111 signed int Ieee1394Service::allocateIsoChannelCMP(
1112     nodeid_t xmit_node, int xmit_plug,
1113     nodeid_t recv_node, int recv_plug
1114     ) {
1115
1116     if (xmit_node == INVALID_NODE_ID) {
1117         debugWarning("operation on invalid node (XMIT)\n");
1118         return -1;
1119     }
1120     if (recv_node == INVALID_NODE_ID) {
1121         debugWarning("operation on invalid node (RECV)\n");
1122         return -1;
1123     }
1124
1125     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using IEC61883 CMP...\n" );
1126     Util::MutexLockHelper lock(*m_handle_lock);
1127
1128     struct ChannelInfo cinfo;
1129
1130     int c = -1;
1131     int bandwidth=1;
1132     #if IEEE1394SERVICE_SKIP_IEC61883_BANDWIDTH_ALLOCATION
1133     bandwidth=0;
1134     #endif
1135
1136     // do connection management: make connection
1137     c = iec61883_cmp_connect(
1138         m_handle,
1139         xmit_node | 0xffc0,
1140         &xmit_plug,
1141         recv_node | 0xffc0,
1142         &recv_plug,
1143         &bandwidth);
1144
1145     if((c<0) || (c>63)) {
1146         debugError("Could not do CMP from %04X:%02d to %04X:%02d\n",
1147             xmit_node, xmit_plug, recv_node, recv_plug
1148             );
1149         return -1;
1150     }
1151
1152     cinfo.channel=c;
1153     cinfo.bandwidth=bandwidth;
1154     cinfo.alloctype=AllocCMP;
1155
1156     cinfo.xmit_node=xmit_node;
1157     cinfo.xmit_plug=xmit_plug;
1158     cinfo.recv_node=recv_node;
1159     cinfo.recv_plug=recv_plug;
1160
1161     if (registerIsoChannel(c, cinfo)) {
1162         return c;
1163     }
1164
1165     return -1;
1166 }
1167
1168 /**
1169  * Deallocates an iso channel.  Silently ignores a request to deallocate
1170  * a negative channel number.
1171  *
1172  * Figures out the method that was used to allocate the channel (generic, cmp, ...)
1173  * and uses the appropriate method to deallocate. Also frees the bandwidth
1174  * that was reserved along with this channel.
1175  *
1176  * @param c channel number
1177  * @return true if successful
1178  */
1179 bool Ieee1394Service::freeIsoChannel(signed int c) {
1180     debugOutput(DEBUG_LEVEL_VERBOSE, "Freeing ISO channel %d...\n", c );
1181     Util::MutexLockHelper lock(*m_handle_lock);
1182
1183     if (c < 0 || c > 63) {
1184         debugWarning("Invalid channel number: %d\n", c);
1185         return false;
1186     }
1187
1188     switch (m_channels[c].alloctype) {
1189         default:
1190             debugError(" BUG: invalid allocation type!\n");
1191             return false;
1192
1193         case AllocFree:
1194             debugWarning(" Channel %d not registered\n", c);
1195             return false;
1196
1197         case AllocGeneric:
1198             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using generic routine...\n" );
1199             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing %d bandwidth units...\n", m_channels[c].bandwidth );
1200             if (raw1394_bandwidth_modify(m_handle, m_channels[c].bandwidth, RAW1394_MODIFY_FREE) !=0) {
1201                 debugWarning("Failed to deallocate bandwidth\n");
1202             }
1203             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing channel %d...\n", m_channels[c].channel );
1204             if (raw1394_channel_modify (m_handle, m_channels[c].channel, RAW1394_MODIFY_FREE) != 0) {
1205                 debugWarning("Failed to free channel\n");
1206             }
1207             if (!unregisterIsoChannel(c))
1208                 return false;
1209             return true;
1210
1211         case AllocCMP:
1212             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using IEC61883 CMP...\n" );
1213             debugOutput(DEBUG_LEVEL_VERBOSE, " performing IEC61883 CMP disconnect...\n" );
1214             if(iec61883_cmp_disconnect(
1215                     m_handle,
1216                     m_channels[c].xmit_node | 0xffc0,
1217                     m_channels[c].xmit_plug,
1218                     m_channels[c].recv_node | 0xffc0,
1219                     m_channels[c].recv_plug,
1220                     m_channels[c].channel,
1221                     m_channels[c].bandwidth) != 0) {
1222                 debugWarning("Could not do CMP disconnect for channel %d!\n",c);
1223             }
1224             if (!unregisterIsoChannel(c))
1225                 return false;
1226             return true;
1227     }
1228
1229     // unreachable
1230     debugError("BUG: unreachable code reached!\n");
1231
1232     return false;
1233 }
1234
1235 /**
1236  * Registers a channel as managed by this ieee1394service
1237  * @param c channel number
1238  * @param cinfo channel info struct
1239  * @return true if successful
1240  */
1241 bool Ieee1394Service::registerIsoChannel(unsigned int c, struct ChannelInfo cinfo) {
1242     if (c < 63) {
1243         if (m_channels[c].alloctype != AllocFree) {
1244             debugWarning("Channel %d already registered with bandwidth %d\n",
1245                 m_channels[c].channel, m_channels[c].bandwidth);
1246         }
1247
1248         memcpy(&m_channels[c], &cinfo, sizeof(struct ChannelInfo));
1249
1250     } else return false;
1251     return true;
1252 }
1253
1254 /**
1255  * unegisters a channel from this ieee1394service
1256  * @param c channel number
1257  * @return true if successful
1258  */
1259 bool Ieee1394Service::unregisterIsoChannel(unsigned int c) {
1260     if (c < 63) {
1261         if (m_channels[c].alloctype == AllocFree) {
1262             debugWarning("Channel %d not registered\n", c);
1263             return false;
1264         }
1265
1266         m_channels[c].channel=-1;
1267         m_channels[c].bandwidth=-1;
1268         m_channels[c].alloctype=AllocFree;
1269         m_channels[c].xmit_node=0xFFFF;
1270         m_channels[c].xmit_plug=-1;
1271         m_channels[c].recv_node=0xFFFF;
1272         m_channels[c].recv_plug=-1;
1273
1274     } else return false;
1275     return true;
1276 }
1277
1278 /**
1279  * Returns the current value of the `bandwidth available' register on
1280  * the IRM, or -1 on error.
1281  * @return
1282  */
1283 signed int Ieee1394Service::getAvailableBandwidth() {
1284     quadlet_t buffer;
1285     Util::MutexLockHelper lock(*m_handle_lock);
1286     signed int result = raw1394_read (m_handle, raw1394_get_irm_id (m_handle),
1287         CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
1288         sizeof (quadlet_t), &buffer);
1289
1290     if (result < 0)
1291         return -1;
1292     return CondSwapFromBus32(buffer);
1293 }
1294
1295 void
1296 Ieee1394Service::setVerboseLevel(int l)
1297 {
1298     if (m_pIsoManager) m_pIsoManager->setVerboseLevel(l);
1299     if (m_pCTRHelper) m_pCTRHelper->setVerboseLevel(l);
1300     if (m_pWatchdog) m_pWatchdog->setVerboseLevel(l);
1301     setDebugLevel(l);
1302     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1303 }
1304
1305 void
1306 Ieee1394Service::show()
1307 {
1308     #ifdef DEBUG
1309     uint32_t cycle_timer;
1310     uint64_t local_time;
1311     if(!readCycleTimerReg(&cycle_timer, &local_time)) {
1312         debugWarning("Could not read cycle timer register\n");
1313    
1314     }
1315     uint64_t ctr = CYCLE_TIMER_TO_TICKS( cycle_timer );
1316
1317     debugOutput( DEBUG_LEVEL_VERBOSE, "Port:  %d\n", getPort() );
1318     debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() );
1319     debugOutput( DEBUG_LEVEL_VERBOSE, " CycleTimerHelper: %p, IsoManager: %p, WatchDog: %p\n",
1320                  m_pCTRHelper, m_pIsoManager, m_pWatchdog );
1321     debugOutput( DEBUG_LEVEL_VERBOSE, " Time: %011llu (%03us %04ucy %04uticks)\n",
1322                 ctr,
1323                 (unsigned int)TICKS_TO_SECS( ctr ),
1324                 (unsigned int)TICKS_TO_CYCLES( ctr ),
1325                 (unsigned int)TICKS_TO_OFFSET( ctr ) );
1326     debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n");
1327     #endif
1328     if (m_pIsoManager) m_pIsoManager->dumpInfo();
1329 }
Note: See TracBrowser for help on using the browser.