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

Revision 977, 17.9 kB (checked in by ppalmers, 13 years ago)

switch back to DMA bufferfill for receive

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
29 #include "libstreaming/generic/StreamProcessor.h"
30 #include "libutil/PosixThread.h"
31
32 #include <errno.h>
33 #include <netinet/in.h>
34 #include <assert.h>
35 #include <unistd.h>
36 #include <string.h>
37
38 #include <iostream>
39 using namespace std;
40 using namespace Streaming;
41
42 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
43
44 /* the C callbacks */
45 enum raw1394_iso_disposition
46 IsoHandler::iso_transmit_handler(raw1394handle_t handle,
47         unsigned char *data, unsigned int *length,
48         unsigned char *tag, unsigned char *sy,
49         int cycle, unsigned int dropped1) {
50
51     IsoHandler *xmitHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
52     assert(xmitHandler);
53     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
54     unsigned int dropped = dropped1 & 0xFFFF;
55
56     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped, skipped);
57 }
58
59 enum raw1394_iso_disposition
60 IsoHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
61                         unsigned int length, unsigned char channel,
62                         unsigned char tag, unsigned char sy, unsigned int cycle,
63                         unsigned int dropped1) {
64
65     IsoHandler *recvHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
66     assert(recvHandler);
67
68     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
69     unsigned int dropped = dropped1 & 0xFFFF;
70
71     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped, skipped);
72 }
73
74 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
75 {
76     debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
77
78     IsoHandler *handler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
79     assert(handler);
80     return handler->handleBusReset(generation);
81 }
82
83 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t)
84    : m_manager( manager )
85    , m_type ( t )
86    , m_handle( 0 )
87    , m_buf_packets( 400 )
88    , m_max_packet_size( 1024 )
89    , m_irq_interval( -1 )
90    , m_Client( 0 )
91    , m_speed( RAW1394_ISO_SPEED_400 )
92    , m_prebuffers( 0 )
93    , m_State( E_Created )
94 #ifdef DEBUG
95    , m_packets ( 0 )
96 #endif
97 {
98 }
99
100 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t,
101                        unsigned int buf_packets, unsigned int max_packet_size, int irq)
102    : m_manager( manager )
103    , m_type ( t )
104    , m_handle( 0 )
105    , m_buf_packets( buf_packets )
106    , m_max_packet_size( max_packet_size )
107    , m_irq_interval( irq )
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 #endif
115 {
116 }
117
118 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t, unsigned int buf_packets,
119                        unsigned int max_packet_size, int irq,
120                        enum raw1394_iso_speed speed)
121    : m_manager( manager )
122    , m_type ( t )
123    , m_handle( 0 )
124    , m_buf_packets( buf_packets )
125    , m_max_packet_size( max_packet_size )
126    , m_irq_interval( irq )
127    , m_Client( 0 )
128    , m_speed( speed )
129    , m_prebuffers( 0 )
130    , m_State( E_Created )
131 #ifdef DEBUG
132    , m_packets ( 0 )
133 #endif
134 {
135 }
136
137 IsoHandler::~IsoHandler() {
138 // Don't call until libraw1394's raw1394_new_handle() function has been
139 // fixed to correctly initialise the iso_packet_infos field.  Bug is
140 // confirmed present in libraw1394 1.2.1.  In any case,
141 // raw1394_destroy_handle() will do any iso system shutdown required.
142 //     raw1394_iso_shutdown(m_handle);
143     if(m_handle) {
144         if (m_State == E_Running) {
145             disable();
146         }
147         raw1394_destroy_handle(m_handle);
148     }
149 }
150
151 bool
152 IsoHandler::waitForClient()
153 {
154     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n");
155     if(m_Client) {
156         bool result;
157         if (m_type == eHT_Receive) {
158             result = m_Client->waitForProducePacket();
159         } else {
160             result = m_Client->waitForConsumePacket();
161         }
162         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
163         return result;
164     } else {
165         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, " no client\n");
166     }
167     return false;
168 }
169
170 bool
171 IsoHandler::tryWaitForClient()
172 {
173     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n");
174     if(m_Client) {
175         bool result;
176         if (m_type == eHT_Receive) {
177             result = m_Client->canProducePacket();
178         } else {
179             result = m_Client->canConsumePacket();
180         }
181         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
182         return result;
183     } else {
184         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " no client\n");
185     }
186     return false;
187 }
188 /*
189 bool
190 IsoHandler::Execute()
191 {
192     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE, "%p: Execute thread...\n", this);
193
194     // bypass if not running
195     if (m_State != E_Running) {
196         debugOutput( DEBUG_LEVEL_VERBOSE, "%p: not polling since not running...\n", this);
197         usleep(m_poll_timeout * 1000);
198         debugOutput( DEBUG_LEVEL_VERBOSE, "%p: done sleeping...\n", this);
199         return true;
200     }
201
202     // wait for the availability of frames in the client
203     // (blocking for transmit handlers)
204     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Waiting for Client activity...\n", this, getTypeString());
205     if (waitForClient()) {
206 #if ISOHANDLER_USE_POLL
207         bool result = true;
208         while(result && m_Client && tryWaitForClient()) {
209             int err = poll(&m_poll_fd, 1, m_poll_timeout);
210             if (err == -1) {
211                 if (errno == EINTR) {
212                     return true;
213                 }
214                 debugFatal("%p, poll error: %s\n", this, strerror (errno));
215                 return false;
216             }
217
218             if(m_poll_fd.revents & (POLLIN)) {
219                 result=iterate();
220                 if(!result) {
221                     debugOutput( DEBUG_LEVEL_VERBOSE,
222                                 "IsoHandler (%p): Failed to iterate handler\n",
223                                 this);
224                 }
225             } else {
226                 if (m_poll_fd.revents & POLLERR) {
227                     debugWarning("error on fd for %p\n", this);
228                 }
229                 if (m_poll_fd.revents & POLLHUP) {
230                     debugWarning("hangup on fd for %p\n",this);
231                 }
232                 break;
233             }
234         }
235         return result;
236 #else
237         // iterate() is blocking if no 1394 data is available
238         // so poll'ing is not really necessary
239         bool result = true;
240         while(result && m_Client && tryWaitForClient()) {
241             result = iterate();
242 //             if (getType() == eHT_Receive) {
243 //                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterate returned: %d\n",
244 //                             this, (m_type==eHT_Receive?"Receive":"Transmit"), result);
245 //             }
246         }
247         return result;
248 #endif
249     } else {
250         debugError("waitForClient() failed.\n");
251         return false;
252     }
253 }*/
254
255 bool
256 IsoHandler::iterate() {
257     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler...\n",
258                 this, getTypeString());
259     if(m_State == E_Running) {
260 #if ISOHANDLER_FLUSH_BEFORE_ITERATE
261         flush();
262 #endif
263         if(raw1394_loop_iterate(m_handle)) {
264             debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
265                         this, strerror(errno));
266             return false;
267         }
268         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) done interating ISO handler...\n",
269                            this, getTypeString());
270         return true;
271     } else {
272         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Not iterating a non-running handler...\n",
273                     this, getTypeString());
274         return false;
275     }
276 }
277
278 bool
279 IsoHandler::init()
280 {
281     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
282     // check the state
283     if(m_State != E_Created) {
284         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
285         return false;
286     }
287
288     // the main handle for the ISO traffic
289     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
290     if ( !m_handle ) {
291         if ( !errno ) {
292             debugError("libraw1394 not compatible\n");
293         } else {
294             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
295             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
296         }
297         return false;
298     }
299     raw1394_set_userdata(m_handle, static_cast<void *>(this));
300
301     // bus reset handling
302     if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
303         debugWarning("Could not enable busreset notification.\n");
304         debugWarning(" Error message: %s\n",strerror(errno));
305         debugWarning("Continuing without bus reset support.\n");
306     } else {
307         // apparently this cannot fail
308         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
309     }
310
311     // update the internal state
312     m_State=E_Initialized;
313     return true;
314 }
315
316 bool IsoHandler::disable()
317 {
318     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n",
319                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
320
321     // check state
322     if(m_State == E_Prepared) return true;
323     if(m_State != E_Running) {
324         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
325         return false;
326     }
327
328     // this is put here to try and avoid the
329     // Runaway context problem
330     // don't know if it will help though.
331     raw1394_iso_xmit_sync(m_handle);
332     raw1394_iso_stop(m_handle);
333     m_State = E_Prepared;
334     return true;
335 }
336
337 /**
338  * Bus reset handler
339  *
340  * @return ?
341  */
342
343 int
344 IsoHandler::handleBusReset(unsigned int generation)
345 {
346     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
347
348     #define CSR_CYCLE_TIME            0x200
349     #define CSR_REGISTER_BASE  0xfffff0000000ULL
350     // do a simple read on ourself in order to update the internal structures
351     // this avoids read failures after a bus reset
352     quadlet_t buf=0;
353     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
354                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
355
356     // notify the client of the fact that we have died
357     m_Client->handlerDied();
358
359     if(!disable()) {
360         debugError("(%p) Could not disable IsoHandler\n", this);
361     }
362
363     // request the manager to update it's shadow map
364     m_manager.requestShadowMapUpdate();
365     return 0;
366 }
367
368 void IsoHandler::dumpInfo()
369 {
370     int channel=-1;
371     if (m_Client) channel=m_Client->getChannel();
372
373     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
374             getTypeString());
375     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
376             m_manager.get1394Service().getPort(), channel);
377     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
378             m_buf_packets, m_max_packet_size, m_irq_interval);
379     if (this->getType() == eHT_Transmit) {
380         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed, PreBuffers...........: %2d, %2d\n",
381                                             m_speed, m_prebuffers);
382     }
383 }
384
385 void IsoHandler::setVerboseLevel(int l)
386 {
387     setDebugLevel(l);
388 }
389
390 bool IsoHandler::registerStream(StreamProcessor *stream)
391 {
392     assert(stream);
393     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
394
395     if (m_Client) {
396             debugFatal( "Generic IsoHandlers can have only one client\n");
397             return false;
398     }
399     m_Client=stream;
400     return true;
401 }
402
403 bool IsoHandler::unregisterStream(StreamProcessor *stream)
404 {
405     assert(stream);
406     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
407
408     if(stream != m_Client) {
409             debugFatal( "no client registered\n");
410             return false;
411     }
412     m_Client=0;
413     return true;
414 }
415
416 void IsoHandler::flush()
417 {
418     if(m_type == eHT_Receive) {
419         raw1394_iso_recv_flush(m_handle);
420     } else {
421         // do nothing
422     }
423 }
424
425 // ISO packet interface
426 enum raw1394_iso_disposition IsoHandler::putPacket(
427                     unsigned char *data, unsigned int length,
428                     unsigned char channel, unsigned char tag, unsigned char sy,
429                     unsigned int cycle, unsigned int dropped, unsigned int skipped) {
430
431     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
432                        "received packet: length=%d, channel=%d, cycle=%d\n",
433                        length, channel, cycle);
434     #ifdef DEBUG
435     m_packets++;
436     if (length > m_max_packet_size) {
437         debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
438                      this, getTypeString(), length, m_max_packet_size);
439     }
440     #endif
441     if(m_Client) {
442         return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped, skipped);
443     }
444
445     return RAW1394_ISO_OK;
446 }
447
448
449 enum raw1394_iso_disposition
450 IsoHandler::getPacket(unsigned char *data, unsigned int *length,
451                       unsigned char *tag, unsigned char *sy,
452                       int cycle, unsigned int dropped, unsigned int skipped) {
453
454     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
455                        "sending packet: length=%d, cycle=%d\n",
456                        *length, cycle);
457     #ifdef DEBUG
458     m_packets++;
459     #endif
460     if(m_Client) {
461         enum raw1394_iso_disposition retval;
462         retval = m_Client->getPacket(data, length, tag, sy, cycle, dropped, skipped, m_max_packet_size);
463         #ifdef DEBUG
464         if (*length > m_max_packet_size) {
465             debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
466                          this, getTypeString(), *length, m_max_packet_size);
467         }
468         #endif
469         return retval;
470     }
471     *tag = 0;
472     *sy = 0;
473     *length = 0;
474     return RAW1394_ISO_OK;
475 }
476
477 bool IsoHandler::prepare()
478 {
479     // check the state
480     if(m_State != E_Initialized) {
481         debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State);
482         return false;
483     }
484
485     // Don't call until libraw1394's raw1394_new_handle() function has been
486     // fixed to correctly initialise the iso_packet_infos field.  Bug is
487     // confirmed present in libraw1394 1.2.1.
488     //     raw1394_iso_shutdown(m_handle);
489     m_State = E_Prepared;
490
491     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client);
492     dumpInfo();
493     if (getType() == eHT_Receive) {
494         if(m_irq_interval > 1) {
495             if(raw1394_iso_recv_init(m_handle,
496                                     iso_receive_handler,
497                                     m_buf_packets,
498                                     m_max_packet_size,
499                                     m_Client->getChannel(),
500                                     RAW1394_DMA_BUFFERFILL,
501 //                                     RAW1394_DMA_PACKET_PER_BUFFER,
502                                     m_irq_interval)) {
503                 debugFatal("Could not do receive initialisation (DMA_BUFFERFILL)!\n" );
504                 debugFatal("  %s\n",strerror(errno));
505                 return false;
506             }
507         } else {
508             if(raw1394_iso_recv_init(m_handle,
509                                     iso_receive_handler,
510                                     m_buf_packets,
511                                     m_max_packet_size,
512                                     m_Client->getChannel(),
513                                     RAW1394_DMA_PACKET_PER_BUFFER,
514                                     m_irq_interval)) {
515                 debugFatal("Could not do receive initialisation (PACKET_PER_BUFFER)!\n" );
516                 debugFatal("  %s\n",strerror(errno));
517                 return false;
518             }
519         }
520         return true;
521     } else {
522         if(raw1394_iso_xmit_init(m_handle,
523                                 iso_transmit_handler,
524                                 m_buf_packets,
525                                 m_max_packet_size,
526                                 m_Client->getChannel(),
527                                 m_speed,
528                                 m_irq_interval)) {
529             debugFatal("Could not do xmit initialisation!\n" );
530             return false;
531         }
532         return true;
533     }
534 }
535
536 bool IsoHandler::enable(int cycle)
537 {
538     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
539     // check the state
540     if(m_State != E_Prepared) {
541         if(!prepare()) {
542             debugFatal("Could not prepare handler\n");
543             return false;
544         }
545     }
546
547     if (getType() == eHT_Receive) {
548         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
549             debugFatal("Could not start receive handler (%s)\n",strerror(errno));
550             dumpInfo();
551             return false;
552         }
553     } else {
554         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
555             debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
556             dumpInfo();
557             return false;
558         }
559     }
560
561     m_State = E_Running;
562     return true;
563 }
564
565 /**
566  * @brief convert a EHandlerType to a string
567  * @param t the type
568  * @return a char * describing the state
569  */
570 const char *
571 IsoHandler::eHTToString(enum EHandlerType t) {
572     switch (t) {
573         case eHT_Receive: return "Receive";
574         case eHT_Transmit: return "Transmit";
575         default: return "error: unknown type";
576     }
577 }
Note: See TracBrowser for help on using the browser.