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

Revision 1451, 44.4 kB (checked in by wagi, 12 years ago)

Add workaround for the Edirol FA-101. The device issues more
than one FCP respond to one request. The IEEE1394 allows now
to filter for duplicated FCP packets. Though the filtering is
a rather ugly thing, it is only enabled for the FA-101. For all other
devices nothing changes.

Now with this fix the mixer should work for the FA-101 again.

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