]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/usbohci.c
merge
[plan9front.git] / sys / src / 9 / pc / usbohci.c
old mode 100755 (executable)
new mode 100644 (file)
index c0a790f..fc7f9f2
@@ -220,6 +220,7 @@ struct Isoio
        ulong   frno;           /* next frame number avail for I/O */
        ulong   left;           /* remainder after rounding Hz to samples/ms */
        int     nerrs;          /* consecutive errors on iso I/O */
+       int     delay;          /* maximum number of frames to buffer */
 };
 
 /*
@@ -1101,6 +1102,17 @@ isocanwrite(void *a)
                iso->navail > iso->nframes / 2;
 }
 
+static int
+isodelay(void *a)
+{
+       Isoio *iso;
+
+       iso = a;
+       if(iso->state == Qclose || iso->err != nil || iso->delay == 0)
+               return 1;
+       return (iso->nframes - iso->navail) <= iso->delay;
+}
+
 /*
  * Service a completed/failed Td from the done queue.
  * It may be of any transfer type.
@@ -1134,10 +1146,10 @@ qhinterrupt(Ctlr *, Ep *ep, Qio *io, Td *td, int)
        switch(err){
        case Tddataovr:                 /* Overrun is not an error */
        case Tdok:
-               /* can't make this assertion in virtualbox */
-//             if(td->cbp != 0)
-//                     panic("ohci: full packet but cbp != 0");
-               break;
+               /* virtualbox doesn't always report underflow on short packets */
+               if(td->cbp == 0)
+                       break;
+               /* fall through */
        case Tddataund:
                /* short input packets are ok */
                if(mode == OREAD){
@@ -1326,12 +1338,16 @@ epgettd(Ep *ep, Qio *io, Td **dtdp, int flags, void *a, int count)
        Td *td, *dtd;
        Block *bp;
 
-       if(ep->maxpkt > 0x2000)
-               panic("ohci: max packet > two pages");
-       if(ep->maxpkt < count)
-               error("maxpkt too short");
-       bp = allocb(ep->maxpkt);        /* panics if no mem */
-       assert(bp != nil);
+       if(count <= BY2PG)
+               bp = allocb(count);
+       else{
+               if(count > 2*BY2PG)
+                       panic("ohci: transfer > two pages");
+               /* maximum of one physical page crossing allowed */
+               bp = allocb(count+BY2PG);
+               bp->rp = (uchar*)PGROUND((uintptr)bp->rp);
+               bp->wp = bp->rp;
+       }
        dtd = *dtdp;
        td = dtd;
        td->bp = bp;
@@ -1462,7 +1478,7 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
                print("\t%s\n", buf);
        }
        if(mustlock){
-               qlock(io);
+               eqlock(io);
                if(waserror()){
                        qunlock(io);
                        nexterror();
@@ -1482,7 +1498,7 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
        ltd = td0 = ed->tds;
        load = tot = 0;
        do{
-               n = ep->maxpkt;
+               n = 2*BY2PG;
                if(count-tot < n)
                        n = count-tot;
                if(c != nil && io->tok != Tdtokin)
@@ -1602,7 +1618,7 @@ epread(Ep *ep, void *a, long count)
        switch(ep->ttype){
        case Tctl:
                cio = ep->aux;
-               qlock(cio);
+               eqlock(cio);
                if(waserror()){
                        qunlock(cio);
                        nexterror();
@@ -1675,7 +1691,7 @@ epctlio(Ep *ep, Ctlio *cio, void *a, long count)
                cio, ep->dev->nb, ep->nb, count);
        if(count < Rsetuplen)
                error("short usb command");
-       qlock(cio);
+       eqlock(cio);
        free(cio->data);
        cio->data = nil;
        cio->ndata = 0;
@@ -1780,9 +1796,10 @@ episowrite(Ep *ep, void *a, long count)
 
        ctlr = ep->hp->aux;
        iso = ep->aux;
+       iso->delay = (ep->sampledelay*ep->samplesz + ep->maxpkt-1) / ep->maxpkt;
        iso->debug = ep->debug;
 
-       qlock(iso);
+       eqlock(iso);
        if(waserror()){
                qunlock(iso);
                nexterror();
@@ -1821,6 +1838,11 @@ episowrite(Ep *ep, void *a, long count)
                nw = putsamples(ctlr, ep, 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);
@@ -2168,7 +2190,7 @@ portreset(Hci *hp, int port, int on)
                return 0;
 
        ctlr = hp->aux;
-       qlock(&ctlr->resetl);
+       eqlock(&ctlr->resetl);
        if(waserror()){
                qunlock(&ctlr->resetl);
                nexterror();
@@ -2200,7 +2222,7 @@ portenable(Hci *hp, int port, int on)
 
        ctlr = hp->aux;
        dprint("ohci: %#p port %d enable=%d\n", ctlr->ohci, port, on);
-       qlock(&ctlr->resetl);
+       eqlock(&ctlr->resetl);
        if(waserror()){
                qunlock(&ctlr->resetl);
                nexterror();