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

Revision 1190, 29.6 kB (checked in by ppalmers, 15 years ago)

remove unused code, clean up for release

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