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

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

Host controller reliability changes:

  • make receive DMA mode selectable (but still hardcoded ATM). Some controllers seem to work better in bufferfill mode.
  • introduce a maximum number of ISO buffers for receive, lower the max nb of ISO buffers for xmit
  • make the number of buffers for receive and transmit a power of two
  • ensure at least two hardware interrupts per complete ISO buffer wraparound
  • 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     // init helpers
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
312     m_pIsoManager->setReceiveMode(RAW1394_DMA_PACKET_PER_BUFFER);
313
314     if(!m_pIsoManager->init()) {
315         debugFatal("Could not initialize IsoHandlerManager\n");
316         return false;
317     }
318
319     startRHThread();
320
321     // make sure that the thread parameters of all our helper threads are OK
322     if(!setThreadParameters(m_realtime, m_base_priority)) {
323         debugFatal("Could not set thread parameters\n");
324         return false;
325     }
326     return true;
327 }
328
329 bool
330 Ieee1394Service::setThreadParameters(bool rt, int priority) {
331     bool result = true;
332     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO;
333     m_base_priority = priority;
334     m_realtime = rt;
335     if (m_pIsoManager) {
336         debugOutput(DEBUG_LEVEL_VERBOSE, "Switching IsoManager to (rt=%d, prio=%d)\n",
337                                          rt, priority);
338         result &= m_pIsoManager->setThreadParameters(rt, priority);
339     }
340     if (m_pCTRHelper) {
341         debugOutput(DEBUG_LEVEL_VERBOSE, "Switching CycleTimerHelper to (rt=%d, prio=%d)\n",
342                                          rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
343                                          priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);
344         result &= m_pCTRHelper->setThreadParameters(rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
345                                                     priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);
346     }
347     return result;
348 }
349
350 int
351 Ieee1394Service::getNodeCount()
352 {
353     Util::MutexLockHelper lock(*m_handle_lock);
354     return raw1394_get_nodecount( m_handle );
355 }
356
357 nodeid_t Ieee1394Service::getLocalNodeId() {
358     Util::MutexLockHelper lock(*m_handle_lock);
359     return raw1394_get_local_id(m_handle) & 0x3F;
360 }
361
362 /**
363  * Returns the current value of the cycle timer (in ticks)
364  *
365  * @return the current value of the cycle timer (in ticks)
366  */
367
368 uint32_t
369 Ieee1394Service::getCycleTimerTicks() {
370     return m_pCTRHelper->getCycleTimerTicks();
371 }
372
373 /**
374  * Returns the current value of the cycle timer (as is)
375  *
376  * @return the current value of the cycle timer (as is)
377  */
378 uint32_t
379 Ieee1394Service::getCycleTimer() {
380     return m_pCTRHelper->getCycleTimer();
381 }
382
383 /**
384  * Returns the current value of the cycle timer (in ticks)
385  * for a specific time instant (usecs since epoch)
386  * @return the current value of the cycle timer (in ticks)
387  */
388
389 uint32_t
390 Ieee1394Service::getCycleTimerTicks(uint64_t t) {
391     return m_pCTRHelper->getCycleTimerTicks(t);
392 }
393
394 /**
395  * Returns the current value of the cycle timer (as is)
396  * for a specific time instant (usecs since epoch)
397  * @return the current value of the cycle timer (as is)
398  */
399 uint32_t
400 Ieee1394Service::getCycleTimer(uint64_t t) {
401     return m_pCTRHelper->getCycleTimer(t);
402 }
403
404 uint64_t
405 Ieee1394Service::getSystemTimeForCycleTimerTicks(uint32_t ticks) {
406     return m_pCTRHelper->getSystemTimeForCycleTimerTicks(ticks);
407 }
408
409 uint64_t
410 Ieee1394Service::getSystemTimeForCycleTimer(uint32_t ctr) {
411     return m_pCTRHelper->getSystemTimeForCycleTimer(ctr);
412 }
413
414 bool
415 Ieee1394Service::readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time)
416 {
417     if(m_have_new_ctr_read) {
418         int err;
419         err = raw1394_read_cycle_timer(m_util_handle, cycle_timer, local_time);
420         if(err) {
421             debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err));
422             return false;
423         }
424         return true;
425     } else {
426         // do a normal read of the CTR register
427         // the disadvantage is that local_time and cycle time are not
428         // read at the same time instant (scheduling issues)
429         *local_time = getCurrentTimeAsUsecs();
430         if ( raw1394_read( m_util_handle,
431                 getLocalNodeId() | 0xFFC0,
432                 CSR_REGISTER_BASE | CSR_CYCLE_TIME,
433                 sizeof(uint32_t), cycle_timer ) == 0 ) {
434             *cycle_timer = CondSwapFromBus32(*cycle_timer);
435             return true;
436         } else {
437             return false;
438         }
439     }
440 }
441
442 uint64_t
443 Ieee1394Service::getCurrentTimeAsUsecs() {
444     return Util::SystemTimeSource::getCurrentTimeAsUsecs();
445 }
446
447 bool
448 Ieee1394Service::read( fb_nodeid_t nodeId,
449                        fb_nodeaddr_t addr,
450                        size_t length,
451                        fb_quadlet_t* buffer )
452 {
453     Util::MutexLockHelper lock(*m_handle_lock);
454     return readNoLock(nodeId, addr, length, buffer);
455 }
456
457 bool
458 Ieee1394Service::readNoLock( fb_nodeid_t nodeId,
459                              fb_nodeaddr_t addr,
460                              size_t length,
461                              fb_quadlet_t* buffer )
462 {
463     if (nodeId == INVALID_NODE_ID) {
464         debugWarning("operation on invalid node\n");
465         return false;
466     }
467     if ( raw1394_read( m_handle, nodeId, addr, length*4, buffer ) == 0 ) {
468
469         #ifdef DEBUG
470         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
471             "read: node 0x%hX, addr = 0x%016llX, length = %u\n",
472             nodeId, addr, length);
473         printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, buffer );
474         #endif
475
476         return true;
477     } else {
478         #ifdef DEBUG
479         debugOutput(DEBUG_LEVEL_NORMAL,
480                     "raw1394_read failed: node 0x%hX, addr = 0x%016llX, length = %u\n",
481                     nodeId, addr, length);
482         #endif
483         return false;
484     }
485 }
486
487 bool
488 Ieee1394Service::read_quadlet( fb_nodeid_t nodeId,
489                                fb_nodeaddr_t addr,
490                                fb_quadlet_t* buffer )
491 {
492     return read( nodeId,  addr, sizeof( *buffer )/4, buffer );
493 }
494
495 bool
496 Ieee1394Service::read_octlet( fb_nodeid_t nodeId,
497                               fb_nodeaddr_t addr,
498                               fb_octlet_t* buffer )
499 {
500     return read( nodeId, addr, sizeof( *buffer )/4,
501                  reinterpret_cast<fb_quadlet_t*>( buffer ) );
502 }
503
504 bool
505 Ieee1394Service::write( fb_nodeid_t nodeId,
506                         fb_nodeaddr_t addr,
507                         size_t length,
508                         fb_quadlet_t* data )
509 {
510     Util::MutexLockHelper lock(*m_handle_lock);
511     return writeNoLock(nodeId, addr, length, data);
512 }
513
514 bool
515 Ieee1394Service::writeNoLock( fb_nodeid_t nodeId,
516                               fb_nodeaddr_t addr,
517                               size_t length,
518                               fb_quadlet_t* data )
519 {
520     if (nodeId == INVALID_NODE_ID) {
521         debugWarning("operation on invalid node\n");
522         return false;
523     }
524
525     #ifdef DEBUG
526     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"write: node 0x%hX, addr = 0x%016llX, length = %d\n",
527                 nodeId, addr, length);
528     printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, data );
529     #endif
530
531     return raw1394_write( m_handle, nodeId, addr, length*4, data ) == 0;
532 }
533
534 bool
535 Ieee1394Service::write_quadlet( fb_nodeid_t nodeId,
536                                 fb_nodeaddr_t addr,
537                                 fb_quadlet_t data )
538 {
539     return write( nodeId, addr, sizeof( data )/4, &data );
540 }
541
542 bool
543 Ieee1394Service::write_octlet( fb_nodeid_t nodeId,
544                                fb_nodeaddr_t addr,
545                                fb_octlet_t data )
546 {
547     return write( nodeId, addr, sizeof( data )/4,
548                   reinterpret_cast<fb_quadlet_t*>( &data ) );
549 }
550
551 bool
552 Ieee1394Service::lockCompareSwap64( fb_nodeid_t nodeId,
553                                     fb_nodeaddr_t addr,
554                                     fb_octlet_t compare_value,
555                                     fb_octlet_t swap_value,
556                                     fb_octlet_t* result )
557 {
558     if (nodeId == INVALID_NODE_ID) {
559         debugWarning("operation on invalid node\n");
560         return false;
561     }
562     #ifdef DEBUG
563     debugOutput(DEBUG_LEVEL_VERBOSE,"lockCompareSwap64: node 0x%X, addr = 0x%016llX\n",
564                 nodeId, addr);
565     debugOutput(DEBUG_LEVEL_VERBOSE,"  if (*(addr)==0x%016llX) *(addr)=0x%016llX\n",
566                 compare_value, swap_value);
567     fb_octlet_t buffer;
568     if(!read_octlet( nodeId, addr,&buffer )) {
569         debugWarning("Could not read register\n");
570     } else {
571         debugOutput(DEBUG_LEVEL_VERBOSE,"before = 0x%016llX\n", buffer);
572     }
573     #endif
574
575     // do endiannes swapping
576     compare_value = CondSwapToBus64(compare_value);
577     swap_value    = CondSwapToBus64(swap_value);
578
579     // do separate locking here (no MutexLockHelper) since
580     // we use read_octlet in the DEBUG code in this function
581     m_handle_lock->Lock();
582     int retval=raw1394_lock64(m_handle, nodeId, addr,
583                               RAW1394_EXTCODE_COMPARE_SWAP,
584                               swap_value, compare_value, result);
585     m_handle_lock->Unlock();
586
587     if(retval) {
588         debugError("raw1394_lock64 failed: %s\n", strerror(errno));
589     }
590
591     #ifdef DEBUG
592     if(!read_octlet( nodeId, addr,&buffer )) {
593         debugWarning("Could not read register\n");
594     } else {
595         debugOutput(DEBUG_LEVEL_VERBOSE,"after = 0x%016llX\n", buffer);
596     }
597     #endif
598
599     *result = CondSwapFromBus64(*result);
600
601     return (retval == 0);
602 }
603
604 fb_quadlet_t*
605 Ieee1394Service::transactionBlock( fb_nodeid_t nodeId,
606                                    fb_quadlet_t* buf,
607                                    int len,
608                                    unsigned int* resp_len )
609 {
610     // FIXME: simplify semantics
611     if (nodeId == INVALID_NODE_ID) {
612         debugWarning("operation on invalid node\n");
613         return false;
614     }
615     // NOTE: this expects a call to transactionBlockClose to unlock
616     m_handle_lock->Lock();
617
618     // clear the request & response memory
619     memset(&m_fcp_block, 0, sizeof(m_fcp_block));
620
621     // make a local copy of the request
622     if(len < MAX_FCP_BLOCK_SIZE_QUADS) {
623         memcpy(m_fcp_block.request, buf, len*sizeof(quadlet_t));
624         m_fcp_block.request_length = len;
625     } else {
626         debugWarning("Truncating FCP request\n");
627         memcpy(m_fcp_block.request, buf, MAX_FCP_BLOCK_SIZE_BYTES);
628         m_fcp_block.request_length = MAX_FCP_BLOCK_SIZE_QUADS;
629     }
630     m_fcp_block.target_nodeid = 0xffc0 | nodeId;
631
632     bool success = doFcpTransaction();
633     if(success) {
634         *resp_len = m_fcp_block.response_length;
635         return m_fcp_block.response;
636     } else {
637         debugWarning("FCP transaction failed\n");
638         *resp_len = 0;
639         return NULL;
640     }
641 }
642
643 bool
644 Ieee1394Service::transactionBlockClose()
645 {
646     m_handle_lock->Unlock();
647     return true;
648 }
649
650 // FCP code
651 bool
652 Ieee1394Service::doFcpTransaction()
653 {
654     for(int i=0; i < IEEE1394SERVICE_FCP_MAX_TRIES; i++) {
655         if(doFcpTransactionTry()) {
656             return true;
657         } else {
658             debugOutput(DEBUG_LEVEL_VERBOSE, "FCP transaction try %d failed\n", i);
659             Util::SystemTimeSource::SleepUsecRelative( IEEE1394SERVICE_FCP_SLEEP_BETWEEN_FAILURES_USECS);
660         }
661     }
662     debugError("FCP transaction didn't succeed in %d tries\n", IEEE1394SERVICE_FCP_MAX_TRIES);
663     return false;
664 }
665
666 #define FCP_COMMAND_ADDR   0xFFFFF0000B00ULL
667 #define FCP_RESPONSE_ADDR  0xFFFFF0000D00ULL
668
669 /* AV/C FCP response codes */
670 #define FCP_RESPONSE_NOT_IMPLEMENTED 0x08000000
671 #define FCP_RESPONSE_ACCEPTED 0x09000000
672 #define FCP_RESPONSE_REJECTED 0x0A000000
673 #define FCP_RESPONSE_IN_TRANSITION 0x0B000000
674 #define FCP_RESPONSE_IMPLEMENTED 0x0C000000
675 #define FCP_RESPONSE_STABLE 0x0C000000
676 #define FCP_RESPONSE_CHANGED 0x0D000000
677 #define FCP_RESPONSE_INTERIM 0x0F000000
678
679 /* AV/C FCP mask macros */
680 #define FCP_MASK_START(x) ((x) & 0xF0000000)
681 #define FCP_MASK_CTYPE(x) ((x) & 0x0F000000)
682 #define FCP_MASK_RESPONSE(x) ((x) & 0x0F000000)
683 #define FCP_MASK_SUBUNIT(x) ((x) & 0x00FF0000)
684 #define FCP_MASK_SUBUNIT_TYPE(x) ((x) & 0x00F80000)
685 #define FCP_MASK_SUBUNIT_ID(x) ((x) & 0x00070000)
686 #define FCP_MASK_OPCODE(x) ((x) & 0x0000FF00)
687 #define FCP_MASK_SUBUNIT_AND_OPCODE(x) ((x) & 0x00FFFF00)
688 #define FCP_MASK_OPERAND0(x) ((x) & 0x000000FF)
689 #define FCP_MASK_OPERAND(x, n) ((x) & (0xFF000000 >> ((((n)-1)%4)*8)))
690 #define FCP_MASK_RESPONSE_OPERAND(x, n) ((x) & (0xFF000000 >> (((n)%4)*8)))
691
692 bool
693 Ieee1394Service::doFcpTransactionTry()
694 {
695     // NOTE that access to this is protected by the m_handle lock
696     int err;
697     bool retval = true;
698     uint64_t timeout;
699
700     // prepare an fcp response handler
701     raw1394_set_fcp_handler(m_handle, _avc_fcp_handler);
702
703     // start listening for FCP requests
704     // this fails if some other program is listening for a FCP response
705     err = raw1394_start_fcp_listen(m_handle);
706     if(err) {
707         debugOutput(DEBUG_LEVEL_VERBOSE, "could not start FCP listen (err=%d, errno=%d)\n", err, errno);
708         retval = false;
709         goto out;
710     }
711
712     m_fcp_block.status = eFS_Waiting;
713
714     #ifdef DEBUG
715     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"fcp request: node 0x%hX, length = %d bytes\n",
716                 m_fcp_block.target_nodeid, m_fcp_block.request_length*4);
717     printBuffer(DEBUG_LEVEL_VERY_VERBOSE, m_fcp_block.request_length, m_fcp_block.request );
718     #endif
719
720     // write the FCP request
721     if(!writeNoLock( m_fcp_block.target_nodeid, FCP_COMMAND_ADDR,
722                      m_fcp_block.request_length, m_fcp_block.request)) {
723         debugOutput(DEBUG_LEVEL_VERBOSE, "write of FCP request failed\n");
724         retval = false;
725         goto out;
726     }
727
728     // wait for the response to arrive
729     struct pollfd raw1394_poll;
730     raw1394_poll.fd = raw1394_get_fd(m_handle);
731     raw1394_poll.events = POLLIN;
732
733     timeout = Util::SystemTimeSource::getCurrentTimeAsUsecs() +
734               IEEE1394SERVICE_FCP_RESPONSE_TIMEOUT_USEC;
735
736     while(m_fcp_block.status == eFS_Waiting
737           && Util::SystemTimeSource::getCurrentTimeAsUsecs() < timeout) {
738         if(poll( &raw1394_poll, 1, IEEE1394SERVICE_FCP_POLL_TIMEOUT_MSEC) > 0) {
739             if (raw1394_poll.revents & POLLIN) {
740                 raw1394_loop_iterate(m_handle);
741             }
742         }
743     }
744
745     // stop listening for FCP responses
746     err = raw1394_stop_fcp_listen(m_handle);
747     if(err) {
748         debugOutput(DEBUG_LEVEL_VERBOSE, "could not stop FCP listen (err=%d, errno=%d)\n", err, errno);
749         retval = false;
750         goto out;
751     }
752
753     // check the request and figure out what happened
754     if(m_fcp_block.status == eFS_Waiting) {
755         debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response timed out\n");
756         retval = false;
757         goto out;
758     }
759     if(m_fcp_block.status == eFS_Error) {
760         debugError("FCP request/response error\n");
761         retval = false;
762         goto out;
763     }
764
765 out:
766     m_fcp_block.status = eFS_Empty;
767     return retval;
768 }
769
770 int
771 Ieee1394Service::_avc_fcp_handler(raw1394handle_t handle, nodeid_t nodeid,
772                                   int response, size_t length,
773                                   unsigned char *data)
774 {
775     Ieee1394Service *service = static_cast<Ieee1394Service *>(raw1394_get_userdata(handle));
776     if(service) {
777         return service->handleFcpResponse(nodeid, response, length, data);
778     } else return -1;
779 }
780
781 int
782 Ieee1394Service::handleFcpResponse(nodeid_t nodeid,
783                                    int response, size_t length,
784                                    unsigned char *data)
785 {
786     fb_quadlet_t *data_quads = (fb_quadlet_t *)data;
787     #ifdef DEBUG
788     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"fcp response: node 0x%hX, response = %d, length = %d bytes\n",
789                 nodeid, response, length);
790     printBuffer(DEBUG_LEVEL_VERY_VERBOSE, (length+3)/4, data_quads );
791     #endif
792
793     if (response && length > 3) {
794         if(length > MAX_FCP_BLOCK_SIZE_BYTES) {
795             length = MAX_FCP_BLOCK_SIZE_BYTES;
796             debugWarning("Truncated FCP response\n");
797         }
798
799         // is it an actual response or is it INTERIM?
800         quadlet_t first_quadlet = CondSwapFromBus32(data_quads[0]);
801         if(FCP_MASK_RESPONSE(first_quadlet) == FCP_RESPONSE_INTERIM) {
802             debugOutput(DEBUG_LEVEL_VERBOSE, "INTERIM\n");
803         } else {
804             // it's an actual response, check if it matches our request
805             if(nodeid != m_fcp_block.target_nodeid) {
806                 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response node id's don't match! (%x, %x)\n",
807                                                  m_fcp_block.target_nodeid, nodeid);
808             } else if (first_quadlet == 0) {
809                 debugWarning("Bogus FCP response\n");
810                 printBuffer(DEBUG_LEVEL_WARNING, (length+3)/4, data_quads );
811 #ifdef DEBUG
812             } else if(FCP_MASK_RESPONSE(first_quadlet) < 0x08000000) {
813                 debugWarning("Bogus AV/C FCP response code\n");
814                 printBuffer(DEBUG_LEVEL_WARNING, (length+3)/4, data_quads );
815 #endif
816             } else if(FCP_MASK_SUBUNIT_AND_OPCODE(first_quadlet)
817                       != FCP_MASK_SUBUNIT_AND_OPCODE(CondSwapFromBus32(m_fcp_block.request[0]))) {
818                 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response not for this request: %08lX != %08lX\n",
819                              FCP_MASK_SUBUNIT_AND_OPCODE(first_quadlet),
820                              FCP_MASK_SUBUNIT_AND_OPCODE(CondSwapFromBus32(m_fcp_block.request[0])));
821             } else {
822                 m_fcp_block.response_length = (length + sizeof(quadlet_t) - 1) / sizeof(quadlet_t);
823                 memcpy(m_fcp_block.response, data, length);
824                 m_fcp_block.status = eFS_Responded;
825             }
826        }
827     }
828     return 0;
829 }
830
831 bool
832 Ieee1394Service::setSplitTimeoutUsecs(fb_nodeid_t nodeId, unsigned int timeout)
833 {
834     Util::MutexLockHelper lock(*m_handle_lock);
835     debugOutput(DEBUG_LEVEL_VERBOSE, "setting SPLIT_TIMEOUT on node 0x%X to %uusecs...\n", nodeId, timeout);
836     unsigned int secs = timeout / 1000000;
837     unsigned int usecs = timeout % 1000000;
838
839     quadlet_t split_timeout_hi = CondSwapToBus32(secs & 7);
840     quadlet_t split_timeout_low = CondSwapToBus32(((usecs / 125) & 0x1FFF) << 19);
841
842     // write the CSR registers
843     if(!writeNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_HI, 1,
844                   &split_timeout_hi)) {
845         debugOutput(DEBUG_LEVEL_VERBOSE, "write of CSR_SPLIT_TIMEOUT_HI failed\n");
846         return false;
847     }
848     if(!writeNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_LO, 1,
849                   &split_timeout_low)) {
850         debugOutput(DEBUG_LEVEL_VERBOSE, "write of CSR_SPLIT_TIMEOUT_LO failed\n");
851         return false;
852     }
853     return true;
854 }
855
856 int
857 Ieee1394Service::getSplitTimeoutUsecs(fb_nodeid_t nodeId)
858 {
859     Util::MutexLockHelper lock(*m_handle_lock);
860     quadlet_t split_timeout_hi;
861     quadlet_t split_timeout_low;
862
863     debugOutput(DEBUG_LEVEL_VERBOSE, "reading SPLIT_TIMEOUT on node 0x%X...\n", nodeId);
864
865     if(!readNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_HI, 1,
866                   &split_timeout_hi)) {
867         debugOutput(DEBUG_LEVEL_VERBOSE, "read of CSR_SPLIT_TIMEOUT_HI failed\n");
868         return 0;
869     }
870     debugOutput(DEBUG_LEVEL_VERBOSE, " READ HI: 0x%08lX\n", split_timeout_hi);
871
872     if(!readNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_LO, 1,
873                   &split_timeout_low)) {
874         debugOutput(DEBUG_LEVEL_VERBOSE, "read of CSR_SPLIT_TIMEOUT_LO failed\n");
875         return 0;
876     }
877     debugOutput(DEBUG_LEVEL_VERBOSE, " READ LO: 0x%08lX\n", split_timeout_low);
878
879     split_timeout_hi = CondSwapFromBus32(split_timeout_hi);
880     split_timeout_low = CondSwapFromBus32(split_timeout_low);
881
882     return (split_timeout_hi & 7) * 1000000 + (split_timeout_low >> 19) * 125;
883 }
884
885 int
886 Ieee1394Service::getVerboseLevel()
887 {
888     return getDebugLevel();
889 }
890
891 void
892 Ieee1394Service::printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const
893 {
894
895     for ( unsigned int i=0; i < length; ++i ) {
896         if ( ( i % 4 ) == 0 ) {
897             if ( i > 0 ) {
898                 debugOutputShort(level,"\n");
899             }
900             debugOutputShort(level," %4d: ",i*4);
901         }
902         debugOutputShort(level,"%08X ",buffer[i]);
903     }
904     debugOutputShort(level,"\n");
905 }
906 void
907 Ieee1394Service::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const
908 {
909
910     for ( unsigned int i=0; i < length; ++i ) {
911         if ( ( i % 16 ) == 0 ) {
912             if ( i > 0 ) {
913                 debugOutputShort(level,"\n");
914             }
915             debugOutputShort(level," %4d: ",i*16);
916         }
917         debugOutputShort(level,"%02X ",buffer[i]);
918     }
919     debugOutputShort(level,"\n");
920 }
921
922 int
923 Ieee1394Service::resetHandlerLowLevel( raw1394handle_t handle,
924                                        unsigned int generation )
925 {
926     raw1394_update_generation ( handle, generation );
927     Ieee1394Service* instance
928         = (Ieee1394Service*) raw1394_get_userdata( handle );
929     instance->resetHandler( generation );
930
931     return 0;
932 }
933
934 bool
935 Ieee1394Service::resetHandler( unsigned int generation )
936 {
937     quadlet_t buf=0;
938
939     m_handle_lock->Lock();
940     raw1394_update_generation(m_handle, generation);
941     m_handle_lock->Unlock();
942
943     // do a simple read on ourself in order to update the internal structures
944     // this avoids failures after a bus reset
945     read_quadlet( getLocalNodeId() | 0xFFC0,
946                   CSR_REGISTER_BASE | CSR_CYCLE_TIME,
947                   &buf );
948
949     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
950           it != m_busResetHandlers.end();
951           ++it )
952     {
953         Util::Functor* func = *it;
954         ( *func )();
955     }
956
957     return true;
958 }
959
960 bool
961 Ieee1394Service::startRHThread()
962 {
963     int i;
964
965     if ( m_threadRunning ) {
966         return true;
967     }
968     m_RHThread_lock->Lock();
969     i = pthread_create( &m_thread, 0, rHThread, this );
970     m_RHThread_lock->Unlock();
971     if (i) {
972         debugFatal("Could not start ieee1394 service thread\n");
973         return false;
974     }
975     m_threadRunning = true;
976
977     return true;
978 }
979
980 void
981 Ieee1394Service::stopRHThread()
982 {
983     if ( m_threadRunning ) {
984         // wait for the thread to finish it's work
985         m_RHThread_lock->Lock();
986         pthread_cancel (m_thread);
987         pthread_join (m_thread, 0);
988         m_RHThread_lock->Unlock();
989         m_threadRunning = false;
990     }
991 }
992
993 void*
994 Ieee1394Service::rHThread( void* arg )
995 {
996     Ieee1394Service* pIeee1394Service = (Ieee1394Service*) arg;
997
998     while (true) {
999         // protect ourselves from dying
1000         {
1001             // use a scoped lock such that it is unlocked
1002             // even if we are cancelled while running
1003             // FIXME: check if this is true!
1004 //             Util::MutexLockHelper lock(*(pIeee1394Service->m_RHThread_lock));
1005             raw1394_loop_iterate (pIeee1394Service->m_resetHandle);
1006         }
1007         pthread_testcancel ();
1008     }
1009
1010     return 0;
1011 }
1012
1013 bool
1014 Ieee1394Service::addBusResetHandler( Util::Functor* functor )
1015 {
1016     debugOutput(DEBUG_LEVEL_VERBOSE, "Adding busreset handler (%p)\n", functor);
1017     m_busResetHandlers.push_back( functor );
1018     return true;
1019 }
1020
1021 bool
1022 Ieee1394Service::remBusResetHandler( Util::Functor* functor )
1023 {
1024     debugOutput(DEBUG_LEVEL_VERBOSE, "Removing busreset handler (%p)\n", functor);
1025
1026     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
1027           it != m_busResetHandlers.end();
1028           ++it )
1029     {
1030         if ( *it == functor ) {
1031             debugOutput(DEBUG_LEVEL_VERBOSE, " found\n");
1032             m_busResetHandlers.erase( it );
1033             return true;
1034         }
1035     }
1036     debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n");
1037     return false;
1038 }
1039
1040 /**
1041  * Allocates an iso channel for use by the interface in a similar way to
1042  * libiec61883.  Returns -1 on error (due to there being no free channels)
1043  * or an allocated channel number.
1044  *
1045  * Does not perform anything other than registering the channel and the
1046  * bandwidth at the IRM
1047  *
1048  * Also allocates the necessary bandwidth (in ISO allocation units).
1049  *
1050  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
1051  * bug or it's omitted since that's the channel preferred by video devices.
1052  *
1053  * @param bandwidth the bandwidth to allocate for this channel
1054  * @return the channel number
1055  */
1056 signed int Ieee1394Service::allocateIsoChannelGeneric(unsigned int bandwidth) {
1057     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using generic method...\n" );
1058
1059     Util::MutexLockHelper lock(*m_handle_lock);
1060     struct ChannelInfo cinfo;
1061
1062     int c = -1;
1063     for (c = 0; c < 63; c++) {
1064         if (raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_ALLOC) == 0)
1065             break;
1066     }
1067     if (c < 63) {
1068         if (raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
1069             debugFatal("Could not allocate bandwidth of %d\n", bandwidth);
1070
1071             raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
1072             return -1;
1073         } else {
1074             cinfo.channel=c;
1075             cinfo.bandwidth=bandwidth;
1076             cinfo.alloctype=AllocGeneric;
1077
1078             cinfo.xmit_node=-1;
1079             cinfo.xmit_plug=-1;
1080             cinfo.recv_node=-1;
1081             cinfo.recv_plug=-1;
1082
1083             if (registerIsoChannel(c, cinfo)) {
1084                 return c;
1085             } else {
1086                 raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_FREE);
1087                 raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
1088                 return -1;
1089             }
1090         }
1091     }
1092     return -1;
1093 }
1094
1095 /**
1096  * Allocates an iso channel for use by the interface in a similar way to
1097  * libiec61883.  Returns -1 on error (due to there being no free channels)
1098  * or an allocated channel number.
1099  *
1100  * Uses IEC61883 Connection Management Procedure to establish the connection.
1101  *
1102  * Also allocates the necessary bandwidth (in ISO allocation units).
1103  *
1104  * @param xmit_node  node id of the transmitter
1105  * @param xmit_plug  the output plug to use. If -1, find the first online plug, and
1106  * upon return, contains the plug number used.
1107  * @param recv_node  node id of the receiver
1108  * @param recv_plug the input plug to use. If -1, find the first online plug, and
1109  * upon return, contains the plug number used.
1110  *
1111  * @return the channel number
1112  */
1113
1114 signed int Ieee1394Service::allocateIsoChannelCMP(
1115     nodeid_t xmit_node, int xmit_plug,
1116     nodeid_t recv_node, int recv_plug
1117     ) {
1118
1119     if (xmit_node == INVALID_NODE_ID) {
1120         debugWarning("operation on invalid node (XMIT)\n");
1121         return -1;
1122     }
1123     if (recv_node == INVALID_NODE_ID) {
1124         debugWarning("operation on invalid node (RECV)\n");
1125         return -1;
1126     }
1127
1128     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using IEC61883 CMP...\n" );
1129     Util::MutexLockHelper lock(*m_handle_lock);
1130
1131     struct ChannelInfo cinfo;
1132
1133     int c = -1;
1134     int bandwidth=1;
1135     #if IEEE1394SERVICE_SKIP_IEC61883_BANDWIDTH_ALLOCATION
1136     bandwidth=0;
1137     #endif
1138
1139     // do connection management: make connection
1140     c = iec61883_cmp_connect(
1141         m_handle,
1142         xmit_node | 0xffc0,
1143         &xmit_plug,
1144         recv_node | 0xffc0,
1145         &recv_plug,
1146         &bandwidth);
1147
1148     if((c<0) || (c>63)) {
1149         debugError("Could not do CMP from %04X:%02d to %04X:%02d\n",
1150             xmit_node, xmit_plug, recv_node, recv_plug
1151             );
1152         return -1;
1153     }
1154
1155     cinfo.channel=c;
1156     cinfo.bandwidth=bandwidth;
1157     cinfo.alloctype=AllocCMP;
1158
1159     cinfo.xmit_node=xmit_node;
1160     cinfo.xmit_plug=xmit_plug;
1161     cinfo.recv_node=recv_node;
1162     cinfo.recv_plug=recv_plug;
1163
1164     if (registerIsoChannel(c, cinfo)) {
1165         return c;
1166     }
1167
1168     return -1;
1169 }
1170
1171 /**
1172  * Deallocates an iso channel.  Silently ignores a request to deallocate
1173  * a negative channel number.
1174  *
1175  * Figures out the method that was used to allocate the channel (generic, cmp, ...)
1176  * and uses the appropriate method to deallocate. Also frees the bandwidth
1177  * that was reserved along with this channel.
1178  *
1179  * @param c channel number
1180  * @return true if successful
1181  */
1182 bool Ieee1394Service::freeIsoChannel(signed int c) {
1183     debugOutput(DEBUG_LEVEL_VERBOSE, "Freeing ISO channel %d...\n", c );
1184     Util::MutexLockHelper lock(*m_handle_lock);
1185
1186     if (c < 0 || c > 63) {
1187         debugWarning("Invalid channel number: %d\n", c);
1188         return false;
1189     }
1190
1191     switch (m_channels[c].alloctype) {
1192         default:
1193             debugError(" BUG: invalid allocation type!\n");
1194             return false;
1195
1196         case AllocFree:
1197             debugWarning(" Channel %d not registered\n", c);
1198             return false;
1199
1200         case AllocGeneric:
1201             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using generic routine...\n" );
1202             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing %d bandwidth units...\n", m_channels[c].bandwidth );
1203             if (raw1394_bandwidth_modify(m_handle, m_channels[c].bandwidth, RAW1394_MODIFY_FREE) !=0) {
1204                 debugWarning("Failed to deallocate bandwidth\n");
1205             }
1206             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing channel %d...\n", m_channels[c].channel );
1207             if (raw1394_channel_modify (m_handle, m_channels[c].channel, RAW1394_MODIFY_FREE) != 0) {
1208                 debugWarning("Failed to free channel\n");
1209             }
1210             if (!unregisterIsoChannel(c))
1211                 return false;
1212             return true;
1213
1214         case AllocCMP:
1215             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using IEC61883 CMP...\n" );
1216             debugOutput(DEBUG_LEVEL_VERBOSE, " performing IEC61883 CMP disconnect...\n" );
1217             if(iec61883_cmp_disconnect(
1218                     m_handle,
1219                     m_channels[c].xmit_node | 0xffc0,
1220                     m_channels[c].xmit_plug,
1221                     m_channels[c].recv_node | 0xffc0,
1222                     m_channels[c].recv_plug,
1223                     m_channels[c].channel,
1224                     m_channels[c].bandwidth) != 0) {
1225                 debugWarning("Could not do CMP disconnect for channel %d!\n",c);
1226             }
1227             if (!unregisterIsoChannel(c))
1228                 return false;
1229             return true;
1230     }
1231
1232     // unreachable
1233     debugError("BUG: unreachable code reached!\n");
1234
1235     return false;
1236 }
1237
1238 /**
1239  * Registers a channel as managed by this ieee1394service
1240  * @param c channel number
1241  * @param cinfo channel info struct
1242  * @return true if successful
1243  */
1244 bool Ieee1394Service::registerIsoChannel(unsigned int c, struct ChannelInfo cinfo) {
1245     if (c < 63) {
1246         if (m_channels[c].alloctype != AllocFree) {
1247             debugWarning("Channel %d already registered with bandwidth %d\n",
1248                 m_channels[c].channel, m_channels[c].bandwidth);
1249         }
1250
1251         memcpy(&m_channels[c], &cinfo, sizeof(struct ChannelInfo));
1252
1253     } else return false;
1254     return true;
1255 }
1256
1257 /**
1258  * unegisters a channel from this ieee1394service
1259  * @param c channel number
1260  * @return true if successful
1261  */
1262 bool Ieee1394Service::unregisterIsoChannel(unsigned int c) {
1263     if (c < 63) {
1264         if (m_channels[c].alloctype == AllocFree) {
1265             debugWarning("Channel %d not registered\n", c);
1266             return false;
1267         }
1268
1269         m_channels[c].channel=-1;
1270         m_channels[c].bandwidth=-1;
1271         m_channels[c].alloctype=AllocFree;
1272         m_channels[c].xmit_node=0xFFFF;
1273         m_channels[c].xmit_plug=-1;
1274         m_channels[c].recv_node=0xFFFF;
1275         m_channels[c].recv_plug=-1;
1276
1277     } else return false;
1278     return true;
1279 }
1280
1281 /**
1282  * Returns the current value of the `bandwidth available' register on
1283  * the IRM, or -1 on error.
1284  * @return
1285  */
1286 signed int Ieee1394Service::getAvailableBandwidth() {
1287     quadlet_t buffer;
1288     Util::MutexLockHelper lock(*m_handle_lock);
1289     signed int result = raw1394_read (m_handle, raw1394_get_irm_id (m_handle),
1290         CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
1291         sizeof (quadlet_t), &buffer);
1292
1293     if (result < 0)
1294         return -1;
1295     return CondSwapFromBus32(buffer);
1296 }
1297
1298 void
1299 Ieee1394Service::setVerboseLevel(int l)
1300 {
1301     if (m_pIsoManager) m_pIsoManager->setVerboseLevel(l);
1302     if (m_pCTRHelper) m_pCTRHelper->setVerboseLevel(l);
1303     if (m_pWatchdog) m_pWatchdog->setVerboseLevel(l);
1304     setDebugLevel(l);
1305     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1306 }
1307
1308 void
1309 Ieee1394Service::show()
1310 {
1311     #ifdef DEBUG
1312     uint32_t cycle_timer;
1313     uint64_t local_time;
1314     if(!readCycleTimerReg(&cycle_timer, &local_time)) {
1315         debugWarning("Could not read cycle timer register\n");
1316    
1317     }
1318     uint64_t ctr = CYCLE_TIMER_TO_TICKS( cycle_timer );
1319
1320     debugOutput( DEBUG_LEVEL_VERBOSE, "Port:  %d\n", getPort() );
1321     debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() );
1322     debugOutput( DEBUG_LEVEL_VERBOSE, " CycleTimerHelper: %p, IsoManager: %p, WatchDog: %p\n",
1323                  m_pCTRHelper, m_pIsoManager, m_pWatchdog );
1324     debugOutput( DEBUG_LEVEL_VERBOSE, " Time: %011llu (%03us %04ucy %04uticks)\n",
1325                 ctr,
1326                 (unsigned int)TICKS_TO_SECS( ctr ),
1327                 (unsigned int)TICKS_TO_CYCLES( ctr ),
1328                 (unsigned int)TICKS_TO_OFFSET( ctr ) );
1329     debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n");
1330     #endif
1331     if (m_pIsoManager) m_pIsoManager->dumpInfo();
1332 }
Note: See TracBrowser for help on using the browser.