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

Revision 1348, 24.2 kB (checked in by ppalmers, 12 years ago)

merge 2.0 branch changes to trunk. svn merge -r 1337:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

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