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

Revision 1970, 67.5 kB (checked in by adi, 10 years ago)

Fix compiler warning

When the default branch in the switch-case statement is taken,
receive_mode would be uninitialised.

src/libieee1394/IsoHandlerManager.cpp:754:40: warning: 'receive_mode'
may be used uninitialized in this functio

Let's at least assign something to it.

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    , m_MissedCyclesOK ( false )
469 {
470 }
471
472 IsoHandlerManager::~IsoHandlerManager()
473 {
474     stopHandlers();
475     pruneHandlers();
476     if(m_IsoHandlers.size() > 0) {
477         debugError("Still some handlers in use\n");
478     }
479     if (m_IsoThreadTransmit) {
480         m_IsoThreadTransmit->Stop();
481         delete m_IsoThreadTransmit;
482     }
483     if (m_IsoThreadReceive) {
484         m_IsoThreadReceive->Stop();
485         delete m_IsoThreadReceive;
486     }
487     if (m_IsoTaskTransmit) {
488         delete m_IsoTaskTransmit;
489     }
490     if (m_IsoTaskReceive) {
491         delete m_IsoTaskReceive;
492     }
493 }
494
495 bool
496 IsoHandlerManager::handleBusReset()
497 {
498     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
499     // A few things can happen on bus reset:
500     // 1) no devices added/removed => streams are still valid, but might have to be restarted
501     // 2) a device was removed => some streams become invalid
502     // 3) a device was added => same as 1, new device is ignored
503     if (!m_IsoTaskTransmit) {
504         debugError("No xmit task\n");
505         return false;
506     }
507     if (!m_IsoTaskReceive) {
508         debugError("No receive task\n");
509         return false;
510     }
511     if (!m_IsoTaskTransmit->handleBusReset()) {
512         debugWarning("could no handle busreset on xmit\n");
513     }
514     if (!m_IsoTaskReceive->handleBusReset()) {
515         debugWarning("could no handle busreset on recv\n");
516     }
517     return true;
518 }
519
520 void
521 IsoHandlerManager::requestShadowMapUpdate()
522 {
523     if(m_IsoTaskTransmit) m_IsoTaskTransmit->requestShadowMapUpdate();
524     if(m_IsoTaskReceive) m_IsoTaskReceive->requestShadowMapUpdate();
525 }
526
527 bool
528 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
529     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
530     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
531     if (priority < THREAD_MIN_RTPRIO) priority = THREAD_MIN_RTPRIO; // cap the priority
532     m_realtime = rt;
533     m_priority = priority;
534
535     // grab the options from the parent
536     Util::Configuration *config = m_service.getConfiguration();
537     int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE;
538     int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT;
539     int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV;
540     if(config) {
541         config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase);
542         config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit);
543         config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv);
544     }
545
546     if (m_IsoThreadTransmit) {
547         if (m_realtime) {
548             m_IsoThreadTransmit->AcquireRealTime(m_priority
549                                                  + ihm_iso_prio_increase
550                                                  + ihm_iso_prio_increase_xmit);
551         } else {
552             m_IsoThreadTransmit->DropRealTime();
553         }
554     }
555     if (m_IsoThreadReceive) {
556         if (m_realtime) {
557             m_IsoThreadReceive->AcquireRealTime(m_priority
558                                                 + ihm_iso_prio_increase
559                                                 + ihm_iso_prio_increase_recv);
560         } else {
561             m_IsoThreadReceive->DropRealTime();
562         }
563     }
564
565     return true;
566 }
567
568 bool IsoHandlerManager::init()
569 {
570     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
571     // check state
572     if(m_State != E_Created) {
573         debugError("Manager already initialized...\n");
574         return false;
575     }
576
577     // grab the options from the parent
578     Util::Configuration *config = m_service.getConfiguration();
579     int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE;
580     int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT;
581     int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV;
582     int64_t isotask_activity_timeout_usecs = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS;
583     if(config) {
584         config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase);
585         config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit);
586         config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv);
587         config->getValueForSetting("ieee1394.isomanager.isotask_activity_timeout_usecs", isotask_activity_timeout_usecs);
588     }
589
590     // create threads to iterate our ISO handlers
591     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p transmit...\n", this);
592     m_IsoTaskTransmit = new IsoTask( *this, IsoHandler::eHT_Transmit );
593     if(!m_IsoTaskTransmit) {
594         debugFatal("No task\n");
595         return false;
596     }
597     m_IsoTaskTransmit->setVerboseLevel(getDebugLevel());
598     m_IsoTaskTransmit->m_activity_wait_timeout_nsec = isotask_activity_timeout_usecs * 1000LL;
599     m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime,
600                                                 m_priority + ihm_iso_prio_increase
601                                                 + ihm_iso_prio_increase_xmit,
602                                                 PTHREAD_CANCEL_DEFERRED);
603
604     if(!m_IsoThreadTransmit) {
605         debugFatal("No thread\n");
606         return false;
607     }
608     m_IsoThreadTransmit->setVerboseLevel(getDebugLevel());
609
610     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p receive...\n", this);
611     m_IsoTaskReceive = new IsoTask( *this, IsoHandler::eHT_Receive );
612     if(!m_IsoTaskReceive) {
613         debugFatal("No task\n");
614         return false;
615     }
616     m_IsoTaskReceive->setVerboseLevel(getDebugLevel());
617     m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime,
618                                                m_priority + ihm_iso_prio_increase
619                                                + ihm_iso_prio_increase_recv,
620                                                PTHREAD_CANCEL_DEFERRED);
621
622     if(!m_IsoThreadReceive) {
623         debugFatal("No thread\n");
624         return false;
625     }
626     m_IsoThreadReceive->setVerboseLevel(getDebugLevel());
627     // register the thread with the RT watchdog
628     Util::Watchdog *watchdog = m_service.getWatchdog();
629     if(watchdog) {
630         if(!watchdog->registerThread(m_IsoThreadTransmit)) {
631             debugWarning("could not register iso transmit thread with watchdog\n");
632         }
633         if(!watchdog->registerThread(m_IsoThreadReceive)) {
634             debugWarning("could not register iso receive thread with watchdog\n");
635         }
636     } else {
637         debugWarning("could not find valid watchdog\n");
638     }
639
640     if (m_IsoThreadTransmit->Start() != 0) {
641         debugFatal("Could not start ISO Transmit thread\n");
642         return false;
643     }
644     if (m_IsoThreadReceive->Start() != 0) {
645         debugFatal("Could not start ISO Receive thread\n");
646         return false;
647     }
648
649     m_State=E_Running;
650     return true;
651 }
652
653 void
654 IsoHandlerManager::signalActivityTransmit()
655 {
656     assert(m_IsoTaskTransmit);
657     m_IsoTaskTransmit->signalActivity();
658 }
659
660 void
661 IsoHandlerManager::signalActivityReceive()
662 {
663     assert(m_IsoTaskReceive);
664     m_IsoTaskReceive->signalActivity();
665 }
666
667 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
668 {
669     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
670     assert(handler);
671     handler->setVerboseLevel(getDebugLevel());
672     m_IsoHandlers.push_back(handler);
673     requestShadowMapUpdate();
674     return true;
675 }
676
677 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
678 {
679     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
680     assert(handler);
681
682     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
683       it != m_IsoHandlers.end();
684       ++it )
685     {
686         if ( *it == handler ) {
687             m_IsoHandlers.erase(it);
688             requestShadowMapUpdate();
689             return true;
690         }
691     }
692     debugFatal("Could not find handler (%p)\n", handler);
693     return false; //not found
694 }
695
696 /**
697  * Registers an StreamProcessor with the IsoHandlerManager.
698  *
699  * If nescessary, an IsoHandler is created to handle this stream.
700  * Once an StreamProcessor is registered to the handler, it will be included
701  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
702  *
703  * @param stream the stream to register
704  * @return true if registration succeeds
705  *
706  * \todo : currently there is a one-to-one mapping
707  *        between streams and handlers, this is not ok for
708  *        multichannel receive
709  */
710 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
711 {
712     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering %s stream %p\n", stream->getTypeString(), stream);
713     assert(stream);
714
715     IsoHandler* h = NULL;
716
717     // make sure the stream isn't already attached to a handler
718     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
719       it != m_IsoHandlers.end();
720       ++it )
721     {
722         if((*it)->isStreamRegistered(stream)) {
723             debugError( "stream already registered!\n");
724             return false;
725         }
726     }
727
728     // clean up all handlers that aren't used
729     pruneHandlers();
730
731     // allocate a handler for this stream
732     if (stream->getType()==StreamProcessor::ePT_Receive) {
733         // grab the options from the parent
734         Util::Configuration *config = m_service.getConfiguration();
735         int receive_mode_setting = DEFAULT_ISO_RECEIVE_MODE;
736         int bufferfill_mode_threshold = BUFFERFILL_MODE_THRESHOLD;
737         int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
738         int max_nb_buffers_recv = MAX_RECV_NB_BUFFERS;
739         int min_packetsize_recv = MIN_RECV_PACKET_SIZE;
740         if(config) {
741             config->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting);
742             config->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold);
743             config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
744             config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv);
745             config->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv);
746         }
747
748         // setup the optimal parameters for the raw1394 ISO buffering
749         unsigned int packets_per_period = stream->getPacketsPerPeriod();
750         // reserve space for the 1394 header too (might not be necessary)
751         unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
752         unsigned int page_size = getpagesize();
753
754         enum raw1394_iso_dma_recv_mode receive_mode =
755                 RAW1394_DMA_PACKET_PER_BUFFER;
756         switch(receive_mode_setting) {
757             case 0:
758                 if(packets_per_period < (unsigned)bufferfill_mode_threshold) {
759                     debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (auto) [%d, %d]\n",
760                                  packets_per_period, bufferfill_mode_threshold);
761                     receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
762                 } else {
763                     debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (auto) [%d, %d]\n",
764                                  packets_per_period, bufferfill_mode_threshold);
765                     receive_mode = RAW1394_DMA_BUFFERFILL;
766                 }
767                 break;
768             case 1:
769                 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (config)\n");
770                 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
771                 break;
772             case 2:
773                 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (config)\n");
774                 receive_mode = RAW1394_DMA_BUFFERFILL;
775                 break;
776             default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting);
777         }
778
779         // Ensure we don't request a packet size bigger than the
780         // kernel-enforced maximum which is currently 1 page.
781         // NOTE: PP: this is not really true AFAICT
782         if (max_packet_size > page_size) {
783             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
784             return false;
785         }
786         if (max_packet_size < (unsigned)min_packetsize_recv) {
787             debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n",
788                        max_packet_size, min_packetsize_recv);
789             max_packet_size = min_packetsize_recv;
790         }
791
792         // apparently a too small value causes issues too
793         if(max_packet_size < 200) max_packet_size = 200;
794
795         // the interrupt/wakeup interval prediction of raw1394 is a mess...
796         int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
797         if(irq_interval <= 0) irq_interval=1;
798
799         // the receive buffer size doesn't matter for the latency,
800         // it does seem to be confined to a certain region for correct
801         // operation. However it is not clear how many.
802         int buffers = max_nb_buffers_recv;
803
804         // ensure at least 2 hardware interrupts per ISO buffer wraparound
805         if(irq_interval > buffers/2) {
806             irq_interval = buffers/2;
807         }
808
809         // create the actual handler
810         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
811         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
812                            buffers, max_packet_size, irq_interval);
813
814         if(!h) {
815             debugFatal("Could not create IsoRecvHandler\n");
816             return false;
817         }
818
819         h->setReceiveMode(receive_mode);
820
821     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
822         // grab the options from the parent
823         Util::Configuration *config = m_service.getConfiguration();
824         int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
825         int max_nb_buffers_xmit = MAX_XMIT_NB_BUFFERS;
826         int max_packetsize_xmit = MAX_XMIT_PACKET_SIZE;
827         int min_packetsize_xmit = MIN_XMIT_PACKET_SIZE;
828         if(config) {
829             config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
830             config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit);
831             config->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit);
832             config->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit);
833         }
834
835         // setup the optimal parameters for the raw1394 ISO buffering
836         // reserve space for the 1394 header too (might not be necessary)
837         unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
838
839         if (max_packet_size > (unsigned)max_packetsize_xmit) {
840             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
841                        max_packet_size, max_packetsize_xmit);
842             return false;
843         }
844         if (max_packet_size < (unsigned)min_packetsize_xmit) {
845             debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n",
846                        max_packet_size, min_packetsize_xmit);
847             max_packet_size = min_packetsize_xmit;
848         }
849
850         int buffers = max_nb_buffers_xmit;
851         unsigned int packets_per_period = stream->getPacketsPerPeriod();
852
853         int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
854         if(irq_interval <= 0) irq_interval=1;
855         // ensure at least 2 hardware interrupts per ISO buffer wraparound
856         if(irq_interval > buffers/2) {
857             irq_interval = buffers/2;
858         }
859
860         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
861
862         // create the actual handler
863         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
864                            buffers, max_packet_size, irq_interval);
865
866         if(!h) {
867             debugFatal("Could not create IsoXmitHandler\n");
868             return false;
869         }
870
871     } else {
872         debugFatal("Bad stream type\n");
873         return false;
874     }
875
876     h->setVerboseLevel(getDebugLevel());
877
878     // register the stream with the handler
879     if(!h->registerStream(stream)) {
880         debugFatal("Could not register receive stream with handler\n");
881         return false;
882     }
883
884     // register the handler with the manager
885     if(!registerHandler(h)) {
886         debugFatal("Could not register receive handler with manager\n");
887         return false;
888     }
889     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
890
891     m_StreamProcessors.push_back(stream);
892     debugOutput( DEBUG_LEVEL_VERBOSE, " %zd streams, %zd handlers registered\n",
893                                       m_StreamProcessors.size(), m_IsoHandlers.size());
894     return true;
895 }
896
897 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
898 {
899     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering %s stream %p\n", stream->getTypeString(), stream);
900     assert(stream);
901
902     // make sure the stream isn't attached to a handler anymore
903     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
904       it != m_IsoHandlers.end();
905       ++it )
906     {
907         if((*it)->isStreamRegistered(stream)) {
908             if(!(*it)->unregisterStream(stream)) {
909                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
910                 return false;
911             }
912             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
913         }
914     }
915
916     // clean up all handlers that aren't used
917     pruneHandlers();
918
919     // remove the stream from the registered streams list
920     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
921       it != m_StreamProcessors.end();
922       ++it )
923     {
924         if ( *it == stream ) {
925             m_StreamProcessors.erase(it);
926             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
927             return true;
928         }
929     }
930     return false; //not found
931 }
932
933 /**
934  * @brief unregister a handler from the manager
935  * @note called without the lock held.
936  */
937 void IsoHandlerManager::pruneHandlers() {
938     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
939     IsoHandlerVector toUnregister;
940
941     // find all handlers that are not in use
942     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
943           it != m_IsoHandlers.end();
944           ++it )
945     {
946         if(!((*it)->inUse())) {
947             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
948             toUnregister.push_back(*it);
949         }
950     }
951     // delete them
952     for ( IsoHandlerVectorIterator it = toUnregister.begin();
953           it != toUnregister.end();
954           ++it )
955     {
956         unregisterHandler(*it);
957
958         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
959
960         // Now the handler's been unregistered it won't be reused
961         // again.  Therefore it really needs to be formally deleted
962         // to free up the raw1394 handle.  Otherwise things fall
963         // apart after several xrun recoveries as the system runs
964         // out of resources to support all the disused but still
965         // allocated raw1394 handles.  At least this is the current
966         // theory as to why we end up with "memory allocation"
967         // failures after several Xrun recoveries.
968         delete *it;
969     }
970 }
971
972 int
973 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
974     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
975       it != m_IsoHandlers.end();
976       ++it )
977     {
978         if((*it)->isStreamRegistered(stream)) {
979             return (*it)->getIrqInterval();
980         }
981     }
982     debugError("Stream %p has no attached handler\n", stream);
983     return 0;
984 }
985
986 IsoHandlerManager::IsoHandler *
987 IsoHandlerManager::getHandlerForStream(Streaming::StreamProcessor *stream) {
988     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
989       it != m_IsoHandlers.end();
990       ++it )
991     {
992         if((*it)->isStreamRegistered(stream)) {
993             return (*it);
994         }
995     }
996     debugError("Stream %p has no attached handler\n", stream);
997     return NULL;
998 }
999
1000 void
1001 IsoHandlerManager::dumpInfoForStream(Streaming::StreamProcessor *stream)
1002 {
1003     IsoHandler *h = getHandlerForStream(stream);
1004     if (h) {
1005         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packets, Dropped, Skipped : %d, %d, %d\n",
1006                             h->m_packets, h->m_dropped, h->m_skipped);
1007     } else {
1008         debugError("No handler for stream %p??\n", stream);
1009     }
1010 }
1011
1012 void IsoHandlerManager::setIsoStartCycleForStream(Streaming::StreamProcessor *stream, signed int cycle) {
1013     // Permit the direct manipulation of the m_switch_on_cycle field from
1014     // the stream's handler.  This is usually used to set it to -1 so the
1015     // kernel (at least with the ieee1394 stack) starts the streaming as
1016     // soon as possible, something that is required for some interfaces (eg:
1017     // RME).  Note that as of 20 Dec 2010 it seems that ordinarily
1018     // m_switch_on_cycle remains fixed at 0 (its initialised value) because
1019     // requestEnable() doesn't set it.  This allows the override configured
1020     // by this function to take effect.
1021     IsoHandler *h = getHandlerForStream(stream);
1022     h->setIsoStartCycle(cycle);
1023 }
1024
1025 bool
1026 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
1027     return startHandlerForStream(stream, -1);
1028 }
1029
1030 bool
1031 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
1032     // check state
1033     if(m_State != E_Running) {
1034         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1035         return false;
1036     }
1037     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1038       it != m_IsoHandlers.end();
1039       ++it )
1040     {
1041         if((*it)->isStreamRegistered(stream)) {
1042             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
1043             if(!(*it)->requestEnable(cycle)) {
1044                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not request enable for handler %p)\n",*it);
1045                 return false;
1046             }
1047
1048             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1049                 m_IsoTaskTransmit->requestShadowMapUpdate();
1050             } else {
1051                 m_IsoTaskReceive->requestShadowMapUpdate();
1052             }
1053
1054             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " requested enable for handler %p\n", *it);
1055             return true;
1056         }
1057     }
1058     debugError("Stream %p has no attached handler\n", stream);
1059     return false;
1060 }
1061
1062 bool
1063 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
1064     // check state
1065     if(m_State != E_Running) {
1066         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1067         return false;
1068     }
1069     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1070       it != m_IsoHandlers.end();
1071       ++it )
1072     {
1073         if((*it)->isStreamRegistered(stream)) {
1074             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
1075             if(!(*it)->requestDisable()) {
1076                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not request disable for handler %p\n",*it);
1077                 return false;
1078             }
1079
1080             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1081                 m_IsoTaskTransmit->requestShadowMapUpdate();
1082             } else {
1083                 m_IsoTaskReceive->requestShadowMapUpdate();
1084             }
1085
1086             debugOutput(DEBUG_LEVEL_VERBOSE, " requested disable for handler %p\n", *it);
1087             return true;
1088         }
1089     }
1090     debugError("Stream %p has no attached handler\n", stream);
1091     return false;
1092 }
1093
1094 bool IsoHandlerManager::stopHandlers() {
1095     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1096
1097     // check state
1098     if(m_State != E_Running) {
1099         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1100         return false;
1101     }
1102
1103     bool retval=true;
1104
1105     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1106         it != m_IsoHandlers.end();
1107         ++it )
1108     {
1109         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
1110
1111         if(!(*it)->requestDisable()) {
1112             debugOutput( DEBUG_LEVEL_VERBOSE, " could not request disable for handler %p\n",*it);
1113             return false;
1114         }
1115
1116         if((*it)->getType() == IsoHandler::eHT_Transmit) {
1117             m_IsoTaskTransmit->requestShadowMapUpdate();
1118         } else {
1119             m_IsoTaskReceive->requestShadowMapUpdate();
1120         }
1121
1122         debugOutput(DEBUG_LEVEL_VERBOSE, " requested disable for handler %p\n", *it);
1123     }
1124
1125     if (retval) {
1126         m_State=E_Prepared;
1127     } else {
1128         m_State=E_Error;
1129     }
1130     return retval;
1131 }
1132
1133 bool IsoHandlerManager::reset() {
1134     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1135     // check state
1136     if(m_State == E_Error) {
1137         debugFatal("Resetting from error condition not yet supported...\n");
1138         return false;
1139     }
1140     // if not in an error condition, reset means stop the handlers
1141     return stopHandlers();
1142 }
1143
1144 void IsoHandlerManager::setVerboseLevel(int i) {
1145     setDebugLevel(i);
1146     // propagate the debug level
1147     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1148           it != m_IsoHandlers.end();
1149           ++it )
1150     {
1151         (*it)->setVerboseLevel(i);
1152     }
1153     if(m_IsoThreadTransmit) m_IsoThreadTransmit->setVerboseLevel(i);
1154     if(m_IsoTaskTransmit)   m_IsoTaskTransmit->setVerboseLevel(i);
1155     if(m_IsoThreadReceive)  m_IsoThreadReceive->setVerboseLevel(i);
1156     if(m_IsoTaskReceive)    m_IsoTaskReceive->setVerboseLevel(i);
1157     setDebugLevel(i);
1158     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
1159 }
1160
1161 void IsoHandlerManager::dumpInfo() {
1162     #ifdef DEBUG
1163     unsigned int i=0;
1164     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
1165     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
1166
1167     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1168           it != m_IsoHandlers.end();
1169           ++it )
1170     {
1171         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
1172         (*it)->dumpInfo();
1173     }
1174     #endif
1175 }
1176
1177 const char *
1178 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
1179     switch (s) {
1180         default: return "Invalid";
1181         case E_Created: return "Created";
1182         case E_Prepared: return "Prepared";
1183         case E_Running: return "Running";
1184         case E_Error: return "Error";
1185     }
1186 }
1187
1188
1189 // ISOHANDLER
1190
1191 /* the C callbacks */
1192 enum raw1394_iso_disposition
1193 IsoHandlerManager::IsoHandler::iso_transmit_handler(raw1394handle_t handle,
1194         unsigned char *data, unsigned int *length,
1195         unsigned char *tag, unsigned char *sy,
1196         int cycle, unsigned int dropped1) {
1197
1198     IsoHandler *xmitHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
1199     assert(xmitHandler);
1200     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
1201     unsigned int dropped = dropped1 & 0xFFFF;
1202     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped, skipped);
1203 }
1204
1205 enum raw1394_iso_disposition
1206 IsoHandlerManager::IsoHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
1207                         unsigned int length, unsigned char channel,
1208                         unsigned char tag, unsigned char sy, unsigned int cycle,
1209                         unsigned int dropped) {
1210
1211     IsoHandler *recvHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
1212     assert(recvHandler);
1213
1214     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
1215 }
1216
1217 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t)
1218    : m_manager( manager )
1219    , m_type ( t )
1220    , m_handle( NULL )
1221    , m_buf_packets( 400 )
1222    , m_max_packet_size( 1024 )
1223    , m_irq_interval( -1 )
1224    , m_last_cycle( -1 )
1225    , m_last_now( 0xFFFFFFFF )
1226    , m_last_packet_handled_at( 0xFFFFFFFF )
1227    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
1228    , m_Client( 0 )
1229    , m_speed( RAW1394_ISO_SPEED_400 )
1230    , m_State( eHS_Stopped )
1231    , m_NextState( eHS_Stopped )
1232    , m_switch_on_cycle(0)
1233 #ifdef DEBUG
1234    , m_packets ( 0 )
1235    , m_dropped( 0 )
1236    , m_skipped( 0 )
1237    , m_min_ahead( 7999 )
1238 #endif
1239 {
1240 }
1241
1242 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t,
1243                        unsigned int buf_packets, unsigned int max_packet_size, int irq)
1244    : m_manager( manager )
1245    , m_type ( t )
1246    , m_handle( NULL )
1247    , m_buf_packets( buf_packets )
1248    , m_max_packet_size( max_packet_size )
1249    , m_irq_interval( irq )
1250    , m_last_cycle( -1 )
1251    , m_last_now( 0xFFFFFFFF )
1252    , m_last_packet_handled_at( 0xFFFFFFFF )
1253    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
1254    , m_Client( 0 )
1255    , m_speed( RAW1394_ISO_SPEED_400 )
1256    , m_State( eHS_Stopped )
1257    , m_NextState( eHS_Stopped )
1258    , m_switch_on_cycle(0)
1259 #ifdef DEBUG
1260    , m_packets ( 0 )
1261    , m_dropped( 0 )
1262    , m_skipped( 0 )
1263    , m_min_ahead( 7999 )
1264 #endif
1265 {
1266 }
1267
1268 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t, unsigned int buf_packets,
1269                        unsigned int max_packet_size, int irq,
1270                        enum raw1394_iso_speed speed)
1271    : m_manager( manager )
1272    , m_type ( t )
1273    , m_handle( NULL )
1274    , m_buf_packets( buf_packets )
1275    , m_max_packet_size( max_packet_size )
1276    , m_irq_interval( irq )
1277    , m_last_cycle( -1 )
1278    , m_last_now( 0xFFFFFFFF )
1279    , m_last_packet_handled_at( 0xFFFFFFFF )
1280    , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER )
1281    , m_Client( 0 )
1282    , m_speed( speed )
1283    , m_State( eHS_Stopped )
1284    , m_NextState( eHS_Stopped )
1285    , m_switch_on_cycle(0)
1286 #ifdef DEBUG
1287    , m_packets( 0 )
1288    , m_dropped( 0 )
1289    , m_skipped( 0 )
1290    , m_min_ahead( 7999 )
1291 #endif
1292 {
1293 }
1294
1295 IsoHandlerManager::IsoHandler::~IsoHandler() {
1296 // Don't call until libraw1394's raw1394_new_handle() function has been
1297 // fixed to correctly initialise the iso_packet_infos field.  Bug is
1298 // confirmed present in libraw1394 1.2.1.  In any case,
1299 // raw1394_destroy_handle() will do any iso system shutdown required.
1300 //     raw1394_iso_shutdown(m_handle);
1301     if(m_handle) {
1302         if (m_State == eHS_Running) {
1303             debugError("BUG: Handler still running!\n");
1304             disable();
1305         }
1306     }
1307 }
1308
1309 bool
1310 IsoHandlerManager::IsoHandler::canIterateClient()
1311 {
1312     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "checking...\n");
1313     if(m_Client) {
1314         bool result;
1315
1316         if (m_type == eHT_Receive) {
1317             result = m_Client->canProducePacket();
1318         } else {
1319             result = m_Client->canConsumePacket();
1320         }
1321         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
1322         return result && (m_State != eHS_Error);
1323     } else {
1324         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " no client\n");
1325     }
1326     return false;
1327 }
1328
1329 bool
1330 IsoHandlerManager::IsoHandler::iterate() {
1331     return iterate(m_manager.get1394Service().getCycleTimer());
1332 }
1333
1334 bool
1335 IsoHandlerManager::IsoHandler::iterate(uint32_t cycle_timer_now) {
1336     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler at %08X...\n",
1337                        this, getTypeString(), cycle_timer_now);
1338     m_last_now = cycle_timer_now;
1339     if(m_State == eHS_Running) {
1340         assert(m_handle);
1341
1342         #if ISOHANDLER_FLUSH_BEFORE_ITERATE
1343         // this flushes all packets received since the poll() returned
1344         // from kernel to userspace such that they are processed by this
1345         // iterate. Doing so might result in lower latency capability
1346         // and/or better reliability
1347         if(m_type == eHT_Receive) {
1348             raw1394_iso_recv_flush(m_handle);
1349         }
1350         #endif
1351
1352         if(raw1394_loop_iterate(m_handle)) {
1353             debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
1354                         this, strerror(errno));
1355             return false;
1356         }
1357         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) done interating ISO handler...\n",
1358                            this, getTypeString());
1359         return true;
1360     } else {
1361         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Not iterating a non-running handler...\n",
1362                     this, getTypeString());
1363         return false;
1364     }
1365 }
1366
1367 /**
1368  * Bus reset handler
1369  *
1370  * @return ?
1371  */
1372
1373 bool
1374 IsoHandlerManager::IsoHandler::handleBusReset()
1375 {
1376     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
1377     m_last_packet_handled_at = 0xFFFFFFFF;
1378
1379     #define CSR_CYCLE_TIME            0x200
1380     #define CSR_REGISTER_BASE  0xfffff0000000ULL
1381     // do a simple read on ourself in order to update the internal structures
1382     // this avoids read failures after a bus reset
1383     quadlet_t buf=0;
1384     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
1385                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
1386
1387     return m_Client->handleBusReset();
1388 }
1389
1390 /**
1391  * Call this if you find out that this handler has died for some
1392  * external reason.
1393  */
1394 void
1395 IsoHandlerManager::IsoHandler::notifyOfDeath()
1396 {
1397     m_State = eHS_Error;
1398     m_NextState = eHS_Error;
1399
1400     // notify the client of the fact that we have died
1401     m_Client->handlerDied();
1402
1403     // wake ourselves up
1404     if(m_handle) raw1394_wake_up(m_handle);
1405 }
1406
1407 void IsoHandlerManager::IsoHandler::dumpInfo()
1408 {
1409     int channel=-1;
1410     if (m_Client) channel=m_Client->getChannel();
1411
1412     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
1413             getTypeString());
1414     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
1415             m_manager.get1394Service().getPort(), channel);
1416     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
1417             m_buf_packets, m_max_packet_size, m_irq_interval);
1418     if (this->getType() == eHT_Transmit) {
1419         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed ..................: %2d\n",
1420                                             m_speed);
1421         #ifdef DEBUG
1422         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Min ISOXMT bufferfill : %04d\n", m_min_ahead);
1423         #endif
1424     }
1425     #ifdef DEBUG
1426     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last cycle, dropped.........: %4d, %4u, %4u\n",
1427             m_last_cycle, m_dropped, m_skipped);
1428     #endif
1429
1430 }
1431
1432 void IsoHandlerManager::IsoHandler::setVerboseLevel(int l)
1433 {
1434     setDebugLevel(l);
1435     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1436 }
1437
1438 bool IsoHandlerManager::IsoHandler::registerStream(StreamProcessor *stream)
1439 {
1440     assert(stream);
1441     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
1442
1443     if (m_Client) {
1444             debugFatal( "Generic IsoHandlers can have only one client\n");
1445             return false;
1446     }
1447     m_Client=stream;
1448     return true;
1449 }
1450
1451 bool IsoHandlerManager::IsoHandler::unregisterStream(StreamProcessor *stream)
1452 {
1453     assert(stream);
1454     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
1455
1456     if(stream != m_Client) {
1457             debugFatal( "no client registered\n");
1458             return false;
1459     }
1460     m_Client=0;
1461     return true;
1462 }
1463
1464 // ISO packet interface
1465 enum raw1394_iso_disposition IsoHandlerManager::IsoHandler::putPacket(
1466                     unsigned char *data, unsigned int length,
1467                     unsigned char channel, unsigned char tag, unsigned char sy,
1468                     unsigned int cycle, unsigned int dropped) {
1469     // keep track of dropped cycles
1470     int dropped_cycles = 0;
1471     if (m_last_cycle != (int)cycle && m_last_cycle != -1 && m_manager.m_MissedCyclesOK == false) {
1472         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
1473         #ifdef DEBUG
1474         if (dropped_cycles < 0) {
1475             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d\n",
1476                          this, dropped_cycles, cycle, m_last_cycle, dropped);
1477         }
1478         if (dropped_cycles > 0) {
1479             debugOutput(DEBUG_LEVEL_VERBOSE,
1480                         "(%p) dropped %d packets on cycle %u, 'dropped'=%u, cycle=%d, m_last_cycle=%d\n",
1481                         this, dropped_cycles, cycle, dropped, cycle, m_last_cycle);
1482             m_dropped += dropped_cycles;
1483         }
1484         #endif
1485     }
1486     m_last_cycle = cycle;
1487
1488     // the m_last_now value is set when the iterate() function is called.
1489     uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(m_last_now);
1490
1491     // two cases can occur:
1492     // (1) this packet has been received before iterate() was called (normal case).
1493     // (2) this packet has been received after iterate() was called.
1494     //     happens when the kernel flushes more packets while we are already processing.
1495     //
1496     // In case (1) now_cycles is a small number of cycles larger than cycle. In
1497     // case (2) now_cycles is a small number of cycles smaller than cycle.
1498     // hence  abs(diffCycles(now_cycles, cycles)) has to be 'small'
1499
1500     // we can calculate the time of arrival for this packet as
1501     // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE
1502     // in its properly wrapped version
1503     int64_t diff_cycles = diffCycles(cycle, now_cycles);
1504     int64_t tmp = CYCLE_TIMER_TO_TICKS(m_last_now);
1505     tmp += diff_cycles * (int64_t)TICKS_PER_CYCLE;
1506     uint64_t pkt_ctr_ticks = wrapAtMinMaxTicks(tmp);
1507     uint32_t pkt_ctr = TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks);
1508     #ifdef DEBUG
1509     if( (now_cycles < cycle)
1510         && diffCycles(now_cycles, cycle) < 0
1511         // ignore this on dropped cycles, since it's normal
1512         // that now is ahead on the received packets (as we miss packets)
1513         && dropped_cycles == 0)
1514     {
1515         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Special non-unwrapping happened\n");
1516     }
1517     #endif
1518
1519     #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
1520     // add a seconds field
1521     uint32_t now = m_manager.get1394Service().getCycleTimer();
1522     uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
1523     // causality results in the fact that 'now' is always after 'cycle'
1524     // or at best, equal (if this handler was called within 125us after
1525     // the packet was on the wire).
1526     if(CYCLE_TIMER_GET_CYCLES(now) < cycle) {
1527         // the cycle field has wrapped, substract one second
1528         if(now_secs_ref == 0) {
1529             now_secs_ref = 127;
1530         } else  {
1531             now_secs_ref -= 1;
1532         }
1533     }
1534     uint32_t pkt_ctr_ref = cycle << 12;
1535     pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
1536
1537     if((pkt_ctr & ~0x0FFFL) != pkt_ctr_ref) {
1538         debugWarning("reconstructed CTR counter discrepancy\n");
1539         debugWarning(" ingredients: %X, %X, %X, %X, %X, %d, %ld, %ld, %"PRId64"\n",
1540                      cycle, pkt_ctr_ref, pkt_ctr,
1541                      now, m_last_now, now_secs_ref,
1542                      (long int)CYCLE_TIMER_GET_SECS(now),
1543                      (long int)CYCLE_TIMER_GET_SECS(m_last_now),
1544                      tmp);
1545         debugWarning(" diffcy = %"PRId64" \n", diff_cycles);
1546     }
1547     #endif
1548     m_last_packet_handled_at = pkt_ctr;
1549
1550     // leave the offset field (for now?)
1551
1552     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
1553                 "received packet: length=%d, channel=%d, cycle=%d, at %08X\n",
1554                 length, channel, cycle, pkt_ctr);
1555     m_packets++;
1556     #ifdef DEBUG
1557     if (length > m_max_packet_size) {
1558         debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
1559                      this, getTypeString(), length, m_max_packet_size);
1560     }
1561     if(m_last_cycle == -1) {
1562         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle);
1563     }
1564     #endif
1565
1566     // iterate the client if required
1567     if(m_Client)
1568         return m_Client->putPacket(data, length, channel, tag, sy, pkt_ctr, dropped_cycles);
1569
1570     return RAW1394_ISO_OK;
1571 }
1572
1573 enum raw1394_iso_disposition
1574 IsoHandlerManager::IsoHandler::getPacket(unsigned char *data, unsigned int *length,
1575                       unsigned char *tag, unsigned char *sy,
1576                       int cycle, unsigned int dropped, unsigned int skipped) {
1577
1578     uint32_t pkt_ctr;
1579     if (cycle < 0) {
1580         // mark invalid
1581         pkt_ctr = 0xFFFFFFFF;
1582     } else {
1583         // the m_last_now value is set when the iterate() function is called.
1584         uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(m_last_now);
1585
1586         // two cases can occur:
1587         // (1) this packet has been received before iterate() was called (normal case).
1588         // (2) this packet has been received after iterate() was called.
1589         //     happens when the kernel flushes more packets while we are already processing.
1590         //
1591         // In case (1) now_cycles is a small number of cycles larger than cycle. In
1592         // case (2) now_cycles is a small number of cycles smaller than cycle.
1593         // hence  abs(diffCycles(now_cycles, cycles)) has to be 'small'
1594
1595         // we can calculate the time of arrival for this packet as
1596         // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE
1597         // in its properly wrapped version
1598         int64_t diff_cycles = diffCycles(cycle, now_cycles);
1599         int64_t tmp = CYCLE_TIMER_TO_TICKS(m_last_now);
1600         tmp += diff_cycles * (int64_t)TICKS_PER_CYCLE;
1601         uint64_t pkt_ctr_ticks = wrapAtMinMaxTicks(tmp);
1602         pkt_ctr = TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks);
1603
1604         #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
1605         // add a seconds field
1606         uint32_t now = m_manager.get1394Service().getCycleTimer();
1607         uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
1608         // causality results in the fact that 'now' is always after 'cycle'
1609         if(CYCLE_TIMER_GET_CYCLES(now) > (unsigned int)cycle) {
1610             // the cycle field has wrapped, add one second
1611             now_secs_ref += 1;
1612             // no need for this:
1613             if(now_secs_ref == 128) {
1614                now_secs_ref = 0;
1615             }
1616         }
1617         uint32_t pkt_ctr_ref = cycle << 12;
1618         pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
1619
1620         if(((pkt_ctr & ~0x0FFFL) != pkt_ctr_ref) && (m_packets > m_buf_packets)) {
1621             debugWarning("reconstructed CTR counter discrepancy\n");
1622             debugWarning(" ingredients: %X, %X, %X, %X, %X, %d, %ld, %ld, %"PRId64"\n",
1623                         cycle, pkt_ctr_ref, pkt_ctr,
1624                          now, m_last_now, now_secs_ref,
1625                          (long int)CYCLE_TIMER_GET_SECS(now),
1626                          (long int)CYCLE_TIMER_GET_SECS(m_last_now),
1627                          tmp);
1628             debugWarning(" diffcy = %"PRId64" \n", diff_cycles);
1629         }
1630         #endif
1631     }
1632     if (m_packets < m_buf_packets) { // these are still prebuffer packets
1633         m_last_packet_handled_at = 0xFFFFFFFF;
1634     } else {
1635         m_last_packet_handled_at = pkt_ctr;
1636     }
1637     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
1638                 "sending packet: length=%d, cycle=%d, at %08X\n",
1639                 *length, cycle, pkt_ctr);
1640
1641     m_packets++;
1642
1643     #ifdef DEBUG
1644     if(m_last_cycle == -1) {
1645         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive. cycle=%d state=%i\n", getTypeString(), this, cycle, m_State);
1646     }
1647     #endif
1648
1649     // keep track of dropped cycles
1650     int dropped_cycles = 0;
1651     if (m_last_cycle != cycle && m_last_cycle != -1) {
1652         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
1653         // correct for skipped packets
1654         // since those are not dropped, but only delayed
1655         dropped_cycles -= skipped;
1656
1657         #ifdef DEBUG
1658         if(skipped) {
1659             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
1660                         "(%p) skipped %d cycles, cycle: %d, last_cycle: %d, dropped: %d\n",
1661                         this, skipped, cycle, m_last_cycle, dropped);
1662             m_skipped += skipped;
1663         }
1664         if (dropped_cycles < 0) {
1665             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d, skipped: %d\n",
1666                          this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
1667         }
1668         if (dropped_cycles > 0) {
1669             debugOutput(DEBUG_LEVEL_VERBOSE,
1670                         "(%p) dropped %d packets on cycle %u (last_cycle=%u, dropped=%d, skipped: %d)\n",
1671                         this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
1672             m_dropped += dropped_cycles - skipped;
1673         }
1674         #endif
1675     }
1676     if (cycle >= 0) {
1677         m_last_cycle = cycle;
1678        
1679         #ifdef DEBUG
1680 /*        int ahead = diffCycles(cycle, now_cycles);
1681         if (ahead < m_min_ahead) m_min_ahead = ahead;
1682 */
1683         #endif
1684     }
1685
1686     #ifdef DEBUG
1687     if (dropped > 0) {
1688         debugOutput(DEBUG_LEVEL_VERBOSE,
1689                     "(%p) OHCI issue on cycle %u (dropped_cycles=%d, last_cycle=%u, dropped=%d, skipped: %d)\n",
1690                     this, cycle, dropped_cycles, m_last_cycle, dropped, skipped);
1691     }
1692     #endif
1693
1694     if(m_Client) {
1695         enum raw1394_iso_disposition retval;
1696         retval = m_Client->getPacket(data, length, tag, sy, pkt_ctr, dropped_cycles, skipped, m_max_packet_size);
1697         #ifdef DEBUG
1698         if (*length > m_max_packet_size) {
1699             debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
1700                          this, getTypeString(), *length, m_max_packet_size);
1701         }
1702         #endif
1703             return retval;
1704     }
1705
1706     *tag = 0;
1707     *sy = 0;
1708     *length = 0;
1709     return RAW1394_ISO_OK;
1710 }
1711
1712 bool
1713 IsoHandlerManager::IsoHandler::enable(int cycle)
1714 {
1715     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
1716
1717     // check the state
1718     if(m_State != eHS_Stopped) {
1719         debugError("Incorrect state, expected eHS_Stopped, got %d\n",(int)m_State);
1720         return false;
1721     }
1722
1723     assert(m_handle == NULL);
1724
1725     // create a handle for the ISO traffic
1726     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
1727     if ( !m_handle ) {
1728         if ( !errno ) {
1729             debugError("libraw1394 not compatible\n");
1730         } else {
1731             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
1732             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
1733         }
1734         return false;
1735     }
1736     raw1394_set_userdata(m_handle, static_cast<void *>(this));
1737
1738     // prepare the handler, allocate the resources
1739     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client);
1740     dumpInfo();
1741     if (getType() == eHT_Receive) {
1742         if(raw1394_iso_recv_init(m_handle,
1743                                 iso_receive_handler,
1744                                 m_buf_packets,
1745                                 m_max_packet_size,
1746                                 m_Client->getChannel(),
1747                                 m_receive_mode,
1748                                 m_irq_interval)) {
1749             debugFatal("Could not do receive initialization (PACKET_PER_BUFFER)!\n" );
1750             debugFatal("  %s\n",strerror(errno));
1751             return false;
1752         }
1753
1754         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
1755             debugFatal("Could not start receive handler (%s)\n",strerror(errno));
1756             dumpInfo();
1757             return false;
1758         }
1759     } else {
1760         if(raw1394_iso_xmit_init(m_handle,
1761                                 iso_transmit_handler,
1762                                 m_buf_packets,
1763                                 m_max_packet_size,
1764                                 m_Client->getChannel(),
1765                                 m_speed,
1766                                 m_irq_interval)) {
1767             debugFatal("Could not do xmit initialisation!\n" );
1768             return false;
1769         }
1770
1771         if(raw1394_iso_xmit_start(m_handle, cycle, 0)) {
1772             debugFatal("Could not start xmit handler (%s)\n", strerror(errno));
1773             dumpInfo();
1774             return false;
1775         }
1776     }
1777
1778 #ifdef DEBUG
1779     m_min_ahead = 7999;
1780 #endif
1781
1782     m_packets = 0;
1783
1784     // indicate that the first iterate() still has to occur.
1785     m_last_now = 0xFFFFFFFF;
1786     m_last_packet_handled_at = 0xFFFFFFFF;
1787
1788     m_State = eHS_Running;
1789     m_NextState = eHS_Running;
1790     return true;
1791 }
1792
1793 bool
1794 IsoHandlerManager::IsoHandler::disable()
1795 {
1796     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n",
1797                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
1798
1799     // check state
1800     if(m_State != eHS_Running) {
1801         debugError("Incorrect state, expected eHS_Running, got %d\n",(int)m_State);
1802         return false;
1803     }
1804
1805     assert(m_handle != NULL);
1806
1807     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) wake up handle...\n",
1808                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
1809
1810     // wake up any waiting reads/polls
1811     raw1394_wake_up(m_handle);
1812
1813     // this is put here to try and avoid the
1814     // Runaway context problem
1815     // don't know if it will help though.
1816 /*    if(m_State != eHS_Error) { // if the handler is dead, this might block forever
1817         raw1394_iso_xmit_sync(m_handle);
1818     }*/
1819     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) stop...\n",
1820                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
1821     // stop iso traffic
1822     raw1394_iso_stop(m_handle);
1823     // deallocate resources
1824
1825     // Don't call until libraw1394's raw1394_new_handle() function has been
1826     // fixed to correctly initialise the iso_packet_infos field.  Bug is
1827     // confirmed present in libraw1394 1.2.1.
1828     raw1394_iso_shutdown(m_handle);
1829
1830     raw1394_destroy_handle(m_handle);
1831     m_handle = NULL;
1832
1833     m_State = eHS_Stopped;
1834     m_NextState = eHS_Stopped;
1835     return true;
1836 }
1837
1838 // functions to request enable or disable at the next opportunity
1839 bool
1840 IsoHandlerManager::IsoHandler::requestEnable(int cycle)
1841 {
1842     if (m_State == eHS_Running) {
1843         debugError("Enable requested on enabled stream '%s'\n", getTypeString());
1844         return false;
1845     }
1846     if (m_State != eHS_Stopped) {
1847         debugError("Enable requested on stream '%s' with state: %d\n", getTypeString(), m_State);
1848         return false;
1849     }
1850     m_NextState = eHS_Running;
1851     return true;
1852 }
1853
1854 bool
1855 IsoHandlerManager::IsoHandler::requestDisable()
1856 {
1857     if (m_State == eHS_Stopped) {
1858         // Don't treat this as an error condition because during a user
1859         // shutdown the stream would have been disabled by
1860         // stopHandlerForStream().  Therefore when requestDisable() is
1861         // subnsequently called by IsoHandlerManager::stopHandlers() in the
1862         // IsoHandlerManager destructor with the stream disabled the
1863         // condition is not an error.
1864         //
1865         // For now print a warning, but this might be removed in future if
1866         // the above framework remains in place.
1867         debugWarning("Disable requested on disabled stream\n");
1868         return true;
1869     }
1870     if (m_State != eHS_Running) {
1871         debugError("Disable requested on stream with state=%d\n", m_State);
1872         return false;
1873     }
1874     m_NextState = eHS_Stopped;
1875     return true;
1876 }
1877
1878 // Explicitly preset m_switch_on_cycle since requestEnable doesn't do this
1879 // and thus all enables requested via that route always occur on cycle 0.
1880 void
1881 IsoHandlerManager::IsoHandler::setIsoStartCycle(signed int cycle)
1882 {
1883   m_switch_on_cycle = cycle;
1884 }
1885
1886 void
1887 IsoHandlerManager::IsoHandler::updateState()
1888 {
1889     // execute state changes requested
1890     if(m_State != m_NextState) {
1891         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) handler needs state update from %d => %d\n", this, m_State, m_NextState);
1892         if(m_State == eHS_Stopped && m_NextState == eHS_Running) {
1893             debugOutput(DEBUG_LEVEL_VERBOSE, "handler has to be enabled\n");
1894             enable(m_switch_on_cycle);
1895         } else if(m_State == eHS_Running && m_NextState == eHS_Stopped) {
1896             debugOutput(DEBUG_LEVEL_VERBOSE, "handler has to be disabled\n");
1897             disable();
1898         } else {
1899             debugError("Unknown state transition\n");
1900         }
1901     }
1902 }
1903
1904 /**
1905  * @brief convert a EHandlerType to a string
1906  * @param t the type
1907  * @return a char * describing the state
1908  */
1909 const char *
1910 IsoHandlerManager::IsoHandler::eHTToString(enum EHandlerType t) {
1911     switch (t) {
1912         case eHT_Receive: return "Receive";
1913         case eHT_Transmit: return "Transmit";
1914         default: return "error: unknown type";
1915     }
1916 }
Note: See TracBrowser for help on using the browser.