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

Revision 1373, 42.6 kB (checked in by ppalmers, 12 years ago)

make IsoManager? and SPM settings from config.h overridable by the user/distro config file.

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