static long eptrans(Ep *ep, int rw, void *a, long n) { Hostchan *hc; if(ep->clrhalt){ ep->clrhalt = 0; if(ep->mode != OREAD) ep->toggle[Write] = DATA0; if(ep->mode != OWRITE) ep->toggle[Read] = DATA0; } hc = chanalloc(ep); if(waserror()){ ep->toggle[rw] = hc->hctsiz & Pid; chanrelease(ep, hc); if(strcmp(up->errstr, Estalled) == 0) return 0; nexterror(); } chansetup(hc, ep); if(rw == Read && ep->ttype == Tbulk) n = multitrans(ep, hc, rw, a, n); else{ n = chanio(ep, hc, rw == Read? Epin : Epout, ep->toggle[rw], a, n); ep->toggle[rw] = hc->hctsiz & Pid; } chanrelease(ep, hc); poperror(); return n; }
static long ctltrans(Ep *ep, uchar *req, long n) { Hostchan *hc; Epio *epio; Block *b; uchar *data; int datalen; epio = ep->aux; if(epio->cb != nil){ freeb(epio->cb); epio->cb = nil; } if(n < Rsetuplen) error(Ebadlen); if(req[Rtype] & Rd2h){ datalen = GET2(req+Rcount); if(datalen <= 0 || datalen > Maxctllen) error(Ebadlen); /* XXX cache madness */ epio->cb = b = allocb(ROUND(datalen, ep->maxpkt) + CACHELINESZ); b->wp = (uchar*)ROUND((uintptr)b->wp, CACHELINESZ); //epio->cb = b = allocb(ROUND(datalen, ep->maxpkt)); //assert(((uintptr)b->wp & (BLOCKALIGN-1)) == 0); memset(b->wp, 0x55, b->lim - b->wp); cachedwbinvse(b->wp, b->lim - b->wp); data = b->wp; }else{ b = nil; datalen = n - Rsetuplen; data = req + Rsetuplen; } hc = chanalloc(ep); if(waserror()){ chanrelease(ep, hc); if(strcmp(up->env->errstr, Estalled) == 0) return 0; nexterror(); } chansetup(hc, ep); chanio(ep, hc, Epout, SETUP, req, Rsetuplen); if(req[Rtype] & Rd2h){ if(ep->dev->hub <= 1){ ep->toggle[Read] = DATA1; b->wp += multitrans(ep, hc, Read, data, datalen); }else b->wp += chanio(ep, hc, Epin, DATA1, data, datalen); chanio(ep, hc, Epout, DATA1, nil, 0); n = Rsetuplen; }else{ if(datalen > 0) chanio(ep, hc, Epout, DATA1, data, datalen); chanio(ep, hc, Epin, DATA1, nil, 0); n = Rsetuplen + datalen; } chanrelease(ep, hc); poperror(); return n; }