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

Revision 1372, 24.4 kB (checked in by ppalmers, 12 years ago)

Host controller reliability changes:

  • make receive DMA mode selectable (but still hardcoded ATM). Some controllers seem to work better in bufferfill mode.
  • introduce a maximum number of ISO buffers for receive, lower the max nb of ISO buffers for xmit
  • make the number of buffers for receive and transmit a power of two
  • ensure at least two hardware interrupts per complete ISO buffer wraparound
Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25
26 #include "IsoHandler.h"
27 #include "ieee1394service.h"
28 #include "IsoHandlerManager.h"
29
30 #include "cycletimer.h"
31
32 #include "libstreaming/generic/StreamProcessor.h"
33 #include "libutil/PosixThread.h"
34
35 #include <errno.h>
36 #include "libutil/ByteSwap.h"
37 #include <assert.h>
38 #include <unistd.h>
39 #include <string.h>
40
41 #include <iostream>
42 using namespace std;
43 using namespace Streaming;
44
45 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
46
47 /* the C callbacks */
48 enum raw1394_iso_disposition
49 IsoHandler::iso_transmit_handler(raw1394handle_t handle,
50         unsigned char *data, unsigned int *length,
51         unsigned char *tag, unsigned char *sy,
52         int cycle, unsigned int dropped1) {
53
54     IsoHandler *xmitHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
55     assert(xmitHandler);
56     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
57     unsigned int dropped = dropped1 & 0xFFFF;
58     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped, skipped);
59 }
60
61 enum raw1394_iso_disposition
62 IsoHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
63                         unsigned int length, unsigned char channel,
64                         unsigned char tag, unsigned char sy, unsigned int cycle,
65                         unsigned int dropped) {
66
67     IsoHandler *recvHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
68     assert(recvHandler);
69
70     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
71 }
72
73 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t)
74    : m_manager( manager )
75    , m_type ( t )
76    , m_handle( 0 )
77    , m_buf_packets( 400 )
78    , m_max_packet_size( 1024 )
79    , m_irq_interval( -1 )
80    , m_last_cycle( -1 )
81    , m_last_now( 0xFFFFFFFF )
82    , m_last_packet_handled_at( 0xFFFFFFFF )
83    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
84    , m_Client( 0 )
85    , m_speed( RAW1394_ISO_SPEED_400 )
86    , m_prebuffers( 0 )
87    , m_dont_exit_iterate_loop( true )
88    , m_State( E_Created )
89 #ifdef DEBUG
90    , m_packets ( 0 )
91    , m_dropped( 0 )
92    , m_skipped( 0 )
93    , m_min_ahead( 7999 )
94 #endif
95 {
96 }
97
98 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t,
99                        unsigned int buf_packets, unsigned int max_packet_size, int irq)
100    : m_manager( manager )
101    , m_type ( t )
102    , m_handle( 0 )
103    , m_buf_packets( buf_packets )
104    , m_max_packet_size( max_packet_size )
105    , m_irq_interval( irq )
106    , m_last_cycle( -1 )
107    , m_last_now( 0xFFFFFFFF )
108    , m_last_packet_handled_at( 0xFFFFFFFF )
109    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
110    , m_Client( 0 )
111    , m_speed( RAW1394_ISO_SPEED_400 )
112    , m_prebuffers( 0 )
113    , m_State( E_Created )
114 #ifdef DEBUG
115    , m_packets ( 0 )
116    , m_dropped( 0 )
117    , m_skipped( 0 )
118    , m_min_ahead( 7999 )
119 #endif
120 {
121 }
122
123 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t, unsigned int buf_packets,
124                        unsigned int max_packet_size, int irq,
125                        enum raw1394_iso_speed speed)
126    : m_manager( manager )
127    , m_type ( t )
128    , m_handle( 0 )
129    , m_buf_packets( buf_packets )
130    , m_max_packet_size( max_packet_size )
131    , m_irq_interval( irq )
132    , m_last_cycle( -1 )
133    , m_last_now( 0xFFFFFFFF )
134    , m_last_packet_handled_at( 0xFFFFFFFF )
135    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
136    , m_Client( 0 )
137    , m_speed( speed )
138    , m_prebuffers( 0 )
139    , m_State( E_Created )
140 #ifdef DEBUG
141    , m_packets( 0 )
142    , m_dropped( 0 )
143    , m_skipped( 0 )
144    , m_min_ahead( 7999 )
145 #endif
146 {
147 }
148
149 IsoHandler::~IsoHandler() {
150 // Don't call until libraw1394's raw1394_new_handle() function has been
151 // fixed to correctly initialise the iso_packet_infos field.  Bug is
152 // confirmed present in libraw1394 1.2.1.  In any case,
153 // raw1394_destroy_handle() will do any iso system shutdown required.
154 //     raw1394_iso_shutdown(m_handle);
155     if(m_handle) {
156         if (m_State == E_Running) {
157             disable();
158         }
159         raw1394_destroy_handle(m_handle);
160     }
161 }
162
163 bool
164 IsoHandler::canIterateClient()
165 {
166     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "checking...\n");
167     if(m_Client) {
168         bool result;
169
170         if (m_type == eHT_Receive) {
171             result = m_Client->canProducePacket();
172         } else {
173             result = m_Client->canConsumePacket();
174         }
175         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
176         return result && (m_State != E_Error);
177     } else {
178         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " no client\n");
179     }
180     return false;
181 }
182
183 bool
184 IsoHandler::iterate() {
185     return iterate(m_manager.get1394Service().getCycleTimer());
186 }
187
188 bool
189 IsoHandler::iterate(uint32_t cycle_timer_now) {
190     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler at %08X...\n",
191                        this, getTypeString(), cycle_timer_now);
192     m_last_now = cycle_timer_now;
193     if(m_State == E_Running) {
194 #if ISOHANDLER_FLUSH_BEFORE_ITERATE
195         flush();
196 #endif
197         if(raw1394_loop_iterate(m_handle)) {
198             debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
199                         this, strerror(errno));
200             return false;
201         }
202         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) done interating ISO handler...\n",
203                            this, getTypeString());
204         return true;
205     } else {
206         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Not iterating a non-running handler...\n",
207                     this, getTypeString());
208         return false;
209     }
210 }
211
212 bool
213 IsoHandler::init()
214 {
215     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
216     // check the state
217     if(m_State != E_Created) {
218         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
219         return false;
220     }
221
222     // the main handle for the ISO traffic
223     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
224     if ( !m_handle ) {
225         if ( !errno ) {
226             debugError("libraw1394 not compatible\n");
227         } else {
228             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
229             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
230         }
231         return false;
232     }
233     raw1394_set_userdata(m_handle, static_cast<void *>(this));
234
235     // update the internal state
236     m_State=E_Initialized;
237     return true;
238 }
239
240 bool IsoHandler::disable()
241 {
242     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n",
243                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
244
245     // check state
246     if(m_State == E_Prepared) return true;
247     if(m_State != E_Running) {
248         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
249         return false;
250     }
251
252     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) wake up handle...\n",
253                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
254
255     // wake up any waiting reads/polls
256     raw1394_wake_up(m_handle);
257
258     // this is put here to try and avoid the
259     // Runaway context problem
260     // don't know if it will help though.
261 /*    if(m_State != E_Error) { // if the handler is dead, this might block forever
262         raw1394_iso_xmit_sync(m_handle);
263     }*/
264     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) stop...\n",
265                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
266     raw1394_iso_stop(m_handle);
267     m_State = E_Prepared;
268     return true;
269 }
270
271 /**
272  * Bus reset handler
273  *
274  * @return ?
275  */
276
277 bool
278 IsoHandler::handleBusReset()
279 {
280     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
281     m_last_packet_handled_at = 0xFFFFFFFF;
282
283     #define CSR_CYCLE_TIME            0x200
284     #define CSR_REGISTER_BASE  0xfffff0000000ULL
285     // do a simple read on ourself in order to update the internal structures
286     // this avoids read failures after a bus reset
287     quadlet_t buf=0;
288     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
289                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
290
291     return m_Client->handleBusReset();
292 }
293
294 /**
295  * Call this if you find out that this handler has died for some
296  * external reason.
297  */
298 void
299 IsoHandler::notifyOfDeath()
300 {
301     m_State = E_Error;
302
303     // notify the client of the fact that we have died
304     m_Client->handlerDied();
305
306     // wake ourselves up
307     raw1394_wake_up(m_handle);
308 }
309
310 void IsoHandler::dumpInfo()
311 {
312     int channel=-1;
313     if (m_Client) channel=m_Client->getChannel();
314
315     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
316             getTypeString());
317     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
318             m_manager.get1394Service().getPort(), channel);
319     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
320             m_buf_packets, m_max_packet_size, m_irq_interval);
321     if (this->getType() == eHT_Transmit) {
322         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed, PreBuffers...........: %2d, %2d\n",
323                                             m_speed, m_prebuffers);
324         #ifdef DEBUG
325         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Min ISOXMT bufferfill : %04d\n", m_min_ahead);
326         #endif
327     }
328     #ifdef DEBUG
329     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last cycle, dropped.........: %4d, %4u, %4u\n",
330             m_last_cycle, m_dropped, m_skipped);
331     #endif
332
333 }
334
335 void IsoHandler::setVerboseLevel(int l)
336 {
337     setDebugLevel(l);
338     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
339 }
340
341 bool IsoHandler::registerStream(StreamProcessor *stream)
342 {
343     assert(stream);
344     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
345
346     if (m_Client) {
347             debugFatal( "Generic IsoHandlers can have only one client\n");
348             return false;
349     }
350     m_Client=stream;
351     return true;
352 }
353
354 bool IsoHandler::unregisterStream(StreamProcessor *stream)
355 {
356     assert(stream);
357     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
358
359     if(stream != m_Client) {
360             debugFatal( "no client registered\n");
361             return false;
362     }
363     m_Client=0;
364     return true;
365 }
366
367 void IsoHandler::flush()
368 {
369     if(m_type == eHT_Receive) {
370         raw1394_iso_recv_flush(m_handle);
371     } else {
372         // do nothing
373     }
374 }
375
376 // ISO packet interface
377 enum raw1394_iso_disposition IsoHandler::putPacket(
378                     unsigned char *data, unsigned int length,
379                     unsigned char channel, unsigned char tag, unsigned char sy,
380                     unsigned int cycle, unsigned int dropped) {
381
382     // keep track of dropped cycles
383     int dropped_cycles = 0;
384     if (m_last_cycle != (int)cycle && m_last_cycle != -1) {
385         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
386         #ifdef DEBUG
387         if (dropped_cycles < 0) {
388             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d\n",
389                          this, dropped_cycles, cycle, m_last_cycle, dropped);
390         }
391         if (dropped_cycles > 0) {
392             debugOutput(DEBUG_LEVEL_VERBOSE,
393                         "(%p) dropped %d packets on cycle %u, 'dropped'=%u, cycle=%d, m_last_cycle=%d\n",
394                         this, dropped_cycles, cycle, dropped, cycle, m_last_cycle);
395             m_dropped += dropped_cycles;
396         }
397         #endif
398     }
399     m_last_cycle = cycle;
400
401     uint32_t pkt_ctr = cycle << 12;
402
403     // if we assume that one iterate() loop doesn't take longer than 0.5 seconds,
404     // the seconds field won't change while the iterate loop runs
405     // this means that we can preset 'now' before running iterate()
406     uint32_t now_secs = CYCLE_TIMER_GET_SECS(m_last_now);
407     // causality results in the fact that 'now' is always after 'cycle'
408     // except if additional packets are received between setting the
409     // m_last_now and the starting the iterate() loop.
410     // this causes the m_last_now to be set at a time before the last packet
411     // in this loop is received. however, it's not going to be >4000 cycles.
412     // hence:
413     // - if the m_last_now > cycle, there is no need to unwrap
414     //   both values are within the same second
415     // - if m_last_now < cycle it can mean two things:
416     //    * m_last_now has wrapped, but is still later than cycle
417     //      hence diffCycles(m_last_now, cycle) > 0. We should unwrap
418     //    * m_last_now has not wrapped, and cycle is ahead of m_last_now
419     //      this means that the cycle is more recent than the saved
420     //      m_last_now value
421     // . Hence if we calculate
422     // the unwrapped difference, and it's larger than 0, this means
423     // that m_last_now is after the current cycle. .
424     // it m_last_now is before the current cycle, we should not unwrap
425     // NOTE: another option is to reread the m_last_now
426     if( (CYCLE_TIMER_GET_CYCLES(m_last_now) < cycle)
427         && diffCycles(CYCLE_TIMER_GET_CYCLES(m_last_now), cycle) >= 0) {
428         debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
429                            "unwrapping %d => %d, %d\n",
430                            CYCLE_TIMER_GET_CYCLES(m_last_now),
431                            cycle);
432         // the cycle field has wrapped, substract one second
433         if(now_secs == 0) {
434             now_secs = 127;
435         } else  {
436             now_secs -= 1;
437         }
438     }
439
440     #ifdef DEBUG
441     if( (CYCLE_TIMER_GET_CYCLES(m_last_now) < cycle)
442         && diffCycles(CYCLE_TIMER_GET_CYCLES(m_last_now), cycle) < 0
443         // ignore this on dropped cycles, since it's normal
444         // that now is ahead on the received packets (as we miss packets)
445         && dropped_cycles == 0)
446     {
447         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Special non-unwrapping happened\n");
448     }
449     #endif
450     pkt_ctr |= (now_secs & 0x7F) << 25;
451
452     #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
453     // add a seconds field
454     uint32_t now = m_manager.get1394Service().getCycleTimer();
455     uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
456     // causality results in the fact that 'now' is always after 'cycle'
457     // or at best, equal (if this handler was called within 125us after
458     // the packet was on the wire).
459     if(CYCLE_TIMER_GET_CYCLES(now) < cycle) {
460         // the cycle field has wrapped, substract one second
461         if(now_secs_ref == 0) {
462             now_secs_ref = 127;
463         } else  {
464             now_secs_ref -= 1;
465         }
466     }
467     uint32_t pkt_ctr_ref = cycle << 12;
468     pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
469
470     if(pkt_ctr != pkt_ctr_ref) {
471         debugWarning("reconstructed CTR counter discrepancy\n");
472         debugWarning(" ingredients: %X, %lX, %lX, %lX, %lX, %ld, %ld\n",
473                        cycle, pkt_ctr_ref, pkt_ctr, now, m_last_now, now_secs_ref, now_secs);
474     }
475     #endif
476     m_last_packet_handled_at = pkt_ctr;
477
478     // leave the offset field (for now?)
479
480     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
481                 "received packet: length=%d, channel=%d, cycle=%d, at %08X\n",
482                 length, channel, cycle, pkt_ctr);
483     m_packets++;
484     #ifdef DEBUG
485     if (length > m_max_packet_size) {
486         debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
487                      this, getTypeString(), length, m_max_packet_size);
488     }
489     if(m_last_cycle == -1) {
490         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle);
491     }
492     #endif
493
494     // iterate the client if required
495     if(m_Client) {
496         enum raw1394_iso_disposition retval = m_Client->putPacket(data, length, channel, tag, sy, pkt_ctr, dropped_cycles);
497         if (retval == RAW1394_ISO_OK) {
498             if (m_dont_exit_iterate_loop) {
499                 return RAW1394_ISO_OK;
500             } else {
501                 m_dont_exit_iterate_loop = true;
502                 debugOutput(DEBUG_LEVEL_VERBOSE,
503                                 "(%p) loop exit requested\n",
504                                 this);
505                 return RAW1394_ISO_DEFER;
506             }
507         } else {
508             return retval;
509         }
510     }
511
512     return RAW1394_ISO_OK;
513 }
514
515 enum raw1394_iso_disposition
516 IsoHandler::getPacket(unsigned char *data, unsigned int *length,
517                       unsigned char *tag, unsigned char *sy,
518                       int cycle, unsigned int dropped, unsigned int skipped) {
519
520     uint32_t pkt_ctr;
521     if (cycle < 0) {
522         // mark invalid
523         pkt_ctr = 0xFFFFFFFF;
524     } else {
525         pkt_ctr = cycle << 12;
526
527         // if we assume that one iterate() loop doesn't take longer than 0.5 seconds,
528         // the seconds field won't change while the iterate loop runs
529         // this means that we can preset 'now' before running iterate()
530         uint32_t now_secs = CYCLE_TIMER_GET_SECS(m_last_now);
531         // causality results in the fact that 'now' is always after 'cycle'
532         if(CYCLE_TIMER_GET_CYCLES(m_last_now) > (unsigned int)cycle) {
533             // the cycle field has wrapped, add one second
534             now_secs += 1;
535             // no need for this:
536             //if(now_secs == 128) {
537             //    now_secs = 0;
538             //}
539             // since we mask later on
540         }
541         pkt_ctr |= (now_secs & 0x7F) << 25;
542
543         #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
544         // add a seconds field
545         uint32_t now = m_manager.get1394Service().getCycleTimer();
546         uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
547         // causality results in the fact that 'now' is always after 'cycle'
548         if(CYCLE_TIMER_GET_CYCLES(now) > (unsigned int)cycle) {
549             // the cycle field has wrapped, add one second
550             now_secs_ref += 1;
551             // no need for this:
552             //if(now_secs == 128) {
553             //    now_secs = 0;
554             //}
555             // since we mask later on
556         }
557         uint32_t pkt_ctr_ref = cycle << 12;
558         pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
559
560         if(pkt_ctr != pkt_ctr_ref) {
561             debugWarning("reconstructed CTR counter discrepancy\n");
562             pkt_ctr=pkt_ctr_ref;
563         }
564         #endif
565     }
566     if (m_packets < m_buf_packets) { // these are still prebuffer packets
567         m_last_packet_handled_at = 0xFFFFFFFF;
568     } else {
569         m_last_packet_handled_at = pkt_ctr;
570     }
571     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
572                 "sending packet: length=%d, cycle=%d, at %08X\n",
573                 *length, cycle, pkt_ctr);
574
575     m_packets++;
576
577     #ifdef DEBUG
578     if(m_last_cycle == -1) {
579         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %d)\n", getTypeString(), this, cycle);
580     }
581     #endif
582
583     // keep track of dropped cycles
584     int dropped_cycles = 0;
585     if (m_last_cycle != cycle && m_last_cycle != -1) {
586         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
587         // correct for skipped packets
588         // since those are not dropped, but only delayed
589         dropped_cycles -= skipped;
590
591         #ifdef DEBUG
592         if(skipped) {
593             debugOutput(DEBUG_LEVEL_VERBOSE,
594                         "(%p) skipped %d cycles, cycle: %d, last_cycle: %d, dropped: %d\n",
595                         this, skipped, cycle, m_last_cycle, dropped);
596             m_skipped += skipped;
597         }
598         if (dropped_cycles < 0) {
599             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d, skipped: %d\n",
600                          this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
601         }
602         if (dropped_cycles > 0) {
603             debugOutput(DEBUG_LEVEL_VERBOSE,
604                         "(%p) dropped %d packets on cycle %u (last_cycle=%u, dropped=%d, skipped: %d)\n",
605                         this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
606             m_dropped += dropped_cycles - skipped;
607         }
608         #endif
609     }
610     if (cycle >= 0) {
611         m_last_cycle = cycle;
612        
613         #ifdef DEBUG
614 /*        int ahead = diffCycles(cycle, now_cycles);
615         if (ahead < m_min_ahead) m_min_ahead = ahead;
616 */
617         #endif
618     }
619
620     #ifdef DEBUG
621     if (dropped > 0) {
622         debugOutput(DEBUG_LEVEL_VERBOSE,
623                     "(%p) OHCI issue on cycle %u (dropped_cycles=%d, last_cycle=%u, dropped=%d, skipped: %d)\n",
624                     this, cycle, dropped_cycles, m_last_cycle, dropped, skipped);
625     }
626     #endif
627
628     if(m_Client) {
629         enum raw1394_iso_disposition retval;
630         retval = m_Client->getPacket(data, length, tag, sy, pkt_ctr, dropped_cycles, skipped, m_max_packet_size);
631         #ifdef DEBUG
632         if (*length > m_max_packet_size) {
633             debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
634                          this, getTypeString(), *length, m_max_packet_size);
635         }
636         #endif
637         if (retval == RAW1394_ISO_OK) {
638             if (m_dont_exit_iterate_loop) {
639                 return RAW1394_ISO_OK;
640             } else {
641                 m_dont_exit_iterate_loop = true;
642                 debugOutput(DEBUG_LEVEL_VERBOSE,
643                                 "(%p) loop exit requested\n",
644                                 this);
645                 return RAW1394_ISO_DEFER;
646             }
647         } else {
648             return retval;
649         }
650     }
651
652     *tag = 0;
653     *sy = 0;
654     *length = 0;
655     return RAW1394_ISO_OK;
656 }
657
658 bool IsoHandler::prepare()
659 {
660     // check the state
661     if(m_State != E_Initialized) {
662         debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State);
663         return false;
664     }
665
666     // Don't call until libraw1394's raw1394_new_handle() function has been
667     // fixed to correctly initialise the iso_packet_infos field.  Bug is
668     // confirmed present in libraw1394 1.2.1.
669     //     raw1394_iso_shutdown(m_handle);
670     m_State = E_Prepared;
671
672     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client);
673     dumpInfo();
674     if (getType() == eHT_Receive) {
675         if(raw1394_iso_recv_init(m_handle,
676                                 iso_receive_handler,
677                                 m_buf_packets,
678                                 m_max_packet_size,
679                                 m_Client->getChannel(),
680                                 m_receive_mode,
681                                 m_irq_interval)) {
682             debugFatal("Could not do receive initialisation!\n" );
683             debugFatal("  %s\n",strerror(errno));
684             return false;
685         }
686         return true;
687     } else {
688         if(raw1394_iso_xmit_init(m_handle,
689                                 iso_transmit_handler,
690                                 m_buf_packets,
691                                 m_max_packet_size,
692                                 m_Client->getChannel(),
693                                 m_speed,
694                                 m_irq_interval)) {
695             debugFatal("Could not do xmit initialisation!\n" );
696             return false;
697         }
698         return true;
699     }
700 }
701
702 bool IsoHandler::enable(int cycle)
703 {
704     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
705     // check the state
706     if(m_State != E_Prepared) {
707         if(!prepare()) {
708             debugFatal("Could not prepare handler\n");
709             return false;
710         }
711     }
712
713     if (getType() == eHT_Receive) {
714         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
715             debugFatal("Could not start receive handler (%s)\n",strerror(errno));
716             dumpInfo();
717             return false;
718         }
719     } else {
720         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
721             debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
722             dumpInfo();
723             return false;
724         }
725     }
726
727 #ifdef DEBUG
728     m_min_ahead = 7999;
729 #endif
730
731     // indicate that the first iterate() still has to occur.
732     m_last_now = 0xFFFFFFFF;
733
734     m_State = E_Running;
735     return true;
736 }
737
738 /**
739  * @brief convert a EHandlerType to a string
740  * @param t the type
741  * @return a char * describing the state
742  */
743 const char *
744 IsoHandler::eHTToString(enum EHandlerType t) {
745     switch (t) {
746         case eHT_Receive: return "Receive";
747         case eHT_Transmit: return "Transmit";
748         default: return "error: unknown type";
749     }
750 }
Note: See TracBrowser for help on using the browser.