diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-08-01 19:02:50 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-08-01 19:02:50 +0200 |
commit | 676a876df607eda5488d7635592a99228066d0f9 (patch) | |
tree | 624a13da9b0f0fc5dc107fe2e69fda149f5220ae /sys/src/9/pc/usbuhci.c | |
parent | 89ab1f286e7c9c5f21109eaf351e5e3c195fb337 (diff) |
usb: added buffer delay control
Diffstat (limited to 'sys/src/9/pc/usbuhci.c')
-rw-r--r-- | sys/src/9/pc/usbuhci.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/sys/src/9/pc/usbuhci.c b/sys/src/9/pc/usbuhci.c index 6a1dab01d..d5a107a68 100644 --- a/sys/src/9/pc/usbuhci.c +++ b/sys/src/9/pc/usbuhci.c @@ -195,6 +195,7 @@ struct Isoio int debug; /* debug flag from the endpoint */ Isoio* next; /* in list of active Isoios */ Td* tdps[Nframes]; /* pointer to Td used for i-th frame or nil */ + int delay; /* maximum number of bytes to buffer */ }; struct Tdpool @@ -775,6 +776,29 @@ isocanwrite(void *a) iso->tok == Tdtokout && iso->tdu->next != iso->tdi); } +static int +isodelay(void *a) +{ + Isoio *iso; + int delay; + Td *tdi; + + iso = a; + if(iso->state == Qclose || iso->err || iso->delay == 0) + return 1; + + delay = 0; + for(tdi = iso->tdi; tdi->next != iso->tdu; tdi = tdi->next){ + if((tdi->csw & Tdactive) == 0) + continue; + delay += maxtdlen(tdi); + if(delay > iso->delay) + break; + } + + return delay <= iso->delay; +} + static void tdisoinit(Isoio *iso, Td *td, long count) { @@ -812,7 +836,6 @@ isointerrupt(Ctlr *ctlr, Isoio* iso) nframes = iso->nframes / 2; /* limit how many we look */ if(nframes > 64) nframes = 64; - for(i = 0; i < nframes && (tdi->csw & Tdactive) == 0; i++){ tdi->csw &= ~Tdioc; err = tdi->csw & Tderrors; @@ -839,7 +862,7 @@ isointerrupt(Ctlr *ctlr, Isoio* iso) } tdi = tdi->next; } - ddiprint("isointr: %d frames processed\n", nframes); + ddiprint("isointr: %d frames processed\n", i); if(i == nframes) tdi->csw |= Tdioc; iso->tdi = tdi; @@ -848,7 +871,6 @@ isointerrupt(Ctlr *ctlr, Isoio* iso) iso->tdi, iso->tdu); wakeup(iso); } - } /* @@ -1005,6 +1027,7 @@ episowrite(Ep *ep, Isoio *iso, void *a, long count) char *err; iso->debug = ep->debug; + iso->delay = ep->sampledelay * ep->samplesz; diprint("uhci: episowrite: %#p ep%d.%d\n", iso, ep->dev->nb, ep->nb); ctlr = ep->hp->aux; @@ -1046,6 +1069,11 @@ episowrite(Ep *ep, Isoio *iso, void *a, long count) nw = putsamples(iso, b+tot, count-tot); ilock(ctlr); } + while(isodelay(iso) == 0){ + iunlock(ctlr); + sleep(iso, isodelay, iso); + ilock(ctlr); + } if(iso->state != Qclose) iso->state = Qdone; iunlock(ctlr); @@ -1678,7 +1706,7 @@ isoopen(Ep *ep) } ltd->next = iso->tdps[iso->td0frno]; iso->tdi = iso->tdps[iso->td0frno]; - iso->tdu = iso->tdi; /* read: right now; write: 1s ahead */ + iso->tdu = iso->tdi; ilock(ctlr); frno = iso->td0frno; for(i = 0; i < iso->nframes; i++){ |