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

Revision 1163, 35.3 kB (checked in by ppalmers, 15 years ago)

make dbus server handle busresets cleanly (fixes #102)

  • 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 "ARMHandler.h"
28 #include "cycletimer.h"
29 #include "IsoHandlerManager.h"
30 #include "CycleTimerHelper.h"
31
32 #include <libavc1394/avc1394.h>
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
40 #include <errno.h>
41 #include "libutil/ByteSwap.h"
42
43 #include <string.h>
44
45 #include <iostream>
46 #include <iomanip>
47
48 IMPL_DEBUG_MODULE( Ieee1394Service, Ieee1394Service, DEBUG_LEVEL_NORMAL );
49
50 Ieee1394Service::Ieee1394Service()
51     : m_handle( 0 )
52     , m_handle_lock( new Util::PosixMutex() )
53     , m_resetHandle( 0 )
54     , m_util_handle( 0 )
55     , m_port( -1 )
56     , m_RHThread_lock( new Util::PosixMutex() )
57     , m_threadRunning( false )
58     , m_realtime ( false )
59     , m_base_priority ( 0 )
60     , m_pIsoManager( new IsoHandlerManager( *this ) )
61     , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC ) )
62     , m_have_new_ctr_read ( false )
63     , m_pWatchdog ( new Util::Watchdog() )
64 {
65     for (unsigned int i=0; i<64; i++) {
66         m_channels[i].channel=-1;
67         m_channels[i].bandwidth=-1;
68         m_channels[i].alloctype=AllocFree;
69         m_channels[i].xmit_node=0xFFFF;
70         m_channels[i].xmit_plug=-1;
71         m_channels[i].recv_node=0xFFFF;
72         m_channels[i].recv_plug=-1;
73     }
74 }
75
76 Ieee1394Service::Ieee1394Service(bool rt, int prio)
77     : m_handle( 0 )
78     , m_handle_lock( new Util::PosixMutex() )
79     , m_resetHandle( 0 )
80     , m_util_handle( 0 )
81     , m_port( -1 )
82     , m_RHThread_lock( new Util::PosixMutex() )
83     , m_threadRunning( false )
84     , m_realtime ( rt )
85     , m_base_priority ( prio )
86     , m_pIsoManager( new IsoHandlerManager( *this, rt, prio ) )
87     , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC,
88                                            rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
89                                            prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) )
90     , m_have_new_ctr_read ( false )
91     , m_pWatchdog ( new Util::Watchdog() )
92 {
93     for (unsigned int i=0; i<64; i++) {
94         m_channels[i].channel=-1;
95         m_channels[i].bandwidth=-1;
96         m_channels[i].alloctype=AllocFree;
97         m_channels[i].xmit_node=0xFFFF;
98         m_channels[i].xmit_plug=-1;
99         m_channels[i].recv_node=0xFFFF;
100         m_channels[i].recv_plug=-1;
101     }
102 }
103
104 Ieee1394Service::~Ieee1394Service()
105 {
106     delete m_pIsoManager;
107     delete m_pCTRHelper;
108     stopRHThread();
109     for ( arm_handler_vec_t::iterator it = m_armHandlers.begin();
110           it != m_armHandlers.end();
111           ++it )
112     {
113         debugOutput(DEBUG_LEVEL_VERBOSE, "Unregistering ARM handler for 0x%016llX\n", (*it)->getStart());
114         int err=raw1394_arm_unregister(m_resetHandle, (*it)->getStart());
115         if (err) {
116             debugError(" Failed to unregister ARM handler for 0x%016llX\n", (*it)->getStart());
117             debugError(" Error: %s\n", strerror(errno));
118         }
119     }
120
121     delete m_pWatchdog;
122     if ( m_handle ) {
123         raw1394_destroy_handle( m_handle );
124     }
125     delete m_handle_lock;
126
127     if ( m_resetHandle ) {
128         raw1394_destroy_handle( m_resetHandle );
129     }
130     delete m_RHThread_lock;
131     if ( m_util_handle ) {
132         raw1394_destroy_handle( m_util_handle );
133     }
134 }
135
136 int
137 Ieee1394Service::detectNbPorts()
138 {
139     raw1394handle_t tmp_handle = raw1394_new_handle();
140     if ( tmp_handle == NULL ) {
141         debugError("Could not get libraw1394 handle.\n");
142         return -1;
143     }
144     struct raw1394_portinfo pinf[IEEE1394SERVICE_MAX_FIREWIRE_PORTS];
145     int nb_detected_ports = raw1394_get_port_info(tmp_handle, pinf, IEEE1394SERVICE_MAX_FIREWIRE_PORTS);
146     raw1394_destroy_handle(tmp_handle);
147
148     if (nb_detected_ports < 0) {
149         debugError("Failed to detect number of ports\n");
150         return -1;
151     }
152     return nb_detected_ports;
153 }
154
155 void
156 Ieee1394Service::doBusReset() {
157     debugOutput(DEBUG_LEVEL_VERBOSE, "Issue bus reset on service %p (port %d).\n", this, getPort());
158     raw1394_reset_bus(m_handle);
159 }
160
161 bool
162 Ieee1394Service::initialize( int port )
163 {
164     using namespace std;
165
166     int nb_ports = detectNbPorts();
167     if (port + 1 > nb_ports) {
168         debugFatal("Requested port (%d) out of range (# ports: %d)\n", port, nb_ports);
169     }
170
171     if(!m_pWatchdog) {
172         debugError("No valid RT watchdog found.\n");
173         return false;
174     }
175     if(!m_pWatchdog->start()) {
176         debugError("Could not start RT watchdog.\n");
177         return false;
178     }
179
180     m_handle = raw1394_new_handle_on_port( port );
181     if ( !m_handle ) {
182         if ( !errno ) {
183             debugFatal("libraw1394 not compatible\n");
184         } else {
185             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s\n",
186                 strerror(errno) );
187             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
188         }
189         return false;
190     }
191
192     m_resetHandle = raw1394_new_handle_on_port( port );
193     if ( !m_resetHandle ) {
194         if ( !errno ) {
195             debugFatal("libraw1394 not compatible\n");
196         } else {
197             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s",
198                 strerror(errno) );
199             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
200         }
201         return false;
202     }
203
204     m_util_handle = raw1394_new_handle_on_port( port );
205     if ( !m_util_handle ) {
206         if ( !errno ) {
207             debugFatal("libraw1394 not compatible\n");
208         } else {
209             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s",
210                 strerror(errno) );
211             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
212         }
213         return false;
214     }
215
216     // test the cycle timer read function
217     int err;
218     uint32_t cycle_timer;
219     uint64_t local_time;
220     err=raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time);
221     if(err) {
222         debugOutput(DEBUG_LEVEL_VERBOSE, "raw1394_read_cycle_timer failed.\n");
223         debugOutput(DEBUG_LEVEL_VERBOSE, " Error descr: %s\n", strerror(err));
224         debugWarning("==================================================================\n");
225         debugWarning(" This system doesn't support the raw1394_read_cycle_timer call.   \n");
226         debugWarning(" Fallback to indirect CTR read method.                            \n");
227         debugWarning(" FFADO should work, but achieving low-latency might be a problem. \n");
228         debugWarning(" Upgrade the kernel to version 2.6.21 or higher to solve this.    \n");
229         debugWarning("==================================================================\n");
230         m_have_new_ctr_read = false;
231     } else {
232         debugOutput(DEBUG_LEVEL_VERBOSE, "This system supports the raw1394_read_cycle_timer call, using it.\n");
233         m_have_new_ctr_read = true;
234     }
235
236     m_port = port;
237
238     // obtain port name
239     raw1394handle_t tmp_handle = raw1394_new_handle();
240     if ( tmp_handle == NULL ) {
241         debugError("Could not get temporaty libraw1394 handle.\n");
242         return false;
243     }
244     struct raw1394_portinfo pinf[IEEE1394SERVICE_MAX_FIREWIRE_PORTS];
245     int nb_detected_ports = raw1394_get_port_info(tmp_handle, pinf, IEEE1394SERVICE_MAX_FIREWIRE_PORTS);
246     raw1394_destroy_handle(tmp_handle);
247
248     if (nb_detected_ports < 0) {
249         debugError("Failed to detect number of ports\n");
250         return false;
251     }
252
253     if(nb_detected_ports && port < IEEE1394SERVICE_MAX_FIREWIRE_PORTS) {
254         m_portName = pinf[port].name;
255     } else {
256         m_portName = "Unknown";
257     }
258     if (m_portName == "") {
259         m_portName = "Unknown";
260     }
261
262     raw1394_set_userdata( m_handle, this );
263     raw1394_set_userdata( m_resetHandle, this );
264     raw1394_set_userdata( m_util_handle, this );
265     raw1394_set_bus_reset_handler( m_resetHandle,
266                                    this->resetHandlerLowLevel );
267
268     m_default_arm_handler = raw1394_set_arm_tag_handler( m_resetHandle,
269                                    this->armHandlerLowLevel );
270
271     if(!m_pCTRHelper) {
272         debugFatal("No CycleTimerHelper available, bad!\n");
273         return false;
274     }
275     m_pCTRHelper->setVerboseLevel(getDebugLevel());
276     if(!m_pCTRHelper->Start()) {
277         debugFatal("Could not start CycleTimerHelper\n");
278         return false;
279     }
280
281     if(!m_pIsoManager) {
282         debugFatal("No IsoHandlerManager available, bad!\n");
283         return false;
284     }
285     m_pIsoManager->setVerboseLevel(getDebugLevel());
286     if(!m_pIsoManager->init()) {
287         debugFatal("Could not initialize IsoHandlerManager\n");
288         return false;
289     }
290
291     startRHThread();
292
293     // make sure that the thread parameters of all our helper threads are OK
294     if(!setThreadParameters(m_realtime, m_base_priority)) {
295         debugFatal("Could not set thread parameters\n");
296         return false;
297     }
298     return true;
299 }
300
301 bool
302 Ieee1394Service::setThreadParameters(bool rt, int priority) {
303     bool result = true;
304     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO;
305     m_base_priority = priority;
306     m_realtime = rt;
307     if (m_pIsoManager) {
308         debugOutput(DEBUG_LEVEL_VERBOSE, "Switching IsoManager to (rt=%d, prio=%d)\n",
309                                          rt, priority);
310         result &= m_pIsoManager->setThreadParameters(rt, priority);
311     }
312     if (m_pCTRHelper) {
313         debugOutput(DEBUG_LEVEL_VERBOSE, "Switching CycleTimerHelper to (rt=%d, prio=%d)\n",
314                                          rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
315                                          priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);
316         result &= m_pCTRHelper->setThreadParameters(rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME,
317                                                     priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);
318     }
319     return result;
320 }
321
322 int
323 Ieee1394Service::getNodeCount()
324 {
325     Util::MutexLockHelper lock(*m_handle_lock);
326     return raw1394_get_nodecount( m_handle );
327 }
328
329 nodeid_t Ieee1394Service::getLocalNodeId() {
330     Util::MutexLockHelper lock(*m_handle_lock);
331     return raw1394_get_local_id(m_handle) & 0x3F;
332 }
333
334 /**
335  * Returns the current value of the cycle timer (in ticks)
336  *
337  * @return the current value of the cycle timer (in ticks)
338  */
339
340 uint32_t
341 Ieee1394Service::getCycleTimerTicks() {
342     return m_pCTRHelper->getCycleTimerTicks();
343 }
344
345 /**
346  * Returns the current value of the cycle timer (as is)
347  *
348  * @return the current value of the cycle timer (as is)
349  */
350 uint32_t
351 Ieee1394Service::getCycleTimer() {
352     return m_pCTRHelper->getCycleTimer();
353 }
354
355 /**
356  * Returns the current value of the cycle timer (in ticks)
357  * for a specific time instant (usecs since epoch)
358  * @return the current value of the cycle timer (in ticks)
359  */
360
361 uint32_t
362 Ieee1394Service::getCycleTimerTicks(uint64_t t) {
363     return m_pCTRHelper->getCycleTimerTicks(t);
364 }
365
366 /**
367  * Returns the current value of the cycle timer (as is)
368  * for a specific time instant (usecs since epoch)
369  * @return the current value of the cycle timer (as is)
370  */
371 uint32_t
372 Ieee1394Service::getCycleTimer(uint64_t t) {
373     return m_pCTRHelper->getCycleTimer(t);
374 }
375
376 bool
377 Ieee1394Service::readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time)
378 {
379     if(m_have_new_ctr_read) {
380         int err;
381         err = raw1394_read_cycle_timer(m_util_handle, cycle_timer, local_time);
382         if(err) {
383             debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err));
384             return false;
385         }
386         return true;
387     } else {
388         // do a normal read of the CTR register
389         // the disadvantage is that local_time and cycle time are not
390         // read at the same time instant (scheduling issues)
391         *local_time = getCurrentTimeAsUsecs();
392         if ( raw1394_read( m_util_handle,
393                 getLocalNodeId() | 0xFFC0,
394                 CSR_REGISTER_BASE | CSR_CYCLE_TIME,
395                 sizeof(uint32_t), cycle_timer ) == 0 ) {
396             *cycle_timer = CondSwapFromBus32(*cycle_timer);
397             return true;
398         } else {
399             return false;
400         }
401     }
402 }
403
404 uint64_t
405 Ieee1394Service::getCurrentTimeAsUsecs() {
406     return Util::SystemTimeSource::getCurrentTimeAsUsecs();
407 }
408
409 bool
410 Ieee1394Service::read( fb_nodeid_t nodeId,
411                        fb_nodeaddr_t addr,
412                        size_t length,
413                        fb_quadlet_t* buffer )
414 {
415     Util::MutexLockHelper lock(*m_handle_lock);
416     using namespace std;
417     if ( raw1394_read( m_handle, nodeId, addr, length*4, buffer ) == 0 ) {
418
419         #ifdef DEBUG
420         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
421             "read: node 0x%hX, addr = 0x%016llX, length = %u\n",
422             nodeId, addr, length);
423         printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, buffer );
424         #endif
425
426         return true;
427     } else {
428         #ifdef DEBUG
429         debugOutput(DEBUG_LEVEL_NORMAL,
430                     "raw1394_read failed: node 0x%hX, addr = 0x%016llX, length = %u\n",
431                     nodeId, addr, length);
432         #endif
433         return false;
434     }
435 }
436
437 bool
438 Ieee1394Service::read_quadlet( fb_nodeid_t nodeId,
439                                fb_nodeaddr_t addr,
440                                fb_quadlet_t* buffer )
441 {
442     return read( nodeId,  addr, sizeof( *buffer )/4, buffer );
443 }
444
445 bool
446 Ieee1394Service::read_octlet( fb_nodeid_t nodeId,
447                               fb_nodeaddr_t addr,
448                               fb_octlet_t* buffer )
449 {
450     return read( nodeId, addr, sizeof( *buffer )/4,
451                  reinterpret_cast<fb_quadlet_t*>( buffer ) );
452 }
453
454 bool
455 Ieee1394Service::write( fb_nodeid_t nodeId,
456                         fb_nodeaddr_t addr,
457                         size_t length,
458                         fb_quadlet_t* data )
459 {
460     Util::MutexLockHelper lock(*m_handle_lock);
461     using namespace std;
462
463     #ifdef DEBUG
464     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"write: node 0x%hX, addr = 0x%016llX, length = %d\n",
465                 nodeId, addr, length);
466     printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, data );
467     #endif
468
469     return raw1394_write( m_handle, nodeId, addr, length*4, data ) == 0;
470 }
471
472 bool
473 Ieee1394Service::write_quadlet( fb_nodeid_t nodeId,
474                                 fb_nodeaddr_t addr,
475                                 fb_quadlet_t data )
476 {
477     return write( nodeId, addr, sizeof( data )/4, &data );
478 }
479
480 bool
481 Ieee1394Service::write_octlet( fb_nodeid_t nodeId,
482                                fb_nodeaddr_t addr,
483                                fb_octlet_t data )
484 {
485     return write( nodeId, addr, sizeof( data )/4,
486                   reinterpret_cast<fb_quadlet_t*>( &data ) );
487 }
488
489 bool
490 Ieee1394Service::lockCompareSwap64(  fb_nodeid_t nodeId,
491                         fb_nodeaddr_t addr,
492                         fb_octlet_t  compare_value,
493                         fb_octlet_t  swap_value,
494                         fb_octlet_t* result )
495 {
496     #ifdef DEBUG
497     debugOutput(DEBUG_LEVEL_VERBOSE,"lockCompareSwap64: node 0x%X, addr = 0x%016llX\n",
498                 nodeId, addr);
499     debugOutput(DEBUG_LEVEL_VERBOSE,"  if (*(addr)==0x%016llX) *(addr)=0x%016llX\n",
500                 compare_value, swap_value);
501     fb_octlet_t buffer;
502     if(!read_octlet( nodeId, addr,&buffer )) {
503         debugWarning("Could not read register\n");
504     } else {
505         debugOutput(DEBUG_LEVEL_VERBOSE,"before = 0x%016llX\n", buffer);
506     }
507     #endif
508
509     // do endiannes swapping
510     compare_value = CondSwapToBus64(compare_value);
511     swap_value    = CondSwapToBus64(swap_value);
512
513     // do separate locking here (no MutexLockHelper) since
514     // we use read_octlet in the DEBUG code in this function
515     m_handle_lock->Lock();
516     int retval=raw1394_lock64(m_handle, nodeId, addr,
517                               RAW1394_EXTCODE_COMPARE_SWAP,
518                               swap_value, compare_value, result);
519     m_handle_lock->Unlock();
520
521     if(retval) {
522         debugError("raw1394_lock64 failed: %s\n", strerror(errno));
523     }
524
525     #ifdef DEBUG
526     if(!read_octlet( nodeId, addr,&buffer )) {
527         debugWarning("Could not read register\n");
528     } else {
529         debugOutput(DEBUG_LEVEL_VERBOSE,"after = 0x%016llX\n", buffer);
530     }
531     #endif
532
533     *result = CondSwapFromBus64(*result);
534
535     return (retval == 0);
536 }
537
538 fb_quadlet_t*
539 Ieee1394Service::transactionBlock( fb_nodeid_t nodeId,
540                                    fb_quadlet_t* buf,
541                                    int len,
542                                    unsigned int* resp_len )
543 {
544     // FIXME: this requires transactionBlockClose to unlock
545     m_handle_lock->Lock();
546     for (int i = 0; i < len; ++i) {
547         buf[i] = CondSwapFromBus32( buf[i] );
548     }
549
550     fb_quadlet_t* result =
551         avc1394_transaction_block2( m_handle,
552                                     nodeId,
553                                     buf,
554                                     len,
555                                     resp_len,
556                                     10 );
557
558     for ( unsigned int i = 0; i < *resp_len; ++i ) {
559         result[i] = CondSwapToBus32( result[i] );
560     }
561
562     return result;
563 }
564
565
566 bool
567 Ieee1394Service::transactionBlockClose()
568 {
569     avc1394_transaction_block_close( m_handle );
570     m_handle_lock->Unlock();
571     return true;
572 }
573
574 int
575 Ieee1394Service::getVerboseLevel()
576 {
577     return getDebugLevel();
578 }
579
580 void
581 Ieee1394Service::printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const
582 {
583
584     for ( unsigned int i=0; i < length; ++i ) {
585         if ( ( i % 4 ) == 0 ) {
586             if ( i > 0 ) {
587                 debugOutputShort(level,"\n");
588             }
589             debugOutputShort(level," %4d: ",i*4);
590         }
591         debugOutputShort(level,"%08X ",buffer[i]);
592     }
593     debugOutputShort(level,"\n");
594 }
595 void
596 Ieee1394Service::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const
597 {
598
599     for ( unsigned int i=0; i < length; ++i ) {
600         if ( ( i % 16 ) == 0 ) {
601             if ( i > 0 ) {
602                 debugOutputShort(level,"\n");
603             }
604             debugOutputShort(level," %4d: ",i*16);
605         }
606         debugOutputShort(level,"%02X ",buffer[i]);
607     }
608     debugOutputShort(level,"\n");
609 }
610
611 int
612 Ieee1394Service::resetHandlerLowLevel( raw1394handle_t handle,
613                                        unsigned int generation )
614 {
615     raw1394_update_generation ( handle, generation );
616     Ieee1394Service* instance
617         = (Ieee1394Service*) raw1394_get_userdata( handle );
618     instance->resetHandler( generation );
619
620     return 0;
621 }
622
623 bool
624 Ieee1394Service::resetHandler( unsigned int generation )
625 {
626     quadlet_t buf=0;
627
628     // do a simple read on ourself in order to update the internal structures
629     // this avoids failures after a bus reset
630     read_quadlet( getLocalNodeId() | 0xFFC0,
631                   CSR_REGISTER_BASE | CSR_CYCLE_TIME,
632                   &buf );
633
634     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
635           it != m_busResetHandlers.end();
636           ++it )
637     {
638         Util::Functor* func = *it;
639         ( *func )();
640     }
641
642     return true;
643 }
644
645 bool Ieee1394Service::registerARMHandler(ARMHandler *h) {
646     debugOutput(DEBUG_LEVEL_VERBOSE, "Registering ARM handler (%p) for 0x%016llX, length %u\n",
647         h, h->getStart(), h->getLength());
648
649     int err=raw1394_arm_register(m_resetHandle, h->getStart(),
650                                  h->getLength(), h->getBuffer(), (octlet_t)h,
651                                  h->getAccessRights(),
652                                  h->getNotificationOptions(),
653                                  h->getClientTransactions());
654     if (err) {
655         debugError("Failed to register ARM handler for 0x%016llX\n", h->getStart());
656         debugError(" Error: %s\n", strerror(errno));
657         return false;
658     }
659
660     m_armHandlers.push_back( h );
661
662     return true;
663 }
664
665 bool Ieee1394Service::unregisterARMHandler( ARMHandler *h ) {
666     debugOutput(DEBUG_LEVEL_VERBOSE, "Unregistering ARM handler (%p) for 0x%016llX\n",
667         h, h->getStart());
668
669     for ( arm_handler_vec_t::iterator it = m_armHandlers.begin();
670           it != m_armHandlers.end();
671           ++it )
672     {
673         if((*it) == h) {
674             int err=raw1394_arm_unregister(m_resetHandle, h->getStart());
675             if (err) {
676                 debugError("Failed to unregister ARM handler (%p)\n", h);
677                 debugError(" Error: %s\n", strerror(errno));
678             } else {
679                 m_armHandlers.erase(it);
680                 return true;
681             }
682         }
683     }
684     debugOutput(DEBUG_LEVEL_VERBOSE, " handler not found!\n");
685
686     return false;
687 }
688 /**
689  * @brief Tries to find a free ARM address range
690  *
691  * @param start  address to start with
692  * @param length length of the block needed (bytes)
693  * @param step   step to use when searching (bytes)
694  * @return The base address that is free, and 0xFFFFFFFFFFFFFFFF when failed
695  */
696 nodeaddr_t Ieee1394Service::findFreeARMBlock( nodeaddr_t start, size_t length, size_t step ) {
697     debugOutput(DEBUG_LEVEL_VERBOSE, "Finding free ARM block of %d bytes, from 0x%016llX in steps of %d bytes\n",
698         length, start, step);
699
700     int cnt=0;
701     const int maxcnt=10;
702     int err=1;
703     while(err && cnt++ < maxcnt) {
704         // try to register
705         err=raw1394_arm_register(m_resetHandle, start, length, 0, 0, 0, 0, 0);
706
707         if (err) {
708             debugOutput(DEBUG_LEVEL_VERBOSE, " -> cannot use 0x%016llX\n", start);
709             debugError("    Error: %s\n", strerror(errno));
710             start += step;
711         } else {
712             debugOutput(DEBUG_LEVEL_VERBOSE, " -> use 0x%016llX\n", start);
713             err=raw1394_arm_unregister(m_resetHandle, start);
714             if (err) {
715                 debugOutput(DEBUG_LEVEL_VERBOSE, " error unregistering test handler\n");
716                 debugError("    Error: %s\n", strerror(errno));
717                 return 0xFFFFFFFFFFFFFFFFLLU;
718             }
719             return start;
720         }
721     }
722     debugOutput(DEBUG_LEVEL_VERBOSE, " Could not find free block in %d tries\n",cnt);
723     return 0xFFFFFFFFFFFFFFFFLLU;
724 }
725
726 int
727 Ieee1394Service::armHandlerLowLevel(raw1394handle_t handle,
728                      unsigned long arm_tag,
729                      byte_t request_type, unsigned int requested_length,
730                      void *data)
731 {
732     Ieee1394Service* instance
733         = (Ieee1394Service*) raw1394_get_userdata( handle );
734     instance->armHandler( arm_tag, request_type, requested_length, data );
735
736     return 0;
737 }
738
739 bool
740 Ieee1394Service::armHandler(  unsigned long arm_tag,
741                      byte_t request_type, unsigned int requested_length,
742                      void *data)
743 {
744     for ( arm_handler_vec_t::iterator it = m_armHandlers.begin();
745           it != m_armHandlers.end();
746           ++it )
747     {
748         if((*it) == (ARMHandler *)arm_tag) {
749             struct raw1394_arm_request_response *arm_req_resp;
750             arm_req_resp  = (struct raw1394_arm_request_response *) data;
751             raw1394_arm_request_t arm_req=arm_req_resp->request;
752             raw1394_arm_response_t arm_resp=arm_req_resp->response;
753
754             debugOutput(DEBUG_LEVEL_VERBOSE,"ARM handler for address 0x%016llX called\n",
755                 (*it)->getStart());
756             debugOutput(DEBUG_LEVEL_VERBOSE," request type   : 0x%02X\n",request_type);
757             debugOutput(DEBUG_LEVEL_VERBOSE," request length : %04d\n",requested_length);
758
759             switch(request_type) {
760                 case RAW1394_ARM_READ:
761                     (*it)->handleRead(arm_req);
762                     *arm_resp=*((*it)->getResponse());
763                     break;
764                 case RAW1394_ARM_WRITE:
765                     (*it)->handleWrite(arm_req);
766                     *arm_resp=*((*it)->getResponse());
767                     break;
768                 case RAW1394_ARM_LOCK:
769                     (*it)->handleLock(arm_req);
770                     *arm_resp=*((*it)->getResponse());
771                     break;
772                 default:
773                     debugWarning("Unknown request type received, ignoring...\n");
774             }
775
776             return true;
777         }
778     }
779
780     debugOutput(DEBUG_LEVEL_VERBOSE,"default ARM handler called\n");
781
782     m_default_arm_handler(m_resetHandle, arm_tag, request_type, requested_length, data );
783     return true;
784 }
785
786 bool
787 Ieee1394Service::startRHThread()
788 {
789     int i;
790
791     if ( m_threadRunning ) {
792         return true;
793     }
794     m_RHThread_lock->Lock();
795     i = pthread_create( &m_thread, 0, rHThread, this );
796     m_RHThread_lock->Unlock();
797     if (i) {
798         debugFatal("Could not start ieee1394 service thread\n");
799         return false;
800     }
801     m_threadRunning = true;
802
803     return true;
804 }
805
806 void
807 Ieee1394Service::stopRHThread()
808 {
809     if ( m_threadRunning ) {
810         m_RHThread_lock->Lock();
811         pthread_cancel (m_thread);
812         pthread_join (m_thread, 0);
813         m_RHThread_lock->Unlock();
814         m_threadRunning = false;
815     }
816 }
817
818 void*
819 Ieee1394Service::rHThread( void* arg )
820 {
821     Ieee1394Service* pIeee1394Service = (Ieee1394Service*) arg;
822
823     while (true) {
824         raw1394_loop_iterate (pIeee1394Service->m_resetHandle);
825         pthread_testcancel ();
826     }
827
828     return 0;
829 }
830
831 bool
832 Ieee1394Service::addBusResetHandler( Util::Functor* functor )
833 {
834     debugOutput(DEBUG_LEVEL_VERBOSE, "Adding busreset handler (%p)\n", functor);
835     m_busResetHandlers.push_back( functor );
836     return true;
837 }
838
839 bool
840 Ieee1394Service::remBusResetHandler( Util::Functor* functor )
841 {
842     debugOutput(DEBUG_LEVEL_VERBOSE, "Removing busreset handler (%p)\n", functor);
843
844     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
845           it != m_busResetHandlers.end();
846           ++it )
847     {
848         if ( *it == functor ) {
849             debugOutput(DEBUG_LEVEL_VERBOSE, " found\n");
850             m_busResetHandlers.erase( it );
851             return true;
852         }
853     }
854     debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n");
855     return false;
856 }
857
858 /**
859  * Allocates an iso channel for use by the interface in a similar way to
860  * libiec61883.  Returns -1 on error (due to there being no free channels)
861  * or an allocated channel number.
862  *
863  * Does not perform anything other than registering the channel and the
864  * bandwidth at the IRM
865  *
866  * Also allocates the necessary bandwidth (in ISO allocation units).
867  *
868  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
869  * bug or it's omitted since that's the channel preferred by video devices.
870  *
871  * @param bandwidth the bandwidth to allocate for this channel
872  * @return the channel number
873  */
874 signed int Ieee1394Service::allocateIsoChannelGeneric(unsigned int bandwidth) {
875     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using generic method...\n" );
876
877     Util::MutexLockHelper lock(*m_handle_lock);
878     struct ChannelInfo cinfo;
879
880     int c = -1;
881     for (c = 0; c < 63; c++) {
882         if (raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_ALLOC) == 0)
883             break;
884     }
885     if (c < 63) {
886         if (raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
887             debugFatal("Could not allocate bandwidth of %d\n", bandwidth);
888
889             raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
890             return -1;
891         } else {
892             cinfo.channel=c;
893             cinfo.bandwidth=bandwidth;
894             cinfo.alloctype=AllocGeneric;
895
896             cinfo.xmit_node=-1;
897             cinfo.xmit_plug=-1;
898             cinfo.recv_node=-1;
899             cinfo.recv_plug=-1;
900
901             if (registerIsoChannel(c, cinfo)) {
902                 return c;
903             } else {
904                 raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_FREE);
905                 raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
906                 return -1;
907             }
908         }
909     }
910     return -1;
911 }
912
913 /**
914  * Allocates an iso channel for use by the interface in a similar way to
915  * libiec61883.  Returns -1 on error (due to there being no free channels)
916  * or an allocated channel number.
917  *
918  * Uses IEC61883 Connection Management Procedure to establish the connection.
919  *
920  * Also allocates the necessary bandwidth (in ISO allocation units).
921  *
922  * @param xmit_node  node id of the transmitter
923  * @param xmit_plug  the output plug to use. If -1, find the first online plug, and
924  * upon return, contains the plug number used.
925  * @param recv_node  node id of the receiver
926  * @param recv_plug the input plug to use. If -1, find the first online plug, and
927  * upon return, contains the plug number used.
928  *
929  * @return the channel number
930  */
931
932 signed int Ieee1394Service::allocateIsoChannelCMP(
933     nodeid_t xmit_node, int xmit_plug,
934     nodeid_t recv_node, int recv_plug
935     ) {
936
937     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using IEC61883 CMP...\n" );
938     Util::MutexLockHelper lock(*m_handle_lock);
939
940     struct ChannelInfo cinfo;
941
942     int c = -1;
943     int bandwidth=1;
944     #if IEEE1394SERVICE_SKIP_IEC61883_BANDWIDTH_ALLOCATION
945     bandwidth=0;
946     #endif
947
948     // do connection management: make connection
949     c = iec61883_cmp_connect(
950         m_handle,
951         xmit_node | 0xffc0,
952         &xmit_plug,
953         recv_node | 0xffc0,
954         &recv_plug,
955         &bandwidth);
956
957     if((c<0) || (c>63)) {
958         debugError("Could not do CMP from %04X:%02d to %04X:%02d\n",
959             xmit_node, xmit_plug, recv_node, recv_plug
960             );
961         return -1;
962     }
963
964     cinfo.channel=c;
965     cinfo.bandwidth=bandwidth;
966     cinfo.alloctype=AllocCMP;
967
968     cinfo.xmit_node=xmit_node;
969     cinfo.xmit_plug=xmit_plug;
970     cinfo.recv_node=recv_node;
971     cinfo.recv_plug=recv_plug;
972
973     if (registerIsoChannel(c, cinfo)) {
974         return c;
975     }
976
977     return -1;
978 }
979
980 /**
981  * Deallocates an iso channel.  Silently ignores a request to deallocate
982  * a negative channel number.
983  *
984  * Figures out the method that was used to allocate the channel (generic, cmp, ...)
985  * and uses the appropriate method to deallocate. Also frees the bandwidth
986  * that was reserved along with this channel.
987  *
988  * @param c channel number
989  * @return true if successful
990  */
991 bool Ieee1394Service::freeIsoChannel(signed int c) {
992     debugOutput(DEBUG_LEVEL_VERBOSE, "Freeing ISO channel %d...\n", c );
993     Util::MutexLockHelper lock(*m_handle_lock);
994
995     if (c < 0 || c > 63) {
996         debugWarning("Invalid channel number: %d\n", c);
997         return false;
998     }
999
1000     switch (m_channels[c].alloctype) {
1001         default:
1002             debugError(" BUG: invalid allocation type!\n");
1003             return false;
1004
1005         case AllocFree:
1006             debugWarning(" Channel %d not registered\n", c);
1007             return false;
1008
1009         case AllocGeneric:
1010             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using generic routine...\n" );
1011             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing %d bandwidth units...\n", m_channels[c].bandwidth );
1012             if (raw1394_bandwidth_modify(m_handle, m_channels[c].bandwidth, RAW1394_MODIFY_FREE) !=0) {
1013                 debugWarning("Failed to deallocate bandwidth\n");
1014             }
1015             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing channel %d...\n", m_channels[c].channel );
1016             if (raw1394_channel_modify (m_handle, m_channels[c].channel, RAW1394_MODIFY_FREE) != 0) {
1017                 debugWarning("Failed to free channel\n");
1018             }
1019             if (!unregisterIsoChannel(c))
1020                 return false;
1021             return true;
1022
1023         case AllocCMP:
1024             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using IEC61883 CMP...\n" );
1025             debugOutput(DEBUG_LEVEL_VERBOSE, " performing IEC61883 CMP disconnect...\n" );
1026             if(iec61883_cmp_disconnect(
1027                     m_handle,
1028                     m_channels[c].xmit_node | 0xffc0,
1029                     m_channels[c].xmit_plug,
1030                     m_channels[c].recv_node | 0xffc0,
1031                     m_channels[c].recv_plug,
1032                     m_channels[c].channel,
1033                     m_channels[c].bandwidth) != 0) {
1034                 debugWarning("Could not do CMP disconnect for channel %d!\n",c);
1035             }
1036             if (!unregisterIsoChannel(c))
1037                 return false;
1038             return true;
1039     }
1040
1041     // unreachable
1042     debugError("BUG: unreachable code reached!\n");
1043
1044     return false;
1045 }
1046
1047 /**
1048  * Registers a channel as managed by this ieee1394service
1049  * @param c channel number
1050  * @param cinfo channel info struct
1051  * @return true if successful
1052  */
1053 bool Ieee1394Service::registerIsoChannel(unsigned int c, struct ChannelInfo cinfo) {
1054     if (c < 63) {
1055         if (m_channels[c].alloctype != AllocFree) {
1056             debugWarning("Channel %d already registered with bandwidth %d\n",
1057                 m_channels[c].channel, m_channels[c].bandwidth);
1058         }
1059
1060         memcpy(&m_channels[c], &cinfo, sizeof(struct ChannelInfo));
1061
1062     } else return false;
1063     return true;
1064 }
1065
1066 /**
1067  * unegisters a channel from this ieee1394service
1068  * @param c channel number
1069  * @return true if successful
1070  */
1071 bool Ieee1394Service::unregisterIsoChannel(unsigned int c) {
1072     if (c < 63) {
1073         if (m_channels[c].alloctype == AllocFree) {
1074             debugWarning("Channel %d not registered\n", c);
1075             return false;
1076         }
1077
1078         m_channels[c].channel=-1;
1079         m_channels[c].bandwidth=-1;
1080         m_channels[c].alloctype=AllocFree;
1081         m_channels[c].xmit_node=0xFFFF;
1082         m_channels[c].xmit_plug=-1;
1083         m_channels[c].recv_node=0xFFFF;
1084         m_channels[c].recv_plug=-1;
1085
1086     } else return false;
1087     return true;
1088 }
1089
1090 /**
1091  * Returns the current value of the `bandwidth available' register on
1092  * the IRM, or -1 on error.
1093  * @return
1094  */
1095 signed int Ieee1394Service::getAvailableBandwidth() {
1096     quadlet_t buffer;
1097     Util::MutexLockHelper lock(*m_handle_lock);
1098     signed int result = raw1394_read (m_handle, raw1394_get_irm_id (m_handle),
1099         CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
1100         sizeof (quadlet_t), &buffer);
1101
1102     if (result < 0)
1103         return -1;
1104     return CondSwapFromBus32(buffer);
1105 }
1106
1107 void
1108 Ieee1394Service::setVerboseLevel(int l)
1109 {
1110     if (m_pIsoManager) m_pIsoManager->setVerboseLevel(l);
1111     if (m_pCTRHelper) m_pCTRHelper->setVerboseLevel(l);
1112     if (m_pWatchdog) m_pWatchdog->setVerboseLevel(l);
1113     setDebugLevel(l);
1114     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1115 }
1116
1117 void
1118 Ieee1394Service::show()
1119 {
1120     #ifdef DEBUG
1121     uint32_t cycle_timer;
1122     uint64_t local_time;
1123     if(!readCycleTimerReg(&cycle_timer, &local_time)) {
1124         debugWarning("Could not read cycle timer register\n");
1125    
1126     }
1127     uint64_t ctr = CYCLE_TIMER_TO_TICKS( cycle_timer );
1128
1129     debugOutput( DEBUG_LEVEL_VERBOSE, "Port:  %d\n", getPort() );
1130     debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() );
1131     debugOutput( DEBUG_LEVEL_VERBOSE, " CycleTimerHelper: %p, IsoManager: %p, WatchDog: %p\n",
1132                  m_pCTRHelper, m_pIsoManager, m_pWatchdog );
1133     debugOutput( DEBUG_LEVEL_VERBOSE, " Time: %011llu (%03us %04ucy %04uticks)\n",
1134                 ctr,
1135                 (unsigned int)TICKS_TO_SECS( ctr ),
1136                 (unsigned int)TICKS_TO_CYCLES( ctr ),
1137                 (unsigned int)TICKS_TO_OFFSET( ctr ) );
1138     debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n");
1139     #endif
1140     if (m_pIsoManager) m_pIsoManager->dumpInfo();
1141 }
Note: See TracBrowser for help on using the browser.