From 219e80a1a54784b13b5165d8887a88c3be595a9b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 24 Jun 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-06-24 --- pc/devusb.c | 1086 +-------------------------------------------------- port/qio.c | 3 +- 2 files changed, 3 insertions(+), 1086 deletions(-) diff --git a/pc/devusb.c b/pc/devusb.c index 20cb14c6faa5a69bfb1f7cf5b53e8eb70d607d1f..3d56f242b1d34d975a13a581e89ec073a6d0af20 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -879,1088 +879,4 @@ schedendpt(Endpt *e) QH *qh; int q; - if(!e->periodic || e->sched >= 0) - return 0; - ub = &ubus; - if(e->epq == nil){ - e->epq = allocqh(ub); - if(e->epq == nil) - return -1; - } - qlock(ub->tree); - q = pickschedq(ub->tree, e->pollms, e->bw, ~0); /* TO DO: bus bandwidth limit */ - if(q < 0) - return -1; - ub->tree->bw[q] += e->bw; - qh = &ub->tree->root[q]; - e->sched = q; - e->epq->head = qh->entries; - e->epq->entries = Terminate; - qh->entries = PADDR(e->epq) | IsQH; - qunlock(ub->tree); - return 0; -} - -static void -unschedendpt(Endpt *e) -{ - Ctlr *ub; - ulong p; - QH *qh; - int q; - - ub = &ubus; - if(!e->periodic || (q = e->sched) < 0) - return; - p = PADDR(e->epq) | IsQH; - qlock(ub->tree); - ub->tree->bw[q] -= e->bw; - qh = &ub->tree->root[q]; - for(; qh->entries != p; qh = QFOL(qh->entries)) - if(qh->entries & Terminate || (qh->entries & IsQH) == 0){ - qunlock(ub->tree); - panic("usb: unschedendpt"); - } - qh->entries = e->epq->head; - qunlock(ub->tree); - e->epq->head = Terminate; -} - -static Endpt * -devendpt(Udev *d, int id, int add) -{ - Endpt *e, **p; - Ctlr *ub; - - ub = &ubus; - p = &d->ep[id&0xF]; - lock(d); - if((e = *p) != nil){ - incref(e); - unlock(d); - return e; - } - unlock(d); - if(!add) - return nil; - e = mallocz(sizeof(*e), 1); - e->ref = 1; - e->x = id&0xF; - e->id = id; - e->periodic = 0; - e->sched = -1; - e->maxpkt = 8; - e->pollms = 0; - e->bw = 0; - e->nbuf = 1; - e->dev = d; - e->active = 0; - e->epq = allocqh(ub); - if(e->epq == nil) - panic("devendpt"); - - lock(d); - if(*p != nil){ - incref(*p); - unlock(d); - free(e); - return *p; - } - *p = e; - unlock(d); - e->rq = qopen(8*1024, 0, nil, e); - e->wq = qopen(8*1024, 0, nil, e); - return e; -} - -static void -freept(Endpt *e) -{ - if(e != nil && decref(e) == 0){ - XPRINT("freept(%d,%d)\n", e->dev->x, e->x); - unschedendpt(e); - e->dev->ep[e->x] = nil; - eptdeactivate(e); - if(e->epq != nil) - freeqh(&ubus, e->epq); - free(e); - } -} - -static void -usbdevreset(Udev *d) -{ - d->state = Disabled; - if(Class(d->csp) == Hubclass) - for(d = d->ports; d != nil; d = d->next) - usbdevreset(d); -} - -static void -freedev(Udev *d) -{ - int i; - - if(d != nil && decref(d) == 0){ - for(i=0; iep); i++) - freept(d->ep[i]); - if(d->x >= 0) - usbdev[d->x] = nil; - free(d); - } -} - -static void -hubportreset(Udev *h, int p) -{ - USED(h, p); - /* reset state of each attached device? */ -} - -static int ioports[] = {-1, Portsc0, Portsc1}; - -static void -portreset(int port) -{ - Ctlr *ub; - int i, p; - - /* should check that device not being configured on other port? */ - p = ioports[port]; - ub = &ubus; - qlock(&ub->resetl); - if(waserror()){ - qunlock(&ub->resetl); - nexterror(); - } - XPRINT("r: %x\n", IN(p)); - ilock(ub); - OUT(p, PortReset); - delay(12); /* BUG */ - XPRINT("r2: %x\n", IN(p)); - OUT(p, IN(p) & ~PortReset); - XPRINT("r3: %x\n", IN(p)); - OUT(p, IN(p) | PortEnable); - microdelay(64); - for(i=0; i<1000 && (IN(p) & PortEnable) == 0; i++) - ; - XPRINT("r': %x %d\n", IN(p), i); - OUT(p, (IN(p) & ~PortReset)|PortEnable); - iunlock(ub); - hubportreset(nil, port); - poperror(); - qunlock(&ub->resetl); -} - -static void -portenable(int port, int on) -{ - Ctlr *ub; - int w, p; - - /* should check that device not being configured on other port? */ - p = ioports[port]; - ub = &ubus; - qlock(&ub->resetl); - if(waserror()){ - qunlock(&ub->resetl); - nexterror(); - } - ilock(ub); - w = IN(p); - if(on) - w |= PortEnable; - else - w &= ~PortEnable; - OUT(p, w); - microdelay(64); - iunlock(ub); - XPRINT("e: %x\n", IN(p)); - if(!on) - hubportreset(nil, port); - poperror(); - qunlock(&ub->resetl); -} - -static int -portinfo(Ctlr *ub, int *p0, int *p1) -{ - int m, v; - - ilock(ub); - m = 0; - if((v = IN(Portsc0)) & PortChange){ - OUT(Portsc0, v); - m |= 1<<0; - } - *p0 = v; - if((v = IN(Portsc1)) & PortChange){ - OUT(Portsc1, v); - m |= 1<<1; - } - *p1 = v; - iunlock(ub); - return m; -} - -static void -interrupt(Ureg*, void *a) -{ - Ctlr *ub; - Endpt *e; - int s; - QH *q; - - ub = a; - s = IN(Status); - XPRINT("usbint: #%x f%d\n", s, IN(Frnum)); - if (s & 0x1a) { - XPRINT("cmd #%x sofmod #%x\n", IN(Cmd), inb(ub->io+SOFMod)); - XPRINT("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1)); - } - OUT(Status, s); - - XPRINT("cleanq(ub->ctlq, 0, 0)\n"); - cleanq(ub->ctlq, 0, 0); - XPRINT("cleanq(ub->bulkq, 0, Vf)\n"); - cleanq(ub->bulkq, 0, Vf); - XPRINT("clean recvq\n"); - for (q = ub->recvq->next; q; q = q->hlink) { - XPRINT("cleanq(q, 0, Vf)\n"); - cleanq(q, 0, Vf); - } - ilock(&activends); - for(e = activends.f; e != nil; e = e->activef) - if(e->epq != nil) { - XPRINT("cleanq(e->epq, 0, 0)\n"); - cleanq(e->epq, 0, 0); - } - iunlock(&activends); -} - -enum -{ - Qtopdir = 0, - Q2nd, - Qbusctl, - Qnew, - Qport, - Q3rd, - Qctl, - Qsetup, - Qdebug, - Qstatus, - Qep0, - /* other endpoint files */ -}; - -/* - * Qid path is: - * 8 bits of file type (qids above) - * 10 bits of slot number +1; 0 means not attached to device - */ -#define QSHIFT 8 /* location in qid of device # */ -#define QMASK ((1<>QSHIFT) - -static Dirtab usbdir2[] = { - "new", {Qnew}, 0, 0666, - "ctl", {Qbusctl}, 0, 0666, - "port", {Qport}, 0, 0444, -}; - -static Dirtab usbdir3[]={ - "ctl", {Qctl}, 0, 0666, - "setup", {Qsetup}, 0, 0666, - "status", {Qstatus}, 0, 0444, - "debug", {Qdebug}, 1, 0666, - /* epNdata names are generated on demand */ -}; - -static Udev * -usbdeviceofpath(ulong path) -{ - int s; - - s = DEVPATH(path); - if(s == 0) - return nil; - return usbdev[s-1]; -} - -static Udev * -usbdevice(Chan *c) -{ - Udev *d; - - d = usbdeviceofpath(c->qid.path); - if(d == nil || d->id != c->qid.vers || d->state == Disabled) - error(Ehungup); - return d; -} - -static Udev * -usbnewdevice(void) -{ - Udev *d; - Endpt *e; - int i; - - d = nil; - qlock(&usbstate); - if(waserror()){ - qunlock(&usbstate); - nexterror(); - } - for(i=0; iref = 1; - d->x = i; - d->id = (ubus.idgen << 8) | i; - d->state = Enabled; - e = devendpt(d, 0, 1); /* always provide control endpoint 0 */ - e->mode = ORDWR; - e->periodic = 0; - e->sched = -1; - usbdev[i] = d; - break; - } - poperror(); - qunlock(&usbstate); - return d; -} - -static void -usbreset(void) -{ - Pcidev *cfg; - int i; - ulong port; - QTree *qt; - TD *t; - Ctlr *ub; - - ub = &ubus; - memset(&cfg, 0, sizeof(cfg)); - cfg = pcimatch(0, 0x8086, 0x7112); /* Intel chipset PIIX 4*/ - if(cfg == nil) { - cfg = pcimatch(0, 0x1106, 0x0586); /* Via chipset */ - if(cfg == nil) { - DPRINT("No USB device found\n"); - return; - } - } - port = cfg->mem[4].bar & ~0x0F; - if (port == 0) { - print("usb: failed to map registers\n"); - return; - } - - DPRINT("USB: %x/%x port 0x%lux size 0x%x irq %d\n", - cfg->vid, cfg->did, port, cfg->mem[4].size, cfg->intl); - - i = inb(port+SOFMod); - if(0){ - OUT(Cmd, 4); /* global reset */ - delay(15); - OUT(Cmd, 0); /* end reset */ - delay(4); - } - outb(port+SOFMod, i); - /* - * Interrupt handler. - * Bail out if no IRQ assigned by the BIOS. - */ - if(cfg->intl == 0xFF || cfg->intl == 0) - return; - intrenable(cfg->intl, interrupt, ub, cfg->tbdf, "usb"); - - ub->io = port; - ub->tdpool = xspanalloc(128*sizeof(TD), 16, 0); - for(i=128; --i>=0;){ - ub->tdpool[i].next = ub->freetd; - ub->freetd = &ub->tdpool[i]; - } - ub->qhpool = xspanalloc(32*sizeof(QH), 16, 0); - for(i=32; --i>=0;){ - ub->qhpool[i].next = ub->freeqh; - ub->freeqh = &ub->qhpool[i]; - } - - /* - * the root of the periodic (interrupt & isochronous) scheduling tree - * points to the control queue and the bandwidth sop for bulk traffic. - * this is looped following the instructions in PIIX4 errata 29773804.pdf: - * a QH links to a looped but inactive TD as its sole entry, - * with its head entry leading on to the bulk traffic, the last QH of which - * links back to the empty QH. - */ - ub->ctlq = allocqh(ub); - ub->bwsop = allocqh(ub); - ub->bulkq = allocqh(ub); - ub->recvq = allocqh(ub); - t = alloctd(ub); /* inactive TD, looped */ - t->link = PADDR(t); - ub->bwsop->entries = PADDR(t); - ub->ctlq->head = PADDR(ub->bwsop) | IsQH; - ub->bwsop->head = PADDR(ub->bulkq) | IsQH; - ub->bulkq->head = PADDR(ub->recvq) | IsQH; - ub->recvq->head = PADDR(ub->bwsop) | IsQH; /* loop back */ - XPRINT("usbcmd\t0x%.4x\nusbsts\t0x%.4x\nusbintr\t0x%.4x\nfrnum\t0x%.2x\n", - IN(Cmd), IN(Status), IN(Usbintr), inb(port+Frnum)); - XPRINT("frbaseadd\t0x%.4x\nsofmod\t0x%x\nportsc1\t0x%.4x\nportsc2\t0x%.4x\n", - IN(Flbaseadd), inb(port+SOFMod), IN(Portsc0), IN(Portsc1)); - OUT(Cmd, 0); /* stop */ - ub->frames = xspanalloc(FRAMESIZE, FRAMESIZE, 0); - qt = mkqhtree(ub->frames, NFRAME, 32); - if(qt == nil){ - print("usb: can't allocate scheduling tree\n"); - ub->io = 0; - return; - } - qt->root->head = PADDR(ub->ctlq) | IsQH; - ub->tree = qt; - XPRINT("usb tree: nel=%d depth=%d\n", qt->nel, qt->depth); - - outl(port+Flbaseadd, PADDR(ub->frames)); - OUT(Frnum, 0); - OUT(Usbintr, 0xF); /* enable all interrupts */ - XPRINT("cmd 0x%x sofmod 0x%x\n", IN(Cmd), inb(port+SOFMod)); - XPRINT("sc0 0x%x sc1 0x%x\n", IN(Portsc0), IN(Portsc1)); -} - -void -usbinit(void) -{ - Udev *d; - - if(ubus.io != 0 && usbdev[0] == nil){ - d = usbnewdevice(); /* reserve device 0 for configuration */ - incref(d); - d->state = Attached; - } -} - -Chan * -usbattach(char *spec) -{ - Ctlr *ub; - - ub = &ubus; - if(ub->io == 0) - error(Enodev); - if((IN(Cmd)&1)==0 || *spec) - OUT(Cmd, 1); /* run */ -// pprint("at: c=%x s=%x c0=%x\n", IN(Cmd), IN(Status), IN(Portsc0)); - return devattach('U', spec); -} - -Chan * -usbclone(Chan *c, Chan *nc) -{ - return devclone(c, nc); -} - -static int -usbgen(Chan *c, Dirtab*, int, int s, Dir *dp) -{ - int t; - Qid q; - ulong path; - Udev *d; - Dirtab *tab; - Endpt *e; - char buf[NAMELEN]; - - /* - * Top level directory contains the name of the device. - */ - if(c->qid.path == CHDIR){ - if(s == DEVDOTDOT){ - devdir(c, (Qid){CHDIR, 0}, "#U", 0, eve, 0555, dp); - return 1; - } - if(s == 0){ - devdir(c, (Qid){CHDIR|Q2nd, 0}, "usb", 0, eve, 0555, dp); - return 1; - } - return -1; - } - - /* - * Second level contains "new" plus all the clients. - */ - t = QID(c->qid); - if(t < Q3rd){ - if(s == DEVDOTDOT){ - devdir(c, (Qid){CHDIR, 0}, "#U", 0, eve, 0555, dp); - return 1; - } - if(s < nelem(usbdir2)){ - tab = &usbdir2[s]; - devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp); - return 1; - } - if((s -= nelem(usbdir2)) >= 0 && s < nelem(usbdev)){ - d = usbdev[s]; - if(d == nil) - return 0; - sprint(buf, "%d", s); - q = (Qid){CHDIR|((s+1)<id}; - devdir(c, q, buf, 0, eve, 0555, dp); - return 1; - } - return -1; - } - - /* - * Third level. - */ - path = c->qid.path&~(CHDIR|QMASK); /* slot component */ - q.vers = c->qid.vers; - if(s == DEVDOTDOT){ - devdir(c, (Qid){CHDIR|Q2nd, 0}, "usb", 0, eve, 0555, dp); - return 1; - } - if(s < nelem(usbdir3)){ - Dirtab *tab = &usbdir3[s]; - q.path = path | tab->qid.path; - devdir(c, q, tab->name, tab->length, eve, tab->perm, dp); - return 1; - } - - /* active endpoints */ - d = usbdeviceofpath(path); - if(d == nil) - return -1; - s -= nelem(usbdir3); - if(s < 0 || s >= nelem(d->ep)) - return -1; - if(s == 0 || (e = d->ep[s]) == nil) /* ep0data is called "setup" */ - return 0; - sprint(buf, "ep%ddata", s); - q.path = path | (Qep0+s); - devdir(c, q, buf, 0, eve, e->mode==OREAD? 0444: e->mode==OWRITE? 0222: 0666, dp); - return 1; -} - -int -usbwalk(Chan *c, char *name) -{ - if(strcmp(name, "..") == 0){ - switch(QID(c->qid)){ - case Qtopdir: - return 1; - case Q2nd: - c->qid = (Qid){CHDIR|Qtopdir, 0}; - break; - case Q3rd: - c->qid = (Qid){CHDIR|Q2nd, 0}; - break; - default: - panic("usbwalk %lux", c->qid.path); - } - return 1; - } - return devwalk(c, name, nil, 0, usbgen); -} - -void -usbstat(Chan *c, char *db) -{ - devstat(c, db, nil, 0, usbgen); -} - -Chan * -usbopen(Chan *c, int omode) -{ - Udev *d; - int f, s; - - if(c->qid.path & CHDIR) - return devopen(c, omode, nil, 0, usbgen); - - f = 0; - if(QID(c->qid) == Qnew){ - d = usbnewdevice(); - if(d == nil) - error(Enodev); - c->qid.path = Qctl|((d->x+1)<qid.vers = d->id; - f = 1; - } - - if(c->qid.path < Q3rd) - return devopen(c, omode, nil, 0, usbgen); - - qlock(&usbstate); - if(waserror()){ - qunlock(&usbstate); - nexterror(); - } - - switch(QID(c->qid)){ - case Qctl: - d = usbdevice(c); - if(0&&d->busy) - error(Einuse); - d->busy = 1; - if(!f) - incref(d); - break; - - default: - d = usbdevice(c); - s = QID(c->qid) - Qep0; - if(s >= 0 && s < nelem(d->ep)){ - Endpt *e; - if((e = d->ep[s]) == nil) - error(Enodev); - if(schedendpt(e) < 0) - error("can't schedule USB endpoint"); - eptactivate(e); - } - incref(d); - break; - } - poperror(); - qunlock(&usbstate); - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -void -usbcreate(Chan *c, char *name, int omode, ulong perm) -{ - USED(c, name, omode, perm); - error(Eperm); -} - -void -usbremove(Chan*) -{ - error(Eperm); -} - -void -usbwstat(Chan *c, char *dp) -{ - USED(c, dp); - error(Eperm); -} - -void -usbclose(Chan *c) -{ - Udev *d; - - if(c->qid.path & CHDIR || c->qid.path < Q3rd) - return; - qlock(&usbstate); - if(waserror()){ - qunlock(&usbstate); - nexterror(); - } - d = usbdevice(c); - if(QID(c->qid) == Qctl) - d->busy = 0; - if(c->flag & COPEN) - freedev(d); - poperror(); - qunlock(&usbstate); -} - -static int -eptinput(void *arg) -{ - Endpt *e; - - e = arg; - return e->eof || e->err || qcanread(e->rq); -} - -static long -readusb(Endpt *e, void *a, long n) -{ - Block *b; - uchar *p; - long l, i; - - XPRINT("qlock(%p)\n", &e->rlock); - qlock(&e->rlock); - XPRINT("got qlock(%p)\n", &e->rlock); - if(waserror()){ - qunlock(&e->rlock); - eptcancel(e); - nexterror(); - } - p = a; - do { - if(e->eof) { - XPRINT("e->eof\n"); - break; - } - if(e->err) - error(e->err); - qrcv(e); - if(!e->iso) - e->data01 ^= 1; - sleep(&e->rr, eptinput, e); - if(e->err) - error(e->err); - b = qget(e->rq); /* TO DO */ - if(b == nil) { - XPRINT("b == nil\n"); - break; - } - if(waserror()){ - freeb(b); - nexterror(); - } - l = BLEN(b); - if((i = l) > n) - i = n; - if(i > 0){ - memmove(p, b->rp, i); - p += i; - } - poperror(); - freeb(b); - n -= i; - } while (l == e->maxpkt && n > 0); - poperror(); - qunlock(&e->rlock); - return p-(uchar*)a; -} - -long -usbread(Chan *c, void *a, long n, vlong offset) -{ - Endpt *e; - Udev *d; - char buf[48], *s; - int t, w0, w1, ps, l, i; - - if(c->qid.path & CHDIR) - return devdirread(c, a, n, nil, 0, usbgen); - - t = QID(c->qid); - switch(t){ - case Qbusctl: - snprint(buf, sizeof(buf), "%11d %11d ", 0, 0); - return readstr(offset, a, n, buf); - - case Qport: - ps = portinfo(&ubus, &w0, &w1); - snprint(buf, sizeof(buf), "0x%ux 0x%ux 0x%ux ", ps, w0, w1); - return readstr(offset, a, n, buf); - - case Qctl: - d = usbdevice(c); - sprint(buf, "%11d %11d ", d->x, d->id); - return readstr(offset, a, n, buf); - - case Qsetup: /* endpoint 0 */ - d = usbdevice(c); - if((e = d->ep[0]) == nil) - error(Eio); /* can't happen */ - e->data01 = 1; - n = readusb(e, a, n); - if(e->setin){ - e->setin = 0; - e->data01 = 1; - writeusb(e, "", 0, TokOUT); - } - break; - - case Qdebug: - n=0; - break; - - case Qstatus: - d = usbdevice(c); - s = smalloc(READSTR); - if(waserror()){ - free(s); - nexterror(); - } - l = snprint(s, READSTR, "%s %#6.6lux\n", devstates[d->state], d->csp); - for(i=0; iep); i++) - if((e = d->ep[i]) != nil) /* TO DO: freeze e */ - l += snprint(s+l, READSTR-l, "%2d %#6.6lux %10lud bytes %10lud blocks\n", i, e->csp, e->nbytes, e->nblocks); - n = readstr(offset, a, n, s); - poperror(); - free(s); - break; - - default: - d = usbdevice(c); - if((t -= Qep0) < 0 || t >= nelem(d->ep)) - error(Eio); - if((e = d->ep[t]) == nil || e->mode == OWRITE) - error(Eio); /* can't happen */ - n=readusb(e, a, n); - break; - } - return n; -} - -static int -qisempty(void *arg) -{ - return ((QH*)arg)->entries & Terminate; -} - -static long -writeusb(Endpt *e, void *a, long n, int tok) -{ - long i; - Block *b; - uchar *p; - QH *qh; - - p = a; - qlock(&e->wlock); - if(waserror()){ - qunlock(&e->wlock); - eptcancel(e); - nexterror(); - } - do { - int j; - - if(e->err) - error(e->err); - if((i = n) >= e->maxpkt) - i = e->maxpkt; - b = allocb(i); - if(waserror()){ - freeb(b); - nexterror(); - } - XPRINT("out [%ld]", i); - for (j = 0; j < i; j++) XPRINT(" %.2x", p[j]); - XPRINT("\n"); - memmove(b->wp, p, i); - b->wp += i; - p += i; - n -= i; - poperror(); - qh = qxmit(e, b, tok); - tok = TokOUT; - if(!e->iso) - e->data01 ^= 1; - if(e->ntd >= e->nbuf) { - XPRINT("writeusb: sleep %lux\n", &e->wr); - sleep(&e->wr, qisempty, qh); - XPRINT("writeusb: awake\n"); - } - } while(n > 0); - poperror(); - qunlock(&e->wlock); - return p-(uchar*)a; -} - -long -usbwrite(Chan *c, void *a, long n, vlong) -{ - Udev *d; - Endpt *e; - int id, nw, nf, t, i; - char cmd[50], *fields[10]; - - if(c->qid.path & CHDIR) - error(Egreg); - t = QID(c->qid); - if(t == Qbusctl){ - if(n >= sizeof(cmd)-1) - n = sizeof(cmd)-1; - memmove(cmd, a, n); - cmd[n] = 0; - nf = getfields(cmd, fields, nelem(fields), 0, " \t\n"); - if(nf==1 && strcmp(fields[0], "dump")==0){ - dumpframe(-1, -1); - return n; - } - if(nf < 2) - error(Ebadarg); - id = strtol(fields[1], nil, 0); - if(id != 1 && id != 2) - error(Ebadarg); /* there are two ports on the root hub */ - if(strcmp(fields[0], "reset") == 0) - portreset(id); - else if(strcmp(fields[0], "enable") == 0) - portenable(id, 1); - else if(strcmp(fields[0], "disable") == 0) - portenable(id, 0); - else - error(Ebadarg); - return n; - } - d = usbdevice(c); - t = QID(c->qid); - switch(t){ - case Qctl: - if(n >= sizeof(cmd)-1) - n = sizeof(cmd)-1; - memmove(cmd, a, n); - cmd[n] = 0; - nf = getfields(cmd, fields, nelem(fields), 0, " \t\n"); - if(nf > 1 && strcmp(fields[0], "speed") == 0){ - d->ls = strtoul(fields[1], nil, 0) == 0; - } else if(nf > 3 && strcmp(fields[0], "class") == 0){ - i = strtoul(fields[2], nil, 0); - d->npt = strtoul(fields[1], nil, 0); - /* class config# csp ( == class subclass proto) */ - if (i < 0 || i >= nelem(d->ep) - || d->npt > nelem(d->ep) || i >= d->npt) - error(Ebadarg); - if (i == 0) { - d->csp = strtoul(fields[3], nil, 0); - } - if(d->ep[i] == nil) - d->ep[i] = devendpt(d, i, 1); - d->ep[i]->csp = strtoul(fields[3], nil, 0); - }else if(nf > 2 && strcmp(fields[0], "data") == 0){ - i = strtoul(fields[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); - e = d->ep[i]; - e->data01 = strtoul(fields[2], nil, 0) != 0; - }else if(nf > 2 && strcmp(fields[0], "maxpkt") == 0){ - i = strtoul(fields[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); - e = d->ep[i]; - e->maxpkt = strtoul(fields[2], nil, 0); - if(e->maxpkt > 1500) - e->maxpkt = 1500; - }else if(nf > 2 && strcmp(fields[0], "debug") == 0){ - i = strtoul(fields[1], nil, 0); - if(i < -1 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); - if (i == -1) - debug = 0; - else { - debug = 1; - e = d->ep[i]; - e->debug = strtoul(fields[2], nil, 0); - } - }else if(nf > 1 && strcmp(fields[0], "unstall") == 0){ - i = strtoul(fields[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); - e = d->ep[i]; - e->err = nil; - }else if(nf == 6 && strcmp(fields[0], "ep") == 0){ - /* ep n maxpkt mode poll nbuf */ - i = strtoul(fields[1], nil, 0); - if(i < 0 || i >= nelem(d->ep)) { - XPRINT("field 1: 0 <= %d < %d\n", i, nelem(d->ep)); - error(Ebadarg); - } - if((e = d->ep[i]) == nil) - e = devendpt(d, i, 1); - if(waserror()){ - freept(e); - nexterror(); - } - i = strtoul(fields[2], nil, 0); - if(i < 8 || i > 1023) - i = 8; - e->maxpkt = i; - e->mode = strcmp(fields[3],"r") == 0? OREAD : - strcmp(fields[3],"w") == 0? OWRITE : ORDWR; - e->periodic = 0; - e->sched = -1; - if(strcmp(fields[4], "bulk") == 0){ - Ctlr *ub; - - ub = &ubus; - /* Each bulk device gets a queue head hanging off the - * bulk queue head - */ - if (e->epq == nil) { - e->epq = allocqh(ub); - if(e->epq == nil) - panic("usbwrite: allocqh"); - } - queueqh(e->epq); - } else { - e->periodic = 1; - i = strtoul(fields[4], nil, 0); - if(i > 0 && i <= 1000) - e->pollms = i; - else { - XPRINT("field 4: 0 <= %d <= 1000\n", i); - error(Ebadarg); - } - } - i = strtoul(fields[5], nil, 0); - if(i >= 1 && i <= 32) - e->nbuf = i; - poperror(); - }else { - XPRINT("command %s, fields %d\n", fields[0], nf); - error(Ebadarg); - } - return n; - - case Qsetup: /* SETUP endpoint 0 */ - /* should canqlock etc */ - if((e = d->ep[0]) == nil) - error(Eio); /* can't happen */ - if(n < 8 || n > 1023) - error(Eio); - nw = *(uchar*)a & RD2H; - e->data01 = 0; - n = writeusb(e, a, n, TokSETUP); - if(nw == 0){ /* host to device: use IN[DATA1] to ack */ - e->data01 = 1; - nw = readusb(e, cmd, 8); - if(nw != 0) - error(Eio); /* could provide more status */ - }else - e->setin = 1; /* two-phase */ - break; - - default: /* sends DATA[01] */ - if((t -= Qep0) < 0 || t >= nelem(d->ep)) { - print("t = %d\n", t); - error(Eio); - } - if((e = d->ep[t]) == nil || e->mode == OREAD) { - error(Eio); /* can't happen */ - } - n = writeusb(e, a, n, TokOUT); - break; - } - return n; -} - -Dev usbdevtab = { - 'U', - "usb", - - usbreset, - usbinit, - usbattach, - usbclone, - usbwalk, - usbstat, - usbopen, - devcreate, - usbclose, - usbread, - devbread, - usbwrite, - devbwrite, - devremove, - devwstat, -}; + if(!e->periodic || e->sched diff --git a/port/qio.c b/port/qio.c index d646deee404d89ca76f75738b5baf6b4581fa8b4..2fb7e78f4ba440fc59c73fdcf3115528b469f050 100644 --- a/port/qio.c +++ b/port/qio.c @@ -1220,9 +1220,10 @@ qwrite(Queue *q, void *vp, int len) QDEBUG if(!islo()) print("qwrite hi %lux\n", getcallerpc(&q)); + next = nil; b = mem2bl(vp, len); if(waserror()){ - freeblist(b); + freeblist(next); nexterror(); } for(; b != nil; b = next){