root/trunk/libffado/src/libieee1394/ieee1394service.cpp

Revision 1535, 50.1 kB (checked in by ppalmers, 15 years ago)

add support for the FCA-202, and possibly other Oxford FW-92x devices

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