root/branches/streaming-rework/src/libieee1394/ieee1394service.cpp

Revision 436, 25.1 kB (checked in by pieterpalmers, 16 years ago)

- fixed verbose level setting
- debugged DICE code, works with EVM

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