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

Revision 748, 27.5 kB (checked in by ppalmers, 15 years ago)

try to reorganize things such that less information is duplicated

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