diff options
| -rw-r--r-- | sys/src/9/pc/usbxhci.c | 115 |
1 files changed, 43 insertions, 72 deletions
diff --git a/sys/src/9/pc/usbxhci.c b/sys/src/9/pc/usbxhci.c index 8b7983f34..45e502c91 100644 --- a/sys/src/9/pc/usbxhci.c +++ b/sys/src/9/pc/usbxhci.c @@ -159,6 +159,10 @@ struct Wait struct Ring { + int id; + + Slot *slot; + u32int *base; u32int size; @@ -168,10 +172,8 @@ struct Ring u32int rp; u32int wp; - struct { - u32int *r; - u32int v; - } doorbell; + u32int *ctx; + u32int *doorbell; Wait *pending; Lock; @@ -264,8 +266,10 @@ freering(Ring *r) static void initring(Ring *r, int shift) { - r->doorbell.v = 0; - r->doorbell.r = nil; + r->id = 0; + r->ctx = nil; + r->slot = nil; + r->doorbell = nil; r->pending = nil; r->shift = shift; r->size = 1<<shift; @@ -337,8 +341,8 @@ init(Hci *hp) ctlr->setrptr(&ctlr->opr[DCBAAP], PADDR(ctlr->dcba)); initring(ctlr->cr, 8); /* 256 entries */ - ctlr->cr->doorbell.r = &ctlr->dba[0]; - ctlr->cr->doorbell.v = 0; + ctlr->cr->doorbell = &ctlr->dba[0]; + ctlr->cr->id = 0; coherence(); ctlr->setrptr(&ctlr->opr[CRCR], PADDR(ctlr->cr[0].base) | 1); @@ -464,7 +468,7 @@ static void kickring(Ring *r) { coherence(); - *r->doorbell.r = r->doorbell.v; + *r->doorbell = r->id; } static char* @@ -742,8 +746,10 @@ initep(Ep *ep) } if(ep->mode != OREAD){ initring(io->ring[OWRITE] = &slot->epr[ep->nb*2-1], 8); - io->ring[OWRITE]->doorbell.r = &ctlr->dba[slot->id]; - io->ring[OWRITE]->doorbell.v = ep->nb*2; + io->ring[OWRITE]->doorbell = &ctlr->dba[slot->id]; + io->ring[OWRITE]->slot = slot; + io->ring[OWRITE]->ctx = &slot->obase[(ep->nb*2+0)*8<<ctlr->csz]; + io->ring[OWRITE]->id = ep->nb*2; w[1] |= 1 << ep->nb*2; if(ep->nb*2 > slot->nep) @@ -751,8 +757,10 @@ initep(Ep *ep) } if(ep->mode != OWRITE){ initring(io->ring[OREAD] = &slot->epr[ep->nb*2], 8); - io->ring[OREAD]->doorbell.r = &ctlr->dba[slot->id]; - io->ring[OREAD]->doorbell.v = ep->nb*2+1; + io->ring[OREAD]->doorbell = &ctlr->dba[slot->id]; + io->ring[OREAD]->slot = slot; + io->ring[OREAD]->ctx = &slot->obase[(ep->nb*2+1)*8<<ctlr->csz]; + io->ring[OREAD]->id = ep->nb*2+1; w[1] |= 2 << ep->nb*2; if(ep->nb*2+1 > slot->nep) @@ -849,8 +857,10 @@ epopen(Ep *ep) /* allocate control ep 0 ring */ initring(io->ring[OWRITE] = &slot->epr[0], 8); - io->ring[OWRITE]->doorbell.r = &ctlr->dba[slot->id]; - io->ring[OWRITE]->doorbell.v = 1; + io->ring[OWRITE]->doorbell = &ctlr->dba[slot->id]; + io->ring[OWRITE]->slot = slot; + io->ring[OWRITE]->ctx = &slot->obase[8]; + io->ring[OWRITE]->id = 1; slot->nep = 1; /* (input) control context */ @@ -905,60 +915,21 @@ epopen(Ep *ep) } static void -resetring(Ring *r) +unstall(Ring *r) { - ilock(r); - r->rp--; /* assume previous td halted */ - while((int)(r->wp - r->rp) > 0){ - u32int *td = &r->base[4*(--r->wp & r->mask)]; - td[0] = td[1] = td[2] = 0; - td[3] = (r->wp>>r->shift)&1; + u64int qp; + + switch(r->ctx[0]&7){ + case 2: + case 4: + ilock(r); + r->rp = r->wp; + qp = PADDR(&r->base[4*(r->wp & r->mask)]) | ((~r->wp>>r->shift) & 1); + iunlock(r); + + ctlrcmd(r->slot->ctlr, CR_RESETEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil); + ctlrcmd(r->slot->ctlr, CR_SETTRDQP | (r->id<<16) | (r->slot->id<<24), 0, qp, nil); } - iunlock(r); -} - -static int -epunstall(Ep *ep, int mode) -{ - Ctlr *ctlr; - Slot *slot; - Epio *io; - u32int *w; - int dci, ret; - - ret = 0; - io = ep->aux; - slot = ep->dev->aux; - ctlr = slot->ctlr; - - if(ep->nb == 0) - dci = 1; - else - dci = ep->nb*2; - - /* (output) ep context */ - w = slot->obase; - w += dci*8<<ctlr->csz; - if(mode != OREAD && io->ring[OWRITE] != nil){ - switch(w[0]&7){ - case 2: - case 4: - resetring(io->ring[OWRITE]); - ctlrcmd(ctlr, CR_RESETEP | (dci<<16) | (slot->id<<24), 0, 0, nil); - ret++; - } - } - w += 8<<ctlr->csz, dci++; - if(mode != OWRITE && io->ring[OREAD] != nil){ - switch(w[0]&7){ - case 2: - case 4: - resetring(io->ring[OREAD]); - ctlrcmd(ctlr, CR_RESETEP | (dci<<16) | (slot->id<<24), 0, 0, nil); - ret++; - } - } - return ret; } static long @@ -972,6 +943,7 @@ epread(Ep *ep, void *va, long n) p = va; io = ep->aux; + if(ep->ttype == Tctl){ qlock(io); if(io->cb == nil || BLEN(io->cb) == 0){ @@ -1001,8 +973,8 @@ epread(Ep *ep, void *va, long n) return n; } - epunstall(ep, OREAD); ring = io->ring[OREAD]; + unstall(ring); ilock(ring); queuetd(ring, TR_NORMAL | 1<<16 | 1<<5, n, PADDR(p), ws); iunlock(ring); @@ -1028,6 +1000,7 @@ epwrite(Ep *ep, void *va, long n) p = va; io = ep->aux; + if(ep->ttype == Tctl){ int dir, len; @@ -1059,8 +1032,8 @@ epwrite(Ep *ep, void *va, long n) } } - epunstall(ep, OWRITE); ring = io->ring[OWRITE]; + unstall(ring); ilock(ring); queuetd(ring, TR_SETUPSTAGE | (len > 0 ? 2+dir : 0)<<16 | 1<<6 | 1<<5, 8, p[0] | p[1]<<8 | GET2(&p[2])<<16 | @@ -1104,8 +1077,8 @@ epwrite(Ep *ep, void *va, long n) return n; } - epunstall(ep, OWRITE); ring = io->ring[OWRITE]; + unstall(ring); ilock(ring); queuetd(ring, TR_NORMAL | 1<<16 | 1<<5, n, PADDR(p), ws); iunlock(ring); @@ -1238,8 +1211,6 @@ reset(Hci *hp) if(getconf("*nousbxhci")) return -1; - fmtinstall(L'H', encodefmt); - scanpci(); /* |
