diff --git a/sys/src/9/pc/usbohci.c b/sys/src/9/pc/usbohci.c index 1b9c3cf0c..154da3062 100644 --- a/sys/src/9/pc/usbohci.c +++ b/sys/src/9/pc/usbohci.c @@ -1762,25 +1762,23 @@ epctlio(Ep *ep, Ctlio *cio, void *a, long count) /* * Put new samples in the dummy Td. - * BUG: This does only a transfer per Td. We could do up to 8. */ static long -putsamples(Ctlr *ctlr, Ep *ep, Isoio *iso, uchar *b, long count) +putsamples(Ctlr *ctlr, Ep *ep, Isoio *iso, uchar *b, long n) { Td *td; - ulong n; td = pa2ptr(iso->ed->tail); - n = count; if(n > td->nbytes - BLEN(td->bp)) n = td->nbytes - BLEN(td->bp); assert(td->bp->wp + n <= td->bp->lim); + iunlock(ctlr); /* We could page fault here */ memmove(td->bp->wp, b, n); - td->bp->wp += n; - if(BLEN(td->bp) == td->nbytes){ /* full Td: activate it */ - ilock(ctlr); - isoadvance(ep, iso, td); - iunlock(ctlr); + ilock(ctlr); + if(td == pa2ptr(iso->ed->tail)){ + td->bp->wp += n; + if(BLEN(td->bp) == td->nbytes) /* full Td: activate it */ + isoadvance(ep, iso, td); } return n; } @@ -1834,9 +1832,7 @@ episowrite(Ep *ep, void *a, long count) } if(iso->state != Qrun) panic("episowrite: iso not running"); - iunlock(ctlr); /* We could page fault here */ nw = putsamples(ctlr, ep, iso, b+tot, count-tot); - ilock(ctlr); } while(isodelay(iso) == 0){ iunlock(ctlr); diff --git a/sys/src/9/pc/usbuhci.c b/sys/src/9/pc/usbuhci.c index a063fcd9a..282648ff7 100644 --- a/sys/src/9/pc/usbuhci.c +++ b/sys/src/9/pc/usbuhci.c @@ -993,21 +993,27 @@ interrupt(Ureg*, void *a) * it is activated and tdu advanced. */ static long -putsamples(Isoio *iso, uchar *b, long count) +putsamples(Ctlr *ctlr, Isoio *iso, uchar *b, long count) { - long tot; - long n; + long n, tot, left; + Td *tdu; for(tot = 0; isocanwrite(iso) && tot < count; tot += n){ n = count-tot; - if(n > maxtdlen(iso->tdu) - iso->nleft) - n = maxtdlen(iso->tdu) - iso->nleft; - memmove(iso->tdu->data+iso->nleft, b+tot, n); + tdu = iso->tdu; + left = iso->nleft; + if(n > maxtdlen(tdu) - left) + n = maxtdlen(tdu) - left; + iunlock(ctlr); /* can pagefault here */ + memmove(tdu->data+left, b+tot, n); + ilock(ctlr); + if(tdu != iso->tdu) + continue; iso->nleft += n; - if(iso->nleft == maxtdlen(iso->tdu)){ - tdisoinit(iso, iso->tdu, iso->nleft); + if(iso->nleft == maxtdlen(tdu)){ + tdisoinit(iso, tdu, iso->nleft); + iso->tdu = tdu->next; iso->nleft = 0; - iso->tdu = iso->tdu->next; } } return tot; @@ -1065,9 +1071,7 @@ episowrite(Ep *ep, Isoio *iso, void *a, long count) } if(iso->state != Qrun) panic("episowrite: iso not running"); - iunlock(ctlr); /* We could page fault here */ - nw = putsamples(iso, b+tot, count-tot); - ilock(ctlr); + nw = putsamples(ctlr, iso, b+tot, count-tot); } while(isodelay(iso) == 0){ iunlock(ctlr); diff --git a/sys/src/9/port/usbehci.c b/sys/src/9/port/usbehci.c index ef1c1ca71..22af2e798 100644 --- a/sys/src/9/port/usbehci.c +++ b/sys/src/9/port/usbehci.c @@ -1996,33 +1996,44 @@ episoread(Ep *ep, Isoio *iso, void *a, long count) * it is activated and tdu advanced. */ static long -putsamples(Isoio *iso, uchar *b, long count) +putsamples(Ctlr *ctlr, Isoio *iso, uchar *b, long count) { - long tot, n; + long left, tot, n; + Sitd *stdu; + Itd *tdu; for(tot = 0; isocanwrite(iso) && tot < count; tot += n){ n = count-tot; + left = iso->nleft; if(iso->hs != 0){ - if(n > iso->tdu->mdata - iso->nleft) - n = iso->tdu->mdata - iso->nleft; - memmove(iso->tdu->data + iso->nleft, b + tot, n); - coherence(); + tdu = iso->tdu; + if(n > tdu->mdata - left) + n = tdu->mdata - left; + iunlock(ctlr); /* We could page fault here */ + memmove(tdu->data + left, b + tot, n); + ilock(ctlr); + if(iso->tdu != tdu) + continue; iso->nleft += n; - if(iso->nleft == iso->tdu->mdata){ - itdinit(iso, iso->tdu); + if(iso->nleft == tdu->mdata){ + itdinit(iso, tdu); + iso->tdu = tdu->next; iso->nleft = 0; - iso->tdu = iso->tdu->next; } }else{ - if(n > iso->stdu->mdata - iso->nleft) - n = iso->stdu->mdata - iso->nleft; - memmove(iso->stdu->data + iso->nleft, b + tot, n); - coherence(); + stdu = iso->stdu; + if(n > stdu->mdata - left) + n = stdu->mdata - left; + iunlock(ctlr); /* We could page fault here */ + memmove(stdu->data + left, b + tot, n); + ilock(ctlr); + if(iso->stdu != stdu) + continue; iso->nleft += n; - if(iso->nleft == iso->stdu->mdata){ - sitdinit(iso, iso->stdu); + if(iso->nleft == stdu->mdata){ + sitdinit(iso, stdu); + iso->stdu = stdu->next; iso->nleft = 0; - iso->stdu = iso->stdu->next; } } } @@ -2081,9 +2092,7 @@ episowrite(Ep *ep, Isoio *iso, void *a, long count) } if(iso->state != Qrun) panic("episowrite: iso not running"); - iunlock(ctlr); /* We could page fault here */ - nw = putsamples(iso, b+tot, count-tot); - ilock(ctlr); + nw = putsamples(ctlr, iso, b+tot, count-tot); } while(isodelay(iso) == 0){ iunlock(ctlr);