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

Revision 1765, 65.8 kB (checked in by ppalmers, 11 years ago)

put everything related to iso streaming into one CPP file. this should give the compiler some more freedom to optimize.

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 "IsoHandlerManager.h"
27 #include "ieee1394service.h"
28 #include "cycletimer.h"
29 #include "libstreaming/generic/StreamProcessor.h"
30
31 #include "libutil/Atomic.h"
32 #include "libutil/PosixThread.h"
33 #include "libutil/SystemTimeSource.h"
34 #include "libutil/Watchdog.h"
35 #include "libutil/Configuration.h"
36
37 #include <cstring>
38 #include <assert.h>
39
40 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
41 IMPL_DEBUG_MODULE( IsoHandlerManager::IsoTask, IsoTask, DEBUG_LEVEL_NORMAL );
42 IMPL_DEBUG_MODULE( IsoHandlerManager::IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
43
44 using namespace Streaming;
45
46 // --- ISO Thread --- //
47
48 IsoHandlerManager::IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType t)
49     : m_manager( manager )
50     , m_SyncIsoHandler ( NULL )
51     , m_handlerType( t )
52     , m_running( false )
53     , m_in_busreset( false )
54     , m_activity_wait_timeout_nsec (ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL)
55 {
56 }
57
58 IsoHandlerManager::IsoTask::~IsoTask()
59 {
60     sem_destroy(&m_activity_semaphore);
61 }
62
63 bool
64 IsoHandlerManager::IsoTask::Init()
65 {
66     request_update = 0;
67
68     int i;
69     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
70         m_IsoHandler_map_shadow[i] = NULL;
71         m_poll_fds_shadow[i].events = 0;
72     }
73     m_poll_nfds_shadow = 0;
74
75     #ifdef DEBUG
76     m_last_loop_entry = 0;
77     m_successive_short_loops = 0;
78     #endif
79
80     sem_init(&m_activity_semaphore, 0, 0);
81     m_running = true;
82     return true;
83 }
84
85 void
86 IsoHandlerManager::IsoTask::requestShadowMapUpdate()
87 {
88     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) enter\n", this);
89     INC_ATOMIC(&request_update);
90
91     // get the thread going again
92     signalActivity();
93     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) exit\n", this);
94 }
95
96 bool
97 IsoHandlerManager::IsoTask::handleBusReset()
98 {
99     bool retval = true;
100     if(!m_running) {
101         // nothing to do here
102         return true;
103     }
104     m_in_busreset = true;
105     requestShadowMapUpdate();
106
107     unsigned int i, max;
108     max = m_manager.m_IsoHandlers.size();
109     for (i = 0; i < max; i++) {
110         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
111         assert(h);
112
113         // skip the handlers not intended for us
114         if(h->getType() != m_handlerType) continue;
115
116         if (!h->handleBusReset()) {
117             debugWarning("Failed to handle busreset on %p\n", h);
118             retval = false;
119         }
120     }
121
122     // re-enable processing
123     m_in_busreset = false;
124     requestShadowMapUpdate();
125     return retval;
126 }
127
128 // updates the internal stream map
129 // note that this should be executed with the guarantee that
130 // nobody will modify the parent data structures
131 void
132 IsoHandlerManager::IsoTask::updateShadowMapHelper()
133 {
134     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updating shadow vars...\n", this);
135     // we are handling a busreset
136     if(m_in_busreset) {
137         m_poll_nfds_shadow = 0;
138         return;
139     }
140     unsigned int i, cnt, max;
141     max = m_manager.m_IsoHandlers.size();
142     m_SyncIsoHandler = NULL;
143     for (i = 0, cnt = 0; i < max; i++) {
144         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
145         assert(h);
146
147         // skip the handlers not intended for us
148         if(h->getType() != m_handlerType) continue;
149
150         // update the state of the handler
151         // FIXME: maybe this is not the best place to do this
152         // it might be better to eliminate the 'requestShadowMapUpdate'
153         // entirely and replace it with a mechanism that implements all
154         // actions on the m_manager.m_IsoHandlers in the loop
155         h->updateState();
156
157         // rebuild the map
158         if (h->isEnabled()) {
159             m_IsoHandler_map_shadow[cnt] = h;
160             m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();
161             m_poll_fds_shadow[cnt].revents = 0;
162             m_poll_fds_shadow[cnt].events = POLLIN;
163             cnt++;
164             // FIXME: need a more generic approach here
165             if(   m_SyncIsoHandler == NULL
166                && h->getType() == IsoHandler::eHT_Transmit) {
167                 m_SyncIsoHandler = h;
168             }
169
170             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p added\n",
171                                               this, h->getTypeString(), h);
172         } else {
173             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p skipped (disabled)\n",
174                                               this, h->getTypeString(), h);
175         }
176         if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {
177             debugWarning("Too much ISO Handlers in thread...\n");
178             break;
179         }
180     }
181
182     // FIXME: need a more generic approach here
183     // if there are no active transmit handlers,
184     // use the first receive handler
185     if(   m_SyncIsoHandler == NULL
186        && m_poll_nfds_shadow) {
187         m_SyncIsoHandler = m_IsoHandler_map_shadow[0];
188     }
189     m_poll_nfds_shadow = cnt;
190     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updated shadow vars...\n", this);
191 }
192
193 bool
194 IsoHandlerManager::IsoTask::Execute()
195 {
196     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
197                 "(%p, %s) Execute\n",
198                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
199     int err;
200     unsigned int i;
201     unsigned int m_poll_timeout = 10;
202
203     #ifdef DEBUG
204     uint64_t now = Util::SystemTimeSource::getCurrentTimeAsUsecs();
205     int diff = now - m_last_loop_entry;
206     if(diff < 100) {
207         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
208                            "(%p, %s) short loop detected (%d usec), cnt: %d\n",
209                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
210                            diff, m_successive_short_loops);
211         m_successive_short_loops++;
212         if(m_successive_short_loops > 10000) {
213             debugError("Shutting down runaway thread\n");
214             m_running = false;
215             return false;
216         }
217     } else {
218         // reset the counter
219         m_successive_short_loops = 0;
220     }
221     m_last_loop_entry = now;
222     #endif
223
224     // if some other thread requested a shadow map update, do it
225     if(request_update) {
226         updateShadowMapHelper();
227         DEC_ATOMIC(&request_update); // ack the update
228         assert(request_update >= 0);
229     }
230
231     // bypass if no handlers are registered
232     if (m_poll_nfds_shadow == 0) {
233         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
234                            "(%p, %s) bypass iterate since no handlers to poll\n",
235                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
236         usleep(m_poll_timeout * 1000);
237         return true;
238     }
239
240     // FIXME: what can happen is that poll() returns, but not all clients are
241     // ready. there might be some busy waiting behavior that still has to be solved.
242
243     // setup the poll here
244     // we should prevent a poll() where no events are specified, since that will only time-out
245     bool no_one_to_poll = true;
246     while(no_one_to_poll) {
247         for (i = 0; i < m_poll_nfds_shadow; i++) {
248             short events = 0;
249             IsoHandler *h = m_IsoHandler_map_shadow[i];
250             // we should only poll on a transmit handler
251             // that has a client that is ready to send
252             // something. Otherwise it will end up in
253             // busy wait looping since the packet function
254             // will defer processing (also avoids the
255             // AGAIN problem)
256             if (h->canIterateClient()) {
257                 events = POLLIN | POLLPRI;
258                 no_one_to_poll = false;
259             }
260             m_poll_fds_shadow[i].events = events;
261         }
262
263         if(no_one_to_poll) {
264             debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
265                         "(%p, %s) No one to poll, waiting for something to happen\n",
266                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
267             // wait for something to happen
268             switch(waitForActivity()) {
269                 case IsoHandlerManager::IsoTask::eAR_Error:
270                     debugError("Error while waiting for activity\n");
271                     return false;
272                 case IsoHandlerManager::IsoTask::eAR_Interrupted:
273                     // FIXME: what to do here?
274                     debugWarning("Interrupted while waiting for activity\n");
275                     break;
276                 case IsoHandlerManager::IsoTask::eAR_Timeout:
277                     // FIXME: what to do here?
278                     debugWarning("Timeout while waiting for activity\n");
279                     no_one_to_poll = false; // exit the loop to be able to detect failing handlers
280                     break;
281                 case IsoHandlerManager::IsoTask::eAR_Activity:
282                     // do nothing
283                     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
284                                        "(%p, %s) something happened\n",
285                                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
286                     break;
287             }
288         }
289     }
290
291     // Use a shadow map of the fd's such that we don't have to update
292     // the fd map everytime we run poll().
293     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
294     uint32_t ctr_at_poll_return = m_manager.get1394Service().getCycleTimer();
295
296     if (err < 0) {
297         if (errno == EINTR) {
298             debugOutput(DEBUG_LEVEL_VERBOSE, "Ignoring poll return due to signal\n");
299             return true;
300         }
301         debugFatal("poll error: %s\n", strerror (errno));
302         m_running = false;
303         return false;
304     }
305
306     // find handlers that have died
307     uint64_t ctr_at_poll_return_ticks = CYCLE_TIMER_TO_TICKS(ctr_at_poll_return);
308     bool handler_died = false;
309     for (i = 0; i < m_poll_nfds_shadow; i++) {
310         // figure out if a handler has died
311
312         // this is the time of the last packet we saw in the iterate() handler
313         uint32_t last_packet_seen = m_IsoHandler_map_shadow[i]->getLastPacketTime();
314         if (last_packet_seen == 0xFFFFFFFF) {
315             // this was not iterated yet, so can't be dead
316             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
317                         "(%p, %s) handler %d didn't see any packets yet\n",
318                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"), i);
319             continue;
320         }
321
322         uint64_t last_packet_seen_ticks = CYCLE_TIMER_TO_TICKS(last_packet_seen);
323         // we use a relatively large value to distinguish between "death" and xrun
324         int64_t max_diff_ticks = TICKS_PER_SECOND * 2;
325         int64_t measured_diff_ticks = diffTicks(ctr_at_poll_return_ticks, last_packet_seen_ticks);
326
327         debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
328                            "(%p, %s) check handler %d: diff = %"PRId64", max = %"PRId64", now: %08X, last: %08X\n",
329                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
330                            i, measured_diff_ticks, max_diff_ticks, ctr_at_poll_return, last_packet_seen);
331         if(measured_diff_ticks > max_diff_ticks) {
332             debugFatal("(%p, %s) Handler died: now: %08X, last: %08X, diff: %"PRId64" (max: %"PRId64")\n",
333                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
334                        ctr_at_poll_return, last_packet_seen, measured_diff_ticks, max_diff_ticks);
335             m_IsoHandler_map_shadow[i]->notifyOfDeath();
336             handler_died = true;
337         }
338     }
339
340     if(handler_died) {
341         m_running = false;
342         return false; // one or more handlers have died
343     }
344
345     // iterate the handlers
346     for (i = 0; i < m_poll_nfds_shadow; i++) {
347         #ifdef DEBUG
348         if(m_poll_fds_shadow[i].revents) {
349             debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
350                         "(%p, %s) received events: %08X for (%d/%d, %p, %s)\n",
351                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
352                         m_poll_fds_shadow[i].revents,
353                         i, m_poll_nfds_shadow,
354                         m_IsoHandler_map_shadow[i],
355                         m_IsoHandler_map_shadow[i]->getTypeString());
356         }
357         #endif
358
359         // if we get here, it means two things:
360         // 1) the kernel can accept or provide packets (poll returned POLLIN)
361         // 2) the client can provide or accept packets (since we enabled polling)
362         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
363             m_IsoHandler_map_shadow[i]->iterate(ctr_at_poll_return);
364         } else {
365             // there might be some error condition
366             if (m_poll_fds_shadow[i].revents & POLLERR) {
367                 debugWarning("(%p) error on fd for %d\n", this, i);
368             }
369             if (m_poll_fds_shadow[i].revents & POLLHUP) {
370                 debugWarning("(%p) hangup on fd for %d\n", this, i);
371             }
372         }
373     }
374     return true;
375 }
376
377 enum IsoHandlerManager::IsoTask::eActivityResult
378 IsoHandlerManager::IsoTask::waitForActivity()
379 {
380     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
381                        "(%p, %s) waiting for activity\n",
382                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
383     struct timespec ts;
384     int result;
385
386     if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
387         debugError("clock_gettime failed\n");
388         return eAR_Error;
389     }
390
391     ts.tv_nsec += m_activity_wait_timeout_nsec;
392     while(ts.tv_nsec >= 1000000000LL) {
393         ts.tv_sec += 1;
394         ts.tv_nsec -= 1000000000LL;
395     }
396
397     result = sem_timedwait(&m_activity_semaphore, &ts);
398
399     if(result != 0) {
400         if (errno == ETIMEDOUT) {
401             debugOutput(DEBUG_LEVEL_VERBOSE,
402                         "(%p) sem_timedwait() timed out (result=%d)\n",
403                         this, result);
404             return eAR_Timeout;
405         } else if (errno == EINTR) {
406             debugOutput(DEBUG_LEVEL_VERBOSE,
407                         "(%p) sem_timedwait() interrupted by signal (result=%d)\n",
408                         this, result);
409             return eAR_Interrupted;
410         } else if (errno == EINVAL) {
411             debugError("(%p) sem_timedwait error (result=%d errno=EINVAL)\n",
412                         this, result);
413             debugError("(%p) timeout_nsec=%lld ts.sec=%"PRId64" ts.nsec=%"PRId64"\n",
414                        this, m_activity_wait_timeout_nsec,
415                        (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec);
416             return eAR_Error;
417         } else {
418             debugError("(%p) sem_timedwait error (result=%d errno=%d)\n",
419                         this, result, errno);
420             debugError("(%p) timeout_nsec=%lld ts.sec=%"PRId64" ts.nsec=%"PRId64"\n",
421                        this, m_activity_wait_timeout_nsec,
422                        (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec);
423             return eAR_Error;
424         }
425     }
426
427     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
428                 "(%p, %s) got activity\n",
429                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
430     return eAR_Activity;
431 }
432
433 void
434 IsoHandlerManager::IsoTask::signalActivity()
435 {
436     // signal the activity cond var
437     sem_post(&m_activity_semaphore);
438     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
439                 "(%p, %s) activity\n",
440                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
441 }
442
443 void IsoHandlerManager::IsoTask::setVerboseLevel(int i) {
444     setDebugLevel(i);
445     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
446 }
447
448 // -- the ISO handler manager -- //
449 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
450    : m_State(E_Created)
451    , m_service( service )
452    , m_realtime(false), m_priority(0)
453    , m_IsoThreadTransmit ( NULL )
454    , m_IsoTaskTransmit ( NULL )
455    , m_IsoThreadReceive ( NULL )
456    , m_IsoTaskReceive ( NULL )
457 {
458 }
459
460 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
461    : m_State(E_Created)
462    , m_service( service )
463    , m_realtime(run_rt), m_priority(rt_prio)
464    , m_IsoThreadTransmit ( NULL )
465    , m_IsoTaskTransmit ( NULL )
466    , m_IsoThreadReceive ( NULL )
467    , m_IsoTaskReceive ( NULL )
468 {
469 }
470
471 IsoHandlerManager::~IsoHandlerManager()
472 {
473     stopHandlers();
474     pruneHandlers();
475     if(m_IsoHandlers.size() > 0) {
476         debugError("Still some handlers in use\n");
477     }
478     if (m_IsoThreadTransmit) {
479         m_IsoThreadTransmit->Stop();
480         delete m_IsoThreadTransmit;
481     }
482     if (m_IsoThreadReceive) {
483         m_IsoThreadReceive->Stop();
484         delete m_IsoThreadReceive;
485     }
486     if (m_IsoTaskTransmit) {
487         delete m_IsoTaskTransmit;
488     }
489     if (m_IsoTaskReceive) {
490         delete m_IsoTaskReceive;
491     }
492 }
493
494 bool
495 IsoHandlerManager::handleBusReset()
496 {
497     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
498     // A few things can happen on bus reset:
499     // 1) no devices added/removed => streams are still valid, but might have to be restarted
500     // 2) a device was removed => some streams become invalid
501     // 3) a device was added => same as 1, new device is ignored
502     if (!m_IsoTaskTransmit) {
503         debugError("No xmit task\n");
504         return false;
505     }
506     if (!m_IsoTaskReceive) {
507         debugError("No receive task\n");
508         return false;
509     }
510     if (!m_IsoTaskTransmit->handleBusReset()) {
511         debugWarning("could no handle busreset on xmit\n");
512     }
513     if (!m_IsoTaskReceive->handleBusReset()) {
514         debugWarning("could no handle busreset on recv\n");
515     }
516     return true;
517 }
518
519 void
520 IsoHandlerManager::requestShadowMapUpdate()
521 {
522     if(m_IsoTaskTransmit) m_IsoTaskTransmit->requestShadowMapUpdate();
523     if(m_IsoTaskReceive) m_IsoTaskReceive->requestShadowMapUpdate();
524 }
525
526 bool
527 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
528     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
529     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
530     if (priority < THREAD_MIN_RTPRIO) priority = THREAD_MIN_RTPRIO; // cap the priority
531     m_realtime = rt;
532     m_priority = priority;
533
534     // grab the options from the parent
535     Util::Configuration *config = m_service.getConfiguration();
536     int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE;
537     int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT;
538     int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV;
539     if(config) {
540         config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase);
541         config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit);
542         config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv);
543     }
544
545     if (m_IsoThreadTransmit) {
546         if (m_realtime) {
547             m_IsoThreadTransmit->AcquireRealTime(m_priority
548                                                  + ihm_iso_prio_increase
549                                                  + ihm_iso_prio_increase_xmit);
550         } else {
551             m_IsoThreadTransmit->DropRealTime();
552         }
553     }
554     if (m_IsoThreadReceive) {
555         if (m_realtime) {
556             m_IsoThreadReceive->AcquireRealTime(m_priority
557                                                 + ihm_iso_prio_increase
558                                                 + ihm_iso_prio_increase_recv);
559         } else {
560             m_IsoThreadReceive->DropRealTime();
561         }
562     }
563
564     return true;
565 }
566
567 bool IsoHandlerManager::init()
568 {
569     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
570     // check state
571     if(m_State != E_Created) {
572         debugError("Manager already initialized...\n");
573         return false;
574     }
575
576     // grab the options from the parent
577     Util::Configuration *config = m_service.getConfiguration();
578     int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE;
579     int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT;
580     int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV;
581     int64_t isotask_activity_timeout_usecs = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS;
582     if(config) {
583         config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase);
584         config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit);
585         config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv);
586         config->getValueForSetting("ieee1394.isomanager.isotask_activity_timeout_usecs", isotask_activity_timeout_usecs);
587     }
588
589     // create threads to iterate our ISO handlers
590     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p transmit...\n", this);
591     m_IsoTaskTransmit = new IsoTask( *this, IsoHandler::eHT_Transmit );
592     if(!m_IsoTaskTransmit) {
593         debugFatal("No task\n");
594         return false;
595     }
596     m_IsoTaskTransmit->setVerboseLevel(getDebugLevel());
597     m_IsoTaskTransmit->m_activity_wait_timeout_nsec = isotask_activity_timeout_usecs * 1000LL;
598     m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime,
599                                                 m_priority + ihm_iso_prio_increase
600                                                 + ihm_iso_prio_increase_xmit,
601                                                 PTHREAD_CANCEL_DEFERRED);
602
603     if(!m_IsoThreadTransmit) {
604         debugFatal("No thread\n");
605         return false;
606     }
607     m_IsoThreadTransmit->setVerboseLevel(getDebugLevel());
608
609     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p receive...\n", this);
610     m_IsoTaskReceive = new IsoTask( *this, IsoHandler::eHT_Receive );
611     if(!m_IsoTaskReceive) {
612         debugFatal("No task\n");
613         return false;
614     }
615     m_IsoTaskReceive->setVerboseLevel(getDebugLevel());
616     m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime,
617                                                m_priority + ihm_iso_prio_increase
618                                                + ihm_iso_prio_increase_recv,
619                                                PTHREAD_CANCEL_DEFERRED);
620
621     if(!m_IsoThreadReceive) {
622         debugFatal("No thread\n");
623         return false;
624     }
625     m_IsoThreadReceive->setVerboseLevel(getDebugLevel());
626     // register the thread with the RT watchdog
627     Util::Watchdog *watchdog = m_service.getWatchdog();
628     if(watchdog) {
629         if(!watchdog->registerThread(m_IsoThreadTransmit)) {
630             debugWarning("could not register iso transmit thread with watchdog\n");
631         }
632         if(!watchdog->registerThread(m_IsoThreadReceive)) {
633             debugWarning("could not register iso receive thread with watchdog\n");
634         }
635     } else {
636         debugWarning("could not find valid watchdog\n");
637     }
638
639     if (m_IsoThreadTransmit->Start() != 0) {
640         debugFatal("Could not start ISO Transmit thread\n");
641         return false;
642     }
643     if (m_IsoThreadReceive->Start() != 0) {
644         debugFatal("Could not start ISO Receive thread\n");
645         return false;
646     }
647
648     m_State=E_Running;
649     return true;
650 }
651
652 void
653 IsoHandlerManager::signalActivityTransmit()
654 {
655     assert(m_IsoTaskTransmit);
656     m_IsoTaskTransmit->signalActivity();
657 }
658
659 void
660 IsoHandlerManager::signalActivityReceive()
661 {
662     assert(m_IsoTaskReceive);
663     m_IsoTaskReceive->signalActivity();
664 }
665
666 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
667 {
668     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
669     assert(handler);
670     handler->setVerboseLevel(getDebugLevel());
671     m_IsoHandlers.push_back(handler);
672     requestShadowMapUpdate();
673     return true;
674 }
675
676 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
677 {
678     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
679     assert(handler);
680
681     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
682       it != m_IsoHandlers.end();
683       ++it )
684     {
685         if ( *it == handler ) {
686             m_IsoHandlers.erase(it);
687             requestShadowMapUpdate();
688             return true;
689         }
690     }
691     debugFatal("Could not find handler (%p)\n", handler);
692     return false; //not found
693 }
694
695 /**
696  * Registers an StreamProcessor with the IsoHandlerManager.
697  *
698  * If nescessary, an IsoHandler is created to handle this stream.
699  * Once an StreamProcessor is registered to the handler, it will be included
700  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
701  *
702  * @param stream the stream to register
703  * @return true if registration succeeds
704  *
705  * \todo : currently there is a one-to-one mapping
706  *        between streams and handlers, this is not ok for
707  *        multichannel receive
708  */
709 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
710 {
711     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering %s stream %p\n", stream->getTypeString(), stream);
712     assert(stream);
713
714     IsoHandler* h = NULL;
715
716     // make sure the stream isn't already attached to a handler
717     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
718       it != m_IsoHandlers.end();
719       ++it )
720     {
721         if((*it)->isStreamRegistered(stream)) {
722             debugError( "stream already registered!\n");
723             return false;
724         }
725     }
726
727     // clean up all handlers that aren't used
728     pruneHandlers();
729
730     // allocate a handler for this stream
731     if (stream->getType()==StreamProcessor::ePT_Receive) {
732         // grab the options from the parent
733         Util::Configuration *config = m_service.getConfiguration();
734         int receive_mode_setting = DEFAULT_ISO_RECEIVE_MODE;
735         int bufferfill_mode_threshold = BUFFERFILL_MODE_THRESHOLD;
736         int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
737         int max_nb_buffers_recv = MAX_RECV_NB_BUFFERS;
738         int min_packetsize_recv = MIN_RECV_PACKET_SIZE;
739         if(config) {
740             config->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting);
741             config->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold);
742             config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
743             config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv);
744             config->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv);
745         }
746
747         // setup the optimal parameters for the raw1394 ISO buffering
748         unsigned int packets_per_period = stream->getPacketsPerPeriod();
749         // reserve space for the 1394 header too (might not be necessary)
750         unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
751         unsigned int page_size = getpagesize();
752
753         enum raw1394_iso_dma_recv_mode receive_mode;
754         switch(receive_mode_setting) {
755             case 0:
756                 if(packets_per_period < (unsigned)bufferfill_mode_threshold) {
757                     debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (auto) [%d, %d]\n",
758                                  packets_per_period, bufferfill_mode_threshold);
759                     receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
760                 } else {
761                     debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (auto) [%d, %d]\n",
762                                  packets_per_period, bufferfill_mode_threshold);
763                     receive_mode = RAW1394_DMA_BUFFERFILL;
764                 }
765                 break;
766             case 1:
767                 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (config)\n");
768                 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
769                 break;
770             case 2:
771                 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (config)\n");
772                 receive_mode = RAW1394_DMA_BUFFERFILL;
773                 break;
774             default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting);
775         }
776
777         // Ensure we don't request a packet size bigger than the
778         // kernel-enforced maximum which is currently 1 page.
779         // NOTE: PP: this is not really true AFAICT
780         if (max_packet_size > page_size) {
781             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
782             return false;
783         }
784         if (max_packet_size < (unsigned)min_packetsize_recv) {
785             debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n",
786                        max_packet_size, min_packetsize_recv);
787             max_packet_size = min_packetsize_recv;
788         }
789
790         // apparently a too small value causes issues too
791         if(max_packet_size < 200) max_packet_size = 200;
792
793         // the interrupt/wakeup interval prediction of raw1394 is a mess...
794         int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
795         if(irq_interval <= 0) irq_interval=1;
796
797         // the receive buffer size doesn't matter for the latency,
798         // it does seem to be confined to a certain region for correct
799         // operation. However it is not clear how many.
800         int buffers = max_nb_buffers_recv;
801
802         // ensure at least 2 hardware interrupts per ISO buffer wraparound
803         if(irq_interval > buffers/2) {
804             irq_interval = buffers/2;
805         }
806
807         // create the actual handler
808         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
809         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
810                            buffers, max_packet_size, irq_interval);
811
812         if(!h) {
813             debugFatal("Could not create IsoRecvHandler\n");
814             return false;
815         }
816
817         h->setReceiveMode(receive_mode);
818
819     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
820         // grab the options from the parent
821         Util::Configuration *config = m_service.getConfiguration();
822         int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
823         int max_nb_buffers_xmit = MAX_XMIT_NB_BUFFERS;
824         int max_packetsize_xmit = MAX_XMIT_PACKET_SIZE;
825         int min_packetsize_xmit = MIN_XMIT_PACKET_SIZE;
826         if(config) {
827             config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
828             config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit);
829             config->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit);
830             config->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit);
831         }
832
833         // setup the optimal parameters for the raw1394 ISO buffering
834         // reserve space for the 1394 header too (might not be necessary)
835         unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
836
837         if (max_packet_size > (unsigned)max_packetsize_xmit) {
838             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
839                        max_packet_size, max_packetsize_xmit);
840             return false;
841         }
842         if (max_packet_size < (unsigned)min_packetsize_xmit) {
843             debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n",
844                        max_packet_size, min_packetsize_xmit);
845             max_packet_size = min_packetsize_xmit;
846         }
847
848         int buffers = max_nb_buffers_xmit;
849         unsigned int packets_per_period = stream->getPacketsPerPeriod();
850
851         int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
852         if(irq_interval <= 0) irq_interval=1;
853         // ensure at least 2 hardware interrupts per ISO buffer wraparound
854         if(irq_interval > buffers/2) {
855             irq_interval = buffers/2;
856         }
857
858         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
859
860         // create the actual handler
861         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
862                            buffers, max_packet_size, irq_interval);
863
864         if(!h) {
865             debugFatal("Could not create IsoXmitHandler\n");
866             return false;
867         }
868
869     } else {
870         debugFatal("Bad stream type\n");
871         return false;
872     }
873
874     h->setVerboseLevel(getDebugLevel());
875
876     // register the stream with the handler
877     if(!h->registerStream(stream)) {
878         debugFatal("Could not register receive stream with handler\n");
879         return false;
880     }
881
882     // register the handler with the manager
883     if(!registerHandler(h)) {
884         debugFatal("Could not register receive handler with manager\n");
885         return false;
886     }
887     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
888
889     m_StreamProcessors.push_back(stream);
890     debugOutput( DEBUG_LEVEL_VERBOSE, " %zd streams, %zd handlers registered\n",
891                                       m_StreamProcessors.size(), m_IsoHandlers.size());
892     return true;
893 }
894
895 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
896 {
897     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering %s stream %p\n", stream->getTypeString(), stream);
898     assert(stream);
899
900     // make sure the stream isn't attached to a handler anymore
901     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
902       it != m_IsoHandlers.end();
903       ++it )
904     {
905         if((*it)->isStreamRegistered(stream)) {
906             if(!(*it)->unregisterStream(stream)) {
907                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
908                 return false;
909             }
910             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
911         }
912     }
913
914     // clean up all handlers that aren't used
915     pruneHandlers();
916
917     // remove the stream from the registered streams list
918     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
919       it != m_StreamProcessors.end();
920       ++it )
921     {
922         if ( *it == stream ) {
923             m_StreamProcessors.erase(it);
924             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
925             return true;
926         }
927     }
928     return false; //not found
929 }
930
931 /**
932  * @brief unregister a handler from the manager
933  * @note called without the lock held.
934  */
935 void IsoHandlerManager::pruneHandlers() {
936     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
937     IsoHandlerVector toUnregister;
938
939     // find all handlers that are not in use
940     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
941           it != m_IsoHandlers.end();
942           ++it )
943     {
944         if(!((*it)->inUse())) {
945             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
946             toUnregister.push_back(*it);
947         }
948     }
949     // delete them
950     for ( IsoHandlerVectorIterator it = toUnregister.begin();
951           it != toUnregister.end();
952           ++it )
953     {
954         unregisterHandler(*it);
955
956         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
957
958         // Now the handler's been unregistered it won't be reused
959         // again.  Therefore it really needs to be formally deleted
960         // to free up the raw1394 handle.  Otherwise things fall
961         // apart after several xrun recoveries as the system runs
962         // out of resources to support all the disused but still
963         // allocated raw1394 handles.  At least this is the current
964         // theory as to why we end up with "memory allocation"
965         // failures after several Xrun recoveries.
966         delete *it;
967     }
968 }
969
970 int
971 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
972     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
973       it != m_IsoHandlers.end();
974       ++it )
975     {
976         if((*it)->isStreamRegistered(stream)) {
977             return (*it)->getIrqInterval();
978         }
979     }
980     debugError("Stream %p has no attached handler\n", stream);
981     return 0;
982 }
983
984 IsoHandlerManager::IsoHandler *
985 IsoHandlerManager::getHandlerForStream(Streaming::StreamProcessor *stream) {
986     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
987       it != m_IsoHandlers.end();
988       ++it )
989     {
990         if((*it)->isStreamRegistered(stream)) {
991             return (*it);
992         }
993     }
994     debugError("Stream %p has no attached handler\n", stream);
995     return NULL;
996 }
997
998 void
999 IsoHandlerManager::dumpInfoForStream(Streaming::StreamProcessor *stream)
1000 {
1001     IsoHandler *h = getHandlerForStream(stream);
1002     if (h) {
1003         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packets, Dropped, Skipped : %d, %d, %d\n",
1004                             h->m_packets, h->m_dropped, h->m_skipped);
1005     } else {
1006         debugError("No handler for stream %p??\n", stream);
1007     }
1008 }
1009
1010 bool
1011 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
1012     return startHandlerForStream(stream, -1);
1013 }
1014
1015 bool
1016 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
1017     // check state
1018     if(m_State != E_Running) {
1019         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1020         return false;
1021     }
1022     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1023       it != m_IsoHandlers.end();
1024       ++it )
1025     {
1026         if((*it)->isStreamRegistered(stream)) {
1027             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
1028             if(!(*it)->requestEnable(cycle)) {
1029                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not request enable for handler %p)\n",*it);
1030                 return false;
1031             }
1032
1033             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1034                 m_IsoTaskTransmit->requestShadowMapUpdate();
1035             } else {
1036                 m_IsoTaskReceive->requestShadowMapUpdate();
1037             }
1038
1039             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " requested enable for handler %p\n", *it);
1040             return true;
1041         }
1042     }
1043     debugError("Stream %p has no attached handler\n", stream);
1044     return false;
1045 }
1046
1047 bool
1048 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
1049     // check state
1050     if(m_State != E_Running) {
1051         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1052         return false;
1053     }
1054     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1055       it != m_IsoHandlers.end();
1056       ++it )
1057     {
1058         if((*it)->isStreamRegistered(stream)) {
1059             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
1060             if(!(*it)->requestDisable()) {
1061                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not request disable for handler %p\n",*it);
1062                 return false;
1063             }
1064
1065             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1066                 m_IsoTaskTransmit->requestShadowMapUpdate();
1067             } else {
1068                 m_IsoTaskReceive->requestShadowMapUpdate();
1069             }
1070
1071             debugOutput(DEBUG_LEVEL_VERBOSE, " requested disable for handler %p\n", *it);
1072             return true;
1073         }
1074     }
1075     debugError("Stream %p has no attached handler\n", stream);
1076     return false;
1077 }
1078
1079 bool IsoHandlerManager::stopHandlers() {
1080     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1081
1082     // check state
1083     if(m_State != E_Running) {
1084         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1085         return false;
1086     }
1087
1088     bool retval=true;
1089
1090     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1091         it != m_IsoHandlers.end();
1092         ++it )
1093     {
1094         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
1095
1096         if(!(*it)->requestDisable()) {
1097             debugOutput( DEBUG_LEVEL_VERBOSE, " could not request disable for handler %p\n",*it);
1098             return false;
1099         }
1100
1101         if((*it)->getType() == IsoHandler::eHT_Transmit) {
1102             m_IsoTaskTransmit->requestShadowMapUpdate();
1103         } else {
1104             m_IsoTaskReceive->requestShadowMapUpdate();
1105         }
1106
1107         debugOutput(DEBUG_LEVEL_VERBOSE, " requested disable for handler %p\n", *it);
1108     }
1109
1110     if (retval) {
1111         m_State=E_Prepared;
1112     } else {
1113         m_State=E_Error;
1114     }
1115     return retval;
1116 }
1117
1118 bool IsoHandlerManager::reset() {
1119     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1120     // check state
1121     if(m_State == E_Error) {
1122         debugFatal("Resetting from error condition not yet supported...\n");
1123         return false;
1124     }
1125     // if not in an error condition, reset means stop the handlers
1126     return stopHandlers();
1127 }
1128
1129 void IsoHandlerManager::setVerboseLevel(int i) {
1130     setDebugLevel(i);
1131     // propagate the debug level
1132     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1133           it != m_IsoHandlers.end();
1134           ++it )
1135     {
1136         (*it)->setVerboseLevel(i);
1137     }
1138     if(m_IsoThreadTransmit) m_IsoThreadTransmit->setVerboseLevel(i);
1139     if(m_IsoTaskTransmit)   m_IsoTaskTransmit->setVerboseLevel(i);
1140     if(m_IsoThreadReceive)  m_IsoThreadReceive->setVerboseLevel(i);
1141     if(m_IsoTaskReceive)    m_IsoTaskReceive->setVerboseLevel(i);
1142     setDebugLevel(i);
1143     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
1144 }
1145
1146 void IsoHandlerManager::dumpInfo() {
1147     #ifdef DEBUG
1148     unsigned int i=0;
1149     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
1150     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
1151
1152     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1153           it != m_IsoHandlers.end();
1154           ++it )
1155     {
1156         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
1157         (*it)->dumpInfo();
1158     }
1159     #endif
1160 }
1161
1162 const char *
1163 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
1164     switch (s) {
1165         default: return "Invalid";
1166         case E_Created: return "Created";
1167         case E_Prepared: return "Prepared";
1168         case E_Running: return "Running";
1169         case E_Error: return "Error";
1170     }
1171 }
1172
1173
1174 // ISOHANDLER
1175
1176 /* the C callbacks */
1177 enum raw1394_iso_disposition
1178 IsoHandlerManager::IsoHandler::iso_transmit_handler(raw1394handle_t handle,
1179         unsigned char *data, unsigned int *length,
1180         unsigned char *tag, unsigned char *sy,
1181         int cycle, unsigned int dropped1) {
1182
1183     IsoHandler *xmitHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
1184     assert(xmitHandler);
1185     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
1186     unsigned int dropped = dropped1 & 0xFFFF;
1187     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped, skipped);
1188 }
1189
1190 enum raw1394_iso_disposition
1191 IsoHandlerManager::IsoHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
1192                         unsigned int length, unsigned char channel,
1193                         unsigned char tag, unsigned char sy, unsigned int cycle,
1194                         unsigned int dropped) {
1195
1196     IsoHandler *recvHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
1197     assert(recvHandler);
1198
1199     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
1200 }
1201
1202 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t)
1203    : m_manager( manager )
1204    , m_type ( t )
1205    , m_handle( NULL )
1206    , m_buf_packets( 400 )
1207    , m_max_packet_size( 1024 )
1208    , m_irq_interval( -1 )
1209    , m_last_cycle( -1 )
1210    , m_last_now( 0xFFFFFFFF )
1211    , m_last_packet_handled_at( 0xFFFFFFFF )
1212    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
1213    , m_Client( 0 )
1214    , m_speed( RAW1394_ISO_SPEED_400 )
1215    , m_State( eHS_Stopped )
1216    , m_NextState( eHS_Stopped )
1217    , m_switch_on_cycle(0)
1218 #ifdef DEBUG
1219    , m_packets ( 0 )
1220    , m_dropped( 0 )
1221    , m_skipped( 0 )
1222    , m_min_ahead( 7999 )
1223 #endif
1224 {
1225 }
1226
1227 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t,
1228                        unsigned int buf_packets, unsigned int max_packet_size, int irq)
1229    : m_manager( manager )
1230    , m_type ( t )
1231    , m_handle( NULL )
1232    , m_buf_packets( buf_packets )
1233    , m_max_packet_size( max_packet_size )
1234    , m_irq_interval( irq )
1235    , m_last_cycle( -1 )
1236    , m_last_now( 0xFFFFFFFF )
1237    , m_last_packet_handled_at( 0xFFFFFFFF )
1238    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
1239    , m_Client( 0 )
1240    , m_speed( RAW1394_ISO_SPEED_400 )
1241    , m_State( eHS_Stopped )
1242    , m_NextState( eHS_Stopped )
1243    , m_switch_on_cycle(0)
1244 #ifdef DEBUG
1245    , m_packets ( 0 )
1246    , m_dropped( 0 )
1247    , m_skipped( 0 )
1248    , m_min_ahead( 7999 )
1249 #endif
1250 {
1251 }
1252
1253 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t, unsigned int buf_packets,
1254                        unsigned int max_packet_size, int irq,
1255                        enum raw1394_iso_speed speed)
1256    : m_manager( manager )
1257    , m_type ( t )
1258    , m_handle( NULL )
1259    , m_buf_packets( buf_packets )
1260    , m_max_packet_size( max_packet_size )
1261    , m_irq_interval( irq )
1262    , m_last_cycle( -1 )
1263    , m_last_now( 0xFFFFFFFF )
1264    , m_last_packet_handled_at( 0xFFFFFFFF )
1265    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
1266    , m_Client( 0 )
1267    , m_speed( speed )
1268    , m_State( eHS_Stopped )
1269    , m_NextState( eHS_Stopped )
1270    , m_switch_on_cycle(0)
1271 #ifdef DEBUG
1272    , m_packets( 0 )
1273    , m_dropped( 0 )
1274    , m_skipped( 0 )
1275    , m_min_ahead( 7999 )
1276 #endif
1277 {
1278 }
1279
1280 IsoHandlerManager::IsoHandler::~IsoHandler() {
1281 // Don't call until libraw1394's raw1394_new_handle() function has been
1282 // fixed to correctly initialise the iso_packet_infos field.  Bug is
1283 // confirmed present in libraw1394 1.2.1.  In any case,
1284 // raw1394_destroy_handle() will do any iso system shutdown required.
1285 //     raw1394_iso_shutdown(m_handle);
1286     if(m_handle) {
1287         if (m_State == eHS_Running) {
1288             debugError("BUG: Handler still running!\n");
1289             disable();
1290         }
1291     }
1292 }
1293
1294 bool
1295 IsoHandlerManager::IsoHandler::canIterateClient()
1296 {
1297     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "checking...\n");
1298     if(m_Client) {
1299         bool result;
1300
1301         if (m_type == eHT_Receive) {
1302             result = m_Client->canProducePacket();
1303         } else {
1304             result = m_Client->canConsumePacket();
1305         }
1306         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
1307         return result && (m_State != eHS_Error);
1308     } else {
1309         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " no client\n");
1310     }
1311     return false;
1312 }
1313
1314 bool
1315 IsoHandlerManager::IsoHandler::iterate() {
1316     return iterate(m_manager.get1394Service().getCycleTimer());
1317 }
1318
1319 bool
1320 IsoHandlerManager::IsoHandler::iterate(uint32_t cycle_timer_now) {
1321     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler at %08X...\n",
1322                        this, getTypeString(), cycle_timer_now);
1323     m_last_now = cycle_timer_now;
1324     if(m_State == eHS_Running) {
1325         assert(m_handle);
1326
1327         #if ISOHANDLER_FLUSH_BEFORE_ITERATE
1328         // this flushes all packets received since the poll() returned
1329         // from kernel to userspace such that they are processed by this
1330         // iterate. Doing so might result in lower latency capability
1331         // and/or better reliability
1332         if(m_type == eHT_Receive) {
1333             raw1394_iso_recv_flush(m_handle);
1334         }
1335         #endif
1336
1337         if(raw1394_loop_iterate(m_handle)) {
1338             debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
1339                         this, strerror(errno));
1340             return false;
1341         }
1342         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) done interating ISO handler...\n",
1343                            this, getTypeString());
1344         return true;
1345     } else {
1346         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Not iterating a non-running handler...\n",
1347                     this, getTypeString());
1348         return false;
1349     }
1350 }
1351
1352 /**
1353  * Bus reset handler
1354  *
1355  * @return ?
1356  */
1357
1358 bool
1359 IsoHandlerManager::IsoHandler::handleBusReset()
1360 {
1361     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
1362     m_last_packet_handled_at = 0xFFFFFFFF;
1363
1364     #define CSR_CYCLE_TIME            0x200
1365     #define CSR_REGISTER_BASE  0xfffff0000000ULL
1366     // do a simple read on ourself in order to update the internal structures
1367     // this avoids read failures after a bus reset
1368     quadlet_t buf=0;
1369     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
1370                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
1371
1372     return m_Client->handleBusReset();
1373 }
1374
1375 /**
1376  * Call this if you find out that this handler has died for some
1377  * external reason.
1378  */
1379 void
1380 IsoHandlerManager::IsoHandler::notifyOfDeath()
1381 {
1382     m_State = eHS_Error;
1383     m_NextState = eHS_Error;
1384
1385     // notify the client of the fact that we have died
1386     m_Client->handlerDied();
1387
1388     // wake ourselves up
1389     if(m_handle) raw1394_wake_up(m_handle);
1390 }
1391
1392 void IsoHandlerManager::IsoHandler::dumpInfo()
1393 {
1394     int channel=-1;
1395     if (m_Client) channel=m_Client->getChannel();
1396
1397     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
1398             getTypeString());
1399     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
1400             m_manager.get1394Service().getPort(), channel);
1401     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
1402             m_buf_packets, m_max_packet_size, m_irq_interval);
1403     if (this->getType() == eHT_Transmit) {
1404         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed ..................: %2d\n",
1405                                             m_speed);
1406         #ifdef DEBUG
1407         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Min ISOXMT bufferfill : %04d\n", m_min_ahead);
1408         #endif
1409     }
1410     #ifdef DEBUG
1411     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last cycle, dropped.........: %4d, %4u, %4u\n",
1412             m_last_cycle, m_dropped, m_skipped);
1413     #endif
1414
1415 }
1416
1417 void IsoHandlerManager::IsoHandler::setVerboseLevel(int l)
1418 {
1419     setDebugLevel(l);
1420     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1421 }
1422
1423 bool IsoHandlerManager::IsoHandler::registerStream(StreamProcessor *stream)
1424 {
1425     assert(stream);
1426     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
1427
1428     if (m_Client) {
1429             debugFatal( "Generic IsoHandlers can have only one client\n");
1430             return false;
1431     }
1432     m_Client=stream;
1433     return true;
1434 }
1435
1436 bool IsoHandlerManager::IsoHandler::unregisterStream(StreamProcessor *stream)
1437 {
1438     assert(stream);
1439     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
1440
1441     if(stream != m_Client) {
1442             debugFatal( "no client registered\n");
1443             return false;
1444     }
1445     m_Client=0;
1446     return true;
1447 }
1448
1449 // ISO packet interface
1450 enum raw1394_iso_disposition IsoHandlerManager::IsoHandler::putPacket(
1451                     unsigned char *data, unsigned int length,
1452                     unsigned char channel, unsigned char tag, unsigned char sy,
1453                     unsigned int cycle, unsigned int dropped) {
1454     // keep track of dropped cycles
1455     int dropped_cycles = 0;
1456     if (m_last_cycle != (int)cycle && m_last_cycle != -1) {
1457         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
1458         #ifdef DEBUG
1459         if (dropped_cycles < 0) {
1460             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d\n",
1461                          this, dropped_cycles, cycle, m_last_cycle, dropped);
1462         }
1463         if (dropped_cycles > 0) {
1464             debugOutput(DEBUG_LEVEL_VERBOSE,
1465                         "(%p) dropped %d packets on cycle %u, 'dropped'=%u, cycle=%d, m_last_cycle=%d\n",
1466                         this, dropped_cycles, cycle, dropped, cycle, m_last_cycle);
1467             m_dropped += dropped_cycles;
1468         }
1469         #endif
1470     }
1471     m_last_cycle = cycle;
1472
1473     // the m_last_now value is set when the iterate() function is called.
1474     uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(m_last_now);
1475
1476     // two cases can occur:
1477     // (1) this packet has been received before iterate() was called (normal case).
1478     // (2) this packet has been received after iterate() was called.
1479     //     happens when the kernel flushes more packets while we are already processing.
1480     //
1481     // In case (1) now_cycles is a small number of cycles larger than cycle. In
1482     // case (2) now_cycles is a small number of cycles smaller than cycle.
1483     // hence  abs(diffCycles(now_cycles, cycles)) has to be 'small'
1484
1485     // we can calculate the time of arrival for this packet as
1486     // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE
1487     // in its properly wrapped version
1488     int64_t diff_cycles = diffCycles(cycle, now_cycles);
1489     int64_t tmp = CYCLE_TIMER_TO_TICKS(m_last_now);
1490     tmp += diff_cycles * (int64_t)TICKS_PER_CYCLE;
1491     uint64_t pkt_ctr_ticks = wrapAtMinMaxTicks(tmp);
1492     uint32_t pkt_ctr = TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks);
1493     #ifdef DEBUG
1494     if( (now_cycles < cycle)
1495         && diffCycles(now_cycles, cycle) < 0
1496         // ignore this on dropped cycles, since it's normal
1497         // that now is ahead on the received packets (as we miss packets)
1498         && dropped_cycles == 0)
1499     {
1500         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Special non-unwrapping happened\n");
1501     }
1502     #endif
1503
1504     #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
1505     // add a seconds field
1506     uint32_t now = m_manager.get1394Service().getCycleTimer();
1507     uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
1508     // causality results in the fact that 'now' is always after 'cycle'
1509     // or at best, equal (if this handler was called within 125us after
1510     // the packet was on the wire).
1511     if(CYCLE_TIMER_GET_CYCLES(now) < cycle) {
1512         // the cycle field has wrapped, substract one second
1513         if(now_secs_ref == 0) {
1514             now_secs_ref = 127;
1515         } else  {
1516             now_secs_ref -= 1;
1517         }
1518     }
1519     uint32_t pkt_ctr_ref = cycle << 12;
1520     pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
1521
1522     if((pkt_ctr & ~0x0FFFL) != pkt_ctr_ref) {
1523         debugWarning("reconstructed CTR counter discrepancy\n");
1524         debugWarning(" ingredients: %X, %X, %X, %X, %X, %d, %ld, %ld, %"PRId64"\n",
1525                      cycle, pkt_ctr_ref, pkt_ctr,
1526                      now, m_last_now, now_secs_ref,
1527                      (long int)CYCLE_TIMER_GET_SECS(now),
1528                      (long int)CYCLE_TIMER_GET_SECS(m_last_now),
1529                      tmp);
1530         debugWarning(" diffcy = %"PRId64" \n", diff_cycles);
1531     }
1532     #endif
1533     m_last_packet_handled_at = pkt_ctr;
1534
1535     // leave the offset field (for now?)
1536
1537     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
1538                 "received packet: length=%d, channel=%d, cycle=%d, at %08X\n",
1539                 length, channel, cycle, pkt_ctr);
1540     m_packets++;
1541     #ifdef DEBUG
1542     if (length > m_max_packet_size) {
1543         debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
1544                      this, getTypeString(), length, m_max_packet_size);
1545     }
1546     if(m_last_cycle == -1) {
1547         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle);
1548     }
1549     #endif
1550
1551     // iterate the client if required
1552     if(m_Client)
1553         return m_Client->putPacket(data, length, channel, tag, sy, pkt_ctr, dropped_cycles);
1554
1555     return RAW1394_ISO_OK;
1556 }
1557
1558 enum raw1394_iso_disposition
1559 IsoHandlerManager::IsoHandler::getPacket(unsigned char *data, unsigned int *length,
1560                       unsigned char *tag, unsigned char *sy,
1561                       int cycle, unsigned int dropped, unsigned int skipped) {
1562
1563     uint32_t pkt_ctr;
1564     if (cycle < 0) {
1565         // mark invalid
1566         pkt_ctr = 0xFFFFFFFF;
1567     } else {
1568         // the m_last_now value is set when the iterate() function is called.
1569         uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(m_last_now);
1570
1571         // two cases can occur:
1572         // (1) this packet has been received before iterate() was called (normal case).
1573         // (2) this packet has been received after iterate() was called.
1574         //     happens when the kernel flushes more packets while we are already processing.
1575         //
1576         // In case (1) now_cycles is a small number of cycles larger than cycle. In
1577         // case (2) now_cycles is a small number of cycles smaller than cycle.
1578         // hence  abs(diffCycles(now_cycles, cycles)) has to be 'small'
1579
1580         // we can calculate the time of arrival for this packet as
1581         // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE
1582         // in its properly wrapped version
1583         int64_t diff_cycles = diffCycles(cycle, now_cycles);
1584         int64_t tmp = CYCLE_TIMER_TO_TICKS(m_last_now);
1585         tmp += diff_cycles * (int64_t)TICKS_PER_CYCLE;
1586         uint64_t pkt_ctr_ticks = wrapAtMinMaxTicks(tmp);
1587         pkt_ctr = TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks);
1588
1589         #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
1590         // add a seconds field
1591         uint32_t now = m_manager.get1394Service().getCycleTimer();
1592         uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
1593         // causality results in the fact that 'now' is always after 'cycle'
1594         if(CYCLE_TIMER_GET_CYCLES(now) > (unsigned int)cycle) {
1595             // the cycle field has wrapped, add one second
1596             now_secs_ref += 1;
1597             // no need for this:
1598             if(now_secs_ref == 128) {
1599                now_secs_ref = 0;
1600             }
1601         }
1602         uint32_t pkt_ctr_ref = cycle << 12;
1603         pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
1604
1605         if(((pkt_ctr & ~0x0FFFL) != pkt_ctr_ref) && (m_packets > m_buf_packets)) {
1606             debugWarning("reconstructed CTR counter discrepancy\n");
1607             debugWarning(" ingredients: %X, %X, %X, %X, %X, %d, %ld, %ld, %"PRId64"\n",
1608                         cycle, pkt_ctr_ref, pkt_ctr,
1609                          now, m_last_now, now_secs_ref,
1610                          (long int)CYCLE_TIMER_GET_SECS(now),
1611                          (long int)CYCLE_TIMER_GET_SECS(m_last_now),
1612                          tmp);
1613             debugWarning(" diffcy = %"PRId64" \n", diff_cycles);
1614         }
1615         #endif
1616     }
1617     if (m_packets < m_buf_packets) { // these are still prebuffer packets
1618         m_last_packet_handled_at = 0xFFFFFFFF;
1619     } else {
1620         m_last_packet_handled_at = pkt_ctr;
1621     }
1622     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
1623                 "sending packet: length=%d, cycle=%d, at %08X\n",
1624                 *length, cycle, pkt_ctr);
1625
1626     m_packets++;
1627
1628     #ifdef DEBUG
1629     if(m_last_cycle == -1) {
1630         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %d)\n", getTypeString(), this, cycle);
1631     }
1632     #endif
1633
1634     // keep track of dropped cycles
1635     int dropped_cycles = 0;
1636     if (m_last_cycle != cycle && m_last_cycle != -1) {
1637         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
1638         // correct for skipped packets
1639         // since those are not dropped, but only delayed
1640         dropped_cycles -= skipped;
1641
1642         #ifdef DEBUG
1643         if(skipped) {
1644             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
1645                         "(%p) skipped %d cycles, cycle: %d, last_cycle: %d, dropped: %d\n",
1646                         this, skipped, cycle, m_last_cycle, dropped);
1647             m_skipped += skipped;
1648         }
1649         if (dropped_cycles < 0) {
1650             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d, skipped: %d\n",
1651                          this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
1652         }
1653         if (dropped_cycles > 0) {
1654             debugOutput(DEBUG_LEVEL_VERBOSE,
1655                         "(%p) dropped %d packets on cycle %u (last_cycle=%u, dropped=%d, skipped: %d)\n",
1656                         this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
1657             m_dropped += dropped_cycles - skipped;
1658         }
1659         #endif
1660     }
1661     if (cycle >= 0) {
1662         m_last_cycle = cycle;
1663        
1664         #ifdef DEBUG
1665 /*        int ahead = diffCycles(cycle, now_cycles);
1666         if (ahead < m_min_ahead) m_min_ahead = ahead;
1667 */
1668         #endif
1669     }
1670
1671     #ifdef DEBUG
1672     if (dropped > 0) {
1673         debugOutput(DEBUG_LEVEL_VERBOSE,
1674                     "(%p) OHCI issue on cycle %u (dropped_cycles=%d, last_cycle=%u, dropped=%d, skipped: %d)\n",
1675                     this, cycle, dropped_cycles, m_last_cycle, dropped, skipped);
1676     }
1677     #endif
1678
1679     if(m_Client) {
1680         enum raw1394_iso_disposition retval;
1681         retval = m_Client->getPacket(data, length, tag, sy, pkt_ctr, dropped_cycles, skipped, m_max_packet_size);
1682         #ifdef DEBUG
1683         if (*length > m_max_packet_size) {
1684             debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
1685                          this, getTypeString(), *length, m_max_packet_size);
1686         }
1687         #endif
1688             return retval;
1689     }
1690
1691     *tag = 0;
1692     *sy = 0;
1693     *length = 0;
1694     return RAW1394_ISO_OK;
1695 }
1696
1697 bool
1698 IsoHandlerManager::IsoHandler::enable(int cycle)
1699 {
1700     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
1701
1702     // check the state
1703     if(m_State != eHS_Stopped) {
1704         debugError("Incorrect state, expected eHS_Stopped, got %d\n",(int)m_State);
1705         return false;
1706     }
1707
1708     assert(m_handle == NULL);
1709
1710     // create a handle for the ISO traffic
1711     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
1712     if ( !m_handle ) {
1713         if ( !errno ) {
1714             debugError("libraw1394 not compatible\n");
1715         } else {
1716             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
1717             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
1718         }
1719         return false;
1720     }
1721     raw1394_set_userdata(m_handle, static_cast<void *>(this));
1722
1723     // prepare the handler, allocate the resources
1724     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client);
1725     dumpInfo();
1726     if (getType() == eHT_Receive) {
1727         if(raw1394_iso_recv_init(m_handle,
1728                                 iso_receive_handler,
1729                                 m_buf_packets,
1730                                 m_max_packet_size,
1731                                 m_Client->getChannel(),
1732                                 m_receive_mode,
1733                                 m_irq_interval)) {
1734             debugFatal("Could not do receive initialization (PACKET_PER_BUFFER)!\n" );
1735             debugFatal("  %s\n",strerror(errno));
1736             return false;
1737         }
1738
1739         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
1740             debugFatal("Could not start receive handler (%s)\n",strerror(errno));
1741             dumpInfo();
1742             return false;
1743         }
1744     } else {
1745         if(raw1394_iso_xmit_init(m_handle,
1746                                 iso_transmit_handler,
1747                                 m_buf_packets,
1748                                 m_max_packet_size,
1749                                 m_Client->getChannel(),
1750                                 m_speed,
1751                                 m_irq_interval)) {
1752             debugFatal("Could not do xmit initialisation!\n" );
1753             return false;
1754         }
1755
1756         if(raw1394_iso_xmit_start(m_handle, cycle, 0)) {
1757             debugFatal("Could not start xmit handler (%s)\n", strerror(errno));
1758             dumpInfo();
1759             return false;
1760         }
1761     }
1762
1763 #ifdef DEBUG
1764     m_min_ahead = 7999;
1765 #endif
1766
1767     m_packets = 0;
1768
1769     // indicate that the first iterate() still has to occur.
1770     m_last_now = 0xFFFFFFFF;
1771     m_last_packet_handled_at = 0xFFFFFFFF;
1772
1773     m_State = eHS_Running;
1774     m_NextState = eHS_Running;
1775     return true;
1776 }
1777
1778 bool
1779 IsoHandlerManager::IsoHandler::disable()
1780 {
1781     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n",
1782                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
1783
1784     // check state
1785     if(m_State != eHS_Running) {
1786         debugError("Incorrect state, expected eHS_Running, got %d\n",(int)m_State);
1787         return false;
1788     }
1789
1790     assert(m_handle != NULL);
1791
1792     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) wake up handle...\n",
1793                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
1794
1795     // wake up any waiting reads/polls
1796     raw1394_wake_up(m_handle);
1797
1798     // this is put here to try and avoid the
1799     // Runaway context problem
1800     // don't know if it will help though.
1801 /*    if(m_State != eHS_Error) { // if the handler is dead, this might block forever
1802         raw1394_iso_xmit_sync(m_handle);
1803     }*/
1804     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) stop...\n",
1805                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
1806     // stop iso traffic
1807     raw1394_iso_stop(m_handle);
1808     // deallocate resources
1809
1810     // Don't call until libraw1394's raw1394_new_handle() function has been
1811     // fixed to correctly initialise the iso_packet_infos field.  Bug is
1812     // confirmed present in libraw1394 1.2.1.
1813     raw1394_iso_shutdown(m_handle);
1814
1815     raw1394_destroy_handle(m_handle);
1816     m_handle = NULL;
1817
1818     m_State = eHS_Stopped;
1819     m_NextState = eHS_Stopped;
1820     return true;
1821 }
1822
1823 // functions to request enable or disable at the next opportunity
1824 bool
1825 IsoHandlerManager::IsoHandler::requestEnable(int cycle)
1826 {
1827     if (m_State == eHS_Running) {
1828         debugError("Enable requested on enabled stream\n");
1829         return false;
1830     }
1831     if (m_State != eHS_Stopped) {
1832         debugError("Enable requested on stream with state: %d\n", m_State);
1833         return false;
1834     }
1835     m_NextState = eHS_Running;
1836     return true;
1837 }
1838
1839 bool
1840 IsoHandlerManager::IsoHandler::requestDisable()
1841 {
1842     if (m_State == eHS_Stopped) {
1843         debugError("Disable requested on disabled stream\n");
1844         return false;
1845     }
1846     if (m_State != eHS_Running) {
1847         debugError("Disable requested on stream with state=%d\n", m_State);
1848         return false;
1849     }
1850     m_NextState = eHS_Stopped;
1851     return true;
1852 }
1853
1854 void
1855 IsoHandlerManager::IsoHandler::updateState()
1856 {
1857     // execute state changes requested
1858     if(m_State != m_NextState) {
1859         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) handler needs state update from %d => %d\n", this, m_State, m_NextState);
1860         if(m_State == eHS_Stopped && m_NextState == eHS_Running) {
1861             debugOutput(DEBUG_LEVEL_VERBOSE, "handler has to be enabled\n");
1862             enable(m_switch_on_cycle);
1863         } else if(m_State == eHS_Running && m_NextState == eHS_Stopped) {
1864             debugOutput(DEBUG_LEVEL_VERBOSE, "handler has to be disabled\n");
1865             disable();
1866         } else {
1867             debugError("Unknown state transition\n");
1868         }
1869     }
1870 }
1871
1872 /**
1873  * @brief convert a EHandlerType to a string
1874  * @param t the type
1875  * @return a char * describing the state
1876  */
1877 const char *
1878 IsoHandlerManager::IsoHandler::eHTToString(enum EHandlerType t) {
1879     switch (t) {
1880         case eHT_Receive: return "Receive";
1881         case eHT_Transmit: return "Transmit";
1882         default: return "error: unknown type";
1883     }
1884 }
Note: See TracBrowser for help on using the browser.