From: aaron Date: Sun, 26 Mar 2000 08:39:45 +0000 (+0000) Subject: Sync with NetBSD. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=eff3e1aa6fc1b31383da181b5125bd29955f38f4;p=openbsd Sync with NetBSD. --- diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c index d2ef61d3f70..58db47c6ba5 100644 --- a/sys/dev/usb/hid.c +++ b/sys/dev/usb/hid.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hid.c,v 1.3 1999/11/07 21:30:18 fgsch Exp $ */ -/* $NetBSD: hid.c,v 1.7 1999/01/08 11:58:25 augustss Exp $ */ +/* $OpenBSD: hid.c,v 1.4 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: hid.c,v 1.12 2000/03/17 18:16:18 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -40,11 +40,10 @@ #include #include +#if defined(__NetBSD__) || defined(__OpenBSD__) #include -#include -#if defined(__FreeBSD__) -#include #endif +#include #include #include @@ -112,7 +111,7 @@ void hid_end_parse(s) struct hid_data *s; { - while (s->cur.next) { + while (s->cur.next != NULL) { struct hid_item *hi = s->cur.next->next; free(s->cur.next, M_TEMP); s->cur.next = hi; @@ -126,7 +125,8 @@ hid_get_item(s, h) struct hid_item *h; { struct hid_item *c = &s->cur; - int bTag, bType, bSize; + unsigned int bTag, bType, bSize; + struct hid_location oldloc; u_char *data; int32_t dval; u_char *p; @@ -134,7 +134,7 @@ hid_get_item(s, h) int i; top: - if (s->multimax) { + if (s->multimax != 0) { if (s->multi < s->multimax) { c->usage = s->usages[min(s->multi, s->nu-1)]; s->multi++; @@ -300,7 +300,9 @@ hid_get_item(s, h) break; case 11: /* Pop */ hi = c->next; + oldloc = c->loc; s->cur = *hi; + c->loc = oldloc; free(hi, M_TEMP); break; default: @@ -381,11 +383,11 @@ hid_report_size(buf, len, k, idp) id = 0; for (d = hid_start_parse(buf, len, 1< #include -#include #include #if defined(__NetBSD__) || defined(__OpenBSD__) +#include #include +#include #elif defined(__FreeBSD__) #include #include #include #include +#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__) +#include +#endif #endif #include #include -#include #include #include @@ -75,6 +78,7 @@ #if defined(__FreeBSD__) #include + #define delay(d) DELAY(d) #endif @@ -111,64 +115,77 @@ void ohci_free_sed __P((ohci_softc_t *, ohci_soft_ed_t *)); ohci_soft_td_t *ohci_alloc_std __P((ohci_softc_t *)); void ohci_free_std __P((ohci_softc_t *, ohci_soft_td_t *)); +ohci_soft_itd_t *ohci_alloc_sitd __P((ohci_softc_t *)); +void ohci_free_sitd __P((ohci_softc_t *, ohci_soft_itd_t *)); + +#if 0 void ohci_free_std_chain __P((ohci_softc_t *, ohci_soft_td_t *, ohci_soft_td_t *)); +#endif usbd_status ohci_alloc_std_chain __P((struct ohci_pipe *, ohci_softc_t *, - int, int, int, usb_dma_t *, + int, int, usbd_xfer_handle, ohci_soft_td_t *, ohci_soft_td_t **)); +void ohci_shutdown __P((void *v)); void ohci_power __P((int, void *)); usbd_status ohci_open __P((usbd_pipe_handle)); void ohci_poll __P((struct usbd_bus *)); -void ohci_waitintr __P((ohci_softc_t *, usbd_request_handle)); -void ohci_rhsc __P((ohci_softc_t *, usbd_request_handle)); -void ohci_process_done __P((ohci_softc_t *, ohci_physaddr_t)); +void ohci_softintr __P((struct usbd_bus *)); +void ohci_waitintr __P((ohci_softc_t *, usbd_xfer_handle)); +void ohci_rhsc __P((ohci_softc_t *, usbd_xfer_handle)); -usbd_status ohci_device_request __P((usbd_request_handle reqh)); +usbd_status ohci_device_request __P((usbd_xfer_handle xfer)); void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); void ohci_rem_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); void ohci_hash_add_td __P((ohci_softc_t *, ohci_soft_td_t *)); void ohci_hash_rem_td __P((ohci_softc_t *, ohci_soft_td_t *)); ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *, ohci_physaddr_t)); +usbd_status ohci_setup_isoc __P((usbd_pipe_handle pipe)); +void ohci_device_isoc_enter __P((usbd_xfer_handle)); + usbd_status ohci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t)); void ohci_freem __P((struct usbd_bus *, usb_dma_t *)); -usbd_status ohci_root_ctrl_transfer __P((usbd_request_handle)); -usbd_status ohci_root_ctrl_start __P((usbd_request_handle)); -void ohci_root_ctrl_abort __P((usbd_request_handle)); +usbd_xfer_handle ohci_allocx __P((struct usbd_bus *)); +void ohci_freex __P((struct usbd_bus *, usbd_xfer_handle)); + +usbd_status ohci_root_ctrl_transfer __P((usbd_xfer_handle)); +usbd_status ohci_root_ctrl_start __P((usbd_xfer_handle)); +void ohci_root_ctrl_abort __P((usbd_xfer_handle)); void ohci_root_ctrl_close __P((usbd_pipe_handle)); +void ohci_root_ctrl_done __P((usbd_xfer_handle)); -usbd_status ohci_root_intr_transfer __P((usbd_request_handle)); -usbd_status ohci_root_intr_start __P((usbd_request_handle)); -void ohci_root_intr_abort __P((usbd_request_handle)); +usbd_status ohci_root_intr_transfer __P((usbd_xfer_handle)); +usbd_status ohci_root_intr_start __P((usbd_xfer_handle)); +void ohci_root_intr_abort __P((usbd_xfer_handle)); void ohci_root_intr_close __P((usbd_pipe_handle)); -void ohci_root_intr_done __P((usbd_request_handle)); +void ohci_root_intr_done __P((usbd_xfer_handle)); -usbd_status ohci_device_ctrl_transfer __P((usbd_request_handle)); -usbd_status ohci_device_ctrl_start __P((usbd_request_handle)); -void ohci_device_ctrl_abort __P((usbd_request_handle)); +usbd_status ohci_device_ctrl_transfer __P((usbd_xfer_handle)); +usbd_status ohci_device_ctrl_start __P((usbd_xfer_handle)); +void ohci_device_ctrl_abort __P((usbd_xfer_handle)); void ohci_device_ctrl_close __P((usbd_pipe_handle)); -void ohci_device_ctrl_done __P((usbd_request_handle)); +void ohci_device_ctrl_done __P((usbd_xfer_handle)); -usbd_status ohci_device_bulk_transfer __P((usbd_request_handle)); -usbd_status ohci_device_bulk_start __P((usbd_request_handle)); -void ohci_device_bulk_abort __P((usbd_request_handle)); +usbd_status ohci_device_bulk_transfer __P((usbd_xfer_handle)); +usbd_status ohci_device_bulk_start __P((usbd_xfer_handle)); +void ohci_device_bulk_abort __P((usbd_xfer_handle)); void ohci_device_bulk_close __P((usbd_pipe_handle)); -void ohci_device_bulk_done __P((usbd_request_handle)); +void ohci_device_bulk_done __P((usbd_xfer_handle)); -usbd_status ohci_device_intr_transfer __P((usbd_request_handle)); -usbd_status ohci_device_intr_start __P((usbd_request_handle)); -void ohci_device_intr_abort __P((usbd_request_handle)); +usbd_status ohci_device_intr_transfer __P((usbd_xfer_handle)); +usbd_status ohci_device_intr_start __P((usbd_xfer_handle)); +void ohci_device_intr_abort __P((usbd_xfer_handle)); void ohci_device_intr_close __P((usbd_pipe_handle)); -void ohci_device_intr_done __P((usbd_request_handle)); +void ohci_device_intr_done __P((usbd_xfer_handle)); -usbd_status ohci_device_isoc_transfer __P((usbd_request_handle)); -usbd_status ohci_device_isoc_start __P((usbd_request_handle)); -void ohci_device_isoc_abort __P((usbd_request_handle)); +usbd_status ohci_device_isoc_transfer __P((usbd_xfer_handle)); +usbd_status ohci_device_isoc_start __P((usbd_xfer_handle)); +void ohci_device_isoc_abort __P((usbd_xfer_handle)); void ohci_device_isoc_close __P((usbd_pipe_handle)); -void ohci_device_isoc_done __P((usbd_request_handle)); +void ohci_device_isoc_done __P((usbd_xfer_handle)); usbd_status ohci_device_setintr __P((ohci_softc_t *sc, struct ohci_pipe *pipe, int ival)); @@ -180,15 +197,14 @@ void ohci_rhsc_able __P((ohci_softc_t *, int)); void ohci_close_pipe __P((usbd_pipe_handle pipe, ohci_soft_ed_t *head)); -void ohci_abort_req __P((usbd_request_handle reqh, +void ohci_abort_xfer __P((usbd_xfer_handle xfer, usbd_status status)); -void ohci_abort_req_end __P((void *)); +void ohci_abort_xfer_end __P((void *)); void ohci_device_clear_toggle __P((usbd_pipe_handle pipe)); void ohci_noop __P((usbd_pipe_handle pipe)); #ifdef OHCI_DEBUG -ohci_softc_t *thesc; void ohci_dumpregs __P((ohci_softc_t *)); void ohci_dump_tds __P((ohci_soft_td_t *)); void ohci_dump_td __P((ohci_soft_td_t *)); @@ -209,7 +225,10 @@ static u_int8_t revbits[OHCI_NO_INTRS] = struct ohci_pipe { struct usbd_pipe pipe; ohci_soft_ed_t *sed; - ohci_soft_td_t *tail; + union { + ohci_soft_td_t *td; + ohci_soft_itd_t *itd; + } tail; /* Info needed for different pipe kinds. */ union { /* Control pipe */ @@ -231,6 +250,7 @@ struct ohci_pipe { /* Iso pipe */ struct iso { int xxxxx; + int next, inuse; } iso; } u; }; @@ -239,9 +259,12 @@ struct ohci_pipe { struct usbd_bus_methods ohci_bus_methods = { ohci_open, + ohci_softintr, ohci_poll, ohci_allocm, ohci_freem, + ohci_allocx, + ohci_freex, }; struct usbd_pipe_methods ohci_root_ctrl_methods = { @@ -250,7 +273,7 @@ struct usbd_pipe_methods ohci_root_ctrl_methods = { ohci_root_ctrl_abort, ohci_root_ctrl_close, ohci_noop, - 0, + ohci_root_ctrl_done, }; struct usbd_pipe_methods ohci_root_intr_methods = { @@ -289,7 +312,6 @@ struct usbd_pipe_methods ohci_device_bulk_methods = { ohci_device_bulk_done, }; -#if 0 struct usbd_pipe_methods ohci_device_isoc_methods = { ohci_device_isoc_transfer, ohci_device_isoc_start, @@ -298,8 +320,8 @@ struct usbd_pipe_methods ohci_device_isoc_methods = { ohci_noop, ohci_device_isoc_done, }; -#endif +#if defined(__NetBSD__) || defined(__OpenBSD__) int ohci_activate(self, act) device_ptr_t self; @@ -335,25 +357,28 @@ ohci_detach(sc, flags) return (rv); powerhook_disestablish(sc->sc_powerhook); + shutdownhook_disestablish(sc->sc_shutdownhook); + /* free data structures XXX */ return (rv); } +#endif ohci_soft_ed_t * ohci_alloc_sed(sc) ohci_softc_t *sc; { ohci_soft_ed_t *sed; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freeeds) { + if (sc->sc_freeeds == NULL) { DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n")); - r = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK, + err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK, OHCI_ED_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (0); for(i = 0; i < OHCI_SED_CHUNK; i++) { offs = i * OHCI_SED_SIZE; @@ -384,16 +409,18 @@ ohci_alloc_std(sc) ohci_softc_t *sc; { ohci_soft_td_t *std; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; + int s; - if (!sc->sc_freetds) { + if (sc->sc_freetds == NULL) { DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); - r = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, + err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, OHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (0); + s = splusb(); for(i = 0; i < OHCI_STD_CHUNK; i++) { offs = i * OHCI_STD_SIZE; std = (ohci_soft_td_t *)((char *)KERNADDR(&dma) +offs); @@ -401,11 +428,18 @@ ohci_alloc_std(sc) std->nexttd = sc->sc_freetds; sc->sc_freetds = std; } + splx(s); } + + s = splusb(); std = sc->sc_freetds; sc->sc_freetds = std->nexttd; memset(&std->td, 0, sizeof(ohci_td_t)); std->nexttd = 0; + + ohci_hash_add_td(sc, std); + splx(s); + return (std); } @@ -414,33 +448,46 @@ ohci_free_std(sc, std) ohci_softc_t *sc; ohci_soft_td_t *std; { + int s; + + s = splusb(); + ohci_hash_rem_td(sc, std); + std->nexttd = sc->sc_freetds; sc->sc_freetds = std; + splx(s); } usbd_status -ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) - struct ohci_pipe *upipe; +ohci_alloc_std_chain(opipe, sc, alen, rd, xfer, sp, ep) + struct ohci_pipe *opipe; ohci_softc_t *sc; - int len, rd, shortok; - usb_dma_t *dma; + int alen, rd; + usbd_xfer_handle xfer; ohci_soft_td_t *sp, **ep; { ohci_soft_td_t *next, *cur; ohci_physaddr_t dataphys, dataphysend; - u_int32_t intr; - int curlen; + u_int32_t tdflags; + int len, curlen; + usb_dma_t *dma = &xfer->dmabuf; + u_int16_t flags = xfer->flags; - DPRINTFN(len >= 4096,("ohci_alloc_std_chain: start len=%d\n", len)); + DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen)); + + len = alen; cur = sp; dataphys = DMAADDR(dma); dataphysend = OHCI_PAGE(dataphys + len - 1); + tdflags = LE( + (rd ? OHCI_TD_IN : OHCI_TD_OUT) | + (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) | + OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR); + for (;;) { next = ohci_alloc_std(sc); - if (next == 0) { - /* XXX free chain */ - return (USBD_NOMEM); - } + if (next == NULL) + goto nomem; /* The OHCI hardware can handle at most one page crossing. */ if (OHCI_PAGE(dataphys) == dataphysend || @@ -451,6 +498,12 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) /* must use multiple TDs, fill as much as possible. */ curlen = 2 * OHCI_PAGE_SIZE - (dataphys & (OHCI_PAGE_SIZE-1)); + /* the length must be a multiple of the max size */ + curlen -= curlen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize); +#ifdef DIAGNOSTIC + if (curlen == 0) + panic("ohci_alloc_std: curlen == 0\n"); +#endif } DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x " "dataphysend=0x%08x len=%d curlen=%d\n", @@ -458,17 +511,14 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) len, curlen)); len -= curlen; - intr = len == 0 ? OHCI_TD_SET_DI(1) : OHCI_TD_NOINTR; - cur->td.td_flags = LE( - (rd ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC | - intr | OHCI_TD_TOGGLE_CARRY | - (shortok ? OHCI_TD_R : 0)); + cur->td.td_flags = tdflags; cur->td.td_cbp = LE(dataphys); cur->nexttd = next; cur->td.td_nexttd = LE(next->physaddr); cur->td.td_be = LE(dataphys + curlen - 1); cur->len = curlen; cur->flags = OHCI_ADD_LEN; + cur->xfer = xfer; DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n", dataphys, dataphys + curlen - 1)); if (len == 0) @@ -477,12 +527,35 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) dataphys += curlen; cur = next; } - cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; - *ep = next; + if ((flags & USBD_FORCE_SHORT_XFER) && + alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) { + /* Force a 0 length transfer at the end. */ + + cur = next; + next = ohci_alloc_std(sc); + if (next == NULL) + goto nomem; + + cur->td.td_flags = tdflags; + cur->td.td_cbp = 0; /* indicate 0 length packet */ + cur->nexttd = next; + cur->td.td_nexttd = LE(next->physaddr); + cur->td.td_be = ~0; + cur->len = 0; + cur->flags = 0; + cur->xfer = xfer; + DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n")); + } + *ep = cur; return (USBD_NORMAL_COMPLETION); + +nomem: + /* XXX free chain */ + return (USBD_NOMEM); } +#if 0 void ohci_free_std_chain(sc, std, stdend) ohci_softc_t *sc; @@ -496,84 +569,131 @@ ohci_free_std_chain(sc, std, stdend) ohci_free_std(sc, std); } } +#endif + +ohci_soft_itd_t * +ohci_alloc_sitd(sc) + ohci_softc_t *sc; +{ + ohci_soft_itd_t *sitd; + usbd_status err; + int i, offs; + usb_dma_t dma; + + if (sc->sc_freeitds == NULL) { + DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n")); + err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, + OHCI_TD_ALIGN, &dma); + if (err) + return (0); + for (i = 0; i < OHCI_STD_CHUNK; i++) { + offs = i * OHCI_STD_SIZE; + sitd = (ohci_soft_itd_t *)((char*)KERNADDR(&dma)+offs); + sitd->physaddr = DMAADDR(&dma) + offs; + sitd->nextitd = sc->sc_freeitds; + sc->sc_freeitds = sitd; + } + } + sitd = sc->sc_freeitds; + sc->sc_freeitds = sitd->nextitd; + memset(&sitd->itd, 0, sizeof(ohci_itd_t)); + sitd->nextitd = 0; + return (sitd); +} + +void +ohci_free_sitd(sc, sitd) + ohci_softc_t *sc; + ohci_soft_itd_t *sitd; +{ + sitd->nextitd = sc->sc_freeitds; + sc->sc_freeitds = sitd; +} usbd_status ohci_init(sc) ohci_softc_t *sc; { ohci_soft_ed_t *sed, *psed; - usbd_status r; - int rev; + usbd_status err; int i; - u_int32_t s, ctl, ival, hcr, fm, per; + u_int32_t s, ctl, ival, hcr, fm, per, rev, desca; DPRINTF(("ohci_init: start\n")); - rev = OREAD4(sc, OHCI_REVISION); #if defined(__OpenBSD__) - printf(" version %d.%d%s", + printf(","); #else - printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev), + printf("%s:", USBDEVNAME(sc->sc_bus.bdev)); #endif - OHCI_REV_HI(rev), OHCI_REV_LO(rev), + rev = OREAD4(sc, OHCI_REVISION); + printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev), OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { -#if defined(__OpenBSD__) - printf(": unsupported\n"); -#else printf("%s: unsupported OHCI revision\n", USBDEVNAME(sc->sc_bus.bdev)); -#endif + sc->sc_bus.usbrev = USBREV_UNKNOWN; return (USBD_INVAL); -#if defined(__OpenBSD__) - } else { - printf("\n"); -#endif } + sc->sc_bus.usbrev = USBREV_1_0; for (i = 0; i < OHCI_HASH_SIZE; i++) LIST_INIT(&sc->sc_hash_tds[i]); + SIMPLEQ_INIT(&sc->sc_free_xfers); + + /* XXX determine alignment by R/W */ /* Allocate the HCCA area. */ - r = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, + err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, OHCI_HCCA_ALIGN, &sc->sc_hccadma); - if (r != USBD_NORMAL_COMPLETION) - return (r); + if (err) + return (err); sc->sc_hcca = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma); memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE); sc->sc_eintrs = OHCI_NORMAL_INTRS; + /* Allocate dummy ED that starts the control list. */ sc->sc_ctrl_head = ohci_alloc_sed(sc); - if (!sc->sc_ctrl_head) { - r = USBD_NOMEM; + if (sc->sc_ctrl_head == NULL) { + err = USBD_NOMEM; goto bad1; } sc->sc_ctrl_head->ed.ed_flags |= LE(OHCI_ED_SKIP); + /* Allocate dummy ED that starts the bulk list. */ sc->sc_bulk_head = ohci_alloc_sed(sc); - if (!sc->sc_bulk_head) { - r = USBD_NOMEM; + if (sc->sc_bulk_head == NULL) { + err = USBD_NOMEM; goto bad2; } sc->sc_bulk_head->ed.ed_flags |= LE(OHCI_ED_SKIP); + /* Allocate dummy ED that starts the isochronous list. */ + sc->sc_isoc_head = ohci_alloc_sed(sc); + if (sc->sc_isoc_head == NULL) { + err = USBD_NOMEM; + goto bad3; + } + sc->sc_isoc_head->ed.ed_flags |= LE(OHCI_ED_SKIP); + /* Allocate all the dummy EDs that make up the interrupt tree. */ for (i = 0; i < OHCI_NO_EDS; i++) { sed = ohci_alloc_sed(sc); - if (!sed) { + if (sed == NULL) { while (--i >= 0) ohci_free_sed(sc, sc->sc_eds[i]); - r = USBD_NOMEM; - goto bad3; + err = USBD_NOMEM; + goto bad4; } /* All ED fields are set to 0. */ sc->sc_eds[i] = sed; sed->ed.ed_flags |= LE(OHCI_ED_SKIP); - if (i != 0) { + if (i != 0) psed = sc->sc_eds[(i-1) / 2]; - sed->next = psed; - sed->ed.ed_nexted = LE(psed->physaddr); - } + else + psed = sc->sc_isoc_head; + sed->next = psed; + sed->ed.ed_nexted = LE(psed->physaddr); } /* * Fill HCCA interrupt table. The bit reversal is to get @@ -583,6 +703,17 @@ ohci_init(sc) sc->sc_hcca->hcca_interrupt_table[revbits[i]] = LE(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr); +#ifdef OHCI_DEBUG + if (ohcidebug > 15) { + for (i = 0; i < OHCI_NO_EDS; i++) { + printf("ed#%d ", i); + ohci_dump_ed(sc->sc_eds[i]); + } + printf("iso "); + ohci_dump_ed(sc->sc_isoc_head); + } +#endif + /* Determine in what context we are running. */ ctl = OREAD4(sc, OHCI_CONTROL); if (ctl & OHCI_IR) { @@ -591,7 +722,7 @@ ohci_init(sc) s = OREAD4(sc, OHCI_COMMAND_STATUS); OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR); for (i = 0; i < 100 && (ctl & OHCI_IR); i++) { - delay(1000); + usb_delay_ms(&sc->sc_bus, 1); ctl = OREAD4(sc, OHCI_CONTROL); } if ((ctl & OHCI_IR) == 0) { @@ -605,13 +736,13 @@ ohci_init(sc) DPRINTF(("ohci_init: BIOS active\n")); if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) { OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL); - delay(USB_RESUME_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); } } else { DPRINTF(("ohci_init: cold started\n")); reset: /* Controller was cold started. */ - delay(USB_BUS_RESET_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); } /* @@ -620,7 +751,7 @@ ohci_init(sc) */ DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev))); OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - delay(USB_BUS_RESET_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); /* We now own the host controller and the bus has been reset. */ ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL)); @@ -635,23 +766,24 @@ ohci_init(sc) } if (hcr) { printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - r = USBD_IOERROR; - goto bad3; + err = USBD_IOERROR; + goto bad5; } #ifdef OHCI_DEBUG - thesc = sc; if (ohcidebug > 15) ohci_dumpregs(sc); #endif - /* The controller is now in suspend state, we have 2ms to finish. */ + /* The controller is now in SUSPEND state, we have 2ms to finish. */ /* Set up HC registers. */ OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma)); OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); + /* disable all interrupts and then switch on all desired interrupts */ OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE); + /* switch on desired functional features */ ctl = OREAD4(sc, OHCI_CONTROL); ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR); ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE | @@ -670,7 +802,12 @@ ohci_init(sc) per = OHCI_PERIODIC(ival); /* 90% periodic */ OWRITE4(sc, OHCI_PERIODIC_START, per); - OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */ + /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */ + desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); + OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP); + OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */ + usb_delay_ms(&sc->sc_bus, 5); + OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca); sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A)); @@ -684,16 +821,22 @@ ohci_init(sc) sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); sc->sc_powerhook = powerhook_establish(ohci_power, sc); + sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc); return (USBD_NORMAL_COMPLETION); + bad5: + for (i = 0; i < OHCI_NO_EDS; i++) + ohci_free_sed(sc, sc->sc_eds[i]); + bad4: + ohci_free_sed(sc, sc->sc_isoc_head); bad3: ohci_free_sed(sc, sc->sc_ctrl_head); bad2: ohci_free_sed(sc, sc->sc_bulk_head); bad1: usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - return (r); + return (err); } usbd_status @@ -721,7 +864,49 @@ ohci_freem(bus, dma) usb_freemem(&sc->sc_bus, dma); } -#if defined(__NetBSD__) || defined(__OpenBSD__) +usbd_xfer_handle +ohci_allocx(bus) + struct usbd_bus *bus; +{ + struct ohci_softc *sc = (struct ohci_softc *)bus; + usbd_xfer_handle xfer; + + xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); + if (xfer != NULL) + SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next); + else + xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT); + if (xfer != NULL) + memset(xfer, 0, sizeof *xfer); + return (xfer); +} + +void ohci_freex(bus, xfer) + struct usbd_bus *bus; + usbd_xfer_handle xfer; +{ + struct ohci_softc *sc = (struct ohci_softc *)bus; + + SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); +} + +void +ohci_shutdown(v) + void *v; +{ + ohci_softc_t *sc = v; + + DPRINTF(("ohci_shutdown: stopping the HC\n")); + OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); +} + +/* + * Handle suspend/resume. + * + * We need to switch to polling mode here, because this routine is + * called from an interrupt context. This is all right since we + * are almost suspended anyway. + */ void ohci_power(why, v) int why; @@ -735,12 +920,8 @@ ohci_power(why, v) ohci_dumpregs(sc); #endif } -#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ #ifdef OHCI_DEBUG -void ohcidump(void); -void ohcidump(void) { ohci_dumpregs(thesc); } - void ohci_dumpregs(sc) ohci_softc_t *sc; @@ -782,11 +963,29 @@ ohci_dumpregs(sc) } #endif +int ohci_intr1 __P((ohci_softc_t *)); + int ohci_intr(p) void *p; { ohci_softc_t *sc = p; + + /* If we get an interrupt while polling, then just ignore it. */ + if (sc->sc_bus.use_polling) { +#ifdef DIAGNOSTIC + printf("ohci_intr: ignored interrupt while polling\n"); +#endif + return (0); + } + + return (ohci_intr1(sc)); +} + +int +ohci_intr1(sc) + ohci_softc_t *sc; +{ u_int32_t intrs, eintrs; ohci_physaddr_t done; @@ -808,8 +1007,10 @@ ohci_intr(p) intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS); } else intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); + if (!intrs) return (0); + intrs &= ~OHCI_MIE; OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */ eintrs = intrs & sc->sc_eintrs; @@ -818,7 +1019,7 @@ ohci_intr(p) sc->sc_bus.intr_context++; sc->sc_bus.no_intrs++; - DPRINTFN(7, ("ohci_intr: sc=%p intrs=%x(%x) eintr=%x\n", + DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintr=0x%x\n", sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), (u_int)eintrs)); @@ -828,7 +1029,21 @@ ohci_intr(p) intrs &= ~OHCI_SO; } if (eintrs & OHCI_WDH) { - ohci_process_done(sc, done &~ OHCI_DONE_INTRS); + done &= ~OHCI_DONE_INTRS; + if (sc->sc_done == 0) + sc->sc_done = done; + else { + /* Tack on at end of the sc_dne. */ + ohci_physaddr_t ldone; + ohci_soft_td_t *std; + + for (ldone = sc->sc_done; ldone != 0; + ldone = LE(std->td.td_nexttd)) + std = ohci_hash_find_td(sc, ldone); + std->td.td_nexttd = LE(done); + } + sc->sc_hcca->hcca_done_head = 0; + usb_schedsoftintr(&sc->sc_bus); intrs &= ~OHCI_WDH; } if (eintrs & OHCI_RD) { @@ -842,7 +1057,7 @@ ohci_intr(p) /* XXX what else */ } if (eintrs & OHCI_RHSC) { - ohci_rhsc(sc, sc->sc_intrreqh); + ohci_rhsc(sc, sc->sc_intrxfer); intrs &= ~OHCI_RHSC; /* @@ -890,23 +1105,34 @@ char *ohci_cc_strs[] = { "DATA_UNDERRUN", "BUFFER_OVERRUN", "BUFFER_UNDERRUN", + "reserved", + "reserved", + "NOT ACCESSED", "NOT_ACCESSED", }; #endif void -ohci_process_done(sc, done) - ohci_softc_t *sc; - ohci_physaddr_t done; +ohci_softintr(bus) + struct usbd_bus *bus; { + ohci_softc_t *sc = (ohci_softc_t *)bus; + ohci_physaddr_t done; ohci_soft_td_t *std, *sdone, *stdnext; - usbd_request_handle reqh; - int len, cc; + usbd_xfer_handle xfer; + int len, cc, s; + + sc->sc_bus.intr_context++; + + s = splhardusb(); + done = sc->sc_done; + sc->sc_done = 0; + splx(s); DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done)); /* Reverse the done list. */ - for (sdone = 0; done; done = LE(std->td.td_nexttd)) { + for (sdone = NULL; done != 0; done = LE(std->td.td_nexttd)) { std = ohci_hash_find_td(sc, done); std->dnext = sdone; sdone = std; @@ -920,29 +1146,30 @@ ohci_process_done(sc, done) #endif for (std = sdone; std; std = stdnext) { - reqh = std->reqh; + xfer = std->xfer; stdnext = std->dnext; - DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n", - std, reqh, reqh->hcpriv)); + DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n", + std, xfer, xfer ? xfer->hcpriv : 0)); cc = OHCI_TD_GET_CC(LE(std->td.td_flags)); - usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); - if (reqh->status == USBD_CANCELLED || - reqh->status == USBD_TIMEOUT) { + usb_untimeout(ohci_timeout, xfer, xfer->timo_handle); + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) { DPRINTF(("ohci_process_done: cancel/timeout %p\n", - reqh)); + xfer)); /* Handled by abort routine. */ } else if (cc == OHCI_CC_NO_ERROR) { len = std->len; if (std->td.td_cbp != 0) len -= LE(std->td.td_be) - LE(std->td.td_cbp) + 1; + DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", + len, std->flags)); if (std->flags & OHCI_ADD_LEN) - reqh->actlen += len; + xfer->actlen += len; if (std->flags & OHCI_CALL_DONE) { - reqh->status = USBD_NORMAL_COMPLETION; - usb_transfer_complete(reqh); + xfer->status = USBD_NORMAL_COMPLETION; + usb_transfer_complete(xfer); } - ohci_hash_rem_td(sc, std); ohci_free_std(sc, std); } else { /* @@ -952,16 +1179,15 @@ ohci_process_done(sc, done) */ ohci_soft_td_t *p, *n; struct ohci_pipe *opipe = - (struct ohci_pipe *)reqh->pipe; + (struct ohci_pipe *)xfer->pipe; - DPRINTFN(-1,("ohci_process_done: error cc=%d (%s)\n", + DPRINTF(("ohci_process_done: error cc=%d (%s)\n", OHCI_TD_GET_CC(LE(std->td.td_flags)), ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))])); /* remove TDs */ - for (p = std; p->reqh == reqh; p = n) { + for (p = std; p->xfer == xfer; p = n) { n = p->nexttd; - ohci_hash_rem_td(sc, p); ohci_free_std(sc, p); } @@ -970,87 +1196,87 @@ ohci_process_done(sc, done) OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); if (cc == OHCI_CC_STALL) - reqh->status = USBD_STALLED; + xfer->status = USBD_STALLED; else - reqh->status = USBD_IOERROR; - usb_transfer_complete(reqh); + xfer->status = USBD_IOERROR; + usb_transfer_complete(xfer); } } + + sc->sc_bus.intr_context--; } void -ohci_device_ctrl_done(reqh) - usbd_request_handle reqh; +ohci_device_ctrl_done(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh)); + DPRINTFN(10,("ohci_ctrl_done: xfer=%p\n", xfer)); #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) { + if (!(xfer->rqflags & URQ_REQUEST)) { panic("ohci_ctrl_done: not a request\n"); } #endif - reqh->hcpriv = 0; + xfer->hcpriv = NULL; } void -ohci_device_intr_done(reqh) - usbd_request_handle reqh; +ohci_device_intr_done(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; ohci_soft_ed_t *sed = opipe->sed; ohci_soft_td_t *data, *tail; + DPRINTFN(10,("ohci_intr_done: xfer=%p, actlen=%d\n", + xfer, xfer->actlen)); - DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n", - reqh, reqh->actlen)); + xfer->hcpriv = NULL; - reqh->hcpriv = 0; - - if (reqh->pipe->repeat) { - data = opipe->tail; + if (xfer->pipe->repeat) { + data = opipe->tail.td; tail = ohci_alloc_std(sc); /* XXX should reuse TD */ - if (!tail) { - reqh->status = USBD_NOMEM; + if (tail == NULL) { + xfer->status = USBD_NOMEM; return; } - tail->reqh = 0; + tail->xfer = NULL; data->td.td_flags = LE( OHCI_TD_IN | OHCI_TD_NOCC | OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY); - if (reqh->flags & USBD_SHORT_XFER_OK) + if (xfer->flags & USBD_SHORT_XFER_OK) data->td.td_flags |= LE(OHCI_TD_R); - data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf)); + data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf)); data->nexttd = tail; data->td.td_nexttd = LE(tail->physaddr); - data->td.td_be = LE(LE(data->td.td_cbp) + reqh->length - 1); - data->len = reqh->length; - data->reqh = reqh; + data->td.td_be = LE(LE(data->td.td_cbp) + xfer->length - 1); + data->len = xfer->length; + data->xfer = xfer; data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; - reqh->hcpriv = data; - reqh->actlen = 0; + xfer->hcpriv = data; + xfer->actlen = 0; - ohci_hash_add_td(sc, data); sed->ed.ed_tailp = LE(tail->physaddr); - opipe->tail = tail; + opipe->tail.td = tail; } } void -ohci_device_bulk_done(reqh) - usbd_request_handle reqh; +ohci_device_bulk_done(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n", - reqh, reqh->actlen)); + DPRINTFN(10,("ohci_bulk_done: xfer=%p, actlen=%d\n", + xfer, xfer->actlen)); - reqh->hcpriv = 0; + xfer->hcpriv = 0; } void -ohci_rhsc(sc, reqh) +ohci_rhsc(sc, xfer) ohci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { usbd_pipe_handle pipe; struct ohci_pipe *opipe; @@ -1059,36 +1285,43 @@ ohci_rhsc(sc, reqh) int hstatus; hstatus = OREAD4(sc, OHCI_RH_STATUS); - DPRINTF(("ohci_rhsc: sc=%p reqh=%p hstatus=0x%08x\n", - sc, reqh, hstatus)); + DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", + sc, xfer, hstatus)); - if (reqh == 0) { + if (xfer == 0) { /* Just ignore the change. */ return; } - pipe = reqh->pipe; + pipe = xfer->pipe; opipe = (struct ohci_pipe *)pipe; - p = KERNADDR(&reqh->dmabuf); - m = min(sc->sc_noport, reqh->length * 8 - 1); - memset(p, 0, reqh->length); + p = KERNADDR(&xfer->dmabuf); + m = min(sc->sc_noport, xfer->length * 8 - 1); + memset(p, 0, xfer->length); for (i = 1; i <= m; i++) { if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16) p[i/8] |= 1 << (i%8); } DPRINTF(("ohci_rhsc: change=0x%02x\n", *p)); - reqh->actlen = reqh->length; - reqh->status = USBD_NORMAL_COMPLETION; + xfer->actlen = xfer->length; + xfer->status = USBD_NORMAL_COMPLETION; + + usb_transfer_complete(xfer); +} - usb_transfer_complete(reqh); +void +ohci_root_intr_done(xfer) + usbd_xfer_handle xfer; +{ + xfer->hcpriv = NULL; } void -ohci_root_intr_done(reqh) - usbd_request_handle reqh; +ohci_root_ctrl_done(xfer) + usbd_xfer_handle xfer; { - reqh->hcpriv = 0; + xfer->hcpriv = NULL; } /* @@ -1097,15 +1330,15 @@ ohci_root_intr_done(reqh) * too long. */ void -ohci_waitintr(sc, reqh) +ohci_waitintr(sc, xfer) ohci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { - int timo = reqh->timeout; + int timo = xfer->timeout; int usecs; u_int32_t intrs; - reqh->status = USBD_IN_PROGRESS; + xfer->status = USBD_IN_PROGRESS; for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { usb_delay_ms(&sc->sc_bus, 1); intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs; @@ -1115,16 +1348,16 @@ ohci_waitintr(sc, reqh) ohci_dumpregs(sc); #endif if (intrs) { - ohci_intr(sc); - if (reqh->status != USBD_IN_PROGRESS) + ohci_intr1(sc); + if (xfer->status != USBD_IN_PROGRESS) return; } } /* Timeout */ DPRINTF(("ohci_waitintr: timeout\n")); - reqh->status = USBD_TIMEOUT; - usb_transfer_complete(reqh); + xfer->status = USBD_TIMEOUT; + usb_transfer_complete(xfer); /* XXX should free TD */ } @@ -1135,23 +1368,23 @@ ohci_poll(bus) ohci_softc_t *sc = (ohci_softc_t *)bus; if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs) - ohci_intr(sc); + ohci_intr1(sc); } usbd_status -ohci_device_request(reqh) - usbd_request_handle reqh; +ohci_device_request(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; - usb_device_request_t *req = &reqh->request; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; + usb_device_request_t *req = &xfer->request; usbd_device_handle dev = opipe->pipe.device; ohci_softc_t *sc = (ohci_softc_t *)dev->bus; int addr = dev->address; - ohci_soft_td_t *setup, *data = 0, *stat, *next, *tail; + ohci_soft_td_t *setup, *stat, *next, *tail; ohci_soft_ed_t *sed; int isread; int len; - usbd_status r; + usbd_status err; int s; isread = req->bmRequestType & UT_READ; @@ -1163,54 +1396,44 @@ ohci_device_request(reqh) UGETW(req->wIndex), len, addr, opipe->pipe.endpoint->edesc->bEndpointAddress)); - setup = opipe->tail; + setup = opipe->tail.td; stat = ohci_alloc_std(sc); - if (!stat) { - r = USBD_NOMEM; + if (stat == NULL) { + err = USBD_NOMEM; goto bad1; } tail = ohci_alloc_std(sc); - if (!tail) { - r = USBD_NOMEM; + if (tail == NULL) { + err = USBD_NOMEM; goto bad2; } - tail->reqh = 0; + tail->xfer = NULL; sed = opipe->sed; opipe->u.ctl.length = len; /* Update device address and length since they may have changed. */ /* XXX This only needs to be done once, but it's too early in open. */ + /* XXXX Should not touch ED here! */ sed->ed.ed_flags = LE( (LE(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) | OHCI_ED_SET_FA(addr) | OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize))); + next = stat; + /* Set up data transaction */ if (len != 0) { - data = ohci_alloc_std(sc); - if (!data) { - r = USBD_NOMEM; + ohci_soft_td_t *std = stat; + + err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, + std, &stat); + stat = stat->nexttd; /* point at free TD */ + if (err) goto bad3; - } - data->td.td_flags = LE( - (isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC | - OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR | - (reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0)); - data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf)); - data->nexttd = stat; - data->td.td_nexttd = LE(stat->physaddr); - data->td.td_be = LE(LE(data->td.td_cbp) + len - 1); - data->len = len; - data->reqh = reqh; - data->flags = OHCI_ADD_LEN; - - next = data; - stat->flags = OHCI_CALL_DONE; - } else { - next = stat; - /* XXX ADD_LEN? */ - stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; + /* Start toggle at 1 and then use the carried toggle. */ + std->td.td_flags &= LE(~OHCI_TD_TOGGLE_MASK); + std->td.td_flags |= LE(OHCI_TD_TOGGLE_1); } memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req); @@ -1221,20 +1444,21 @@ ohci_device_request(reqh) setup->nexttd = next; setup->td.td_nexttd = LE(next->physaddr); setup->td.td_be = LE(LE(setup->td.td_cbp) + sizeof *req - 1); - setup->len = 0; /* XXX The number of byte we count */ - setup->reqh = reqh; + setup->len = 0; + setup->xfer = xfer; setup->flags = 0; - reqh->hcpriv = setup; + xfer->hcpriv = setup; stat->td.td_flags = LE( - (isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC | - OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1)); + (isread ? OHCI_TD_OUT : OHCI_TD_IN) | + OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1)); stat->td.td_cbp = 0; stat->nexttd = tail; stat->td.td_nexttd = LE(tail->physaddr); stat->td.td_be = 0; + stat->flags = OHCI_CALL_DONE; stat->len = 0; - stat->reqh = reqh; + stat->xfer = xfer; #ifdef OHCI_DEBUG if (ohcidebug > 5) { @@ -1246,22 +1470,18 @@ ohci_device_request(reqh) /* Insert ED in schedule */ s = splusb(); - ohci_hash_add_td(sc, setup); - if (len != 0) - ohci_hash_add_td(sc, data); - ohci_hash_add_td(sc, stat); sed->ed.ed_tailp = LE(tail->physaddr); - opipe->tail = tail; + opipe->tail.td = tail; OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(ohci_timeout, reqh, - MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, xfer, + MS_TO_TICKS(xfer->timeout), xfer->timo_handle); } splx(s); -#ifdef OHCI_DEBUG - if (ohcidebug > 5) { - delay(5000); +#if 0 + if (ohcidebug > 10) { + delay(10000); DPRINTF(("ohci_device_request: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); ohci_dump_ed(sed); @@ -1276,7 +1496,7 @@ ohci_device_request(reqh) bad2: ohci_free_std(sc, stat); bad1: - return (r); + return (err); } /* @@ -1307,9 +1527,9 @@ ohci_rem_ed(sed, head) SPLUSBCHECK; /* XXX */ - for (p = head; p && p->next != sed; p = p->next) + for (p = head; p != NULL && p->next != sed; p = p->next) ; - if (!p) + if (p == NULL) panic("ohci_rem_ed: ED not found\n"); p->next = sed->next; p->ed.ed_nexted = sed->ed.ed_nexted; @@ -1359,7 +1579,7 @@ ohci_hash_find_td(sc, a) ohci_soft_td_t *std; for (std = LIST_FIRST(&sc->sc_hash_tds[h]); - std != 0; + std != NULL; std = LIST_NEXT(std, hnext)) if (std->physaddr == a) return (std); @@ -1370,15 +1590,15 @@ void ohci_timeout(addr) void *addr; { - usbd_request_handle reqh = addr; + usbd_xfer_handle xfer = addr; int s; - DPRINTF(("ohci_timeout: reqh=%p\n", reqh)); + DPRINTF(("ohci_timeout: xfer=%p\n", xfer)); s = splusb(); - reqh->device->bus->intr_context++; - ohci_abort_req(reqh, USBD_TIMEOUT); - reqh->device->bus->intr_context--; + xfer->device->bus->intr_context++; + ohci_abort_xfer(xfer, USBD_TIMEOUT); + xfer->device->bus->intr_context--; splx(s); } @@ -1411,8 +1631,8 @@ void ohci_dump_ed(sed) ohci_soft_ed_t *sed; { - DPRINTF(("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx " - "headp=%b nexted=0x%08lx\n", + DPRINTF(("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx " + "headsflags=%b headp=%b nexted=0x%08lx\n", sed, (u_long)sed->physaddr, OHCI_ED_GET_FA(LE(sed->ed.ed_flags)), OHCI_ED_GET_EN(LE(sed->ed.ed_flags)), @@ -1422,6 +1642,7 @@ ohci_dump_ed(sed) (u_long)LE(sed->ed.ed_tailp), (u_long)LE(sed->ed.ed_headp), "\20\1HALT\2CARRY", + (u_long)LE(sed->ed.ed_headp), (u_long)LE(sed->ed.ed_nexted))); } #endif @@ -1435,10 +1656,15 @@ ohci_open(pipe) usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; u_int8_t addr = dev->address; + u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; ohci_soft_ed_t *sed; ohci_soft_td_t *std; - usbd_status r; + ohci_soft_itd_t *sitd; + ohci_physaddr_t tdphys; + u_int32_t fmt; + usbd_status err; int s; + int ival; DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", pipe, addr, ed->bEndpointAddress, sc->sc_addr)); @@ -1455,30 +1681,43 @@ ohci_open(pipe) } } else { sed = ohci_alloc_sed(sc); - if (sed == 0) + if (sed == NULL) goto bad0; - std = ohci_alloc_std(sc); - if (std == 0) - goto bad1; opipe->sed = sed; - opipe->tail = std; + if (xfertype == UE_ISOCHRONOUS) { + sitd = ohci_alloc_sitd(sc); + if (sitd == NULL) { + ohci_free_sitd(sc, sitd); + goto bad1; + } + opipe->tail.itd = sitd; + tdphys = LE(sitd->physaddr); + fmt = OHCI_ED_FORMAT_ISO; + } else { + std = ohci_alloc_std(sc); + if (std == NULL) { + ohci_free_std(sc, std); + goto bad1; + } + opipe->tail.td = std; + tdphys = LE(std->physaddr); + fmt = OHCI_ED_FORMAT_GEN; + } sed->ed.ed_flags = LE( OHCI_ED_SET_FA(addr) | OHCI_ED_SET_EN(ed->bEndpointAddress) | OHCI_ED_DIR_TD | - (dev->lowspeed ? OHCI_ED_SPEED : 0) | - ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ? - OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) | + (dev->lowspeed ? OHCI_ED_SPEED : 0) | fmt | OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); - sed->ed.ed_headp = sed->ed.ed_tailp = LE(std->physaddr); + sed->ed.ed_headp = sed->ed.ed_tailp = tdphys; - switch (ed->bmAttributes & UE_XFERTYPE) { + switch (xfertype) { case UE_CONTROL: pipe->methods = &ohci_device_ctrl_methods; - r = usb_allocmem(&sc->sc_bus, + err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), 0, &opipe->u.ctl.reqdma); - if (r != USBD_NORMAL_COMPLETION) + if (err) goto bad; s = splusb(); ohci_add_ed(sed, sc->sc_ctrl_head); @@ -1486,10 +1725,13 @@ ohci_open(pipe) break; case UE_INTERRUPT: pipe->methods = &ohci_device_intr_methods; - return (ohci_device_setintr(sc, opipe, ed->bInterval)); + ival = pipe->interval; + if (ival == USBD_DEFAULT_INTERVAL) + ival = ed->bInterval; + return (ohci_device_setintr(sc, opipe, ival)); case UE_ISOCHRONOUS: - printf("ohci_open: open iso unimplemented\n"); - return (USBD_INVAL); + pipe->methods = &ohci_device_isoc_methods; + return (ohci_setup_isoc(pipe)); case UE_BULK: pipe->methods = &ohci_device_bulk_methods; s = splusb(); @@ -1526,12 +1768,12 @@ ohci_close_pipe(pipe, head) s = splusb(); #ifdef DIAGNOSTIC sed->ed.ed_flags |= LE(OHCI_ED_SKIP); - if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != - (sed->ed.ed_headp & LE(OHCI_TAILMASK))) { + if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) != + (sed->ed.ed_headp & LE(OHCI_HEADMASK))) { ohci_physaddr_t td = sed->ed.ed_headp; ohci_soft_td_t *std; for (std = LIST_FIRST(&sc->sc_hash_tds[HASH(td)]); - std != 0; + std != NULL; std = LIST_NEXT(std, hnext)) if (std->physaddr == td) break; @@ -1540,14 +1782,13 @@ ohci_close_pipe(pipe, head) (int)LE(sed->ed.ed_headp), (int)LE(sed->ed.ed_tailp), pipe, std); usb_delay_ms(&sc->sc_bus, 2); - if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != - (sed->ed.ed_headp & LE(OHCI_TAILMASK))) + if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) != + (sed->ed.ed_headp & LE(OHCI_HEADMASK))) printf("ohci_close_pipe: pipe still not empty\n"); } #endif ohci_rem_ed(sed, head); splx(s); - ohci_free_std(sc, opipe->tail); ohci_free_sed(sc, opipe->sed); } @@ -1562,38 +1803,47 @@ ohci_close_pipe(pipe, head) * interrupt processing to process it. */ void -ohci_abort_req(reqh, status) - usbd_request_handle reqh; +ohci_abort_xfer(xfer, status) + usbd_xfer_handle xfer; usbd_status status; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_soft_ed_t *sed; - DPRINTF(("ohci_abort_req: reqh=%p pipe=%p\n", reqh, opipe)); + DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p\n", xfer, opipe)); - reqh->status = status; + xfer->status = status; - usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); + usb_untimeout(ohci_timeout, xfer, xfer->timo_handle); sed = opipe->sed; - DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed)); + DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed)); sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */ - if (reqh->device->bus->intr_context) { +#if 1 + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(ohci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND); } else { +#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif usb_delay_ms(opipe->pipe.device->bus, 1); - ohci_abort_req_end(reqh); + ohci_abort_xfer_end(xfer); } +#else + delay(1000); + ohci_abort_xfer_end(xfer); +#endif } void -ohci_abort_req_end(v) +ohci_abort_xfer_end(v) void *v; { - usbd_request_handle reqh = v; - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + usbd_xfer_handle xfer = v; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; ohci_soft_ed_t *sed; ohci_soft_td_t *p, *n; @@ -1601,26 +1851,25 @@ ohci_abort_req_end(v) s = splusb(); - p = reqh->hcpriv; + p = xfer->hcpriv; #ifdef DIAGNOSTIC - if (!p) { - printf("ohci_abort_req: hcpriv==0\n"); + if (p == NULL) { + printf("ohci_abort_xfer: hcpriv==0\n"); return; } #endif - for (; p->reqh == reqh; p = n) { + for (; p->xfer == xfer; p = n) { n = p->nexttd; - ohci_hash_rem_td(sc, p); ohci_free_std(sc, p); } sed = opipe->sed; - DPRINTFN(2,("ohci_abort_req: set hd=%x, tl=%x\n", + DPRINTFN(2,("ohci_abort_xfer: set hd=%x, tl=%x\n", (int)LE(p->physaddr), (int)LE(sed->ed.ed_tailp))); sed->ed.ed_headp = p->physaddr; /* unlink TDs */ sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); /* remove hardware skip */ - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); } @@ -1632,8 +1881,8 @@ usb_device_descriptor_t ohci_devd = { USB_DEVICE_DESCRIPTOR_SIZE, UDESC_DEVICE, /* type */ {0x00, 0x01}, /* USB version */ - UCLASS_HUB, /* class */ - USUBCLASS_HUB, /* subclass */ + UDCLASS_HUB, /* class */ + UDSUBCLASS_HUB, /* subclass */ 0, /* protocol */ 64, /* max packet */ {0},{0},{0x00,0x01}, /* device id */ @@ -1660,8 +1909,8 @@ usb_interface_descriptor_t ohci_ifcd = { 0, 0, 1, - UCLASS_HUB, - USUBCLASS_HUB, + UICLASS_HUB, + UISUBCLASS_HUB, 0, 0 }; @@ -1709,40 +1958,40 @@ ohci_str(p, l, s) * Simulate a hardware hub by handling all the necessary requests. */ usbd_status -ohci_root_ctrl_transfer(reqh) - usbd_request_handle reqh; +ohci_root_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); /* Pipe isn't running, start first */ - return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -ohci_root_ctrl_start(reqh) - usbd_request_handle reqh; +ohci_root_ctrl_start(xfer) + usbd_xfer_handle xfer; { - ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus; + ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; usb_device_request_t *req; void *buf = NULL; int port, i; int s, len, value, index, l, totlen = 0; usb_port_status_t ps; usb_hub_descriptor_t hubd; - usbd_status r; + usbd_status err; u_int32_t v; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) /* XXX panic */ return (USBD_INVAL); #endif - req = &reqh->request; + req = &xfer->request; DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); @@ -1752,7 +2001,7 @@ ohci_root_ctrl_start(reqh) index = UGETW(req->wIndex); if (len != 0) - buf = KERNADDR(&reqh->dmabuf); + buf = KERNADDR(&xfer->dmabuf); #define C(x,y) ((x) | ((y) << 8)) switch(C(req->bRequest, req->bmRequestType)) { @@ -1775,7 +2024,7 @@ ohci_root_ctrl_start(reqh) switch(value >> 8) { case UDESC_DEVICE: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); @@ -1784,7 +2033,7 @@ ohci_root_ctrl_start(reqh) break; case UDESC_CONFIG: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); @@ -1815,7 +2064,7 @@ ohci_root_ctrl_start(reqh) } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -1840,14 +2089,14 @@ ohci_root_ctrl_start(reqh) break; case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): if (value >= USB_MAX_DEVICES) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_addr = value; break; case C(UR_SET_CONFIG, UT_WRITE_DEVICE): if (value != 0 && value != 1) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_conf = value; @@ -1857,7 +2106,7 @@ ohci_root_ctrl_start(reqh) case C(UR_SET_FEATURE, UT_WRITE_DEVICE): case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): break; @@ -1871,7 +2120,7 @@ ohci_root_ctrl_start(reqh) "port=%d feature=%d\n", index, value)); if (index < 1 || index > sc->sc_noport) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } port = OHCI_RH_PORT_STATUS(index); @@ -1901,7 +2150,7 @@ ohci_root_ctrl_start(reqh) OWRITE4(sc, port, UPS_C_PORT_RESET << 16); break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -1920,7 +2169,7 @@ ohci_root_ctrl_start(reqh) break; case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): if (value != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); @@ -1942,7 +2191,7 @@ ohci_root_ctrl_start(reqh) break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } memset(buf, 0, len); /* ? XXX */ @@ -1952,11 +2201,11 @@ ohci_root_ctrl_start(reqh) DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n", index)); if (index < 1 || index > sc->sc_noport) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } v = OREAD4(sc, OHCI_RH_PORT_STATUS(index)); @@ -1969,13 +2218,13 @@ ohci_root_ctrl_start(reqh) totlen = l; break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): break; case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): if (index < 1 || index > sc->sc_noport) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } port = OHCI_RH_PORT_STATUS(index); @@ -2004,28 +2253,28 @@ ohci_root_ctrl_start(reqh) OWRITE4(sc, port, UPS_PORT_POWER); break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } - reqh->actlen = totlen; - r = USBD_NORMAL_COMPLETION; + xfer->actlen = totlen; + err = USBD_NORMAL_COMPLETION; ret: - reqh->status = r; + xfer->status = err; s = splusb(); - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); return (USBD_IN_PROGRESS); } /* Abort a root control request. */ void -ohci_root_ctrl_abort(reqh) - usbd_request_handle reqh; +ohci_root_ctrl_abort(xfer) + usbd_xfer_handle xfer; { /* Nothing to do, all transfers are synchronous. */ } @@ -2040,43 +2289,47 @@ ohci_root_ctrl_close(pipe) } usbd_status -ohci_root_intr_transfer(reqh) - usbd_request_handle reqh; +ohci_root_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); /* Pipe isn't running, start first */ - return (ohci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -ohci_root_intr_start(reqh) - usbd_request_handle reqh; +ohci_root_intr_start(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; + usbd_pipe_handle pipe = xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - sc->sc_intrreqh = reqh; + sc->sc_intrxfer = xfer; return (USBD_IN_PROGRESS); } /* Abort a root interrupt request. */ void -ohci_root_intr_abort(reqh) - usbd_request_handle reqh; +ohci_root_intr_abort(xfer) + usbd_xfer_handle xfer; { - if (reqh->pipe->intrreqh == reqh) { + int s; + + if (xfer->pipe->intrxfer == xfer) { DPRINTF(("ohci_root_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = NULL; } - reqh->status = USBD_CANCELLED; - usb_transfer_complete(reqh); + xfer->status = USBD_CANCELLED; + s = splusb(); + usb_transfer_complete(xfer); + splx(s); } /* Close the root pipe. */ @@ -2088,57 +2341,57 @@ ohci_root_intr_close(pipe) DPRINTF(("ohci_root_intr_close\n")); - sc->sc_intrreqh = 0; + sc->sc_intrxfer = NULL; } /************************/ usbd_status -ohci_device_ctrl_transfer(reqh) - usbd_request_handle reqh; +ohci_device_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); /* Pipe isn't running, start first */ - return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -ohci_device_ctrl_start(reqh) - usbd_request_handle reqh; +ohci_device_ctrl_start(xfer) + usbd_xfer_handle xfer; { - ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus; - usbd_status r; + ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; + usbd_status err; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) { + if (!(xfer->rqflags & URQ_REQUEST)) { /* XXX panic */ printf("ohci_device_ctrl_transfer: not a request\n"); return (USBD_INVAL); } #endif - r = ohci_device_request(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = ohci_device_request(xfer); + if (err) + return (err); if (sc->sc_bus.use_polling) - ohci_waitintr(sc, reqh); + ohci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } /* Abort a device control request. */ void -ohci_device_ctrl_abort(reqh) - usbd_request_handle reqh; +ohci_device_ctrl_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh)); - ohci_abort_req(reqh, USBD_CANCELLED); + DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer)); + ohci_abort_xfer(xfer, USBD_CANCELLED); } /* Close a device control pipe. */ @@ -2146,10 +2399,12 @@ void ohci_device_ctrl_close(pipe) usbd_pipe_handle pipe; { + struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe)); ohci_close_pipe(pipe, sc->sc_ctrl_head); + ohci_free_std(sc, opipe->tail.td); } /************************/ @@ -2160,7 +2415,7 @@ ohci_device_clear_toggle(pipe) { struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - opipe->sed->ed.ed_tailp &= LE(~OHCI_TOGGLECARRY); + opipe->sed->ed.ed_headp &= LE(~OHCI_TOGGLECARRY); } void @@ -2170,48 +2425,48 @@ ohci_noop(pipe) } usbd_status -ohci_device_bulk_transfer(reqh) - usbd_request_handle reqh; +ohci_device_bulk_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); /* Pipe isn't running, start first */ - return (ohci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -ohci_device_bulk_start(reqh) - usbd_request_handle reqh; +ohci_device_bulk_start(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; usbd_device_handle dev = opipe->pipe.device; ohci_softc_t *sc = (ohci_softc_t *)dev->bus; int addr = dev->address; ohci_soft_td_t *data, *tail, *tdp; ohci_soft_ed_t *sed; int s, len, isread, endpt; - usbd_status r; + usbd_status err; #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) { + if (xfer->rqflags & URQ_REQUEST) { /* XXX panic */ printf("ohci_device_bulk_start: a request\n"); return (USBD_INVAL); } #endif - len = reqh->length; - endpt = reqh->pipe->endpoint->edesc->bEndpointAddress; + len = xfer->length; + endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sed = opipe->sed; - DPRINTFN(4,("ohci_device_bulk_start: reqh=%p len=%d isread=%d " - "flags=%d endpt=%d\n", reqh, len, isread, reqh->flags, + DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d " + "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags, endpt)); opipe->u.bulk.isread = isread; @@ -2223,15 +2478,18 @@ ohci_device_bulk_start(reqh) OHCI_ED_SET_FA(addr)); /* Allocate a chain of new TDs (including a new tail). */ - data = opipe->tail; - r = ohci_alloc_std_chain(opipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, data, &tail); - if (r != USBD_NORMAL_COMPLETION) - return (r); - - tail->reqh = 0; - reqh->hcpriv = data; + data = opipe->tail.td; + err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, data, &tail); + /* We want interrupt at the end of the transfer. */ + tail->td.td_flags &= LE(~OHCI_TD_INTR_MASK); + tail->td.td_flags |= LE(OHCI_TD_SET_DI(1)); + tail->flags |= OHCI_CALL_DONE; + tail = tail->nexttd; /* point at sentinel */ + if (err) + return (err); + + tail->xfer = NULL; + xfer->hcpriv = data; DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " "td_cbp=0x%08x td_be=0x%08x\n", @@ -2239,7 +2497,7 @@ ohci_device_bulk_start(reqh) (int)LE(data->td.td_cbp), (int)LE(data->td.td_be))); #ifdef OHCI_DEBUG - if (ohcidebug > 4) { + if (ohcidebug > 5) { ohci_dump_ed(sed); ohci_dump_tds(data); } @@ -2248,22 +2506,21 @@ ohci_device_bulk_start(reqh) /* Insert ED in schedule */ s = splusb(); for (tdp = data; tdp != tail; tdp = tdp->nexttd) { - tdp->reqh = reqh; - ohci_hash_add_td(sc, tdp); + tdp->xfer = xfer; } sed->ed.ed_tailp = LE(tail->physaddr); - opipe->tail = tail; + opipe->tail.td = tail; sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(ohci_timeout, reqh, - MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, xfer, + MS_TO_TICKS(xfer->timeout), xfer->timo_handle); } #if 0 /* This goes wrong if we are too slow. */ - if (ohcidebug > 5) { - delay(5000); + if (ohcidebug > 10) { + delay(10000); DPRINTF(("ohci_device_intr_transfer: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); ohci_dump_ed(sed); @@ -2277,11 +2534,11 @@ ohci_device_bulk_start(reqh) } void -ohci_device_bulk_abort(reqh) - usbd_request_handle reqh; +ohci_device_bulk_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh)); - ohci_abort_req(reqh, USBD_CANCELLED); + DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer)); + ohci_abort_xfer(xfer, USBD_CANCELLED); } /* @@ -2291,34 +2548,36 @@ void ohci_device_bulk_close(pipe) usbd_pipe_handle pipe; { + struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe)); ohci_close_pipe(pipe, sc->sc_bulk_head); + ohci_free_std(sc, opipe->tail.td); } /************************/ usbd_status -ohci_device_intr_transfer(reqh) - usbd_request_handle reqh; +ohci_device_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); /* Pipe isn't running, start first */ - return (ohci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -ohci_device_intr_start(reqh) - usbd_request_handle reqh; +ohci_device_intr_start(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; usbd_device_handle dev = opipe->pipe.device; ohci_softc_t *sc = (ohci_softc_t *)dev->bus; ohci_soft_ed_t *sed = opipe->sed; @@ -2326,36 +2585,36 @@ ohci_device_intr_start(reqh) int len; int s; - DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p len=%d " + DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d " "flags=%d priv=%p\n", - reqh, reqh->length, reqh->flags, reqh->priv)); + xfer, xfer->length, xfer->flags, xfer->priv)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("ohci_device_intr_transfer: a request\n"); #endif - len = reqh->length; + len = xfer->length; - data = opipe->tail; + data = opipe->tail.td; tail = ohci_alloc_std(sc); - if (!tail) + if (tail == NULL) return (USBD_NOMEM); - tail->reqh = 0; + tail->xfer = NULL; data->td.td_flags = LE( OHCI_TD_IN | OHCI_TD_NOCC | OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY); - if (reqh->flags & USBD_SHORT_XFER_OK) + if (xfer->flags & USBD_SHORT_XFER_OK) data->td.td_flags |= LE(OHCI_TD_R); - data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf)); + data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf)); data->nexttd = tail; data->td.td_nexttd = LE(tail->physaddr); data->td.td_be = LE(LE(data->td.td_cbp) + len - 1); data->len = len; - data->reqh = reqh; + data->xfer = xfer; data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; - reqh->hcpriv = data; + xfer->hcpriv = data; #ifdef OHCI_DEBUG if (ohcidebug > 5) { @@ -2367,9 +2626,8 @@ ohci_device_intr_start(reqh) /* Insert ED in schedule */ s = splusb(); - ohci_hash_add_td(sc, data); sed->ed.ed_tailp = LE(tail->physaddr); - opipe->tail = tail; + opipe->tail.td = tail; sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); #if 0 @@ -2379,7 +2637,7 @@ ohci_device_intr_start(reqh) * TD is gone. */ if (ohcidebug > 5) { - delay(5000); + usb_delay_ms(&sc->sc_bus, 5); DPRINTF(("ohci_device_intr_transfer: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); ohci_dump_ed(sed); @@ -2393,14 +2651,14 @@ ohci_device_intr_start(reqh) /* Abort a device control request. */ void -ohci_device_intr_abort(reqh) - usbd_request_handle reqh; +ohci_device_intr_abort(xfer) + usbd_xfer_handle xfer; { - if (reqh->pipe->intrreqh == reqh) { + if (xfer->pipe->intrxfer == xfer) { DPRINTF(("ohci_device_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = NULL; } - ohci_abort_req(reqh, USBD_CANCELLED); + ohci_abort_xfer(xfer, USBD_CANCELLED); } /* Close a device interrupt pipe. */ @@ -2420,14 +2678,16 @@ ohci_device_intr_close(pipe) pipe, nslots, pos)); s = splusb(); sed->ed.ed_flags |= LE(OHCI_ED_SKIP); - if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != - (sed->ed.ed_headp & LE(OHCI_TAILMASK))) + if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) != + (sed->ed.ed_headp & LE(OHCI_HEADMASK))) usb_delay_ms(&sc->sc_bus, 2); for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) ; - if (!p) +#ifdef DIAGNOSTIC + if (p == NULL) panic("ohci_device_intr_close: ED not found\n"); +#endif p->next = sed->next; p->ed.ed_nexted = sed->ed.ed_nexted; splx(s); @@ -2435,7 +2695,7 @@ ohci_device_intr_close(pipe) for (j = 0; j < nslots; j++) --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; - ohci_free_std(sc, opipe->tail); + ohci_free_std(sc, opipe->tail.td); ohci_free_sed(sc, opipe->sed); } @@ -2504,3 +2764,149 @@ ohci_device_setintr(sc, opipe, ival) return (USBD_NORMAL_COMPLETION); } +/***********************/ + +usbd_status +ohci_device_isoc_transfer(xfer) + usbd_xfer_handle xfer; +{ + usbd_status err; + + DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); + + /* Put it on our queue, */ + err = usb_insert_transfer(xfer); + + /* bail out on error, */ + if (err && err != USBD_IN_PROGRESS) + return (err); + + /* XXX should check inuse here */ + + /* insert into schedule */ + ohci_device_isoc_enter(xfer); + + /* and put on interrupt list if the pipe wasn't running */ + if (!err) + ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); + + return (err); +} + +void +ohci_device_isoc_enter(xfer) + usbd_xfer_handle xfer; +{ + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; + usbd_device_handle dev = opipe->pipe.device; + ohci_softc_t *sc = (ohci_softc_t *)dev->bus; + ohci_soft_ed_t *sed = opipe->sed; + struct iso *iso = &opipe->u.iso; + ohci_soft_itd_t *sitd, *nsitd; + ohci_physaddr_t buf, offs; + int i, ncur, nframes; + int ncross; + int s; + + s = splusb(); + sitd = opipe->tail.itd; + buf = DMAADDR(&xfer->dmabuf); + sitd->itd.itd_bp0 = LE(buf & OHCI_ITD_PAGE_MASK); + nframes = xfer->nframes; + offs = buf & OHCI_ITD_OFFSET_MASK; + ncross = 0; + for (i = ncur = 0; i < nframes; i ++, ncur++) { + if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */ + ncross > 1) { /* too many page crossings */ + nsitd = ohci_alloc_sitd(sc); + if (nsitd == NULL) { + /* XXX what now? */ + return; + } + sitd->nextitd = nsitd; + sitd->itd.itd_nextitd = LE(nsitd->physaddr); + sitd->itd.itd_flags = LE( + OHCI_ITD_NOCC | + OHCI_ITD_SET_SF(iso->next) | + OHCI_ITD_NOINTR | + OHCI_ITD_SET_FC(OHCI_ITD_NOFFSET)); + sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1); + nsitd->itd.itd_bp0 = LE((buf + offs) & OHCI_ITD_PAGE_MASK); + sitd = nsitd; + iso->next = iso->next + ncur; + ncur = 0; + ncross = 0; + } + /* XXX byte order */ + sitd->itd.itd_offset[i] = + offs | (ncross == 1 ? OHCI_ITD_PAGE_SELECT : 0); + offs += xfer->frlengths[i]; + /* XXX update ncross */ + } + nsitd = ohci_alloc_sitd(sc); + if (nsitd == NULL) { + /* XXX what now? */ + return; + } + sitd->nextitd = nsitd; + sitd->itd.itd_nextitd = LE(nsitd->physaddr); + sitd->itd.itd_flags = LE( + OHCI_ITD_NOCC | + OHCI_ITD_SET_SF(iso->next) | + OHCI_ITD_SET_DI(0) | + OHCI_ITD_SET_FC(ncur)); + sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1); + iso->next = iso->next + ncur; + + opipe->tail.itd = nsitd; + sed->ed.ed_tailp = LE(nsitd->physaddr); + /* XXX update ED */ + splx(s); +} + +usbd_status +ohci_device_isoc_start(xfer) + usbd_xfer_handle xfer; +{ + printf("ohci_device_isoc_start: not implemented\n"); + return (USBD_INVAL); +} + +void +ohci_device_isoc_abort(xfer) + usbd_xfer_handle xfer; +{ +} + +void +ohci_device_isoc_done(xfer) + usbd_xfer_handle xfer; +{ + printf("ohci_device_isoc_done: not implemented\n"); +} + +usbd_status +ohci_setup_isoc(pipe) + usbd_pipe_handle pipe; +{ + struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; + struct iso *iso = &opipe->u.iso; + + iso->next = -1; + iso->inuse = 0; + + return (USBD_NORMAL_COMPLETION); +} + +void +ohci_device_isoc_close(pipe) + usbd_pipe_handle pipe; +{ + struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; + ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; + + DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe)); + ohci_close_pipe(pipe, sc->sc_isoc_head); + ohci_free_sitd(sc, opipe->tail.itd); +} + diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h index 67b010a0e5a..c9700f6be29 100644 --- a/sys/dev/usb/ohcireg.h +++ b/sys/dev/usb/ohcireg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ohcireg.h,v 1.3 1999/09/27 18:03:55 fgsch Exp $ */ -/* $NetBSD: ohcireg.h,v 1.9 1999/09/15 21:14:03 augustss Exp $ */ +/* $OpenBSD: ohcireg.h,v 1.4 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: ohcireg.h,v 1.15 2000/03/19 22:24:58 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -109,6 +109,9 @@ #define OHCI_GET_NDP(s) ((s) & 0xff) #define OHCI_PSM 0x0100 /* Power Switching Mode */ #define OHCI_NPS 0x0200 /* No Power Switching */ +#define OHCI_DT 0x0400 /* Device Type */ +#define OHCI_OCPM 0x0800 /* Overcurrent Protection Mode */ +#define OHCI_NOCP 0x1000 /* No Overcurrent Protection */ #define OHCI_GET_POTPGT(s) ((s) >> 24) #define OHCI_RH_DESCRIPTOR_B 0x4c #define OHCI_RH_STATUS 0x50 @@ -162,10 +165,10 @@ typedef struct { #define OHCI_ED_SET_MAXP(s) ((s) << 16) #define OHCI_ED_MAXPMASK (0x7ff << 16) ohci_physaddr_t ed_tailp; -#define OHCI_HALTED 0x00000002 -#define OHCI_TOGGLECARRY 0x00000001 -#define OHCI_TAILMASK 0xfffffffc ohci_physaddr_t ed_headp; +#define OHCI_HALTED 0x00000001 +#define OHCI_TOGGLECARRY 0x00000002 +#define OHCI_HEADMASK 0xfffffffc ohci_physaddr_t ed_nexted; } ohci_ed_t; /* #define OHCI_ED_SIZE 16 */ @@ -181,9 +184,11 @@ typedef struct { #define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */ #define OHCI_TD_SET_DI(x) ((x) << 21) #define OHCI_TD_NOINTR 0x00e00000 +#define OHCI_TD_INTR_MASK 0x00e00000 #define OHCI_TD_TOGGLE_CARRY 0x00000000 #define OHCI_TD_TOGGLE_0 0x02000000 #define OHCI_TD_TOGGLE_1 0x03000000 +#define OHCI_TD_TOGGLE_MASK 0x03000000 #define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) /* Error Count */ #define OHCI_TD_GET_CC(x) ((x) >> 28) /* Condition Code */ #define OHCI_TD_NOCC 0xf0000000 @@ -194,6 +199,32 @@ typedef struct { /* #define OHCI_TD_SIZE 16 */ #define OHCI_TD_ALIGN 16 +#define OHCI_ITD_NOFFSET 8 +typedef struct { + u_int32_t itd_flags; +#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff) +#define OHCI_ITD_SET_SF(x) ((x) & 0xffff) +#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) /* Delay interrupt */ +#define OHCI_ITD_SET_DI(x) ((x) << 21) +#define OHCI_ITD_NOINTR 0x00e00000 +#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) /* Frame Count */ +#define OHCI_ITD_SET_FC(x) (((x)-1) << 24) +#define OHCI_ITD_GET_CC(x) ((x) >> 28) /* Condition Code */ +#define OHCI_ITD_NOCC 0xf0000000 + ohci_physaddr_t itd_bp0; /* Buffer Page 0 */ +#define OHCI_ITD_OFFSET_MASK 0x00000fff +#define OHCI_ITD_PAGE_MASK (~OHCI_ITD_OFFSET_MASK) + ohci_physaddr_t itd_nextitd; /* Next ITD */ + ohci_physaddr_t itd_be; /* Buffer End */ + u_int16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets */ +#define itd_pswn itd_offset /* Packet Status Word */ +#define OHCI_ITD_PAGE_SELECT 0x00001000 +#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */ +#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */ +} ohci_itd_t; +/* #define OHCI_ITD_SIZE 32 */ +#define OHCI_ITD_ALIGN 32 + #define OHCI_CC_NO_ERROR 0 #define OHCI_CC_CRC 1 #define OHCI_CC_BIT_STUFFING 2 diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index e33423dfb98..a0ad463063c 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ohcivar.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: ohcivar.h,v 1.11 1999/09/15 21:14:03 augustss Exp $ */ +/* $OpenBSD: ohcivar.h,v 1.7 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: ohcivar.h,v 1.20 2000/02/22 11:30:55 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -52,7 +52,7 @@ typedef struct ohci_soft_td { struct ohci_soft_td *dnext; /* next in done list */ ohci_physaddr_t physaddr; LIST_ENTRY(ohci_soft_td) hnext; - usbd_request_handle reqh; + usbd_xfer_handle xfer; u_int16_t len; u_int16_t flags; #define OHCI_CALL_DONE 0x0001 @@ -61,6 +61,14 @@ typedef struct ohci_soft_td { #define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN) #define OHCI_STD_CHUNK 128 +typedef struct ohci_soft_itd { + ohci_itd_t itd; + struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */ + ohci_physaddr_t physaddr; +} ohci_soft_itd_t; +#define OHCI_SITD_SIZE ((sizeof (struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN) +#define OHCI_SITD_CHUNK 64 + #define OHCI_NO_EDS (2*OHCI_NO_INTRS-1) #define OHCI_HASH_SIZE 128 @@ -76,6 +84,7 @@ typedef struct ohci_softc { u_int sc_bws[OHCI_NO_INTRS]; u_int32_t sc_eintrs; + ohci_soft_ed_t *sc_isoc_head; ohci_soft_ed_t *sc_ctrl_head; ohci_soft_ed_t *sc_bulk_head; @@ -87,19 +96,30 @@ typedef struct ohci_softc { ohci_soft_ed_t *sc_freeeds; ohci_soft_td_t *sc_freetds; + ohci_soft_itd_t *sc_freeitds; + + SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - usbd_request_handle sc_intrreqh; + usbd_xfer_handle sc_intrxfer; + + ohci_physaddr_t sc_done; char sc_vendor[16]; int sc_id_vendor; - void *sc_powerhook; +#if defined(__NetBSD__) || defined(__OpenBSD__) + void *sc_powerhook; /* cookie from power hook */ + void *sc_shutdownhook; /* cookie from shutdown hook */ +#endif + device_ptr_t sc_child; } ohci_softc_t; usbd_status ohci_init __P((ohci_softc_t *)); int ohci_intr __P((void *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) int ohci_detach __P((ohci_softc_t *, int)); int ohci_activate __P((device_ptr_t, enum devact)); +#endif #define MS_TO_TICKS(ms) ((ms) * hz / 1000) diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c index 2c186819ca1..558f721b9d7 100644 --- a/sys/dev/usb/uaudio.c +++ b/sys/dev/usb/uaudio.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uaudio.c,v 1.1 1999/11/11 15:54:59 ho Exp $ */ -/* $NetBSD: uaudio.c,v 1.5 1999/10/25 10:16:49 augustss Exp $ */ +/* $OpenBSD: uaudio.c,v 1.2 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: uaudio.c,v 1.20 2000/03/24 13:02:00 augustss Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -132,11 +132,13 @@ struct chan { int curchanbuf; struct chanbuf { struct chan *chan; - usbd_request_handle reqh; + usbd_xfer_handle xfer; u_char *buffer; u_int16_t sizes[UAUDIO_NFRAMES]; u_int16_t size; } chanbufs[UAUDIO_NCHANBUFS]; + + struct uaudio_softc *sc; /* our softc */ }; struct uaudio_softc { @@ -154,6 +156,8 @@ struct uaudio_softc { int sc_nullalt; + int sc_audio_rev; + struct as_info *sc_alts; int sc_nalts; int sc_props; @@ -204,6 +208,9 @@ void uaudio_add_selector __P((struct uaudio_softc *sc, usb_descriptor_t *v, usb_descriptor_t **dps)); void uaudio_add_feature __P((struct uaudio_softc *sc, usb_descriptor_t *v, usb_descriptor_t **dps)); +void uaudio_add_processing_updown __P((struct uaudio_softc *sc, + usb_descriptor_t *v, + usb_descriptor_t **dps)); void uaudio_add_processing __P((struct uaudio_softc *sc, usb_descriptor_t *v, usb_descriptor_t **dps)); void uaudio_add_extension __P((struct uaudio_softc *sc, usb_descriptor_t *v, @@ -232,11 +239,11 @@ void uaudio_chan_free_buffers __P((struct uaudio_softc *, struct chan *)); void uaudio_chan_set_param __P((struct chan *ch, struct audio_params *param, u_char *start, u_char *end, int blksize)); void uaudio_chan_ptransfer __P((struct chan *ch)); -void uaudio_chan_pintr __P((usbd_request_handle reqh, +void uaudio_chan_pintr __P((usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)); void uaudio_chan_rtransfer __P((struct chan *ch)); -void uaudio_chan_rintr __P((usbd_request_handle reqh, +void uaudio_chan_rintr __P((usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)); @@ -304,14 +311,15 @@ USB_MATCH(uaudio) USB_MATCH_START(uaudio, uaa); usb_interface_descriptor_t *id; - if (!uaa->iface) + if (uaa->iface == NULL) return (UMATCH_NONE); id = usbd_get_interface_descriptor(uaa->iface); /* Trigger on the control interface. */ - if (!id || - id->bInterfaceClass != UCLASS_AUDIO || - id->bInterfaceSubClass != USUBCLASS_AUDIOCONTROL) + if (id == NULL || + id->bInterfaceClass != UICLASS_AUDIO || + id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL || + (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO)) return (UMATCH_NONE); return (UMATCH_IFACECLASS_IFACESUBCLASS); @@ -323,7 +331,7 @@ USB_ATTACH(uaudio) usb_interface_descriptor_t *id; usb_config_descriptor_t *cdesc; char devinfo[1024]; - usbd_status r; + usbd_status err; int i; usbd_devinfo(uaa->device, 0, devinfo); @@ -332,36 +340,50 @@ USB_ATTACH(uaudio) sc->sc_udev = uaa->device; cdesc = usbd_get_config_descriptor(sc->sc_udev); - if (!cdesc) + if (cdesc == NULL) { + printf("%s: failed to get configuration descriptor\n", + USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; + } - r = uaudio_identify(sc, cdesc); - if (r != USBD_NORMAL_COMPLETION) { + err = uaudio_identify(sc, cdesc); + if (err) { printf("%s: audio descriptors make no sense, error=%d\n", - USBDEVNAME(sc->sc_dev), r); + USBDEVNAME(sc->sc_dev), err); USB_ATTACH_ERROR_RETURN; } sc->sc_ac_ifaceh = uaa->iface; /* Pick up the AS interface. */ for (i = 0; i < uaa->nifaces; i++) { - if (uaa->ifaces[i]) { + if (uaa->ifaces[i] != NULL) { id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id->bInterfaceNumber == sc->sc_as_iface) { + if (id != NULL && + id->bInterfaceNumber == sc->sc_as_iface) { sc->sc_as_ifaceh = uaa->ifaces[i]; - uaa->ifaces[i] = 0; + uaa->ifaces[i] = NULL; + break; } } } - if (!sc->sc_as_ifaceh) { + if (sc->sc_as_ifaceh == NULL) { printf("%s: missing AS interface(s)\n",USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } + printf("%s: streaming interface %d, audio rev %d.%02x\n", + USBDEVNAME(sc->sc_dev), sc->sc_as_iface, + sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff); + + sc->sc_chan.sc = sc; + DPRINTF(("uaudio_attach: doing audio_attach_mi\n")); /* sc->sc_audiodev = */ audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev); + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + USB_ATTACH_SUCCESS_RETURN; } @@ -395,9 +417,15 @@ uaudio_detach(self, flags) struct uaudio_softc *sc = (struct uaudio_softc *)self; int rv = 0; - if (sc->sc_audiodev) + /* Wait for outstanding requests to complete. */ + usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES); + + if (sc->sc_audiodev != NULL) rv = config_detach(sc->sc_audiodev, flags); + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + return (rv); } @@ -484,7 +512,7 @@ uaudio_find_iface(buf, size, offsp, subtype) d = (void *)(buf + *offsp); *offsp += d->bLength; if (d->bDescriptorType == UDESC_INTERFACE && - d->bInterfaceClass == UCLASS_AUDIO && + d->bInterfaceClass == UICLASS_AUDIO && d->bInterfaceSubClass == subtype) return (d); } @@ -496,7 +524,7 @@ uaudio_mixer_add_ctl(sc, mc) struct uaudio_softc *sc; struct mixerctl *mc; { - if (sc->sc_nctls == 0) + if (sc->sc_nctls == NULL) sc->sc_ctls = malloc(sizeof *mc, M_USBDEV, M_NOWAIT); else #ifdef __OpenBSD__ @@ -514,7 +542,7 @@ uaudio_mixer_add_ctl(sc, mc) (sc->sc_nctls+1) * sizeof *mc, M_USBDEV, M_NOWAIT); #endif - if (sc->sc_ctls == 0) { + if (sc->sc_ctls == NULL) { printf("uaudio_mixer_add_ctl: no memory\n"); return; } @@ -623,7 +651,7 @@ uaudio_get_cluster(id, dps) bad: printf("uaudio_get_cluster: bad data\n"); memset(&r, 0, sizeof r); - return r; + return (r); } @@ -644,7 +672,6 @@ uaudio_add_input(sc, v, dps) d->bNrChannels, UGETW(d->wChannelConfig), d->iChannelNames, d->iTerminal)); #endif - printf("uaudio_add_input: not implemented\n"); } void @@ -837,7 +864,7 @@ uaudio_add_feature(sc, v, dps) mix.ctlunit = AudioNtreble; break; case GRAPHIC_EQUALIZER_CONTROL: - continue; /* don't add anything */ + continue; /* XXX don't add anything */ break; case AGC_CONTROL: mix.type = MIX_ON_OFF; @@ -872,20 +899,89 @@ uaudio_add_feature(sc, v, dps) } } +void +uaudio_add_processing_updown(sc, v, dps) + struct uaudio_softc *sc; + usb_descriptor_t *v; + usb_descriptor_t **dps; +{ + struct usb_audio_processing_unit *d = + (struct usb_audio_processing_unit *)v; + struct usb_audio_processing_unit_1 *d1 = + (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins]; + struct usb_audio_processing_unit_updown *ud = + (struct usb_audio_processing_unit_updown *) + &d1->bmControls[d1->bControlSize]; + struct mixerctl mix; + int i; + + DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n", + d->bUnitId, ud->bNrModes)); + + if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) { + DPRINTF(("uaudio_add_processing_updown: no mode select\n")); + return; + } + + mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); + mix.nchan = 1; + mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0); + mix.class = -1; + mix.type = MIX_ON_OFF; /* XXX */ + mix.ctlunit = ""; + sprintf(mix.ctlname, "pro%d-mode", d->bUnitId); + + for (i = 0; i < ud->bNrModes; i++) { + DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n", + i, UGETW(ud->waModes[i]))); + /* XXX */ + } + uaudio_mixer_add_ctl(sc, &mix); +} + void uaudio_add_processing(sc, v, dps) struct uaudio_softc *sc; usb_descriptor_t *v; usb_descriptor_t **dps; { -#ifdef UAUDIO_DEBUG struct usb_audio_processing_unit *d = - (struct usb_audio_processing_unit *)v; + (struct usb_audio_processing_unit *)v; + struct usb_audio_processing_unit_1 *d1 = + (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins]; + int ptype = UGETW(d->wProcessType); + struct mixerctl mix; - DPRINTFN(2,("uaudio_add_processing: bUnitId=%d bNrInPins=%d\n", - d->bUnitId, d->bNrInPins)); - printf("uaudio_add_processing: NOT IMPLEMENTED\n"); + DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d " + "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins)); + + if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) { + mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); + mix.nchan = 1; + mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0); + mix.class = -1; + mix.type = MIX_ON_OFF; + mix.ctlunit = ""; + sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype); + uaudio_mixer_add_ctl(sc, &mix); + } + + switch (ptype) { + case UPDOWNMIX_PROCESS: + uaudio_add_processing_updown(sc, v, dps); + break; + case DOLBY_PROLOGIC_PROCESS: + case P3D_STEREO_EXTENDER_PROCESS: + case REVERBATION_PROCESS: + case CHORUS_PROCESS: + case DYN_RANGE_COMP_PROCESS: + default: +#ifdef UAUDIO_DEBUG + printf("uaudio_add_processing: unit %d, type=%d not impl.\n", + d->bUnitId, ptype); #endif + break; + } } void @@ -903,7 +999,7 @@ uaudio_add_extension(sc, v, dps) DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n", d->bUnitId, d->bNrInPins)); - if (d1->bmControls[0] & (1 << UA_EXT_ENABLE)) { + if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); mix.nchan = 1; mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0); @@ -920,11 +1016,11 @@ uaudio_identify(sc, cdesc) struct uaudio_softc *sc; usb_config_descriptor_t *cdesc; { - usbd_status r; + usbd_status err; - r = uaudio_identify_ac(sc, cdesc); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uaudio_identify_ac(sc, cdesc); + if (err) + return (err); return (uaudio_identify_as(sc, cdesc)); } @@ -933,7 +1029,7 @@ uaudio_add_alt(sc, ai) struct uaudio_softc *sc; struct as_info *ai; { - if (sc->sc_nalts == 0) + if (sc->sc_nalts == NULL) sc->sc_alts = malloc(sizeof *ai, M_USBDEV, M_NOWAIT); else #ifdef __OpenBSD__ @@ -1084,7 +1180,7 @@ uaudio_identify_as(sc, cdesc) usb_config_descriptor_t *cdesc; { usb_interface_descriptor_t *id; - usbd_status r; + usbd_status err; char *buf; int size, offs; @@ -1093,8 +1189,8 @@ uaudio_identify_as(sc, cdesc) /* Locate the AudioStreaming interface descriptor. */ offs = 0; - id = uaudio_find_iface(buf, size, &offs, USUBCLASS_AUDIOSTREAM); - if (!id) + id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM); + if (id == NULL) return (USBD_INVAL); sc->sc_as_iface = id->bInterfaceNumber; DPRINTF(("uaudio_identify_as: AS interface is %d\n", sc->sc_as_iface)); @@ -1110,7 +1206,7 @@ uaudio_identify_as(sc, cdesc) sc->sc_nullalt = id->bAlternateSetting; break; case 1: - r = uaudio_process_as(sc, buf, &offs, size, id); + err = uaudio_process_as(sc, buf, &offs, size, id); break; default: #ifdef AUDIO_DEBUG @@ -1120,7 +1216,7 @@ uaudio_identify_as(sc, cdesc) #endif break; } - id = uaudio_find_iface(buf, size, &offs,USUBCLASS_AUDIOSTREAM); + id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM); if (!id) break; } @@ -1151,8 +1247,8 @@ uaudio_identify_ac(sc, cdesc) /* Locate the AudioControl interface descriptor. */ offs = 0; - id = uaudio_find_iface(buf, size, &offs, USUBCLASS_AUDIOCONTROL); - if (!id) + id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL); + if (id == NULL) return (USBD_INVAL); if (offs + sizeof *acdp > size) return (USBD_INVAL); @@ -1173,8 +1269,9 @@ uaudio_identify_ac(sc, cdesc) UGETW(acdp->bcdADC) != UAUDIO_VERSION) return (USBD_INVAL); + sc->sc_audio_rev = UGETW(acdp->bcdADC); DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n", - UGETW(acdp->bcdADC), aclen)); + sc->sc_audio_rev, aclen)); sc->sc_nullalt = -1; @@ -1204,7 +1301,7 @@ uaudio_identify_ac(sc, cdesc) for (i = 0; i < ndps; i++) { dp = dps[i]; - if (dp == 0) + if (dp == NULL) continue; DPRINTF(("uaudio_identify: subtype=%d\n", dp->bDescriptorSubtype)); @@ -1362,7 +1459,7 @@ uaudio_halt_out_dma(addr) struct uaudio_softc *sc = addr; DPRINTF(("uaudio_halt_out_dma: enter\n")); - if (sc->sc_chan.pipe) { + if (sc->sc_chan.pipe != NULL) { uaudio_chan_close(sc, &sc->sc_chan); sc->sc_chan.pipe = 0; uaudio_chan_free_buffers(sc, &sc->sc_chan); @@ -1377,7 +1474,7 @@ uaudio_halt_in_dma(addr) struct uaudio_softc *sc = addr; DPRINTF(("uaudio_halt_in_dma: enter\n")); - if (sc->sc_chan.pipe) { + if (sc->sc_chan.pipe != NULL) { uaudio_chan_close(sc, &sc->sc_chan); sc->sc_chan.pipe = 0; uaudio_chan_free_buffers(sc, &sc->sc_chan); @@ -1437,9 +1534,6 @@ uaudio_get_props(addr) { struct uaudio_softc *sc = addr; - if (sc->sc_dying) - return (EIO); - return (sc->sc_props); } @@ -1450,7 +1544,7 @@ uaudio_get(sc, which, type, wValue, wIndex, len) { usb_device_request_t req; u_int8_t data[4]; - usbd_status r; + usbd_status err; int val; if (wValue == -1) @@ -1464,9 +1558,9 @@ uaudio_get(sc, which, type, wValue, wIndex, len) DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x " "wIndex=0x%04x len=%d\n", type, which, wValue, wIndex, len)); - r = usbd_do_request(sc->sc_udev, &req, &data); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("uaudio_get: r=%d\n", r)); + err = usbd_do_request(sc->sc_udev, &req, &data); + if (err) { + DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err))); return (-1); } switch (len) { @@ -1491,7 +1585,7 @@ uaudio_set(sc, which, type, wValue, wIndex, len, val) { usb_device_request_t req; u_int8_t data[4]; - usbd_status r; + usbd_status err; if (wValue == -1) return; @@ -1515,9 +1609,9 @@ uaudio_set(sc, which, type, wValue, wIndex, len, val) DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x " "wIndex=0x%04x len=%d, val=%d\n", type, which, wValue, wIndex, len, val & 0xffff)); - r = usbd_do_request(sc->sc_udev, &req, &data); + err = usbd_do_request(sc->sc_udev, &req, &data); #ifdef UAUDIO_DEBUG - if (r != USBD_NORMAL_COMPLETION) + if (err) DPRINTF(("uaudio_set: r=%d\n", r)); #endif } @@ -1687,7 +1781,7 @@ uaudio_trigger_input(addr, start, end, blksize, intr, arg, param) { struct uaudio_softc *sc = addr; struct chan *ch = &sc->sc_chan; - usbd_status r; + usbd_status err; int i, s; if (sc->sc_dying) @@ -1701,12 +1795,12 @@ uaudio_trigger_input(addr, start, end, blksize, intr, arg, param) "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, ch->fraction)); - r = uaudio_chan_alloc_buffers(sc, ch); - if (r != USBD_NORMAL_COMPLETION) + err = uaudio_chan_alloc_buffers(sc, ch); + if (err) return (EIO); - r = uaudio_chan_open(sc, ch); - if (r != USBD_NORMAL_COMPLETION) { + err = uaudio_chan_open(sc, ch); + if (err) { uaudio_chan_free_buffers(sc, ch); return (EIO); } @@ -1733,7 +1827,7 @@ uaudio_trigger_output(addr, start, end, blksize, intr, arg, param) { struct uaudio_softc *sc = addr; struct chan *ch = &sc->sc_chan; - usbd_status r; + usbd_status err; int i, s; if (sc->sc_dying) @@ -1747,12 +1841,12 @@ uaudio_trigger_output(addr, start, end, blksize, intr, arg, param) "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, ch->fraction)); - r = uaudio_chan_alloc_buffers(sc, ch); - if (r != USBD_NORMAL_COMPLETION) + err = uaudio_chan_alloc_buffers(sc, ch); + if (err) return (EIO); - r = uaudio_chan_open(sc, ch); - if (r != USBD_NORMAL_COMPLETION) { + err = uaudio_chan_open(sc, ch); + if (err) { uaudio_chan_free_buffers(sc, ch); return (EIO); } @@ -1776,29 +1870,29 @@ uaudio_chan_open(sc, ch) { struct as_info *as = &sc->sc_alts[sc->sc_curaltidx]; int endpt = as->edesc->bEndpointAddress; - usbd_status r; + usbd_status err; DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n", endpt, ch->sample_rate, as->alt)); /* Set alternate interface corresponding to the mode. */ - r = usbd_set_interface(sc->sc_as_ifaceh, as->alt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_interface(sc->sc_as_ifaceh, as->alt); + if (err) + return (err); /* Some devices do not support this request, so ignore errors. */ #ifdef UAUDIO_DEBUG - r = uaudio_set_speed(sc, endpt, ch->sample_rate); - if (r != USBD_NORMAL_COMPLETION) + err = uaudio_set_speed(sc, endpt, ch->sample_rate); + if (err) DPRINTF(("uaudio_chan_open: set_speed failed r=%s\n", - usbd_errstr(r))); + usbd_errstr(err))); #else (void)uaudio_set_speed(sc, endpt, ch->sample_rate); #endif DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt)); - r = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe); - return (r); + err = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe); + return (err); } void @@ -1820,17 +1914,17 @@ uaudio_chan_alloc_buffers(sc, ch) struct uaudio_softc *sc; struct chan *ch; { - usbd_request_handle reqh; + usbd_xfer_handle xfer; void *buf; int i, size; size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES; for (i = 0; i < UAUDIO_NCHANBUFS; i++) { - reqh = usbd_alloc_request(sc->sc_udev); - if (reqh == 0) + xfer = usbd_alloc_xfer(sc->sc_udev); + if (xfer == 0) goto bad; - ch->chanbufs[i].reqh = reqh; - buf = usbd_alloc_buffer(reqh, size); + ch->chanbufs[i].xfer = xfer; + buf = usbd_alloc_buffer(xfer, size); if (buf == 0) { i++; goto bad; @@ -1844,7 +1938,7 @@ uaudio_chan_alloc_buffers(sc, ch) bad: while (--i >= 0) /* implicit buffer free */ - usbd_free_request(ch->chanbufs[i].reqh); + usbd_free_xfer(ch->chanbufs[i].xfer); return (USBD_NOMEM); } @@ -1856,7 +1950,7 @@ uaudio_chan_free_buffers(sc, ch) int i; for (i = 0; i < UAUDIO_NCHANBUFS; i++) - usbd_free_request(ch->chanbufs[i].reqh); + usbd_free_xfer(ch->chanbufs[i].xfer); } /* Called at splusb() */ @@ -1867,6 +1961,9 @@ uaudio_chan_ptransfer(ch) struct chanbuf *cb; int i, n, size, residue, total; + if (ch->sc->sc_dying) + return; + /* Pick the next channel buffer. */ cb = &ch->chanbufs[ch->curchanbuf]; if (++ch->curchanbuf >= UAUDIO_NCHANBUFS) @@ -1913,18 +2010,18 @@ uaudio_chan_ptransfer(ch) } #endif - DPRINTFN(5,("uaudio_chan_transfer: ptransfer reqh=%p\n", cb->reqh)); + DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer)); /* Fill the request */ - usbd_setup_isoc_request(cb->reqh, ch->pipe, cb, cb->sizes, + usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, UAUDIO_NFRAMES, USBD_NO_COPY, uaudio_chan_pintr); - (void)usbd_transfer(cb->reqh); + (void)usbd_transfer(cb->xfer); } void -uaudio_chan_pintr(reqh, priv, status) - usbd_request_handle reqh; +uaudio_chan_pintr(xfer, priv, status) + usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { @@ -1937,7 +2034,7 @@ uaudio_chan_pintr(reqh, priv, status) if (status == USBD_CANCELLED) return; - usbd_get_request_status(reqh, 0, 0, &count, 0); + usbd_get_xfer_status(xfer, NULL, NULL, &count, 0); DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n", count, ch->transferred)); #ifdef DIAGNOSTIC @@ -1970,6 +2067,9 @@ uaudio_chan_rtransfer(ch) struct chanbuf *cb; int i, size, residue, total; + if (ch->sc->sc_dying) + return; + /* Pick the next channel buffer. */ cb = &ch->chanbufs[ch->curchanbuf]; if (++ch->curchanbuf >= UAUDIO_NCHANBUFS) @@ -2001,18 +2101,18 @@ uaudio_chan_rtransfer(ch) } #endif - DPRINTFN(5,("uaudio_chan_rtransfer: transfer reqh=%p\n", cb->reqh)); + DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer)); /* Fill the request */ - usbd_setup_isoc_request(cb->reqh, ch->pipe, cb, cb->sizes, + usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, UAUDIO_NFRAMES, USBD_NO_COPY, uaudio_chan_rintr); - (void)usbd_transfer(cb->reqh); + (void)usbd_transfer(cb->xfer); } void -uaudio_chan_rintr(reqh, priv, status) - usbd_request_handle reqh; +uaudio_chan_rintr(xfer, priv, status) + usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { @@ -2025,7 +2125,7 @@ uaudio_chan_rintr(reqh, priv, status) if (status == USBD_CANCELLED) return; - usbd_get_request_status(reqh, 0, 0, &count, 0); + usbd_get_xfer_status(xfer, NULL, NULL, &count, 0); DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n", count, ch->transferred)); #ifdef DIAGNOSTIC @@ -2098,6 +2198,7 @@ uaudio_set_params(addr, setmode, usemode, p, r) { struct uaudio_softc *sc = addr; int flags = sc->sc_altflags; + int pfactor, rfactor; int enc, i, j; void (*pswcode) __P((void *, u_char *buf, int cnt)); void (*rswcode) __P((void *, u_char *buf, int cnt)); @@ -2105,10 +2206,11 @@ uaudio_set_params(addr, setmode, usemode, p, r) if (sc->sc_dying) return (EIO); - if (sc->sc_chan.pipe) + if (sc->sc_chan.pipe != NULL) return (EBUSY); pswcode = rswcode = 0; + pfactor = rfactor = 1; enc = p->encoding; switch (p->encoding) { case AUDIO_ENCODING_SLINEAR_BE: @@ -2155,6 +2257,13 @@ uaudio_set_params(addr, setmode, usemode, p, r) pswcode = mulaw_to_slinear8; rswcode = slinear8_to_mulaw; enc = AUDIO_ENCODING_SLINEAR_LE; +#if 0 + } else if (flags & HAS_16) { + pswcode = mulaw_to_slinear16_le; + pfactor = 2; + /* XXX recording not handled */ + enc = AUDIO_ENCODING_SLINEAR_LE; +#endif } else return (EINVAL); } @@ -2169,6 +2278,13 @@ uaudio_set_params(addr, setmode, usemode, p, r) pswcode = alaw_to_slinear8; rswcode = slinear8_to_alaw; enc = AUDIO_ENCODING_SLINEAR_LE; +#if 0 + } else if (flags & HAS_16) { + pswcode = alaw_to_slinear16_le; + pfactor = 2; + /* XXX recording not handled */ + enc = AUDIO_ENCODING_SLINEAR_LE; +#endif } else return (EINVAL); } @@ -2188,11 +2304,15 @@ uaudio_set_params(addr, setmode, usemode, p, r) p->precision ==a1d->bBitResolution && enc == sc->sc_alts[i].encoding) { if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) { + DPRINTFN(2,("uaudio_set_params: cont %d-%d\n", + UA_SAMP_LO(a1d), UA_SAMP_HI(a1d))); if (UA_SAMP_LO(a1d) < p->sample_rate && p->sample_rate < UA_SAMP_HI(a1d)) goto found; } else { for (j = 0; j < a1d->bSamFreqType; j++) { + DPRINTFN(2,("uaudio_set_params: disc #" + "%d: %d\n", j, UA_GETSAMP(a1d, j))); /* XXX allow for some slack */ if (UA_GETSAMP(a1d, j) == p->sample_rate) @@ -2206,6 +2326,8 @@ uaudio_set_params(addr, setmode, usemode, p, r) found: p->sw_code = pswcode; r->sw_code = rswcode; + p->factor = pfactor; + r->factor = rfactor; sc->sc_curaltidx = i; DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n", diff --git a/sys/dev/usb/uaudioreg.h b/sys/dev/usb/uaudioreg.h index 113752e6214..15da30f2193 100644 --- a/sys/dev/usb/uaudioreg.h +++ b/sys/dev/usb/uaudioreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uaudioreg.h,v 1.1 1999/11/11 15:54:59 ho Exp $ */ -/* $NetBSD: uaudioreg.h,v 1.2 1999/10/13 20:13:29 augustss Exp $ */ +/* $OpenBSD: uaudioreg.h,v 1.2 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: uaudioreg.h,v 1.4 2000/01/16 09:32:56 augustss Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -156,14 +156,14 @@ struct usb_audio_mixer_unit { uByte bDescriptorSubtype; uByte bUnitId; uByte bNrInPins; - uByte baSourceId[255]; /* length is really bNrInPins */ + uByte baSourceId[255]; /* [bNrInPins] */ /* struct usb_audio_mixer_unit_1 */ }; struct usb_audio_mixer_unit_1 { uByte bNrChannels; uWord wChannelConfig; uByte iChannelNames; - uByte bmControls[255]; + uByte bmControls[255]; /* [bNrChannels] */ /*uByte iMixer;*/ }; @@ -174,7 +174,7 @@ struct usb_audio_selector_unit { uByte bDescriptorSubtype; uByte bUnitId; uByte bNrInPins; - uByte baSourceId[255]; + uByte baSourceId[255]; /* [bNrInPins] */ /* uByte iSelector; */ }; @@ -198,7 +198,7 @@ struct usb_audio_processing_unit { uByte bUnitId; uWord wProcessType; uByte bNrInPins; - uByte baSourceId[255]; + uByte baSourceId[255]; /* [bNrInPins] */ /* struct usb_audio_processing_unit_1 */ }; struct usb_audio_processing_unit_1{ @@ -206,8 +206,14 @@ struct usb_audio_processing_unit_1{ uWord wChannelConfig; uByte iChannelNames; uByte bControlSize; - uByte bmControls[255]; - /*uByte iProcessing;*/ + uByte bmControls[255]; /* [bControlSize] */ +#define UA_PROC_ENABLE_MASK 1 +}; + +struct usb_audio_processing_unit_updown { + uByte iProcessing; + uByte bNrModes; + uWord waModes[255]; /* [bNrModes] */ }; /* UDESCSUB_AC_EXTENSION */ @@ -218,7 +224,7 @@ struct usb_audio_extension_unit { uByte bUnitId; uWord wExtensionCode; uByte bNrInPins; - uByte baSourceId[255]; + uByte baSourceId[255]; /* [bNrInPins] */ /* struct usb_audio_extension_unit_1 */ }; struct usb_audio_extension_unit_1 { @@ -226,8 +232,9 @@ struct usb_audio_extension_unit_1 { uWord wChannelConfig; uByte iChannelNames; uByte bControlSize; - uByte bmControls[255]; -#define UA_EXT_ENABLE 0 + uByte bmControls[255]; /* [bControlSize] */ +#define UA_EXT_ENABLE_MASK 1 +#define UA_EXT_ENABLE 1 /*uByte iExtension;*/ }; @@ -276,3 +283,39 @@ struct usb_audio_extension_unit_1 { #define FORMAT_TYPE_I 1 #define FORMAT_TYPE_II 2 #define FORMAT_TYPE_III 3 + +#define UA_PROC_MASK(n) (1 << ((n)-1)) +#define PROCESS_UNDEFINED 0 +#define XX_ENABLE_CONTROL 1 + +#define UPDOWNMIX_PROCESS 1 +#define UD_ENABLE_CONTROL 1 +#define UD_MODE_SELECT_CONTROL 2 + +#define DOLBY_PROLOGIC_PROCESS 2 +#define DP_ENABLE_CONTROL 1 +#define DP_MODE_SELECT_CONTROL 2 + +#define P3D_STEREO_EXTENDER_PROCESS 3 +#define P3D_ENABLE_CONTROL 1 +#define P3D_SPACIOUSNESS_CONTROL 2 + +#define REVERBATION_PROCESS 4 +#define RV_ENABLE_CONTROL 1 +#define RV_LEVEL_CONTROL 2 +#define RV_TIME_CONTROL 3 +#define RV_FEEDBACK_CONTROL 4 + +#define CHORUS_PROCESS 5 +#define CH_ENABLE_CONTROL 1 +#define CH_LEVEL_CONTROL 2 +#define CH_RATE_CONTROL 3 +#define CH_DEPTH_CONTROL 4 + +#define DYN_RANGE_COMP_PROCESS 6 +#define DR_ENABLE_CONTROL 1 +#define DR_COMPRESSION_RATE_CONTROL 2 +#define DR_MAXAMPL_CONTROL 3 +#define DR_THRESHOLD_CONTROL 4 +#define DR_ATTACK_TIME_CONTROL 5 +#define DR_RELEASE_TIME_CONTROL 6 diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index f49ca1d7bfc..a8f62e257e9 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ugen.c,v 1.7 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: ugen.c,v 1.27 1999/10/28 12:08:38 augustss Exp $ */ +/* $OpenBSD: ugen.c,v 1.8 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: ugen.c,v 1.36 2000/03/06 20:59:17 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -124,24 +124,19 @@ static struct cdevsw ugen_cdevsw = { /* read */ ugenread, /* write */ ugenwrite, /* ioctl */ ugenioctl, - /* stop */ nostop, - /* reset */ noreset, - /* devtotty */ nodevtotty, /* poll */ ugenpoll, /* mmap */ nommap, /* strategy */ nostrategy, /* name */ "ugen", - /* parms */ noparms, /* maj */ UGEN_CDEV_MAJOR, /* dump */ nodump, /* psize */ nopsize, /* flags */ 0, - /* maxio */ 0, /* bmaj */ -1 }; #endif -void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr, +void ugenintr __P((usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)); int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int)); @@ -173,23 +168,49 @@ USB_MATCH(ugen) USB_ATTACH(ugen) { USB_ATTACH_START(ugen, sc, uaa); + usbd_device_handle udev; char devinfo[1024]; - usbd_status r; + usbd_status err; int conf; usbd_devinfo(uaa->device, 0, devinfo); USB_ATTACH_SETUP; printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - sc->sc_udev = uaa->device; - conf = 1; /* XXX should not hard code 1 */ - r = ugen_set_config(sc, conf); - if (r != USBD_NORMAL_COMPLETION) { + sc->sc_udev = udev = uaa->device; + + /* First set configuration index 0, the default one for ugen. */ + err = usbd_set_config_index(udev, 0, 0); + if (err) { + printf("%s: setting configuration index 0 failed\n", + USBDEVNAME(sc->sc_dev)); + sc->sc_dying = 1; + USB_ATTACH_ERROR_RETURN; + } + conf = usbd_get_config_descriptor(udev)->bConfigurationValue; + + /* Set up all the local state for this configuration. */ + err = ugen_set_config(sc, conf); + if (err) { printf("%s: setting configuration %d failed\n", USBDEVNAME(sc->sc_dev), conf); sc->sc_dying = 1; USB_ATTACH_ERROR_RETURN; } + +#ifdef __FreeBSD__ + { + struct int global_init_done = 0; + if (!global_init_done) { + cdevsw_add(&ugen_cdevsw); + global_init_done = 1; + } + } +#endif + + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + USB_ATTACH_SUCCESS_RETURN; } @@ -204,30 +225,30 @@ ugen_set_config(sc, configno) struct ugen_endpoint *sce; u_int8_t niface, nendpt; int ifaceno, endptno, endpt; - usbd_status r; + usbd_status err; int dir; DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", USBDEVNAME(sc->sc_dev), configno, sc)); + /* Avoid setting the current value. */ if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { - /* Avoid setting the current value. */ - r = usbd_set_config_no(dev, configno, 0); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_config_no(dev, configno, 0); + if (err) + return (err); } - r = usbd_interface_count(dev, &niface); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_interface_count(dev, &niface); + if (err) + return (err); memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); for (ifaceno = 0; ifaceno < niface; ifaceno++) { DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); - r = usbd_device2interface_handle(dev, ifaceno, &iface); - if (r != USBD_NORMAL_COMPLETION) - return (r); - r = usbd_endpoint_count(iface, &nendpt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_device2interface_handle(dev, ifaceno, &iface); + if (err) + return (err); + err = usbd_endpoint_count(iface, &nendpt); + if (err) + return (err); for (endptno = 0; endptno < nendpt; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; @@ -258,13 +279,14 @@ ugenopen(dev, flag, mode, p) usb_endpoint_descriptor_t *edesc; struct ugen_endpoint *sce; int dir, isize; - usbd_status r; + usbd_status err; USB_GET_SC_OPEN(ugen, unit, sc); + DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", flag, mode, unit, endpt)); - if (sc->sc_dying) + if (sc == NULL || sc->sc_dying) return (ENXIO); if (sc->sc_is_open[endpt]) @@ -274,6 +296,7 @@ ugenopen(dev, flag, mode, p) sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; return (0); } + /* Make sure there are pipes for all directions. */ for (dir = OUT; dir <= IN; dir++) { if (flag & (dir == OUT ? FWRITE : FREAD)) { @@ -304,11 +327,12 @@ ugenopen(dev, flag, mode, p) endpt, isize)); if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) return (ENOMEM); - r = usbd_open_pipe_intr(sce->iface, + err = usbd_open_pipe_intr(sce->iface, edesc->bEndpointAddress, USBD_SHORT_XFER_OK, &sce->pipeh, sce, - sce->ibuf, isize, ugenintr); - if (r != USBD_NORMAL_COMPLETION) { + sce->ibuf, isize, ugenintr, + USBD_DEFAULT_INTERVAL); + if (err) { free(sce->ibuf, M_USBDEV); clfree(&sce->q); return (EIO); @@ -316,10 +340,10 @@ ugenopen(dev, flag, mode, p) DPRINTFN(5, ("ugenopen: interrupt open done\n")); break; case UE_BULK: - r = usbd_open_pipe(sce->iface, + err = usbd_open_pipe(sce->iface, edesc->bEndpointAddress, 0, &sce->pipeh); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (EIO); break; case UE_CONTROL: @@ -344,6 +368,7 @@ ugenclose(dev, flag, mode, p) int dir; USB_GET_SC(ugen, UGENUNIT(dev), sc); + DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", flag, mode, UGENUNIT(dev), endpt)); @@ -364,7 +389,7 @@ ugenclose(dev, flag, mode, p) if (!(flag & (dir == OUT ? FWRITE : FREAD))) continue; sce = &sc->sc_endpoints[endpt][dir]; - if (!sce || !sce->pipeh) + if (sce == NULL || sce->pipeh == NULL) continue; DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", endpt, dir, sce)); @@ -375,7 +400,7 @@ ugenclose(dev, flag, mode, p) if (sce->ibuf) { free(sce->ibuf, M_USBDEV); - sce->ibuf = 0; + sce->ibuf = NULL; clfree(&sce->q); } } @@ -394,8 +419,8 @@ ugen_do_read(sc, endpt, uio, flag) struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; u_int32_t n, tn; char buf[UGEN_BBSIZE]; - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; int s; int error = 0; u_char buffer[UGEN_CHUNK]; @@ -460,21 +485,21 @@ ugen_do_read(sc, endpt, uio, flag) } break; case UE_BULK: - reqh = usbd_alloc_request(sc->sc_udev); - if (reqh == 0) + xfer = usbd_alloc_xfer(sc->sc_udev); + if (xfer == 0) return (ENOMEM); while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); tn = n; - r = usbd_bulk_transfer( - reqh, sce->pipeh, + err = usbd_bulk_transfer( + xfer, sce->pipeh, sce->state & UGEN_SHORT_OK ? USBD_SHORT_XFER_OK : 0, sce->timeout, buf, &tn, "ugenrb"); - if (r != USBD_NORMAL_COMPLETION) { - if (r == USBD_INTERRUPTED) + if (err) { + if (err == USBD_INTERRUPTED) error = EINTR; - else if (r == USBD_TIMEOUT) + else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; @@ -485,7 +510,7 @@ ugen_do_read(sc, endpt, uio, flag) if (error || tn < n) break; } - usbd_free_request(reqh); + usbd_free_xfer(xfer); break; default: return (ENXIO); @@ -504,6 +529,7 @@ ugenread(dev, uio, flag) int error; USB_GET_SC(ugen, UGENUNIT(dev), sc); + sc->sc_refcnt++; error = ugen_do_read(sc, endpt, uio, flag); if (--sc->sc_refcnt < 0) @@ -522,12 +548,10 @@ ugen_do_write(sc, endpt, uio, flag) u_int32_t n; int error = 0; char buf[UGEN_BBSIZE]; - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; -#if defined(__NetBSD__) || defined(__OpenBSD__) DPRINTFN(5, ("ugenwrite: %d:%d\n", sc->sc_dev.dv_unit, endpt)); -#endif if (sc->sc_dying) return (EIO); @@ -548,25 +572,27 @@ ugen_do_write(sc, endpt, uio, flag) switch (sce->edesc->bmAttributes & UE_XFERTYPE) { case UE_BULK: - reqh = usbd_alloc_request(sc->sc_udev); - if (reqh == 0) + xfer = usbd_alloc_xfer(sc->sc_udev); + if (xfer == 0) return (EIO); while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - r = usbd_bulk_transfer(reqh, sce->pipeh, 0, + err = usbd_bulk_transfer(xfer, sce->pipeh, 0, sce->timeout, buf, &n,"ugenwb"); - if (r != USBD_NORMAL_COMPLETION) { - if (r == USBD_INTERRUPTED) + if (err) { + if (err == USBD_INTERRUPTED) error = EINTR; + else if (err == USBD_TIMEOUT) + error = ETIMEDOUT; else error = EIO; break; } } - usbd_free_request(reqh); + usbd_free_xfer(xfer); break; default: return (ENXIO); @@ -585,6 +611,7 @@ ugenwrite(dev, uio, flag) int error; USB_GET_SC(ugen, UGENUNIT(dev), sc); + sc->sc_refcnt++; error = ugen_do_write(sc, endpt, uio, flag); if (--sc->sc_refcnt < 0) @@ -660,12 +687,15 @@ USB_DETACH(ugen) /* XXX not implemented yet */ #endif + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + return (0); } void -ugenintr(reqh, addr, status) - usbd_request_handle reqh; +ugenintr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { @@ -683,11 +713,11 @@ ugenintr(reqh, addr, status) return; } - usbd_get_request_status(reqh, 0, 0, &count, 0); + usbd_get_xfer_status(xfer, NULL, NULL, &count, 0); ibuf = sce->ibuf; - DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n", - reqh, status, count)); + DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", + xfer, status, count)); DPRINTFN(5, (" data = %02x %02x %02x\n", ibuf[0], ibuf[1], ibuf[2])); @@ -708,25 +738,25 @@ ugen_set_interface(sc, ifaceidx, altno) { usbd_interface_handle iface; usb_endpoint_descriptor_t *ed; - usbd_status r; + usbd_status err; struct ugen_endpoint *sce; u_int8_t niface, nendpt, endptno, endpt; int dir; DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno)); - r = usbd_interface_count(sc->sc_udev, &niface); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_interface_count(sc->sc_udev, &niface); + if (err) + return (err); if (ifaceidx < 0 || ifaceidx >= niface) return (USBD_INVAL); - r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (r != USBD_NORMAL_COMPLETION) - return (r); - r = usbd_endpoint_count(iface, &nendpt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); + if (err) + return (err); + err = usbd_endpoint_count(iface, &nendpt); + if (err) + return (err); for (endptno = 0; endptno < nendpt; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; @@ -738,13 +768,13 @@ ugen_set_interface(sc, ifaceidx, altno) } /* change setting */ - r = usbd_set_interface(iface, altno); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_interface(iface, altno); + if (err) + return (err); - r = usbd_endpoint_count(iface, &nendpt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_endpoint_count(iface, &nendpt); + if (err) + return (err); for (endptno = 0; endptno < nendpt; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; @@ -766,7 +796,7 @@ ugen_get_cdesc(sc, index, lenp) { usb_config_descriptor_t *cdesc, *tdesc, cdescr; int len; - usbd_status r; + usbd_status err; if (index == USB_CURRENT_CONFIG_INDEX) { tdesc = usbd_get_config_descriptor(sc->sc_udev); @@ -777,16 +807,16 @@ ugen_get_cdesc(sc, index, lenp) memcpy(cdesc, tdesc, len); DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len)); } else { - r = usbd_get_config_desc(sc->sc_udev, index, &cdescr); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_config_desc(sc->sc_udev, index, &cdescr); + if (err) return (0); len = UGETW(cdescr.wTotalLength); DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len)); if (lenp) *lenp = len; cdesc = malloc(len, M_TEMP, M_WAITOK); - r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len); + if (err) { free(cdesc, M_TEMP); return (0); } @@ -800,11 +830,11 @@ ugen_get_alt_index(sc, ifaceidx) int ifaceidx; { usbd_interface_handle iface; - usbd_status r; + usbd_status err; - r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (r != USBD_NORMAL_COMPLETION) - return (-1); + err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); + if (err) + return (-1); return (usbd_get_interface_altindex(iface)); } @@ -818,7 +848,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) struct proc *p; { struct ugen_endpoint *sce; - usbd_status r; + usbd_status err; usbd_interface_handle iface; struct usb_config_desc *cd; usb_config_descriptor_t *cdesc; @@ -876,32 +906,32 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) return (EINVAL); switch (cmd) { -#ifdef USB_DEBUG +#ifdef UGEN_DEBUG case USB_SETDEBUG: ugendebug = *(int *)addr; break; #endif case USB_GET_CONFIG: - r = usbd_get_config(sc->sc_udev, &conf); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_config(sc->sc_udev, &conf); + if (err) return (EIO); *(int *)addr = conf; break; case USB_SET_CONFIG: if (!(flag & FWRITE)) return (EPERM); - r = ugen_set_config(sc, *(int *)addr); - if (r != USBD_NORMAL_COMPLETION) + err = ugen_set_config(sc, *(int *)addr); + if (err) return (EIO); break; case USB_GET_ALTINTERFACE: ai = (struct usb_alt_interface *)addr; - r = usbd_device2interface_handle(sc->sc_udev, + err = usbd_device2interface_handle(sc->sc_udev, ai->interface_index, &iface); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (EINVAL); idesc = usbd_get_interface_descriptor(iface); - if (!idesc) + if (idesc == NULL) return (EIO); ai->alt_no = idesc->bAlternateSetting; break; @@ -909,21 +939,21 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) if (!(flag & FWRITE)) return (EPERM); ai = (struct usb_alt_interface *)addr; - r = usbd_device2interface_handle(sc->sc_udev, + err = usbd_device2interface_handle(sc->sc_udev, ai->interface_index, &iface); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (EINVAL); - r = ugen_set_interface(sc, ai->interface_index, ai->alt_no); - if (r != USBD_NORMAL_COMPLETION) + err = ugen_set_interface(sc, ai->interface_index, ai->alt_no); + if (err) return (EINVAL); break; case USB_GET_NO_ALT: ai = (struct usb_alt_interface *)addr; cdesc = ugen_get_cdesc(sc, ai->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); idesc = usbd_find_idesc(cdesc, ai->interface_index, 0); - if (!idesc) { + if (idesc == NULL) { free(cdesc, M_TEMP); return (EINVAL); } @@ -937,7 +967,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) case USB_GET_CONFIG_DESC: cd = (struct usb_config_desc *)addr; cdesc = ugen_get_cdesc(sc, cd->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); cd->desc = *cdesc; free(cdesc, M_TEMP); @@ -945,7 +975,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) case USB_GET_INTERFACE_DESC: id = (struct usb_interface_desc *)addr; cdesc = ugen_get_cdesc(sc, id->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); if (id->config_index == USB_CURRENT_CONFIG_INDEX && id->alt_index == USB_CURRENT_ALT_INDEX) @@ -953,7 +983,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) else alt = id->alt_index; idesc = usbd_find_idesc(cdesc, id->interface_index, alt); - if (!idesc) { + if (idesc == NULL) { free(cdesc, M_TEMP); return (EINVAL); } @@ -963,7 +993,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) case USB_GET_ENDPOINT_DESC: ed = (struct usb_endpoint_desc *)addr; cdesc = ugen_get_cdesc(sc, ed->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); if (ed->config_index == USB_CURRENT_CONFIG_INDEX && ed->alt_index == USB_CURRENT_ALT_INDEX) @@ -972,7 +1002,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) alt = ed->alt_index; edesc = usbd_find_edesc(cdesc, ed->interface_index, alt, ed->endpoint_index); - if (!edesc) { + if (edesc == NULL) { free(cdesc, M_TEMP); return (EINVAL); } @@ -1005,9 +1035,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) } case USB_GET_STRING_DESC: si = (struct usb_string_desc *)addr; - r = usbd_get_string_desc(sc->sc_udev, si->string_index, + err = usbd_get_string_desc(sc->sc_udev, si->string_index, si->language_id, &si->desc); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (EINVAL); break; case USB_DO_REQUEST: @@ -1017,7 +1047,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) struct iovec iov; struct uio uio; void *ptr = 0; - usbd_status r; + usbd_status err; int error = 0; if (!(flag & FWRITE)) @@ -1052,9 +1082,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) goto ret; } } - r = usbd_do_request_flags(sc->sc_udev, &ur->request, + err = usbd_do_request_flags(sc->sc_udev, &ur->request, ptr, ur->flags, &ur->actlen); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { error = EIO; goto ret; } @@ -1093,6 +1123,7 @@ ugenioctl(dev, cmd, addr, flag, p) int error; USB_GET_SC(ugen, UGENUNIT(dev), sc); + sc->sc_refcnt++; error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p); if (--sc->sc_refcnt < 0) @@ -1121,7 +1152,7 @@ ugenpoll(dev, events, p) return (EINVAL); #ifdef DIAGNOSTIC if (!sce->edesc) { - printf("ugenwrite: no edesc\n"); + printf("ugenpoll: no edesc\n"); return (EIO); } if (!sce->pipeh) { @@ -1156,5 +1187,5 @@ ugenpoll(dev, events, p) } #if defined(__FreeBSD__) -DEV_DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, ugen_cdevsw, usbd_driver_load, 0); +DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0); #endif diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index a92739a62c5..14c9c56b562 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhci.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: uhci.c,v 1.62 1999/10/23 00:21:01 augustss Exp $ */ +/* $OpenBSD: uhci.c,v 1.7 2000/03/26 08:39:45 aaron Exp $ */ +/* $NetBSD: uhci.c,v 1.87 2000/02/29 21:37:01 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,10 +42,10 @@ * USB Universal Host Controller driver. * Handles e.g. PIIX3 and PIIX4. * - * Data sheets: ftp://download.intel.com/design/intarch/datashts/29055002.pdf - * ftp://download.intel.com/design/intarch/datashts/29056201.pdf * UHCI spec: http://www.intel.com/design/usb/uhci11d.pdf * USB spec: http://www.usb.org/developers/data/usb11.pdf + * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf + * ftp://download.intel.com/design/intarch/datashts/29056201.pdf */ #include @@ -54,17 +54,18 @@ #include #if defined(__NetBSD__) || defined(__OpenBSD__) #include +#include #elif defined(__FreeBSD__) #include #include +#include +#if defined(DIAGNOSTIC) && defined(__i386) +#include +#endif #endif #include #include -#include -#if defined(__FreeBSD__) -#include -#endif #include #include @@ -91,10 +92,10 @@ struct cfdriver uhci_cd = { }; #endif -#ifdef USB_DEBUG +#ifdef UHCI_DEBUG #define DPRINTF(x) if (uhcidebug) printf x #define DPRINTFN(n,x) if (uhcidebug>(n)) printf x -extern int uhcidebug; +int uhcidebug = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -149,6 +150,7 @@ struct uhci_pipe { LIST_HEAD(, uhci_intr_info) uhci_ii_free; void uhci_busreset __P((uhci_softc_t *)); +void uhci_shutdown __P((void *v)); void uhci_power __P((int, void *)); usbd_status uhci_run __P((uhci_softc_t *, int run)); uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *)); @@ -166,15 +168,15 @@ void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *)); void uhci_free_std_chain __P((uhci_softc_t *, uhci_soft_td_t *, uhci_soft_td_t *)); usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *, - int, int, int, usb_dma_t *, + int, int, u_int16_t, usb_dma_t *, uhci_soft_td_t **, uhci_soft_td_t **)); void uhci_timo __P((void *)); -void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle)); +void uhci_waitintr __P((uhci_softc_t *, usbd_xfer_handle)); void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *)); void uhci_idone __P((uhci_intr_info_t *)); -void uhci_abort_req __P((usbd_request_handle, usbd_status status)); -void uhci_abort_req_end __P((void *v)); +void uhci_abort_xfer __P((usbd_xfer_handle, usbd_status status)); +void uhci_abort_xfer_end __P((void *v)); void uhci_timeout __P((void *)); void uhci_wakeup_ctrl __P((void *, int, int, void *, int)); void uhci_lock_frames __P((uhci_softc_t *)); @@ -184,53 +186,59 @@ void uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *)); void uhci_remove_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *)); void uhci_remove_bulk __P((uhci_softc_t *, uhci_soft_qh_t *)); int uhci_str __P((usb_string_descriptor_t *, int, char *)); + usbd_status uhci_setup_isoc __P((usbd_pipe_handle pipe)); -void uhci_device_isoc_enter __P((usbd_request_handle)); +void uhci_device_isoc_enter __P((usbd_xfer_handle)); -void uhci_wakeup_cb __P((usbd_request_handle reqh)); +void uhci_wakeup_cb __P((usbd_xfer_handle xfer)); usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t)); void uhci_freem __P((struct usbd_bus *, usb_dma_t *)); -usbd_status uhci_device_ctrl_transfer __P((usbd_request_handle)); -usbd_status uhci_device_ctrl_start __P((usbd_request_handle)); -void uhci_device_ctrl_abort __P((usbd_request_handle)); +usbd_xfer_handle uhci_allocx __P((struct usbd_bus *)); +void uhci_freex __P((struct usbd_bus *, usbd_xfer_handle)); + +usbd_status uhci_device_ctrl_transfer __P((usbd_xfer_handle)); +usbd_status uhci_device_ctrl_start __P((usbd_xfer_handle)); +void uhci_device_ctrl_abort __P((usbd_xfer_handle)); void uhci_device_ctrl_close __P((usbd_pipe_handle)); -void uhci_device_ctrl_done __P((usbd_request_handle)); +void uhci_device_ctrl_done __P((usbd_xfer_handle)); -usbd_status uhci_device_intr_transfer __P((usbd_request_handle)); -usbd_status uhci_device_intr_start __P((usbd_request_handle)); -void uhci_device_intr_abort __P((usbd_request_handle)); +usbd_status uhci_device_intr_transfer __P((usbd_xfer_handle)); +usbd_status uhci_device_intr_start __P((usbd_xfer_handle)); +void uhci_device_intr_abort __P((usbd_xfer_handle)); void uhci_device_intr_close __P((usbd_pipe_handle)); -void uhci_device_intr_done __P((usbd_request_handle)); +void uhci_device_intr_done __P((usbd_xfer_handle)); -usbd_status uhci_device_bulk_transfer __P((usbd_request_handle)); -usbd_status uhci_device_bulk_start __P((usbd_request_handle)); -void uhci_device_bulk_abort __P((usbd_request_handle)); +usbd_status uhci_device_bulk_transfer __P((usbd_xfer_handle)); +usbd_status uhci_device_bulk_start __P((usbd_xfer_handle)); +void uhci_device_bulk_abort __P((usbd_xfer_handle)); void uhci_device_bulk_close __P((usbd_pipe_handle)); -void uhci_device_bulk_done __P((usbd_request_handle)); +void uhci_device_bulk_done __P((usbd_xfer_handle)); -usbd_status uhci_device_isoc_transfer __P((usbd_request_handle)); -usbd_status uhci_device_isoc_start __P((usbd_request_handle)); -void uhci_device_isoc_abort __P((usbd_request_handle)); +usbd_status uhci_device_isoc_transfer __P((usbd_xfer_handle)); +usbd_status uhci_device_isoc_start __P((usbd_xfer_handle)); +void uhci_device_isoc_abort __P((usbd_xfer_handle)); void uhci_device_isoc_close __P((usbd_pipe_handle)); -void uhci_device_isoc_done __P((usbd_request_handle)); +void uhci_device_isoc_done __P((usbd_xfer_handle)); -usbd_status uhci_root_ctrl_transfer __P((usbd_request_handle)); -usbd_status uhci_root_ctrl_start __P((usbd_request_handle)); -void uhci_root_ctrl_abort __P((usbd_request_handle)); +usbd_status uhci_root_ctrl_transfer __P((usbd_xfer_handle)); +usbd_status uhci_root_ctrl_start __P((usbd_xfer_handle)); +void uhci_root_ctrl_abort __P((usbd_xfer_handle)); void uhci_root_ctrl_close __P((usbd_pipe_handle)); +void uhci_root_ctrl_done __P((usbd_xfer_handle)); -usbd_status uhci_root_intr_transfer __P((usbd_request_handle)); -usbd_status uhci_root_intr_start __P((usbd_request_handle)); -void uhci_root_intr_abort __P((usbd_request_handle)); +usbd_status uhci_root_intr_transfer __P((usbd_xfer_handle)); +usbd_status uhci_root_intr_start __P((usbd_xfer_handle)); +void uhci_root_intr_abort __P((usbd_xfer_handle)); void uhci_root_intr_close __P((usbd_pipe_handle)); -void uhci_root_intr_done __P((usbd_request_handle)); +void uhci_root_intr_done __P((usbd_xfer_handle)); usbd_status uhci_open __P((usbd_pipe_handle)); void uhci_poll __P((struct usbd_bus *)); +void uhci_softintr __P((struct usbd_bus *)); -usbd_status uhci_device_request __P((usbd_request_handle reqh)); +usbd_status uhci_device_request __P((usbd_xfer_handle xfer)); void uhci_add_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *)); void uhci_remove_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *)); @@ -242,12 +250,14 @@ void uhci_noop __P((usbd_pipe_handle pipe)); #ifdef UHCI_DEBUG static void uhci_dumpregs __P((uhci_softc_t *)); -void uhci_dump_tds __P((uhci_soft_td_t *)); +void uhci_dump_qhs __P((uhci_soft_qh_t *)); void uhci_dump_qh __P((uhci_soft_qh_t *)); void uhci_dump __P((void)); +void uhci_dump_tds __P((uhci_soft_td_t *)); void uhci_dump_td __P((uhci_soft_td_t *)); #endif +#define UWRITE1(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) #define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) #define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r)) @@ -265,9 +275,12 @@ void uhci_dump_td __P((uhci_soft_td_t *)); struct usbd_bus_methods uhci_bus_methods = { uhci_open, + uhci_softintr, uhci_poll, uhci_allocm, uhci_freem, + uhci_allocx, + uhci_freex, }; struct usbd_pipe_methods uhci_root_ctrl_methods = { @@ -276,7 +289,7 @@ struct usbd_pipe_methods uhci_root_ctrl_methods = { uhci_root_ctrl_abort, uhci_root_ctrl_close, uhci_noop, - 0, + uhci_root_ctrl_done, }; struct usbd_pipe_methods uhci_root_intr_methods = { @@ -337,14 +350,14 @@ usbd_status uhci_init(sc) uhci_softc_t *sc; { - usbd_status r; + usbd_status err; int i, j; uhci_soft_qh_t *csqh, *bsqh, *sqh; uhci_soft_td_t *std; DPRINTFN(1,("uhci_init: start\n")); -#if defined(UHCI_DEBUG) +#ifdef UHCI_DEBUG if (uhcidebug > 2) uhci_dumpregs(sc); #endif @@ -355,18 +368,18 @@ uhci_init(sc) uhci_busreset(sc); /* Allocate and initialize real frame array. */ - r = usb_allocmem(&sc->sc_bus, + err = usb_allocmem(&sc->sc_bus, UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), UHCI_FRAMELIST_ALIGN, &sc->sc_dma); - if (r != USBD_NORMAL_COMPLETION) - return (r); + if (err) + return (err); sc->sc_pframes = KERNADDR(&sc->sc_dma); UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */ UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/ /* Allocate the dummy QH where bulk traffic will be queued. */ bsqh = uhci_alloc_sqh(sc); - if (!bsqh) + if (bsqh == NULL) return (USBD_NOMEM); bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */ bsqh->qh.qh_elink = LE(UHCI_PTR_T); @@ -374,7 +387,7 @@ uhci_init(sc) /* Allocate the dummy QH where control traffic will be queued. */ csqh = uhci_alloc_sqh(sc); - if (!csqh) + if (csqh == NULL) return (USBD_NOMEM); csqh->hlink = bsqh; csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q); @@ -389,7 +402,7 @@ uhci_init(sc) for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = uhci_alloc_std(sc); sqh = uhci_alloc_sqh(sc); - if (!std || !sqh) + if (std == NULL || sqh == NULL) return (USBD_NOMEM); std->link.sqh = sqh; std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q); @@ -412,6 +425,8 @@ uhci_init(sc) LIST_INIT(&sc->sc_intrhead); + SIMPLEQ_INIT(&sc->sc_free_xfers); + /* Set up the bus struct. */ sc->sc_bus.methods = &uhci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct uhci_pipe); @@ -419,13 +434,18 @@ uhci_init(sc) sc->sc_suspend = PWR_RESUME; sc->sc_powerhook = powerhook_establish(uhci_power, sc); + sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc); + DPRINTFN(1,("uhci_init: enabling\n")); UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */ + UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */ + return (uhci_run(sc, 1)); /* and here we go... */ } +#if defined(__NetBSD__) || defined(__OpenBSD__) int uhci_activate(self, act) device_ptr_t self; @@ -452,6 +472,7 @@ uhci_detach(sc, flags) struct uhci_softc *sc; int flags; { + usbd_xfer_handle xfer; int rv = 0; if (sc->sc_child != NULL) @@ -461,10 +482,22 @@ uhci_detach(sc, flags) return (rv); powerhook_disestablish(sc->sc_powerhook); - /* free data structures XXX */ + shutdownhook_disestablish(sc->sc_shutdownhook); + + /* Free all xfers associated with this HC. */ + for (;;) { + xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); + if (xfer == NULL) + break; + SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next); + free(xfer, M_USB); + } + + /* XXX free other data structures XXX */ return (rv); } +#endif usbd_status uhci_allocm(bus, dma, size) @@ -472,11 +505,8 @@ uhci_allocm(bus, dma, size) usb_dma_t *dma; u_int32_t size; { -#if defined(__NetBSD__) || defined(__OpenBSD__) - struct uhci_softc *sc = (struct uhci_softc *)bus; -#endif - - return (usb_allocmem(&sc->sc_bus, size, 0, dma)); + return (usb_allocmem(&((struct uhci_softc *)bus)->sc_bus, size, 0, + dma)); } void @@ -484,14 +514,49 @@ uhci_freem(bus, dma) struct usbd_bus *bus; usb_dma_t *dma; { -#if defined(__NetBSD__) || defined(__OpenBSD__) + usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma); +} + +usbd_xfer_handle +uhci_allocx(bus) + struct usbd_bus *bus; +{ struct uhci_softc *sc = (struct uhci_softc *)bus; -#endif + usbd_xfer_handle xfer; - usb_freemem(&sc->sc_bus, dma); + xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); + if (xfer != NULL) + SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next); + else + xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT); + if (xfer != NULL) + memset(xfer, 0, sizeof *xfer); + return (xfer); +} + +void +uhci_freex(bus, xfer) + struct usbd_bus *bus; + usbd_xfer_handle xfer; +{ + struct uhci_softc *sc = (struct uhci_softc *)bus; + + SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); +} + +/* + * Shut down the controller when the system is going down. + */ +void +uhci_shutdown(v) + void *v; +{ + uhci_softc_t *sc = v; + + DPRINTF(("uhci_shutdown: stopping the HC\n")); + uhci_run(sc, 0); /* stop the controller */ } -#if defined(__NetBSD__) || defined(__OpenBSD__) /* * Handle suspend/resume. * @@ -515,26 +580,26 @@ uhci_power(why, v) sc, why, sc->sc_suspend, cmd)); if (why != PWR_RESUME) { -#if defined(UHCI_DEBUG) +#ifdef UHCI_DEBUG if (uhcidebug > 2) uhci_dumpregs(sc); #endif - if (sc->sc_has_timo) + if (sc->sc_has_timo != NULL) usb_untimeout(uhci_timo, sc->sc_has_timo, sc->sc_has_timo->timo_handle); sc->sc_bus.use_polling++; uhci_run(sc, 0); /* stop the controller */ + + /* save some state if BIOS doesn't */ + sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); + sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); + UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); sc->sc_suspend = why; sc->sc_bus.use_polling--; DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); } else { - /* - * XXX We should really do much more here in case the - * controller registers have been lost and BIOS has - * not restored them. - */ #ifdef DIAGNOSTIC if (sc->sc_suspend == PWR_RESUME) printf("uhci_power: weird, resume without suspend.\n"); @@ -543,6 +608,12 @@ uhci_power(why, v) sc->sc_suspend = why; if (cmd & UHCI_CMD_RS) uhci_run(sc, 0); /* in case BIOS has started it */ + + /* restore saved state */ + UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); + UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); + UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); + UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ @@ -551,17 +622,16 @@ uhci_power(why, v) uhci_run(sc, 1); /* and start traffic again */ usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); sc->sc_bus.use_polling--; - if (sc->sc_has_timo) + if (sc->sc_has_timo != NULL) usb_timeout(uhci_timo, sc->sc_has_timo, sc->sc_ival, sc->sc_has_timo->timo_handle); -#if defined(UHCI_DEBUG) +#ifdef UHCI_DEBUG if (uhcidebug > 2) uhci_dumpregs(sc); #endif } splx(s); } -#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ #ifdef UHCI_DEBUG static void @@ -609,14 +679,13 @@ uhci_dump_td(p) } void -uhci_dump_qh(p) - uhci_soft_qh_t *p; +uhci_dump_qh(sqh) + uhci_soft_qh_t *sqh; { - DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", p, - (int)p->physaddr, LE(p->qh.qh_hlink), LE(p->qh.qh_elink))); + DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh, + (int)sqh->physaddr, LE(sqh->qh.qh_hlink), LE(sqh->qh.qh_elink))); } - #if 0 void uhci_dump() @@ -630,14 +699,54 @@ uhci_dump() } #endif +void +uhci_dump_qhs(sqh) + uhci_soft_qh_t *sqh; +{ + uhci_dump_qh(sqh); + + /* uhci_dump_sqh displays all the QHs and TDs from the given QH onwards + * Traverses sideways first, then down. + * + * QH1 + * QH2 + * No QH + * TD2.1 + * TD2.2 + * TD1.1 + * etc. + * + * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1. + */ + + if (sqh->hlink != NULL && !(sqh->qh.qh_hlink & UHCI_PTR_T)) + uhci_dump_qhs(sqh->hlink); + else + DPRINTF(("No QH\n")); + + if (sqh->elink != NULL && !(sqh->qh.qh_elink & UHCI_PTR_T)) + uhci_dump_tds(sqh->elink); + else + DPRINTF(("No TD\n")); +} + void uhci_dump_tds(std) uhci_soft_td_t *std; { - uhci_soft_td_t *p; + uhci_soft_td_t *td; + + for(td = std; td != NULL; td = td->link.std) { + uhci_dump_td(td); - for(p = std; p; p = p->link.std) - uhci_dump_td(p); + /* Check whether the link pointer in this TD marks + * the link pointer as end of queue. This avoids + * printing the free list in case the queue/TD has + * already been moved there (seatbelt). + */ + if (td->td.td_link & UHCI_PTR_T || td->td.td_link == 0) + break; + } } #endif @@ -649,17 +758,17 @@ void uhci_timo(addr) void *addr; { - usbd_request_handle reqh = addr; - usbd_pipe_handle pipe = reqh->pipe; + usbd_xfer_handle xfer = addr; + usbd_pipe_handle pipe = xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; int s; u_char *p; - DPRINTFN(15, ("uhci_timo\n")); + DPRINTFN(20, ("uhci_timo\n")); - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); + usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle); - p = KERNADDR(&reqh->dmabuf); + p = KERNADDR(&xfer->dmabuf); p[0] = 0; if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) p[0] |= 1<<1; @@ -669,19 +778,25 @@ uhci_timo(addr) /* No change, try again in a while */ return; - reqh->actlen = 1; - reqh->status = USBD_NORMAL_COMPLETION; + xfer->actlen = 1; + xfer->status = USBD_NORMAL_COMPLETION; s = splusb(); - reqh->hcpriv = 0; - reqh->device->bus->intr_context++; - usb_transfer_complete(reqh); - reqh->device->bus->intr_context--; + xfer->hcpriv = 0; + xfer->device->bus->intr_context++; + usb_transfer_complete(xfer); + xfer->device->bus->intr_context--; splx(s); } void -uhci_root_intr_done(reqh) - usbd_request_handle reqh; +uhci_root_intr_done(xfer) + usbd_xfer_handle xfer; +{ +} + +void +uhci_root_ctrl_done(xfer) + usbd_xfer_handle xfer; { } @@ -691,7 +806,8 @@ uhci_lock_frames(sc) uhci_softc_t *sc; { int s = splusb(); - while (sc->sc_vflock) { + + while (sc->sc_vflock & UHCI_HAS_LOCK) { sc->sc_vflock |= UHCI_WANT_LOCK; tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0); } @@ -704,6 +820,7 @@ uhci_unlock_frames(sc) uhci_softc_t *sc; { int s = splusb(); + sc->sc_vflock &= ~UHCI_HAS_LOCK; if (sc->sc_vflock & UHCI_WANT_LOCK) wakeup(&sc->sc_vflock); @@ -838,9 +955,8 @@ uhci_intr(arg) uhci_softc_t *sc = arg; int status; int ack; - uhci_intr_info_t *ii; -#if defined(UHCI_DEBUG) +#ifdef UHCI_DEBUG if (uhcidebug > 15) { DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev))); uhci_dumpregs(sc); @@ -867,17 +983,18 @@ uhci_intr(arg) } if (status & UHCI_STS_HSE) { ack |= UHCI_STS_HSE; - printf("%s: host controller process error\n", - USBDEVNAME(sc->sc_bus.bdev)); + printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev)); } if (status & UHCI_STS_HCPE) { ack |= UHCI_STS_HCPE; - printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev)); + printf("%s: host controller process error\n", + USBDEVNAME(sc->sc_bus.bdev)); } if (status & UHCI_STS_HCH) { /* no acknowledge needed */ printf("%s: host controller halted\n", USBDEVNAME(sc->sc_bus.bdev)); + sc->sc_dying = 1; } if (ack) /* acknowledge the ints */ @@ -885,8 +1002,24 @@ uhci_intr(arg) else /* nothing to acknowledge */ return (0); - sc->sc_bus.intr_context++; sc->sc_bus.no_intrs++; + usb_schedsoftintr(&sc->sc_bus); + + DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev))); + + return (1); +} + +void +uhci_softintr(bus) + struct usbd_bus *bus; +{ + uhci_softc_t *sc = (uhci_softc_t *)bus; + uhci_intr_info_t *ii; + + DPRINTFN(10,("%s: uhci_softintr\n", USBDEVNAME(sc->sc_bus.bdev))); + + sc->sc_bus.intr_context++; /* * Interrupts on UHCI really suck. When the host controller @@ -902,11 +1035,7 @@ uhci_intr(arg) for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) uhci_check_intr(sc, ii); - DPRINTFN(10, ("uhci_intr: exit\n")); - sc->sc_bus.intr_context--; - - return (1); } /* Check for an interrupt. */ @@ -920,16 +1049,16 @@ uhci_check_intr(sc, ii) DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii)); #ifdef DIAGNOSTIC - if (!ii) { + if (ii == NULL) { printf("uhci_check_intr: no ii? %p\n", ii); return; } #endif - if (!ii->stdstart) + if (ii->stdstart == NULL) return; lstd = ii->stdend; #ifdef DIAGNOSTIC - if (!lstd) { + if (lstd == NULL) { printf("uhci_check_intr: std==0\n"); return; } @@ -943,9 +1072,16 @@ uhci_check_intr(sc, ii) DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii)); for (std = ii->stdstart; std != lstd; std = std->link.std) { status = LE(std->td.td_status); - if ((status & UHCI_TD_STALLED) || - (status & (UHCI_TD_SPD | UHCI_TD_ACTIVE)) == - UHCI_TD_SPD) + /* If there's an active TD the xfer isn't done. */ + if (status & UHCI_TD_ACTIVE) + break; + /* Any kind of error makes the xfer done. */ + if (status & UHCI_TD_STALLED) + goto done; + /* We want short packets, and it is short: it's done */ + if ((status & UHCI_TD_SPD) && + UHCI_TD_GET_ACTLEN(status) < + UHCI_TD_GET_MAXLEN(LE(std->td.td_token))) goto done; } DPRINTFN(15, ("uhci_check_intr: ii=%p std=%p still active\n", @@ -953,6 +1089,7 @@ uhci_check_intr(sc, ii) return; } done: + DPRINTFN(15, ("uhci_check_intr: ii=%p done\n", ii)); usb_untimeout(uhci_timeout, ii, ii->timeout_handle); uhci_idone(ii); } @@ -962,10 +1099,10 @@ void uhci_idone(ii) uhci_intr_info_t *ii; { - usbd_request_handle reqh = ii->reqh; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + usbd_xfer_handle xfer = ii->xfer; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_soft_td_t *std; - u_int32_t status; + u_int32_t status = 0, nstatus; int actlen; #ifdef DIAGNOSTIC @@ -981,22 +1118,22 @@ uhci_idone(ii) } #endif - if (reqh->status == USBD_CANCELLED || - reqh->status == USBD_TIMEOUT) { - DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh)); + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) { + DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer)); return; } - if (reqh->nframes) { + if (xfer->nframes != 0) { /* Isoc transfer, do things differently. */ uhci_soft_td_t **stds = upipe->u.iso.stds; int i, n, nframes; DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii)); - nframes = reqh->nframes; + nframes = xfer->nframes; actlen = 0; - n = reqh->hcprivint; + n = xfer->hcprivint; for (i = 0; i < nframes; i++) { std = stds[n]; #ifdef UHCI_DEBUG @@ -1011,15 +1148,16 @@ uhci_idone(ii) actlen += UHCI_TD_GET_ACTLEN(status); } upipe->u.iso.inuse -= nframes; - reqh->actlen = actlen; - reqh->status = USBD_NORMAL_COMPLETION; - reqh->hcpriv = ii; - usb_transfer_complete(reqh); + xfer->actlen = actlen; + xfer->status = USBD_NORMAL_COMPLETION; + xfer->hcpriv = ii; + usb_transfer_complete(xfer); return; } #ifdef UHCI_DEBUG - DPRINTFN(10, ("uhci_idone: ii=%p ready\n", ii)); + DPRINTFN(10, ("uhci_idone: ii=%p, xfer=%p, pipe=%p ready\n", + ii, xfer, upipe)); if (uhcidebug > 10) uhci_dump_tds(ii->stdstart); #endif @@ -1027,40 +1165,41 @@ uhci_idone(ii) /* The transfer is done, compute actual length and status. */ /* XXX Is this correct for control xfers? */ actlen = 0; - for (std = ii->stdstart; std; std = std->link.std) { - status = LE(std->td.td_status); - if (status & UHCI_TD_ACTIVE) + for (std = ii->stdstart; std != NULL; std = std->link.std) { + nstatus = LE(std->td.td_status); + if (nstatus & UHCI_TD_ACTIVE) break; - if (UHCI_TD_GET_PID(LE(std->td.td_token)) != - UHCI_TD_PID_SETUP) + + status = nstatus; + if (UHCI_TD_GET_PID(LE(std->td.td_token)) != UHCI_TD_PID_SETUP) actlen += UHCI_TD_GET_ACTLEN(status); } /* If there are left over TDs we need to update the toggle. */ - if (std) + if (std != NULL) upipe->nexttoggle = UHCI_TD_GET_DT(LE(std->td.td_token)); status &= UHCI_TD_ERROR; DPRINTFN(10, ("uhci_check_intr: actlen=%d, status=0x%x\n", actlen, status)); - reqh->actlen = actlen; + xfer->actlen = actlen; if (status != 0) { - DPRINTFN(-1+((status&UHCI_TD_STALLED)!=0), + DPRINTFN((status == UHCI_TD_STALLED)*10, ("uhci_idone: error, addr=%d, endpt=0x%02x, " "status 0x%b\n", - reqh->pipe->device->address, - reqh->pipe->endpoint->edesc->bEndpointAddress, + xfer->pipe->device->address, + xfer->pipe->endpoint->edesc->bEndpointAddress, (int)status, "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" "STALLED\30ACTIVE")); if (status == UHCI_TD_STALLED) - reqh->status = USBD_STALLED; + xfer->status = USBD_STALLED; else - reqh->status = USBD_IOERROR; /* more info XXX */ + xfer->status = USBD_IOERROR; /* more info XXX */ } else { - reqh->status = USBD_NORMAL_COMPLETION; + xfer->status = USBD_NORMAL_COMPLETION; } - reqh->hcpriv = ii; - usb_transfer_complete(reqh); + xfer->hcpriv = ii; + usb_transfer_complete(xfer); } /* @@ -1074,9 +1213,14 @@ uhci_timeout(addr) DPRINTF(("uhci_timeout: ii=%p\n", ii)); - ii->reqh->device->bus->intr_context++; - uhci_abort_req(ii->reqh, USBD_TIMEOUT); - ii->reqh->device->bus->intr_context--; +#ifdef UHCI_DEBUG + if (uhcidebug > 10) + uhci_dump_tds(ii->stdstart); +#endif + + ii->xfer->device->bus->intr_context++; + uhci_abort_xfer(ii->xfer, USBD_TIMEOUT); + ii->xfer->device->bus->intr_context--; } /* @@ -1086,22 +1230,22 @@ uhci_timeout(addr) * Only used during boot when interrupts are not enabled yet. */ void -uhci_waitintr(sc, reqh) +uhci_waitintr(sc, xfer) uhci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { - int timo = reqh->timeout; + int timo = xfer->timeout; uhci_intr_info_t *ii; DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo)); - reqh->status = USBD_IN_PROGRESS; + xfer->status = USBD_IN_PROGRESS; for (; timo >= 0; timo--) { usb_delay_ms(&sc->sc_bus, 1); DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS))); if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) { uhci_intr(sc); - if (reqh->status != USBD_IN_PROGRESS) + if (xfer->status != USBD_IN_PROGRESS) return; } } @@ -1109,11 +1253,11 @@ uhci_waitintr(sc, reqh) /* Timeout */ DPRINTF(("uhci_waitintr: timeout\n")); for (ii = LIST_FIRST(&sc->sc_intrhead); - ii && ii->reqh != reqh; + ii != NULL && ii->xfer != xfer; ii = LIST_NEXT(ii, list)) ; #ifdef DIAGNOSTIC - if (!ii) + if (ii == NULL) panic("uhci_waitintr: lost intr_info\n"); #endif uhci_idone(ii); @@ -1154,11 +1298,17 @@ uhci_run(sc, run) int run; { int s, n, running; + u_int16_t cmd; run = run != 0; s = splusb(); DPRINTF(("uhci_run: setting run=%d\n", run)); - UHCICMD(sc, run ? UHCI_CMD_RS : 0); + cmd = UREAD2(sc, UHCI_CMD); + if (run) + cmd |= UHCI_CMD_RS; + else + cmd &= ~UHCI_CMD_RS; + UHCICMD(sc, cmd); for(n = 0; n < 10; n++) { running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH); /* return when we've entered the state we want */ @@ -1191,15 +1341,15 @@ uhci_alloc_std(sc) uhci_softc_t *sc; { uhci_soft_td_t *std; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freetds) { + if (sc->sc_freetds == NULL) { DPRINTFN(2,("uhci_alloc_std: allocating chunk\n")); - r = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK, + err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK, UHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (0); for(i = 0; i < UHCI_STD_CHUNK; i++) { offs = i * UHCI_STD_SIZE; @@ -1222,7 +1372,7 @@ uhci_free_std(sc, std) { #ifdef DIAGNOSTIC #define TD_IS_FREE 0x12345678 - if (LE(std->td.td_token) == TD_IS_FREE) { + if (std->td.td_token == LE(TD_IS_FREE)) { printf("uhci_free_std: freeing free TD %p\n", std); return; } @@ -1237,15 +1387,15 @@ uhci_alloc_sqh(sc) uhci_softc_t *sc; { uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freeqhs) { + if (sc->sc_freeqhs == NULL) { DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n")); - r = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, + err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, UHCI_QH_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + if (err) return 0; for(i = 0; i < UHCI_SQH_CHUNK; i++) { offs = i * UHCI_SQH_SIZE; @@ -1301,10 +1451,11 @@ uhci_free_std_chain(sc, std, stdend) } usbd_status -uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) +uhci_alloc_std_chain(upipe, sc, len, rd, flags, dma, sp, ep) struct uhci_pipe *upipe; uhci_softc_t *sc; - int len, rd, shortok; + int len, rd; + u_int16_t flags; usb_dma_t *dma; uhci_soft_td_t **sp, **ep; { @@ -1316,20 +1467,22 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d " - "shortok=%d\n", addr, UE_GET_ADDR(endpt), len, - upipe->pipe.device->lowspeed, shortok)); - if (len == 0) { - *sp = *ep = 0; - DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n")); - return (USBD_NORMAL_COMPLETION); - } + "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len, + upipe->pipe.device->lowspeed, flags)); maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize); if (maxp == 0) { printf("uhci_alloc_std_chain: maxp=0\n"); return (USBD_INVAL); } ntd = (len + maxp - 1) / maxp; + if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0) + ntd++; DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd)); + if (ntd == 0) { + *sp = *ep = 0; + DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n")); + return (USBD_NORMAL_COMPLETION); + } tog = upipe->nexttoggle; if (ntd % 2 == 0) tog ^= 1; @@ -1340,23 +1493,27 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE); if (upipe->pipe.device->lowspeed) status |= UHCI_TD_LS; - if (shortok) + if (flags & USBD_SHORT_XFER_OK) status |= UHCI_TD_SPD; for (i = ntd; i >= 0; i--) { p = uhci_alloc_std(sc); - if (!p) { + if (p == NULL) { uhci_free_std_chain(sc, lastp, 0); return (USBD_NOMEM); } p->link.std = lastp; - p->td.td_link = LE(lastlink); + if (lastlink == UHCI_PTR_T) + p->td.td_link = LE(lastlink); + else + p->td.td_link = LE(lastlink|UHCI_PTR_VF); lastp = p; lastlink = p->physaddr; p->td.td_status = LE(status); if (i == ntd) { /* last TD */ l = len % maxp; - if (l == 0) l = maxp; + if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER)) + l = maxp; *ep = p; } else l = maxp; @@ -1387,55 +1544,59 @@ uhci_noop(pipe) } usbd_status -uhci_device_bulk_transfer(reqh) - usbd_request_handle reqh; +uhci_device_bulk_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); - /* Pipe isn't running, start first */ - return (uhci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_bulk_start(reqh) - usbd_request_handle reqh; +uhci_device_bulk_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *data, *dataend; uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int len, isread, endpt; int s; - DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3, ("uhci_device_bulk_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); + + if (sc->sc_dying) + return (USBD_IOERROR); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("uhci_device_bulk_transfer: a request\n"); #endif - len = reqh->length; - endpt = reqh->pipe->endpoint->edesc->bEndpointAddress; + len = xfer->length; + endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sqh = upipe->u.bulk.sqh; upipe->u.bulk.isread = isread; upipe->u.bulk.length = len; - r = uhci_alloc_std_chain(upipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &data, &dataend); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG @@ -1446,13 +1607,16 @@ uhci_device_bulk_start(reqh) #endif /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = data; ii->stdend = dataend; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif #ifdef DIAGNOSTIC + if (!ii->isdone) { + printf("uhci_device_bulk_transfer: not done, ii=%p\n", ii); + } ii->isdone = 0; #endif @@ -1464,8 +1628,8 @@ uhci_device_bulk_start(reqh) uhci_add_bulk(sc, sqh); LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout), + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(uhci_timeout, ii, MS_TO_TICKS(xfer->timeout), ii->timeout_handle); } splx(s); @@ -1478,31 +1642,33 @@ uhci_device_bulk_start(reqh) #endif if (sc->sc_bus.use_polling) - uhci_waitintr(sc, reqh); + uhci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } /* Abort a device bulk request. */ void -uhci_device_bulk_abort(reqh) - usbd_request_handle reqh; +uhci_device_bulk_abort(xfer) + usbd_xfer_handle xfer; { DPRINTF(("uhci_device_bulk_abort:\n")); - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_xfer(xfer, USBD_CANCELLED); } void -uhci_abort_req(reqh, status) - usbd_request_handle reqh; +uhci_abort_xfer(xfer, status) + usbd_xfer_handle xfer; usbd_status status; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *std; + DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status)); + /* Make interrupt routine ignore it, */ - reqh->status = status; + xfer->status = status; /* don't timeout, */ usb_untimeout(uhci_timeout, ii, ii->timeout_handle); @@ -1511,28 +1677,37 @@ uhci_abort_req(reqh, status) for (std = ii->stdstart; std != 0; std = std->link.std) std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - reqh->hcpriv = ii; + xfer->hcpriv = ii; - /* make sure hardware has completed, */ - if (reqh->device->bus->intr_context) { +#if 1 + /* Make sure hardware has completed, */ + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND); } else { - usb_delay_ms(reqh->pipe->device->bus, 1); +#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif + usb_delay_ms(xfer->pipe->device->bus, 1); /* and call final part of interrupt handler. */ - uhci_abort_req_end(reqh); + uhci_abort_xfer_end(xfer); } +#else + delay(1000); + uhci_abort_xfer_end(xfer); +#endif } void -uhci_abort_req_end(v) +uhci_abort_xfer_end(v) void *v; { - usbd_request_handle reqh = v; + usbd_xfer_handle xfer = v; int s; s = splusb(); - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); } @@ -1547,86 +1722,95 @@ uhci_device_bulk_close(pipe) uhci_free_sqh(sc, upipe->u.bulk.sqh); uhci_free_intr_info(upipe->iinfo); - /* XXX free other resources */ + /* XXX free other resources? */ } usbd_status -uhci_device_ctrl_transfer(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); - /* Pipe isn't running, start first */ - return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_ctrl_start(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_start(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; - usbd_status r; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; + usbd_status err; + + if (sc->sc_dying) + return (USBD_IOERROR); #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_device_ctrl_transfer: not a request\n"); #endif - r = uhci_device_request(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uhci_device_request(xfer); + if (err) + return (err); if (sc->sc_bus.use_polling) - uhci_waitintr(sc, reqh); + uhci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } usbd_status -uhci_device_intr_transfer(reqh) - usbd_request_handle reqh; +uhci_device_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); - /* Pipe isn't running, start first */ - return (uhci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_intr_start(reqh) - usbd_request_handle reqh; +uhci_device_intr_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *data, *dataend; uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int i, s; - DPRINTFN(3,("uhci_device_intr_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + if (sc->sc_dying) + return (USBD_IOERROR); + + DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("uhci_device_intr_transfer: a request\n"); #endif - r = uhci_alloc_std_chain(upipe, sc, reqh->length, 1, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &data, &dataend); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG @@ -1639,13 +1823,16 @@ uhci_device_intr_start(reqh) s = splusb(); /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = data; ii->stdend = dataend; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif #ifdef DIAGNOSTIC + if (!ii->isdone) { + printf("uhci_device_intr_transfer: not done, ii=%p\n", ii); + } ii->isdone = 0; #endif @@ -1671,11 +1858,11 @@ uhci_device_intr_start(reqh) /* Abort a device control request. */ void -uhci_device_ctrl_abort(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_abort(xfer) + usbd_xfer_handle xfer; { DPRINTF(("uhci_device_ctrl_abort:\n")); - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_xfer(xfer, USBD_CANCELLED); } /* Close a device control pipe. */ @@ -1691,15 +1878,15 @@ uhci_device_ctrl_close(pipe) /* Abort a device interrupt request. */ void -uhci_device_intr_abort(reqh) - usbd_request_handle reqh; +uhci_device_intr_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(1,("uhci_device_intr_abort: reqh=%p\n", reqh)); - if (reqh->pipe->intrreqh == reqh) { + DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer)); + if (xfer->pipe->intrxfer == xfer) { DPRINTFN(1,("uhci_device_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = 0; } - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_xfer(xfer, USBD_CANCELLED); } /* Close a device interrupt pipe. */ @@ -1740,11 +1927,11 @@ uhci_device_intr_close(pipe) } usbd_status -uhci_device_request(reqh) - usbd_request_handle reqh; +uhci_device_request(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; - usb_device_request_t *req = &reqh->request; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; + usb_device_request_t *req = &xfer->request; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; int addr = dev->address; @@ -1754,7 +1941,7 @@ uhci_device_request(reqh) uhci_soft_qh_t *sqh; int len; u_int32_t ls; - usbd_status r; + usbd_status err; int isread; int s; @@ -1775,14 +1962,13 @@ uhci_device_request(reqh) /* Set up data transaction */ if (len != 0) { upipe->nexttoggle = 1; - r = uhci_alloc_std_chain(upipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &data, &dataend); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); next = data; dataend->link.std = stat; - dataend->td.td_link = LE(stat->physaddr); + dataend->td.td_link = LE(stat->physaddr | UHCI_PTR_VF); } else { next = stat; } @@ -1791,7 +1977,7 @@ uhci_device_request(reqh) memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req); setup->link.std = next; - setup->td.td_link = LE(next->physaddr); + setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF); setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE); setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr)); setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma)); @@ -1806,20 +1992,23 @@ uhci_device_request(reqh) stat->td.td_buffer = LE(0); #ifdef UHCI_DEBUG - if (uhcidebug > 20) { + if (uhcidebug > 10) { DPRINTF(("uhci_device_request: before transfer\n")); uhci_dump_tds(setup); } #endif /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = setup; ii->stdend = stat; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif #ifdef DIAGNOSTIC + if (!ii->isdone) { + printf("uhci_device_request: not done, ii=%p\n", ii); + } ii->isdone = 0; #endif @@ -1844,21 +2033,22 @@ uhci_device_request(reqh) link = LE(std->td.td_link); uhci_dump_td(std); } - for (sxqh = xqh = (uhci_soft_qh_t *)std; - xqh; + sxqh = (uhci_soft_qh_t *)std; + uhci_dump_qh(sxqh); + for (xqh = sxqh; + xqh != NULL; xqh = (maxqh++ == 5 || xqh->hlink==sxqh || xqh->hlink==xqh ? NULL : xqh->hlink)) { uhci_dump_qh(xqh); - uhci_dump_qh(sxqh); } DPRINTF(("Enqueued QH:\n")); uhci_dump_qh(sqh); uhci_dump_tds(sqh->elink); } #endif - if (reqh->timeout && !sc->sc_bus.use_polling) { + if (xfer->timeout && !sc->sc_bus.use_polling) { usb_timeout(uhci_timeout, ii, - MS_TO_TICKS(reqh->timeout), ii->timeout_handle); + MS_TO_TICKS(xfer->timeout), ii->timeout_handle); } splx(s); @@ -1866,37 +2056,37 @@ uhci_device_request(reqh) } usbd_status -uhci_device_isoc_transfer(reqh) - usbd_request_handle reqh; +uhci_device_isoc_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - DPRINTFN(5,("uhci_device_isoc_transfer: reqh=%p\n", reqh)); + DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer)); /* Put it on our queue, */ - r = usb_insert_transfer(reqh); + err = usb_insert_transfer(xfer); /* bail out on error, */ - if (r != USBD_NORMAL_COMPLETION && r != USBD_IN_PROGRESS) - return (r); + if (err && err != USBD_IN_PROGRESS) + return (err); /* XXX should check inuse here */ /* insert into schedule, */ - uhci_device_isoc_enter(reqh); + uhci_device_isoc_enter(xfer); /* and put on interrupt list if the pipe wasn't running */ - if (r == USBD_NORMAL_COMPLETION) - uhci_device_isoc_start(SIMPLEQ_FIRST(&reqh->pipe->queue)); + if (!err) + uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); - return (r); + return (err); } void -uhci_device_isoc_enter(reqh) - usbd_request_handle reqh; +uhci_device_isoc_enter(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; struct iso *iso = &upipe->u.iso; @@ -1904,12 +2094,16 @@ uhci_device_isoc_enter(reqh) u_int32_t buf, len, status; int s, i, next, nframes; - DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d reqh=%p " + DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p " "nframes=%d\n", - iso->inuse, iso->next, reqh, reqh->nframes)); + iso->inuse, iso->next, xfer, xfer->nframes)); + + if (sc->sc_dying) + return; - if (reqh->status == USBD_IN_PROGRESS) { + if (xfer->status == USBD_IN_PROGRESS) { /* This request has already been entered into the frame list */ + /* XXX */ } #ifdef DIAGNOSTIC @@ -1924,20 +2118,20 @@ uhci_device_isoc_enter(reqh) DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next)); } - reqh->status = USBD_IN_PROGRESS; - reqh->hcprivint = next; + xfer->status = USBD_IN_PROGRESS; + xfer->hcprivint = next; - buf = DMAADDR(&reqh->dmabuf); + buf = DMAADDR(&xfer->dmabuf); status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | UHCI_TD_ACTIVE | UHCI_TD_IOS)); - nframes = reqh->nframes; + nframes = xfer->nframes; s = splusb(); for (i = 0; i < nframes; i++) { std = iso->stds[next]; if (++next >= UHCI_VFRAMELIST_COUNT) next = 0; - len = reqh->frlengths[i]; + len = xfer->frlengths[i]; std->td.td_buffer = LE(buf); if (i == nframes - 1) status |= LE(UHCI_TD_IOC); @@ -1953,28 +2147,31 @@ uhci_device_isoc_enter(reqh) buf += len; } iso->next = next; - iso->inuse += reqh->nframes; + iso->inuse += xfer->nframes; splx(s); } usbd_status -uhci_device_isoc_start(reqh) - usbd_request_handle reqh; +uhci_device_isoc_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *end; int s, i; + if (sc->sc_dying) + return (USBD_IOERROR); + #ifdef DIAGNOSTIC - if (reqh->status != USBD_IN_PROGRESS) - printf("uhci_device_isoc_start: not in progress %p\n", reqh); + if (xfer->status != USBD_IN_PROGRESS) + printf("uhci_device_isoc_start: not in progress %p\n", xfer); #endif /* Find the last TD */ - i = reqh->hcprivint + reqh->nframes; + i = xfer->hcprivint + xfer->nframes; if (i >= UHCI_VFRAMELIST_COUNT) i -= UHCI_VFRAMELIST_COUNT; end = upipe->u.iso.stds[i]; @@ -1982,13 +2179,16 @@ uhci_device_isoc_start(reqh) s = splusb(); /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = end; ii->stdend = end; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif #ifdef DIAGNOSTIC + if (!ii->isdone) { + printf("uhci_device_isoc_start: not done, ii=%p\n", ii); + } ii->isdone = 0; #endif LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list); @@ -1999,21 +2199,21 @@ uhci_device_isoc_start(reqh) } void -uhci_device_isoc_abort(reqh) - usbd_request_handle reqh; +uhci_device_isoc_abort(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t **stds = upipe->u.iso.stds; uhci_soft_td_t *std; int i, n, nframes; /* Make interrupt routine ignore it, */ - reqh->status = USBD_CANCELLED; + xfer->status = USBD_CANCELLED; /* make hardware ignore it, */ - nframes = reqh->nframes; - n = reqh->hcprivint; + nframes = xfer->nframes; + n = xfer->hcprivint; for (i = 0; i < nframes; i++) { std = stds[n]; std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); @@ -2021,16 +2221,16 @@ uhci_device_isoc_abort(reqh) n = 0; } - reqh->hcpriv = ii; + xfer->hcpriv = ii; /* make sure hardware has completed, */ - if (reqh->device->bus->intr_context) { + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND); } else { - usb_delay_ms(reqh->pipe->device->bus, 1); + usb_delay_ms(xfer->pipe->device->bus, 1); /* and call final part of interrupt handler. */ - uhci_abort_req_end(reqh); + uhci_abort_xfer_end(xfer); } } @@ -2061,10 +2261,10 @@ uhci_device_isoc_close(pipe) for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = iso->stds[i]; for (vstd = sc->sc_vframes[i].htd; - vstd && vstd->link.std != std; + vstd != NULL && vstd->link.std != std; vstd = vstd->link.std) ; - if (!vstd) { + if (vstd == NULL) { /*panic*/ printf("uhci_device_isoc_close: %p not found\n", std); uhci_unlock_frames(sc); @@ -2136,12 +2336,12 @@ uhci_setup_isoc(pipe) } void -uhci_device_isoc_done(reqh) - usbd_request_handle reqh; +uhci_device_isoc_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; - DPRINTFN(4, ("uhci_isoc_done: length=%d\n", reqh->actlen)); + DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen)); /* Turn off the interrupt since it is active even if the TD is not. */ ii->stdend->td.td_status &= LE(~UHCI_TD_IOC); @@ -2150,16 +2350,16 @@ uhci_device_isoc_done(reqh) } void -uhci_device_intr_done(reqh) - usbd_request_handle reqh; +uhci_device_intr_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_soft_qh_t *sqh; int i, npoll; - DPRINTFN(5, ("uhci_intr_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_intr_done: length=%d\n", xfer->actlen)); npoll = upipe->u.intr.npoll; for(i = 0; i < npoll; i++) { @@ -2170,13 +2370,12 @@ uhci_device_intr_done(reqh) uhci_free_std_chain(sc, ii->stdstart, 0); /* XXX Wasteful. */ - if (reqh->pipe->repeat) { + if (xfer->pipe->repeat) { uhci_soft_td_t *data, *dataend; /* This alloc cannot fail since we freed the chain above. */ - uhci_alloc_std_chain(upipe, sc, reqh->length, 1, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &data, &dataend); + uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags, + &xfer->dmabuf, &data, &dataend); dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG @@ -2193,6 +2392,9 @@ uhci_device_intr_done(reqh) callout_handle_init(&ii->timeout_handle); #endif #ifdef DIAGNOSTIC + if (!ii->isdone) { + printf("uhci_device_intr_done: not done, ii=%p\n", ii); + } ii->isdone = 0; #endif for (i = 0; i < npoll; i++) { @@ -2207,15 +2409,15 @@ uhci_device_intr_done(reqh) /* Deallocate request data structures */ void -uhci_device_ctrl_done(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_ctrl_done: not a request\n"); #endif @@ -2226,17 +2428,17 @@ uhci_device_ctrl_done(reqh) if (upipe->u.ctl.length != 0) uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend); - DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", xfer->actlen)); } /* Deallocate request data structures */ void -uhci_device_bulk_done(reqh) - usbd_request_handle reqh; +uhci_device_bulk_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; LIST_REMOVE(ii, list); /* remove from active list */ @@ -2244,7 +2446,7 @@ uhci_device_bulk_done(reqh) uhci_free_std_chain(sc, ii->stdstart, 0); - DPRINTFN(5, ("uhci_bulk_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen)); } /* Add interrupt QH, called with vflock. */ @@ -2368,7 +2570,8 @@ uhci_open(pipe) uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - usbd_status r; + usbd_status err; + int ival; DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", pipe, pipe->device->address, @@ -2392,23 +2595,23 @@ uhci_open(pipe) case UE_CONTROL: pipe->methods = &uhci_device_ctrl_methods; upipe->u.ctl.sqh = uhci_alloc_sqh(sc); - if (upipe->u.ctl.sqh == 0) + if (upipe->u.ctl.sqh == NULL) goto bad; upipe->u.ctl.setup = uhci_alloc_std(sc); - if (upipe->u.ctl.setup == 0) { + if (upipe->u.ctl.setup == NULL) { uhci_free_sqh(sc, upipe->u.ctl.sqh); goto bad; } upipe->u.ctl.stat = uhci_alloc_std(sc); - if (upipe->u.ctl.stat == 0) { + if (upipe->u.ctl.stat == NULL) { uhci_free_sqh(sc, upipe->u.ctl.sqh); uhci_free_std(sc, upipe->u.ctl.setup); goto bad; } - r = usb_allocmem(&sc->sc_bus, + err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), 0, &upipe->u.ctl.reqdma); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { uhci_free_sqh(sc, upipe->u.ctl.sqh); uhci_free_std(sc, upipe->u.ctl.setup); uhci_free_std(sc, upipe->u.ctl.stat); @@ -2417,14 +2620,17 @@ uhci_open(pipe) break; case UE_INTERRUPT: pipe->methods = &uhci_device_intr_methods; - return (uhci_device_setintr(sc, upipe, ed->bInterval)); + ival = pipe->interval; + if (ival == USBD_DEFAULT_INTERVAL) + ival = ed->bInterval; + return (uhci_device_setintr(sc, upipe, ival)); case UE_ISOCHRONOUS: pipe->methods = &uhci_device_isoc_methods; return (uhci_setup_isoc(pipe)); case UE_BULK: pipe->methods = &uhci_device_bulk_methods; upipe->u.bulk.sqh = uhci_alloc_sqh(sc); - if (upipe->u.bulk.sqh == 0) + if (upipe->u.bulk.sqh == NULL) goto bad; break; } @@ -2443,8 +2649,8 @@ usb_device_descriptor_t uhci_devd = { USB_DEVICE_DESCRIPTOR_SIZE, UDESC_DEVICE, /* type */ {0x00, 0x01}, /* USB version */ - UCLASS_HUB, /* class */ - USUBCLASS_HUB, /* subclass */ + UDCLASS_HUB, /* class */ + UDSUBCLASS_HUB, /* subclass */ 0, /* protocol */ 64, /* max packet */ {0},{0},{0x00,0x01}, /* device id */ @@ -2471,8 +2677,8 @@ usb_interface_descriptor_t uhci_ifcd = { 0, 0, 1, - UCLASS_HUB, - USUBCLASS_HUB, + UICLASS_HUB, + UISUBCLASS_HUB, 0, 0 }; @@ -2520,37 +2726,42 @@ uhci_str(p, l, s) * Simulate a hardware hub by handling all the necessary requests. */ usbd_status -uhci_root_ctrl_transfer(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); - /* Pipe isn't running, start first */ - return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_root_ctrl_start(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_start(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; usb_device_request_t *req; void *buf = NULL; int port, x; int s, len, value, index, status, change, l, totlen = 0; usb_port_status_t ps; - usbd_status r; + usbd_status err; + + if (sc->sc_dying) + return (USBD_IOERROR); #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_root_ctrl_transfer: not a request\n"); #endif - req = &reqh->request; + req = &xfer->request; DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); @@ -2560,7 +2771,7 @@ uhci_root_ctrl_start(reqh) index = UGETW(req->wIndex); if (len != 0) - buf = KERNADDR(&reqh->dmabuf); + buf = KERNADDR(&xfer->dmabuf); #define C(x,y) ((x) | ((y) << 8)) switch(C(req->bRequest, req->bmRequestType)) { @@ -2583,7 +2794,7 @@ uhci_root_ctrl_start(reqh) switch(value >> 8) { case UDESC_DEVICE: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); @@ -2592,7 +2803,7 @@ uhci_root_ctrl_start(reqh) break; case UDESC_CONFIG: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); @@ -2623,7 +2834,7 @@ uhci_root_ctrl_start(reqh) } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -2648,14 +2859,14 @@ uhci_root_ctrl_start(reqh) break; case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): if (value >= USB_MAX_DEVICES) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_addr = value; break; case C(UR_SET_CONFIG, UT_WRITE_DEVICE): if (value != 0 && value != 1) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_conf = value; @@ -2665,7 +2876,7 @@ uhci_root_ctrl_start(reqh) case C(UR_SET_FEATURE, UT_WRITE_DEVICE): case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): break; @@ -2683,7 +2894,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -2713,7 +2924,7 @@ uhci_root_ctrl_start(reqh) break; case UHF_C_PORT_RESET: sc->sc_isreset = 0; - r = USBD_NORMAL_COMPLETION; + err = USBD_NORMAL_COMPLETION; goto ret; case UHF_PORT_CONNECTION: case UHF_PORT_OVER_CURRENT: @@ -2721,7 +2932,7 @@ uhci_root_ctrl_start(reqh) case UHF_PORT_LOW_SPEED: case UHF_C_PORT_SUSPEND: default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -2731,7 +2942,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len > 0) { @@ -2743,7 +2954,7 @@ uhci_root_ctrl_start(reqh) break; case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): if (value != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } l = min(len, USB_HUB_DESCRIPTOR_SIZE); @@ -2752,7 +2963,7 @@ uhci_root_ctrl_start(reqh) break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } memset(buf, 0, len); @@ -2764,11 +2975,11 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } x = UREAD2(sc, port); @@ -2799,7 +3010,7 @@ uhci_root_ctrl_start(reqh) totlen = l; break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): break; @@ -2809,7 +3020,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -2844,31 +3055,31 @@ uhci_root_ctrl_start(reqh) case UHF_C_PORT_SUSPEND: case UHF_C_PORT_RESET: default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } - reqh->actlen = totlen; - r = USBD_NORMAL_COMPLETION; + xfer->actlen = totlen; + err = USBD_NORMAL_COMPLETION; ret: - reqh->status = r; - reqh->hcpriv = 0; + xfer->status = err; + xfer->hcpriv = 0; s = splusb(); - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); return (USBD_IN_PROGRESS); } /* Abort a root control request. */ void -uhci_root_ctrl_abort(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_abort(xfer) + usbd_xfer_handle xfer; { - /* Nothing to do, all transfers are syncronous. */ + /* Nothing to do, all transfers are synchronous. */ } /* Close the root pipe. */ @@ -2876,59 +3087,61 @@ void uhci_root_ctrl_close(pipe) usbd_pipe_handle pipe; { - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - - sc->sc_has_timo = 0; DPRINTF(("uhci_root_ctrl_close\n")); } /* Abort a root interrupt request. */ void -uhci_root_intr_abort(reqh) - usbd_request_handle reqh; +uhci_root_intr_abort(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usb_untimeout(uhci_timo, reqh, reqh->timo_handle); - sc->sc_has_timo = 0; + usb_untimeout(uhci_timo, xfer, xfer->timo_handle); + sc->sc_has_timo = NULL; - if (reqh->pipe->intrreqh == reqh) { + if (xfer->pipe->intrxfer == xfer) { DPRINTF(("uhci_root_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = 0; } - reqh->status = USBD_CANCELLED; - usb_transfer_complete(reqh); + xfer->status = USBD_CANCELLED; + usb_transfer_complete(xfer); } usbd_status -uhci_root_intr_transfer(reqh) - usbd_request_handle reqh; +uhci_root_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; /* Insert last in queue. */ - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_insert_transfer(xfer); + if (err) + return (err); - /* Pipe isn't running, start first */ - return (uhci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue))); + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } /* Start a transfer on the root interrupt pipe */ usbd_status -uhci_root_intr_start(reqh) - usbd_request_handle reqh; +uhci_root_intr_start(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; + usbd_pipe_handle pipe = xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3, ("uhci_root_intr_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); + + if (sc->sc_dying) + return (USBD_IOERROR); - sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval); - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); - sc->sc_has_timo = reqh; + sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); + usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle); + sc->sc_has_timo = xfer; return (USBD_IN_PROGRESS); } @@ -2939,8 +3152,8 @@ uhci_root_intr_close(pipe) { uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle); - sc->sc_has_timo = 0; + usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle); + sc->sc_has_timo = NULL; DPRINTF(("uhci_root_intr_close\n")); } diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h index a49c9c31c3c..2213fdea4b3 100644 --- a/sys/dev/usb/uhcireg.h +++ b/sys/dev/usb/uhcireg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uhcireg.h,v 1.2 1999/08/27 09:00:29 fgsch Exp $ */ -/* $NetBSD: uhcireg.h,v 1.7 1999/08/22 23:19:57 augustss Exp $ */ +/* $OpenBSD: uhcireg.h,v 1.3 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: uhcireg.h,v 1.9 1999/11/20 00:57:09 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -47,6 +47,7 @@ #define PCI_USBREV_MASK 0xff #define PCI_USBREV_PRE_1_0 0x00 #define PCI_USBREV_1_0 0x10 +#define PCI_USBREV_1_1 0x11 #define PCI_LEGSUP 0xc0 /* Legacy Support register */ #define PCI_LEGSUP_USBPIRQDEN 0x2000 /* USB PIRQ D Enable */ diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index 26c6177672f..3f526106f4d 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uhcivar.h,v 1.5 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: uhcivar.h,v 1.16 1999/10/13 08:10:56 augustss Exp $ */ +/* $OpenBSD: uhcivar.h,v 1.6 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: uhcivar.h,v 1.23 2000/02/22 16:03:44 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ typedef union { */ typedef struct uhci_intr_info { struct uhci_softc *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; uhci_soft_td_t *stdstart; uhci_soft_td_t *stdend; LIST_ENTRY(uhci_intr_info) list; @@ -92,7 +92,7 @@ struct uhci_soft_td { }; /* * Make the size such that it is a multiple of UHCI_TD_ALIGN. This way - * we can pack a number of soft TD together and have the real TS well + * we can pack a number of soft TD together and have the real TD well * aligned. * NOTE: Minimum size is 32 bytes. */ @@ -116,7 +116,7 @@ struct uhci_soft_qh { #define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/ /* - * Information about an entry in the virtial frame list. + * Information about an entry in the virtual frame list. */ struct uhci_vframe { uhci_soft_td_t *htd; /* pointer to dummy TD */ @@ -140,35 +140,43 @@ typedef struct uhci_softc { uhci_soft_qh_t *sc_bulk_start; /* dummy QH for bulk */ uhci_soft_qh_t *sc_bulk_end; /* last bulk transfer */ - uhci_soft_td_t *sc_freetds; - uhci_soft_qh_t *sc_freeqhs; + uhci_soft_td_t *sc_freetds; /* TD free list */ + uhci_soft_qh_t *sc_freeqhs; /* QH free list */ + + SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ u_int8_t sc_addr; /* device address */ u_int8_t sc_conf; /* device configuration */ - char sc_isreset; + u_int8_t sc_saved_sof; + u_int16_t sc_saved_frnum; + char sc_isreset; char sc_suspend; - usbd_request_handle sc_has_timo; + char sc_dying; LIST_HEAD(, uhci_intr_info) sc_intrhead; /* Info for the root hub interrupt channel. */ - int sc_ival; + int sc_ival; /* time between root hub intrs */ + usbd_xfer_handle sc_has_timo; /* root hub interrupt transfer */ - char sc_vflock; + char sc_vflock; /* for lock virtual frame list */ #define UHCI_HAS_LOCK 1 #define UHCI_WANT_LOCK 2 - char sc_vendor[16]; - int sc_id_vendor; + char sc_vendor[16]; /* vendor string for root hub */ + int sc_id_vendor; /* vendor ID for root hub */ - void *sc_powerhook; - device_ptr_t sc_child; + void *sc_powerhook; /* cookie from power hook */ + void *sc_shutdownhook; /* cookie from shutdown hook */ + + device_ptr_t sc_child; /* /dev/usb device */ } uhci_softc_t; usbd_status uhci_init __P((uhci_softc_t *)); int uhci_intr __P((void *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) int uhci_detach __P((uhci_softc_t *, int)); int uhci_activate __P((device_ptr_t, enum devact)); - +#endif diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index d0bd5efa5ed..0443d21994a 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhid.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: uhid.c,v 1.26 1999/10/13 08:10:56 augustss Exp $ */ +/* $OpenBSD: uhid.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: uhid.c,v 1.35 2000/03/19 22:23:28 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -83,6 +83,7 @@ int uhiddebug = 0; struct uhid_softc { USBBASEDEVICE sc_dev; /* base device */ + usbd_device_handle sc_udev; usbd_interface_handle sc_iface; /* interface */ usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ int sc_ep_addr; @@ -94,8 +95,8 @@ struct uhid_softc { u_int8_t sc_oid; u_int8_t sc_fid; - char *sc_ibuf; - char *sc_obuf; + u_char *sc_ibuf; + u_char *sc_obuf; void *sc_repdesc; int sc_repdesc_size; @@ -146,7 +147,7 @@ static struct cdevsw uhid_cdevsw = { }; #endif -void uhid_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); +void uhid_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); int uhid_do_read __P((struct uhid_softc *, struct uio *uio, int)); int uhid_do_write __P((struct uhid_softc *, struct uio *uio, int)); @@ -159,10 +160,10 @@ USB_MATCH(uhid) USB_MATCH_START(uhid, uaa); usb_interface_descriptor_t *id; - if (!uaa->iface) + if (uaa->iface == NULL) return (UMATCH_NONE); id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass != UCLASS_HID) + if (id == NULL || id->bInterfaceClass != UICLASS_HID) return (UMATCH_NONE); return (UMATCH_IFACECLASS_GENERIC); } @@ -175,9 +176,10 @@ USB_ATTACH(uhid) usb_endpoint_descriptor_t *ed; int size; void *desc; - usbd_status r; + usbd_status err; char devinfo[1024]; - + + sc->sc_udev = uaa->device; sc->sc_iface = iface; id = usbd_get_interface_descriptor(iface); usbd_devinfo(uaa->device, 0, devinfo); @@ -186,7 +188,7 @@ USB_ATTACH(uhid) devinfo, id->bInterfaceClass, id->bInterfaceSubClass); ed = usbd_interface2endpoint_descriptor(iface, 0); - if (!ed) { + if (ed == NULL) { printf("%s: could not read endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); sc->sc_dying = 1; @@ -212,12 +214,10 @@ USB_ATTACH(uhid) sc->sc_ep_addr = ed->bEndpointAddress; desc = 0; - r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV); + if (err) { printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev)); sc->sc_dying = 1; - if (desc) - free(desc, M_USBDEV); USB_ATTACH_ERROR_RETURN; } @@ -230,6 +230,20 @@ USB_ATTACH(uhid) sc->sc_repdesc = desc; sc->sc_repdesc_size = size; +#ifdef __FreeBSD__ + { + static int global_init_done = 0; + + if (!global_init_done) { + cdevsw_add(&uhid_cdevsw); + global_init_done = 1; + } + } +#endif + + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + USB_ATTACH_SUCCESS_RETURN; } @@ -267,7 +281,7 @@ USB_DETACH(uhid) #endif sc->sc_dying = 1; - if (sc->sc_intrpipe) + if (sc->sc_intrpipe != NULL) usbd_abort_pipe(sc->sc_intrpipe); if (sc->sc_state & UHID_OPEN) { @@ -296,20 +310,32 @@ USB_DETACH(uhid) free(sc->sc_repdesc, M_USBDEV); + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + return (0); } void -uhid_intr(reqh, addr, status) - usbd_request_handle reqh; +uhid_intr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { struct uhid_softc *sc = addr; - DPRINTFN(5, ("uhid_intr: status=%d\n", status)); - DPRINTFN(5, ("uhid_intr: data = %02x %02x %02x\n", - sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2])); +#ifdef UHID_DEBUG + if (uhiddebug > 5) { + u_int32_t cc, i; + + usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); + DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc)); + DPRINTF(("uhid_intr: data=")); + for (i = 0; i < cc; i++) + DPRINTF((" %02x", sc->sc_ibuf[i])); + DPRINTF(("\n")); + } +#endif if (status == USBD_CANCELLED) return; @@ -338,7 +364,7 @@ uhidopen(dev, flag, mode, p) struct proc *p; { struct uhid_softc *sc; - usbd_status r; + usbd_status err; USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc); @@ -360,13 +386,12 @@ uhidopen(dev, flag, mode, p) sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); /* Set up interrupt pipe. */ - r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, - USBD_SHORT_XFER_OK, - &sc->sc_intrpipe, sc, sc->sc_ibuf, - sc->sc_isize, uhid_intr); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, + sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL); + if (err) { DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " - "error=%d\n",r)); + "error=%d\n",err)); free(sc->sc_ibuf, M_USBDEV); free(sc->sc_obuf, M_USBDEV); sc->sc_state &= ~UHID_OPEN; @@ -416,15 +441,15 @@ uhid_do_read(sc, uio, flag) int error = 0; size_t length; u_char buffer[UHID_CHUNK]; - usbd_status r; + usbd_status err; DPRINTFN(1, ("uhidread\n")); if (sc->sc_state & UHID_IMMED) { DPRINTFN(1, ("uhidread immed\n")); - r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, + err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, sc->sc_iid, buffer, sc->sc_isize); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (EIO); return (uiomove(buffer, sc->sc_isize, uio)); } @@ -461,7 +486,7 @@ uhid_do_read(sc, uio, flag) /* Remove a small chunk from the input queue. */ (void) q_to_b(&sc->sc_q, buffer, length); - DPRINTFN(5, ("uhidread: got %d chars\n", length)); + DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); /* Copy the data to the user process. */ if ((error = uiomove(buffer, length, uio)) != 0) @@ -497,7 +522,7 @@ uhid_do_write(sc, uio, flag) { int error; int size; - usbd_status r; + usbd_status err; DPRINTFN(1, ("uhidwrite\n")); @@ -511,15 +536,13 @@ uhid_do_write(sc, uio, flag) error = uiomove(sc->sc_obuf, size, uio); if (!error) { if (sc->sc_oid) - r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - sc->sc_obuf[0], - sc->sc_obuf+1, size-1); + err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, + sc->sc_obuf[0], sc->sc_obuf+1, size-1); else - r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - 0, sc->sc_obuf, size); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, + 0, sc->sc_obuf, size); + if (err) error = EIO; - } } return (error); @@ -554,7 +577,7 @@ uhid_do_ioctl(sc, cmd, addr, flag, p) struct usb_ctl_report_desc *rd; struct usb_ctl_report *re; int size, id; - usbd_status r; + usbd_status err; DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); @@ -575,11 +598,10 @@ uhid_do_ioctl(sc, cmd, addr, flag, p) case USB_SET_IMMED: if (*(int *)addr) { - /* XXX should read into ibuf, but does it matter */ - r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, sc->sc_ibuf, - sc->sc_isize); - if (r != USBD_NORMAL_COMPLETION) + /* XXX should read into ibuf, but does it matter? */ + err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, + sc->sc_iid, sc->sc_ibuf, sc->sc_isize); + if (err) return (EOPNOTSUPP); sc->sc_state |= UHID_IMMED; @@ -605,9 +627,32 @@ uhid_do_ioctl(sc, cmd, addr, flag, p) default: return (EINVAL); } - r = usbd_get_report(sc->sc_iface, re->report, id, - re->data, size); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_report(sc->sc_iface, re->report, id, re->data, + size); + if (err) + return (EIO); + break; + case USB_SET_REPORT: + re = (struct usb_ctl_report *)addr; + switch (re->report) { + case UHID_INPUT_REPORT: + size = sc->sc_isize; + id = sc->sc_iid; + break; + case UHID_OUTPUT_REPORT: + size = sc->sc_osize; + id = sc->sc_oid; + break; + case UHID_FEATURE_REPORT: + size = sc->sc_fsize; + id = sc->sc_fid; + break; + default: + return (EINVAL); + } + err = usbd_set_report(sc->sc_iface, re->report, id, re->data, + size); + if (err) return (EIO); break; @@ -667,6 +712,5 @@ uhidpoll(dev, events, p) } #if defined(__FreeBSD__) -DEV_DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, - uhid_cdevsw, usbd_driver_load, 0); +DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0); #endif diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 517d48a29e3..4ba332ef49e 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhub.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: uhub.c,v 1.32 1999/10/13 08:10:56 augustss Exp $ */ +/* $OpenBSD: uhub.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: uhub.c,v 1.40 2000/02/29 21:37:01 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -48,12 +48,12 @@ #include #if defined(__NetBSD__) || defined(__OpenBSD__) #include +#include #elif defined(__FreeBSD__) #include #include #include "bus_if.h" #endif -#include #include @@ -63,9 +63,9 @@ #include #ifdef UHUB_DEBUG -#define DPRINTF(x) if (usbdebug) logprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x -extern int usbdebug; +#define DPRINTF(x) if (uhubdebug) logprintf x +#define DPRINTFN(n,x) if (uhubdebug>(n)) logprintf x +int uhubdebug; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -81,15 +81,12 @@ struct uhub_softc { usbd_status uhub_init_port __P((struct usbd_port *)); usbd_status uhub_explore __P((usbd_device_handle hub)); -void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); +void uhub_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); #if defined(__FreeBSD__) static bus_child_detached_t uhub_child_detached; #endif -USB_DECLARE_DRIVER_INIT(uhub, - DEVMETHOD(bus_child_detached, uhub_child_detached)); - /* * We need two attachment points: * hub to usb and hub to hub @@ -97,12 +94,17 @@ USB_DECLARE_DRIVER_INIT(uhub, */ #if defined(__NetBSD__) || defined(__OpenBSD__) +USB_DECLARE_DRIVER(uhub); + /* Create the driver instance for the hub connected to hub case */ struct cfattach uhub_uhub_ca = { sizeof(struct uhub_softc), uhub_match, uhub_attach, uhub_detach, uhub_activate }; #elif defined(__FreeBSD__) +USB_DECLARE_DRIVER_INIT(uhub. + DEVMETHOD(bus_child_detached, uhub_child_detached)); + /* Create the driver instance for the hub connected to usb case. */ devclass_t uhubroot_devclass; @@ -131,7 +133,7 @@ USB_MATCH(uhub) * The subclass for hubs seems to be 0 for some and 1 for others, * so we just ignore the subclass. */ - if (uaa->iface == 0 && dd->bDeviceClass == UCLASS_HUB) + if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB) return (UMATCH_DEVCLASS_DEVSUBCLASS); return (UMATCH_NONE); } @@ -141,7 +143,7 @@ USB_ATTACH(uhub) USB_ATTACH_START(uhub, sc, uaa); usbd_device_handle dev = uaa->device; char devinfo[1024]; - usbd_status r; + usbd_status err; struct usbd_hub *hub; usb_device_request_t req; usb_hub_descriptor_t hubdesc; @@ -155,10 +157,10 @@ USB_ATTACH(uhub) USB_ATTACH_SETUP; printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - r = usbd_set_config_index(dev, 0, 1); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_config_index(dev, 0, 1); + if (err) { DPRINTF(("%s: configuration failed, error=%s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(r))); + USBDEVNAME(sc->sc_dev), usbd_errstr(err))); USB_ATTACH_ERROR_RETURN; } @@ -175,15 +177,15 @@ USB_ATTACH(uhub) USETW(req.wIndex, 0); USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); DPRINTFN(1,("usb_init_hub: getting hub descriptor\n")); - r = usbd_do_request(dev, &req, &hubdesc); + err = usbd_do_request(dev, &req, &hubdesc); nports = hubdesc.bNbrPorts; - if (r == USBD_NORMAL_COMPLETION && nports > 7) { + if (!err && nports > 7) { USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8); - r = usbd_do_request(dev, &req, &hubdesc); + err = usbd_do_request(dev, &req, &hubdesc); } - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTF(("%s: getting hub descriptor failed, error=%s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(r))); + USBDEVNAME(sc->sc_dev), usbd_errstr(err))); USB_ATTACH_ERROR_RETURN; } @@ -196,7 +198,7 @@ USB_ATTACH(uhub) hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port), M_USBDEV, M_NOWAIT); - if (hub == 0) + if (hub == NULL) USB_ATTACH_ERROR_RETURN; dev->hub = hub; dev->hub->hubsoftc = sc; @@ -209,7 +211,7 @@ USB_ATTACH(uhub) dev->powersrc->parent ? dev->powersrc->parent->self_powered : 0)); - if (!dev->self_powered && dev->powersrc->parent && + if (!dev->self_powered && dev->powersrc->parent != NULL && !dev->powersrc->parent->self_powered) { printf("%s: bus powered hub connected to bus powered hub, " "ignored\n", USBDEVNAME(sc->sc_dev)); @@ -217,13 +219,13 @@ USB_ATTACH(uhub) } /* Set up interrupt pipe. */ - r = usbd_device2interface_handle(dev, 0, &iface); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_device2interface_handle(dev, 0, &iface); + if (err) { printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev)); goto bad; } ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == 0) { + if (ed == NULL) { printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); goto bad; } @@ -232,11 +234,10 @@ USB_ATTACH(uhub) goto bad; } - r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK, - &sc->sc_ipipe, sc, sc->sc_status, - sizeof(sc->sc_status), - uhub_intr); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, + USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, + sizeof(sc->sc_status), uhub_intr, USBD_DEFAULT_INTERVAL); + if (err) { printf("%s: cannot open interrupt pipe\n", USBDEVNAME(sc->sc_dev)); goto bad; @@ -245,15 +246,17 @@ USB_ATTACH(uhub) /* Wait with power off for a while. */ usbd_delay_ms(dev, USB_POWER_DOWN_TIME); + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev)); + for (p = 0; p < nports; p++) { struct usbd_port *up = &hub->ports[p]; up->device = 0; up->parent = dev; up->portno = p+1; - r = uhub_init_port(up); - if (r != USBD_NORMAL_COMPLETION) + err = uhub_init_port(up); + if (err) printf("%s: init of port %d failed\n", - USBDEVNAME(sc->sc_dev), up->portno); + USBDEVNAME(sc->sc_dev), up->portno); } sc->sc_running = 1; @@ -271,12 +274,12 @@ uhub_init_port(up) { int port = up->portno; usbd_device_handle dev = up->parent; - usbd_status r; + usbd_status err; u_int16_t pstatus; - r = usbd_get_port_status(dev, port, &up->status); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_port_status(dev, port, &up->status); + if (err) + return (err); pstatus = UGETW(up->status.wPortStatus); DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x " "change=0x%04x\n", @@ -287,15 +290,10 @@ uhub_init_port(up) /* First let the device go through a good power cycle, */ usbd_delay_ms(dev, USB_PORT_POWER_DOWN_TIME); -#if 0 -usbd_clear_hub_feature(dev, UHF_C_HUB_OVER_CURRENT); -usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT); -#endif - /* then turn the power on. */ - r = usbd_set_port_feature(dev, port, UHF_PORT_POWER); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); + if (err) + return (err); DPRINTF(("usb_init_port: turn on port %d power status=0x%04x " "change=0x%04x\n", port, UGETW(up->status.wPortStatus), @@ -304,9 +302,9 @@ usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT); usbd_delay_ms(dev, dev->hub->hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR); /* Get the port status again. */ - r = usbd_get_port_status(dev, port, &up->status); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_port_status(dev, port, &up->status); + if (err) + return (err); DPRINTF(("usb_init_port: after power on status=0x%04x " "change=0x%04x\n", UGETW(up->status.wPortStatus), @@ -339,7 +337,7 @@ uhub_explore(dev) usb_hub_descriptor_t *hd = &dev->hub->hubdesc; struct uhub_softc *sc = dev->hub->hubsoftc; struct usbd_port *up; - usbd_status r; + usbd_status err; int port; int change, status; @@ -354,17 +352,16 @@ uhub_explore(dev) for(port = 1; port <= hd->bNbrPorts; port++) { up = &dev->hub->ports[port-1]; - r = usbd_get_port_status(dev, port, &up->status); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_get_port_status(dev, port, &up->status); + if (err) { DPRINTF(("uhub_explore: get port status failed, " - "error=%s\n", - usbd_errstr(r))); + "error=%s\n", usbd_errstr(err))); continue; } status = UGETW(up->status.wPortStatus); change = UGETW(up->status.wPortChange); - DPRINTFN(5, ("uhub_explore: port %d status 0x%04x 0x%04x\n", - port, status, change)); + DPRINTFN(3,("uhub_explore: port %d status 0x%04x 0x%04x\n", + port, status, change)); if (change & UPS_C_PORT_ENABLED) { usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE); if (status & UPS_PORT_ENABLED) { @@ -385,6 +382,8 @@ uhub_explore(dev) } } if (!(change & UPS_C_CONNECT_STATUS)) { + DPRINTFN(3,("uhub_explore: port=%d !C_CONNECT_" + "STATUS\n", port)); /* No status change, just do recursive explore. */ if (up->device && up->device->hub) up->device->hub->explore(up->device); @@ -402,16 +401,19 @@ uhub_explore(dev) * the disconnect. */ disco: - if (up->device) { + if (up->device != NULL) { /* Disconnected */ - DPRINTF(("uhub_explore: device %d disappeared " + DPRINTF(("uhub_explore: device addr=%d disappeared " "on port %d\n", up->device->address, port)); usb_disconnect_port(up, USBDEV(sc->sc_dev)); usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); } - if (!(status & UPS_CURRENT_CONNECT_STATUS)) + if (!(status & UPS_CURRENT_CONNECT_STATUS)) { + DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT" + "_STATUS\n", port)); continue; + } /* Connected */ up->restartcnt = 0; @@ -420,18 +422,20 @@ uhub_explore(dev) usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY); /* Reset port, which implies enabling it. */ - if (usbd_reset_port(dev, port, &up->status) != - USBD_NORMAL_COMPLETION) + if (usbd_reset_port(dev, port, &up->status)) { + DPRINTF(("uhub_explore: port=%d reset failed\n", + port)); continue; + } /* Get device info and set its address. */ - r = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, + err = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, dev->depth + 1, status & UPS_LOW_SPEED, port, up); /* XXX retry a few times? */ - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTFN(-1,("uhub_explore: usb_new_device failed, " - "error=%s\n", usbd_errstr(r))); + "error=%s\n", usbd_errstr(err))); /* Avoid addressing problems by disabling. */ /* usbd_reset_port(dev, port, &up->status); */ @@ -460,8 +464,9 @@ uhub_activate(self, act) enum devact act; { struct uhub_softc *sc = (struct uhub_softc *)self; - usbd_device_handle devhub = sc->sc_hub; - int nports, p, i; + struct usbd_hub *hub = sc->sc_hub->hub; + usbd_device_handle dev; + int nports, port, i; switch (act) { case DVACT_ACTIVATE: @@ -469,10 +474,12 @@ uhub_activate(self, act) break; case DVACT_DEACTIVATE: - nports = devhub->hub->hubdesc.bNbrPorts; - for(p = 0; p < nports; p++) { - usbd_device_handle dev = devhub->hub->ports[p].device; - if (dev) { + if (hub == NULL) /* malfunctioning hub */ + break; + nports = hub->hubdesc.bNbrPorts; + for(port = 0; port < nports; port++) { + dev = hub->ports[port].device; + if (dev != NULL) { for (i = 0; dev->subdevs[i]; i++) config_deactivate(dev->subdevs[i]); } @@ -490,7 +497,7 @@ uhub_activate(self, act) USB_DETACH(uhub) { USB_DETACH_START(uhub, sc); - usbd_device_handle dev = sc->sc_hub; + struct usbd_hub *hub = sc->sc_hub->hub; struct usbd_port *rup; int port, nports; @@ -500,25 +507,61 @@ USB_DETACH(uhub) DPRINTF(("uhub_detach: sc=%port\n", sc)); #endif - if (!dev->hub) /* Must be partially working */ + if (hub == NULL) /* Must be partially working */ return (0); usbd_abort_pipe(sc->sc_ipipe); usbd_close_pipe(sc->sc_ipipe); - nports = dev->hub->hubdesc.bNbrPorts; + nports = hub->hubdesc.bNbrPorts; for(port = 0; port < nports; port++) { - rup = &dev->hub->ports[port]; + rup = &hub->ports[port]; if (rup->device) usb_disconnect_port(rup, self); } + + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, + USBDEV(sc->sc_dev)); - free(dev->hub, M_USBDEV); - dev->hub = 0; + free(hub, M_USBDEV); + sc->sc_hub->hub = NULL; return (0); } +#if defined(__FreeBSD__) +/* Called when a device has been detached from it */ +static void +uhub_child_detached(self, child) + device_t self; + device_t child; +{ + struct uhub_softc *sc = device_get_softc(self); + usbd_device_handle devhub = sc->sc_hub; + usbd_device_handle dev; + int nports; + int port; + int i; + + if (!devhub->hub) + /* should never happen; children are only created after init */ + panic("hub not fully initialised, but child deleted?"); + + nports = devhub->hub->hubdesc.bNbrPorts; + for (port = 0; port < nports; port++) { + dev = devhub->hub->ports[port].device; + if (dev && dev->subdevs) { + for (i = 0; dev->subdevs[i]; i++) { + if (dev->subdevs[i] == child) { + dev->subdevs[i] = NULL; + return; + } + } + } + } +} +#endif + /* * Hub interrupt. * This an indication that some port has changed status. @@ -526,8 +569,8 @@ USB_DETACH(uhub) * to be explored again. */ void -uhub_intr(reqh, addr, status) - usbd_request_handle reqh; +uhub_intr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index e23f43d46c0..22a3b3777cd 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usb.c,v 1.7 1999/11/11 15:57:40 ho Exp $ */ -/* $NetBSD: usb.c,v 1.28 1999/10/13 08:10:57 augustss Exp $ */ +/* $OpenBSD: usb.c,v 1.8 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb.c,v 1.41 2000/03/16 00:46:38 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -51,15 +51,15 @@ #if defined(__NetBSD__) || defined(__OpenBSD__) #include #include +#include #elif defined(__FreeBSD__) #include #include -#include +#include #include #endif #include #include -#include #include #include #include @@ -87,8 +87,17 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller"); #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x int usbdebug = 0; -int uhcidebug; -int ohcidebug; +#ifdef UHCI_DEBUG +int uhcidebug; +#endif +#ifdef OHCI_DEBUG +int ohcidebug; +#endif +/* + * 0 - do usual exploration + * 1 - do not use timeout exploration + * >1 - do no exploration + */ int usb_noexplore = 0; #else #define DPRINTF(x) @@ -100,8 +109,12 @@ struct usb_softc { usbd_bus_handle sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ +#if defined (__FreeBSD__) + /* This part should be deleted when kthreads is available */ struct selinfo sc_consel; /* waiting for connect change */ +#else struct proc *sc_event_thread; +#endif char sc_dying; }; @@ -111,6 +124,7 @@ cdev_decl(usb); #elif defined(__FreeBSD__) d_open_t usbopen; d_close_t usbclose; +d_read_t usbread; d_ioctl_t usbioctl; int usbpoll __P((dev_t, int, struct proc *)); @@ -136,7 +150,7 @@ usbd_status usb_discover __P((struct usb_softc *)); void usb_create_event_thread __P((void *)); void usb_event_thread __P((void *)); -#define USB_MAX_EVENTS 50 +#define USB_MAX_EVENTS 100 struct usb_event_q { struct usb_event ue; SIMPLEQ_ENTRY(usb_event_q) next; @@ -146,11 +160,16 @@ int usb_nevents = 0; struct selinfo usb_selevent; struct proc *usb_async_proc; /* process who wants USB SIGIO */ int usb_dev_open = 0; +void usb_add_event __P((int, struct usb_event *)); int usb_get_next_event __P((struct usb_event *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) /* Flag to see if we are in the cold boot process. */ extern int cold; +#endif + +static const char *usbrev_str[] = USBREV_STR; USB_DECLARE_DRIVER(usb); @@ -169,25 +188,42 @@ USB_ATTACH(usb) void *aux = device_get_ivars(self); #endif usbd_device_handle dev; - usbd_status r; - -#if defined(__NetBSD__) || defined(__OpenBSD__) - printf("\n"); -#elif defined(__FreeBSD__) + usbd_status err; + int usbrev; + struct usb_event ue; + +#if defined(__FreeBSD__) + printf("%s", USBDEVNAME(sc->sc_dev)); sc->sc_dev = self; #endif DPRINTF(("usbd_attach\n")); + usbd_init(); sc->sc_bus = aux; sc->sc_bus->usbctl = sc; sc->sc_port.power = USB_MAX_POWER; - r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, - &sc->sc_port); - if (r == USBD_NORMAL_COMPLETION) { + usbrev = sc->sc_bus->usbrev; + printf(": USB revision %s", usbrev_str[usbrev]); + if (usbrev != USBREV_1_0 && usbrev != USBREV_1_1) { + printf(", not supported\n"); + USB_ATTACH_ERROR_RETURN; + } + printf("\n"); + + /* Make sure not to use tsleep() if we are cold booting. */ + if (cold) + sc->sc_bus->use_polling++; + + ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); + usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); + + err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, + &sc->sc_port); + if (!err) { dev = sc->sc_port.device; - if (!dev->hub) { + if (dev->hub == NULL) { sc->sc_dying = 1; printf("%s: root device is not a hub\n", USBDEVNAME(sc->sc_dev)); @@ -200,23 +236,18 @@ USB_ATTACH(usb) * until the USB event thread is running, which means that * the keyboard will not work until after cold boot. */ - if (cold) { - sc->sc_bus->use_polling++; + if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1) dev->hub->explore(sc->sc_bus->root_hub); - sc->sc_bus->use_polling--; - } #endif } else { printf("%s: root hub problem, error=%d\n", - USBDEVNAME(sc->sc_dev), r); + USBDEVNAME(sc->sc_dev), err); sc->sc_dying = 1; } + if (cold) + sc->sc_bus->use_polling--; -#if defined(__NetBSD__) - kthread_create(usb_create_event_thread, sc); -#elif defined(__OpenBSD__) kthread_create_deferred(usb_create_event_thread, sc); -#endif #if defined(__FreeBSD__) make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR, @@ -253,13 +284,20 @@ usb_event_thread(arg) DPRINTF(("usb_event_thread: start\n")); + /* Make sure first discover does something. */ + sc->sc_bus->needs_explore = 1; + while (!sc->sc_dying) { #ifdef USB_DEBUG - if (!usb_noexplore) + if (usb_noexplore < 2) #endif usb_discover(sc); - (void)tsleep(&sc->sc_bus->needs_explore, - PWAIT, "usbevt", hz*60); + (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", +#ifdef USB_DEBUG + usb_noexplore ? 0 : +#endif + hz*60 + ); DPRINTFN(2,("usb_event_thread: woke up\n")); } sc->sc_event_thread = 0; @@ -397,13 +435,20 @@ usbioctl(devt, cmd, data, flag, p) switch (cmd) { #if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ case USB_DISCOVER: usb_discover(sc); break; #endif #ifdef USB_DEBUG case USB_SETDEBUG: - usbdebug = uhcidebug = ohcidebug = *(int *)data; + usbdebug = ((*(int *)data) & 0x000000ff); +#ifdef UHCI_DEBUG + uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8; +#endif +#ifdef OHCI_DEBUG + ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16; +#endif break; #endif case USB_REQUEST: @@ -414,7 +459,7 @@ usbioctl(devt, cmd, data, flag, p) struct uio uio; void *ptr = 0; int addr = ur->addr; - usbd_status r; + usbd_status err; int error = 0; DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len)); @@ -442,10 +487,9 @@ usbioctl(devt, cmd, data, flag, p) goto ret; } } - r = usbd_do_request_flags(sc->sc_bus->devices[addr], - &ur->request, ptr, - ur->flags, &ur->actlen); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_do_request_flags(sc->sc_bus->devices[addr], + &ur->request, ptr, ur->flags, &ur->actlen); + if (err) { error = EIO; goto ret; } @@ -466,14 +510,14 @@ usbioctl(devt, cmd, data, flag, p) { struct usb_device_info *di = (void *)data; int addr = di->addr; - usbd_device_handle devh; + usbd_device_handle dev; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); - devh = sc->sc_bus->devices[addr]; - if (devh == 0) + dev = sc->sc_bus->devices[addr]; + if (dev == NULL) return (ENXIO); - usbd_fill_deviceinfo(devh, di); + usbd_fill_deviceinfo(dev, di); break; } @@ -495,25 +539,41 @@ usbpoll(dev, events, p) { int revents, mask, s; - if (minor(dev) != USB_DEV_MINOR) - return (ENXIO); + if (minor(dev) != USB_DEV_MINOR) { + revents = 0; + mask = POLLIN | POLLRDNORM; - revents = 0; - s = splusb(); - mask = POLLIN | POLLRDNORM; - if (events & mask) - if (usb_nevents > 0) + s = splusb(); + if (events & mask && usb_nevents > 0) revents |= events & mask; - - DPRINTFN(2, ("usbpoll: revents=0x%x\n", revents)); - if (revents == 0) { - if (events & mask) { - DPRINTFN(2, ("usbpoll: selrecord\n")); + if (revents == 0 && events & mask) selrecord(p, &usb_selevent); - } + splx(s); + + return(revents); + } else { +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + struct usb_softc *sc; + int unit = minor(dev); + + USB_GET_SC(usb, unit, sc); + + revents = 0; + mask = POLLOUT | POLLRDNORM; + + s = splusb(); + if (events & mask && sc->sc_bus->needs_explore) + revents |= events & mask; + if (revents == 0 && events & mask) + selrecord(p, &sc->sc_consel); + splx(s); + + return (revents); +#else + return (ENXIO); +#endif } - splx(s); - return (revents); } /* Explore device tree from the root. */ @@ -521,15 +581,31 @@ usbd_status usb_discover(sc) struct usb_softc *sc; { +#if defined(__FreeBSD__) + /* The splxxx parts should be deleted when kthreads is available */ + int s; +#endif /* * We need mutual exclusion while traversing the device tree, * but this is guaranteed since this function is only called * from the event thread for the controller. */ - do { +#if defined(__FreeBSD__) + s = splusb(); +#endif + while (sc->sc_bus->needs_explore && !sc->sc_dying) { sc->sc_bus->needs_explore = 0; +#if defined(__FreeBSD__) + splx(s); +#endif sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); - } while (sc->sc_bus->needs_explore && !sc->sc_dying); +#if defined(__FreeBSD__) + s = splusb(); +#endif + } +#if defined(__FreeBSD__) + splx(s); +#endif return (USBD_NORMAL_COMPLETION); } @@ -538,6 +614,10 @@ usb_needs_explore(bus) usbd_bus_handle bus; { bus->needs_explore = 1; +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + selwakeup(&bus->usbctl->sc_consel); +#endif wakeup(&bus->needs_explore); } @@ -559,40 +639,66 @@ usb_get_next_event(ue) } void -usbd_add_event(type, devh) +usbd_add_dev_event(type, udev) + int type; + usbd_device_handle udev; +{ + struct usb_event ue; + + usbd_fill_deviceinfo(udev, &ue.u.ue_device); + usb_add_event(type, &ue); +} + +void +usbd_add_drv_event(type, udev, dev) int type; - usbd_device_handle devh; + usbd_device_handle udev; + device_ptr_t dev; +{ + struct usb_event ue; + + ue.u.ue_driver.ue_cookie = udev->cookie; + strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev), + sizeof ue.u.ue_driver.ue_devname); + usb_add_event(type, &ue); +} + +void +usb_add_event(type, uep) + int type; + struct usb_event *uep; { struct usb_event_q *ueq; struct usb_event ue; struct timeval thetime; int s; + microtime(&thetime); + /* Don't want to wait here inside splusb() */ + ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK); + ueq->ue = *uep; + ueq->ue.ue_type = type; + TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); + s = splusb(); if (++usb_nevents >= USB_MAX_EVENTS) { /* Too many queued events, drop an old one. */ DPRINTFN(-1,("usb: event dropped\n")); (void)usb_get_next_event(&ue); } - /* Don't want to wait here inside splusb() */ - ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT); - if (ueq == 0) { - printf("usb: no memory, event dropped\n"); - splx(s); - return; - } - ueq->ue.ue_type = type; - ueq->ue.ue_cookie = devh->cookie; - usbd_fill_deviceinfo(devh, &ueq->ue.ue_device); - microtime(&thetime); - TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next); wakeup(&usb_events); selwakeup(&usb_selevent); - if (usb_async_proc) + if (usb_async_proc != NULL) psignal(usb_async_proc, SIGIO); splx(s); } +void +usb_schedsoftintr(bus) + struct usbd_bus *bus; +{ + bus->methods->soft_intr(bus); +} #if defined(__NetBSD__) || defined(__OpenBSD__) int @@ -626,6 +732,7 @@ usb_detach(self, flags) int flags; { struct usb_softc *sc = (struct usb_softc *)self; + struct usb_event ue; DPRINTF(("usb_detach: start\n")); @@ -645,6 +752,10 @@ usb_detach(self, flags) } usbd_finish(); + + ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); + usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); + return (0); } #elif defined(__FreeBSD__) diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index 1e5ebeadb21..1878d444cd8 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usb.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: usb.h,v 1.38 1999/10/20 21:02:39 augustss Exp $ */ +/* $OpenBSD: usb.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb.h,v 1.42 2000/03/19 22:23:28 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -335,54 +335,78 @@ typedef struct { #define UPS_C_PORT_RESET 0x0010 } usb_port_status_t; -#define UCLASS_UNSPEC 0 -#define UCLASS_AUDIO 1 -#define USUBCLASS_AUDIOCONTROL 1 -#define USUBCLASS_AUDIOSTREAM 2 -#define USUBCLASS_MIDISTREAM 3 -#define UCLASS_CDC 2 /* communication */ -#define USUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 -#define USUBCLASS_ABSTRACT_CONTROL_MODEL 2 -#define USUBCLASS_TELEPHONE_CONTROL_MODEL 3 -#define USUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -#define USUBCLASS_CAPI_CONTROLMODEL 5 -#define USUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -#define USUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 -#define UPROTO_CDC_AT 1 -#define UCLASS_HID 3 -#define USUBCLASS_BOOT 1 -#define UCLASS_PRINTER 7 -#define USUBCLASS_PRINTER 1 -#define UPROTO_PRINTER_UNI 1 -#define UPROTO_PRINTER_BI 2 -#define UCLASS_MASS 8 -#define USUBCLASS_RBC 1 -#define USUBCLASS_SFF8020I 2 -#define USUBCLASS_QIC157 3 -#define USUBCLASS_UFI 4 -#define USUBCLASS_SFF8070I 5 -#define USUBCLASS_SCSI 6 -#define UPROTO_MASS_CBI_I 0 -#define UPROTO_MASS_CBI 1 -#define UPROTO_MASS_BULK 2 -#define UPROTO_MASS_BULK_P 80 -#define UCLASS_HUB 9 -#define USUBCLASS_HUB 0 -#define UCLASS_DATA 10 -#define USUBCLASS_DATA 0 -#define UPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ -#define UPROTO_DATA_HDLC 0x31 /* HDLC */ -#define UPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ -#define UPROTO_DATA_Q921M 0x50 /* Management for Q921 */ -#define UPROTO_DATA_Q921 0x51 /* Data for Q921 */ -#define UPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ -#define UPROTO_DATA_V42BIS 0x90 /* Data compression */ -#define UPROTO_DATA_Q931 0x91 /* Euro-ISDN */ -#define UPROTO_DATA_V120 0x92 /* V.24 rate adaption */ -#define UPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ -#define UPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ -#define UPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ -#define UPROTO_DATA_VENDOR 0xff /* Vendor specific */ +/* Device class codes */ +#define UDCLASS_AUDIO 0x00 +#define UDCLASS_COMM 0x02 +#define UDCLASS_HID 0x00 +#define UDCLASS_HUB 0x09 +#define UDSUBCLASS_HUB 0 +#define UDCLASS_MASS 0x00 + +/* Interface class codes */ +#define UICLASS_UNSPEC 0x00 + +#define UICLASS_AUDIO 0x01 +#define UISUBCLASS_AUDIOCONTROL 1 +#define UISUBCLASS_AUDIOSTREAM 2 +#define UISUBCLASS_MIDISTREAM 3 + +#define UICLASS_CDC 0x02 /* communication */ +#define UI_SUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 +#define UI_SUBCLASS_ABSTRACT_CONTROL_MODEL 2 +#define UI_SUBCLASS_TELEPHONE_CONTROL_MODEL 3 +#define UI_SUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 +#define UI_SUBCLASS_CAPI_CONTROL_MODEL 5 +#define UI_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 +#define UI_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 +#define UIPROTO_CDC_AT 1 + +#define UICLASS_HID 0x03 +#define UI_SUBCLASS_BOOT 1 +#define UIPROTO_BOOT_KEYBOARD 1 + +#define UICLASS_PHYSICAL 0x05 + +#define UICLASS_PRINTER 0x07 +#define UISUBCLASS_PRINTER 1 +#define UIPROTO_PRINTER_UNI 1 +#define UIPROTO_PRINTER_BI 2 + +#define UICLASS_MASS 0x08 +#define UISUBCLASS_RBC 1 +#define UISUBCLASS_SFF8020I 2 +#define UISUBCLASS_QIC157 3 +#define UISUBCLASS_UFI 4 +#define UISUBCLASS_SFF8070I 5 +#define UISUBCLASS_SCSI 6 +#define UIPROTO_MASS_CBI_I 0 +#define UIPROTO_MASS_CBI 1 +#define UIPROTO_MASS_BULK 2 +#define UIPROTO_MASS_BULK_P 80 + +#define UICLASS_HUB 0x09 +#define UISUBCLASS_HUB 0 + +#define UICLASS_CDC_DATA 0x0a +#define UISUBCLASS_DATA 0 +#define UIPROTO_DATA_ISDNBRI 0x30 +#define UIPROTO_DATA_HDLC 0x31 +#define UIPROTO_DATA_TRANSPARENT 0x32 +#define UIPROTO_DATA_Q921M 0x50 +#define UIPROTO_DATA_Q921 0x51 +#define UIPROTO_DATA_Q921TM 0x52 +#define UIPROTO_DATA_V42BIS 0x90 +#define UIPROTO_DATA_Q931 0x91 +#define UIPROTO_DATA_V120 0x92 +#define UIPROTO_DATA_CAPI 0x93 +#define UIPROTO_DATA_HOST_BASED 0xfd +#define UIPROTO_DATA_PUF 0xfe +#define UIPROTO_DATA_VENDOR 0xff + +#define UICLASS_FIRM_UPD 0x0c + +#define UICLASS_APPL_SPEC 0xfe +#define UICLASS_VENDOR 0xff #define USB_HUB_MAX_DEPTH 5 @@ -476,18 +500,28 @@ struct usb_ctl_report_desc { u_char data[1024]; /* filled data size will vary */ }; +typedef struct { u_int32_t cookie; } usb_event_cookie_t; + +#define USB_MAX_DEVNAMES 4 +#define USB_MAX_DEVNAMELEN 16 struct usb_device_info { + u_int8_t bus; u_int8_t addr; /* device address */ + usb_event_cookie_t cookie; char product[USB_MAX_STRING_LEN]; char vendor[USB_MAX_STRING_LEN]; char release[8]; u_int16_t productNo; u_int16_t vendorNo; + u_int16_t releaseNo; u_int8_t class; + u_int8_t subclass; + u_int8_t protocol; u_int8_t config; u_int8_t lowspeed; int power; /* power consumption in mA, 0 if selfpowered */ int nports; + char devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; u_int8_t ports[16];/* hub only: addresses of devices on ports */ #define USB_PORT_ENABLED 0xff #define USB_PORT_SUSPENDED 0xfe @@ -504,15 +538,26 @@ struct usb_device_stats { u_long requests[4]; /* indexed by transfer type UE_* */ }; -typedef struct { u_int32_t cookie; } usb_event_cookie_t; /* Events that can be read from /dev/usb */ struct usb_event { int ue_type; -#define USB_EVENT_ATTACH 1 -#define USB_EVENT_DETACH 2 - struct usb_device_info ue_device; +#define USB_EVENT_CTRLR_ATTACH 1 +#define USB_EVENT_CTRLR_DETACH 2 +#define USB_EVENT_DEVICE_ATTACH 3 +#define USB_EVENT_DEVICE_DETACH 4 +#define USB_EVENT_DRIVER_ATTACH 5 +#define USB_EVENT_DRIVER_DETACH 6 struct timespec ue_time; - usb_event_cookie_t ue_cookie; + union { + struct { + int ue_bus; + } ue_ctrlr; + struct usb_device_info ue_device; + struct { + usb_event_cookie_t ue_cookie; + char ue_devname[USB_MAX_DEVNAMELEN]; + } ue_driver; + } u; }; /* USB controller */ @@ -526,6 +571,7 @@ struct usb_event { #define USB_GET_REPORT_DESC _IOR ('U', 21, struct usb_ctl_report_desc) #define USB_SET_IMMED _IOW ('U', 22, int) #define USB_GET_REPORT _IOWR('U', 23, struct usb_ctl_report) +#define USB_SET_REPORT _IOW ('U', 24, struct usb_ctl_report) /* Generic USB device */ #define USB_GET_CONFIG _IOR ('U', 100, int) diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c index 06be4c7befe..df3bdf152ed 100644 --- a/sys/dev/usb/usb_mem.c +++ b/sys/dev/usb/usb_mem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_mem.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: usb_mem.c,v 1.15 1999/10/12 11:24:22 augustss Exp $ */ +/* $OpenBSD: usb_mem.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb_mem.c,v 1.17 1999/12/18 22:47:11 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -103,7 +103,8 @@ usb_block_allocmem(tag, size, align, dmap) usb_dma_block_t *p; int s; - DPRINTFN(5, ("usb_block_allocmem: size=%d align=%d\n", size, align)); + DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n", + (u_long)size, (u_long)align)); #ifdef DIAGNOSTIC if (!curproc) { @@ -119,8 +120,8 @@ usb_block_allocmem(tag, size, align, dmap) LIST_REMOVE(p, next); splx(s); *dmap = p; - DPRINTFN(6,("usb_block_allocmem: free list size=%d\n", - p->size)); + DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n", + (u_long)p->size)); return (USBD_NORMAL_COMPLETION); } } @@ -135,7 +136,7 @@ usb_block_allocmem(tag, size, align, dmap) DPRINTFN(6, ("usb_block_allocmem: no free\n")); p = malloc(sizeof *p, M_USB, M_NOWAIT); - if (p == 0) + if (p == NULL) return (USBD_NOMEM); *dmap = p; @@ -162,7 +163,7 @@ usb_block_allocmem(tag, size, align, dmap) BUS_DMA_NOWAIT); if (error) goto destroy; - return 0; + return (USBD_NORMAL_COMPLETION); destroy: bus_dmamap_destroy(tag, p->map); @@ -203,7 +204,7 @@ usb_block_freemem(p) { int s; - DPRINTFN(6, ("usb_block_freemem: size=%d\n", p->size)); + DPRINTFN(6, ("usb_block_freemem: size=%lu\n", (u_long)p->size)); s = splusb(); LIST_INSERT_HEAD(&usb_blk_freelist, p, next); splx(s); @@ -217,7 +218,7 @@ usb_allocmem(bus, size, align, p) usb_dma_t *p; { bus_dma_tag_t tag = bus->dmatag; - usbd_status r; + usbd_status err; struct usb_frag_dma *f; usb_dma_block_t *b; int i; @@ -227,12 +228,12 @@ usb_allocmem(bus, size, align, p) if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) { DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size)); size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1); - r = usb_block_allocmem(tag, size, align, &p->block); - if (r == USBD_NORMAL_COMPLETION) { + err = usb_block_allocmem(tag, size, align, &p->block); + if (!err) { p->block->fullblock = 1; p->offs = 0; } - return (r); + return (err); } s = splusb(); @@ -240,12 +241,12 @@ usb_allocmem(bus, size, align, p) for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next)) if (f->block->tag == tag) break; - if (!f) { + if (f == NULL) { DPRINTFN(1, ("usb_allocmem: adding fragments\n")); - r = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b); - if (r != USBD_NORMAL_COMPLETION) { + err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b); + if (err) { splx(s); - return (r); + return (err); } b->fullblock = 0; for (i = 0; i < USB_MEM_BLOCK; i += USB_MEM_SMALL) { diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h index 0dca4f7d792..0e48fd4082d 100644 --- a/sys/dev/usb/usb_mem.h +++ b/sys/dev/usb/usb_mem.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_mem.h,v 1.4 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: usb_mem.h,v 1.10 1999/10/13 18:52:54 augustss Exp $ */ +/* $OpenBSD: usb_mem.h,v 1.5 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb_mem.h,v 1.12 2000/03/12 23:10:29 nathanw Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -51,7 +51,7 @@ typedef struct usb_dma_block { LIST_ENTRY(usb_dma_block) next; } usb_dma_block_t; -#define DMAADDR(dma) ((dma)->block->segs[0].ds_addr + (dma)->offs) +#define DMAADDR(dma) ((dma)->block->map->dm_segs[0].ds_addr + (dma)->offs) #define KERNADDR(dma) ((void *)((dma)->block->kaddr + (dma)->offs)) usbd_status usb_allocmem __P((usbd_bus_handle,size_t,size_t, usb_dma_t *)); diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h index e5f69af8938..83a8f6b8024 100644 --- a/sys/dev/usb/usb_port.h +++ b/sys/dev/usb/usb_port.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_port.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: usb_port.h,v 1.14 1999/10/14 01:18:39 augustss Exp $ */ +/* $OpenBSD: usb_port.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb_port.h,v 1.21 2000/02/02 07:34:00 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -57,14 +57,21 @@ #define UHCI_DEBUG 1 #define UHUB_DEBUG 1 #define ULPT_DEBUG 1 +#define UCOM_DEBUG 1 +#define UMODEM_DEBUG 1 #define UAUDIO_DEBUG 1 +#define AUE_DEBUG 1 +#define CUE_DEBUG 1 +#define KUE_DEBUG 1 #endif typedef struct device *device_ptr_t; #define USBBASEDEVICE struct device #define USBDEV(bdev) (&(bdev)) #define USBDEVNAME(bdev) ((bdev).dv_xname) +#define USBDEVUNIT(bdev) ((bdev).dv_unit) #define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname) +#define USBGETSOFTC(d) ((void *)(d)) #define DECLARE_USB_DMA_T \ struct usb_dma_block; \ @@ -78,7 +85,7 @@ typedef struct device *device_ptr_t; #define logprintf printf -#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2) \ +#define USB_DECLARE_DRIVER_(dname) \ int __CONCAT(dname,_match) __P((struct device *, struct cfdata *, void *)); \ void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \ int __CONCAT(dname,_detach) __P((struct device *, int)); \ @@ -156,8 +163,15 @@ __CONCAT(dname,_detach)(self, flags) \ #define UHCI_DEBUG 1 #define UHUB_DEBUG 1 #define ULPT_DEBUG 1 +#define UCOM_DEBUG 1 +#define UMODEM_DEBUG 1 +#define UAUDIO_DEBUG 1 +#define AUE_DEBUG 1 +#define CUE_DEBUG 1 +#define KUE_DEBUG 1 #endif +typedef struct device *device_ptr_t; #define memcpy(d, s, l) bcopy((s),(d),(l)) #define memset(d, v, l) bzero((d),(l)) #define bswap32(x) swap32(x) @@ -166,11 +180,12 @@ __CONCAT(dname,_detach)(self, flags) \ #define uhidpoll uhidselect #define ugenpoll ugenselect -typedef struct device *device_ptr_t; #define USBBASEDEVICE struct device #define USBDEV(bdev) (&(bdev)) #define USBDEVNAME(bdev) ((bdev).dv_xname) +#define USBDEVUNIT(bdev) ((bdev).dv_unit) #define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname) +#define USBGETSOFTC(d) ((void *)(d)) #define DECLARE_USB_DMA_T \ struct usb_dma_block; \ @@ -182,8 +197,8 @@ typedef struct device *device_ptr_t; #define usb_timeout(f, d, t, h) timeout((f), (d), (t)) #define usb_untimeout(f, d, h) untimeout((f), (d)) -#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2) \ -int __CONCAT(dname,_match) __P((struct device *, void *, void *)); \ +#define USB_DECLARE_DRIVER(dname) \ +int __CONCAT(dname,_match) __P((struct device *, void *, void *)); \ void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \ int __CONCAT(dname,_detach) __P((struct device *, int)); \ int __CONCAT(dname,_activate) __P((struct device *, enum devact)); \ @@ -260,10 +275,13 @@ __CONCAT(dname,_detach)(self, flags) \ #define USBVERBOSE +#define device_ptr_t device_t #define USBBASEDEVICE device_t #define USBDEV(bdev) (bdev) #define USBDEVNAME(bdev) device_get_nameunit(bdev) +#define USBDEVUNIT(bdev) device_get_unit(bdev) #define USBDEVPTRNAME(bdev) device_get_nameunit(bdev) +#define USBGETSOFTC(bdev) (device_get_softc(bdev)) #define DECLARE_USB_DMA_T typedef void * usb_dma_t @@ -271,23 +289,22 @@ __CONCAT(dname,_detach)(self, flags) \ */ #define memcpy(d, s, l) bcopy((s),(d),(l)) #define memset(d, v, l) bzero((d),(l)) -#define bswap32(x) swap32(x) /* XXX not available in FreeBSD */ -#define kthread_create1 -#define kthread_create +#define bswap32(x) swap32(x) +#define kthread_create1(function, sc, priv, string, name) +#define kthread_create(create_function, sc) +#define kthread_exit(err) #define usb_timeout(f, d, t, h) ((h) = timeout((f), (d), (t))) #define usb_untimeout(f, d, h) untimeout((f), (d), (h)) -#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (x)), 0) +#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (s)), 0) #define clfree(p) clist_free_cblocks((p)) -#define powerhook_establish(fn, sc) 0 +#define powerhook_establish(fn, sc) (fn) #define powerhook_disestablish(hdl) #define PWR_RESUME 0 -#define config_detach(d, _1) device_delete_child(device_get_parent((d)), (d)) - -#define USB_DECLARE_DRIVER_NAME_INIT(name, dname, init) \ +#define USB_DECLARE_DRIVER_INIT(dname, init) \ static device_probe_t __CONCAT(dname,_match); \ static device_attach_t __CONCAT(dname,_attach); \ static device_detach_t __CONCAT(dname,_detach); \ @@ -303,10 +320,12 @@ static device_method_t __CONCAT(dname,_methods)[] = { \ }; \ \ static driver_t __CONCAT(dname,_driver) = { \ - name, \ + #dname, \ __CONCAT(dname,_methods), \ sizeof(struct __CONCAT(dname,_softc)) \ } +#define METHODS_NONE {0,0} +#define USB_DECLARE_DRIVER(dname) USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE) #define USB_MATCH(dname) \ static int \ @@ -373,14 +392,3 @@ __CONCAT(dname,_detach)(device_t self) #define logprintf printf #endif /* __FreeBSD__ */ - -#define NONE {0,0} - -#define USB_DECLARE_DRIVER_NAME(name, dname) \ - USB_DECLARE_DRIVER_NAME_INIT(#name, dname, NONE ) -#define USB_DECLARE_DRIVER_INIT(dname, init) \ - USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, init) -#define USB_DECLARE_DRIVER(dname) \ - USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, NONE ) - -#undef NONE diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c index aa273cd8c27..d607943fc90 100644 --- a/sys/dev/usb/usb_quirks.c +++ b/sys/dev/usb/usb_quirks.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_quirks.c,v 1.2 1999/09/27 18:03:56 fgsch Exp $ */ -/* $NetBSD: usb_quirks.c,v 1.14 1999/09/15 13:57:09 augustss Exp $ */ +/* $OpenBSD: usb_quirks.c,v 1.3 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb_quirks.c,v 1.22 2000/03/16 21:51:24 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -40,9 +40,6 @@ #include #include -#if defined(__FreeBSD__) -#include -#endif #include @@ -58,15 +55,17 @@ struct usbd_quirk_entry { u_int16_t idProduct; u_int16_t bcdDevice; struct usbd_quirks quirks; -} quirks[] = { +} usb_quirks[] = { { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE, 0x100, { UQ_NO_SET_PROTO}}, { USB_VENDOR_INSIDEOUT,USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094, { UQ_SWAP_UNICODE}}, { USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932, 0x100, { UQ_NO_STRINGS }}, - { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET, 0x002, { UQ_NO_STRINGS }}, + { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT, 0x002, { UQ_NO_STRINGS }}, { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }}, { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }}, - { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N48, 0x110, { UQ_MS_REVZ }}, + { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, { UQ_BAD_ADC }}, + { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }}, + { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, {UQ_SPUR_BUT_UP}}, { 0, 0, 0, { 0 } } }; @@ -78,7 +77,7 @@ usbd_find_quirk(d) { struct usbd_quirk_entry *t; - for (t = quirks; t->idVendor != 0; t++) { + for (t = usb_quirks; t->idVendor != 0; t++) { if (t->idVendor == UGETW(d->idVendor) && t->idProduct == UGETW(d->idProduct) && t->bcdDevice == UGETW(d->bcdDevice)) diff --git a/sys/dev/usb/usb_quirks.h b/sys/dev/usb/usb_quirks.h index f74a645641b..816791f8302 100644 --- a/sys/dev/usb/usb_quirks.h +++ b/sys/dev/usb/usb_quirks.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_quirks.h,v 1.2 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: usb_quirks.h,v 1.8 1999/10/11 09:16:39 augustss Exp $ */ +/* $OpenBSD: usb_quirks.h,v 1.3 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb_quirks.h,v 1.10 1999/11/18 23:32:31 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -46,6 +46,8 @@ struct usbd_quirks { #define UQ_NO_STRINGS 0x08 /* string descriptors are broken. */ #define UQ_BAD_ADC 0x10 /* bad audio spec version number. */ #define UQ_BUS_POWERED 0x20 /* device is bus powered, despite claim */ +#define UQ_BAD_AUDIO 0x40 /* device claims audio class, but isn't */ +#define UQ_SPUR_BUT_UP 0x80 /* spurious mouse button up events */ }; extern struct usbd_quirks usbd_no_quirk; diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index f8dc1eaacb5..1a4cd5af419 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_subr.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */ -/* $NetBSD: usb_subr.c,v 1.52 1999/10/13 08:10:58 augustss Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb_subr.c,v 1.67 2000/03/13 23:52:37 soren Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -44,12 +44,12 @@ #include #if defined(__NetBSD__) || defined(__OpenBSD__) #include +#include #elif defined(__FreeBSD__) #include #include #endif #include -#include #include @@ -158,16 +158,16 @@ usbd_get_string_desc(dev, sindex, langid, sdesc) usb_string_descriptor_t *sdesc; { usb_device_request_t req; - usbd_status r; + usbd_status err; req.bmRequestType = UT_READ_DEVICE; req.bRequest = UR_GET_DESCRIPTOR; USETW2(req.wValue, UDESC_STRING, sindex); USETW(req.wIndex, langid); USETW(req.wLength, 1); /* only size byte first */ - r = usbd_do_request(dev, &req, sdesc); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_do_request(dev, &req, sdesc); + if (err) + return (err); USETW(req.wLength, sdesc->bLength); /* the whole string */ return (usbd_do_request(dev, &req, sdesc)); } @@ -183,7 +183,7 @@ usbd_get_string(dev, si, buf) char *s; int i, n; u_int16_t c; - usbd_status r; + usbd_status err; if (si == 0) return (0); @@ -191,16 +191,16 @@ usbd_get_string(dev, si, buf) return (0); if (dev->langid == USBD_NOLANG) { /* Set up default language */ - r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us); - if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) { + err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us); + if (err || us.bLength < 4) { dev->langid = 0; /* Well, just pick English then */ } else { /* Pick the first language as the default. */ dev->langid = UGETW(us.bString[0]); } } - r = usbd_get_string_desc(dev, si, dev->langid, &us); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_string_desc(dev, si, dev->langid, &us); + if (err) return (0); s = buf; n = us.bLength / 2 - 1; @@ -215,7 +215,7 @@ usbd_get_string(dev, si, buf) *s++ = '?'; } *s++ = 0; - return buf; + return (buf); } void @@ -229,7 +229,7 @@ usbd_devinfo_vp(dev, v, p) struct usb_knowndev *kdp; #endif - if (!dev) { + if (dev == NULL) { v[0] = p[0] = '\0'; return; } @@ -237,7 +237,7 @@ usbd_devinfo_vp(dev, v, p) vendor = usbd_get_string(dev, udd->iManufacturer, v); product = usbd_get_string(dev, udd->iProduct, p); #ifdef USBVERBOSE - if (!vendor) { + if (vendor == NULL || product == NULL) { for(kdp = usb_knowndevs; kdp->vendorname != NULL; kdp++) { @@ -246,20 +246,20 @@ usbd_devinfo_vp(dev, v, p) (kdp->flags & USB_KNOWNDEV_NOPROD) != 0)) break; } - if (kdp->vendorname == NULL) - vendor = product = NULL; - else { - vendor = kdp->vendorname; + if (kdp->vendorname != NULL) { + if (!vendor) + vendor = kdp->vendorname; + if (!product) product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ? - kdp->productname : NULL; + kdp->productname : NULL; } } #endif - if (vendor) + if (vendor != NULL) strcpy(v, vendor); else sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor)); - if (product) + if (product != NULL) strcpy(p, product); else sprintf(p, "product 0x%04x", UGETW(udd->idProduct)); @@ -305,8 +305,10 @@ usb_delay_ms(bus, ms) usbd_bus_handle bus; u_int ms; { + extern int cold; + /* Wait at least two clock ticks so we know the time has passed. */ - if (bus->use_polling) + if (bus->use_polling || cold) delay((ms+1) * 1000); else tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1); @@ -328,7 +330,7 @@ usbd_reset_port(dev, port, ps) usb_port_status_t *ps; { usb_device_request_t req; - usbd_status r; + usbd_status err; int n; req.bmRequestType = UT_WRITE_CLASS_OTHER; @@ -336,34 +338,35 @@ usbd_reset_port(dev, port, ps) USETW(req.wValue, UHF_PORT_RESET); USETW(req.wIndex, port); USETW(req.wLength, 0); - r = usbd_do_request(dev, &req, 0); + err = usbd_do_request(dev, &req, 0); DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n", - port, usbd_errstr(r))); - if (r != USBD_NORMAL_COMPLETION) - return (r); + port, usbd_errstr(err))); + if (err) + return (err); n = 10; do { /* Wait for device to recover from reset. */ usbd_delay_ms(dev, USB_PORT_RESET_DELAY); - r = usbd_get_port_status(dev, port, ps); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("usbd_reset_port: get status failed %d\n",r)); - return (r); + err = usbd_get_port_status(dev, port, ps); + if (err) { + DPRINTF(("usbd_reset_port: get status failed %d\n", + err)); + return (err); } } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0); if (n == 0) { printf("usbd_reset_port: timeout\n"); return (USBD_IOERROR); } - r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); + err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); #ifdef USB_DEBUG - if (r != USBD_NORMAL_COMPLETION) + if (err) DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r)); #endif /* Wait for the device to recover from reset. */ usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY); - return (r); + return (err); } usb_interface_descriptor_t * @@ -397,7 +400,7 @@ usbd_find_idesc(cd, ifaceidx, altidx) return (d); } } - return (0); + return (NULL); } usb_endpoint_descriptor_t * @@ -414,10 +417,10 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx) int curidx; d = usbd_find_idesc(cd, ifaceidx, altidx); - if (!d) - return (0); + if (d == NULL) + return (NULL); if (endptidx >= d->bNumEndpoints) /* quick exit */ - return (0); + return (NULL); curidx = -1; for (p = (char *)d + d->bLength; p < end; ) { @@ -426,14 +429,14 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx) break; p += e->bLength; if (p <= end && e->bDescriptorType == UDESC_INTERFACE) - return (0); + return (NULL); if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) { curidx++; if (curidx == endptidx) return (e); } } - return (0); + return (NULL); } usbd_status @@ -455,15 +458,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx) ifc->index = ifaceidx; ifc->altindex = altidx; nendpt = ifc->idesc->bNumEndpoints; - DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt)); + DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt)); if (nendpt != 0) { ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint), M_USB, M_NOWAIT); - if (ifc->endpoints == 0) + if (ifc->endpoints == NULL) return (USBD_NOMEM); } else - ifc->endpoints = 0; - ifc->priv = 0; + ifc->endpoints = NULL; + ifc->priv = NULL; p = (char *)ifc->idesc + ifc->idesc->bLength; end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength); #define ed ((usb_endpoint_descriptor_t *)p) @@ -477,11 +480,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx) if (p + ed->bLength <= end && ed->bLength != 0 && ed->bDescriptorType == UDESC_ENDPOINT) goto found; - if (ed->bDescriptorType == UDESC_INTERFACE || - ed->bLength == 0) + if (ed->bLength == 0 || + ed->bDescriptorType == UDESC_INTERFACE) break; } /* passed end, or bad desc */ + DPRINTF(("usbd_fill_iface_data: bad descriptor(s): %s\n", + ed->bLength == 0 ? "0 length" : + ed->bDescriptorType == UDESC_INTERFACE ? "iface desc": + "out of data")); goto bad; found: ifc->endpoints[endpt].edesc = ed; @@ -493,7 +500,8 @@ usbd_fill_iface_data(dev, ifaceidx, altidx) return (USBD_NORMAL_COMPLETION); bad: - free(ifc->endpoints, M_USB); + if (ifc->endpoints != NULL) + free(ifc->endpoints, M_USB); return (USBD_INVAL); } @@ -530,14 +538,14 @@ usbd_set_config_no(dev, no, msg) { int index; usb_config_descriptor_t cd; - usbd_status r; + usbd_status err; DPRINTFN(5,("usbd_set_config_no: %d\n", no)); /* Figure out what config index to use. */ for (index = 0; index < dev->ddesc.bNumConfigurations; index++) { - r = usbd_get_config_desc(dev, index, &cd); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_config_desc(dev, index, &cd); + if (err) + return (err); if (cd.bConfigurationValue == no) return (usbd_set_config_index(dev, index, msg)); } @@ -552,7 +560,7 @@ usbd_set_config_index(dev, index, msg) { usb_status_t ds; usb_config_descriptor_t cd, *cdp; - usbd_status r; + usbd_status err; int ifcidx, nifc, len, selfpowered, power; DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index)); @@ -566,26 +574,26 @@ usbd_set_config_index(dev, index, msg) usbd_free_iface_data(dev, ifcidx); free(dev->ifaces, M_USB); free(dev->cdesc, M_USB); - dev->ifaces = 0; - dev->cdesc = 0; + dev->ifaces = NULL; + dev->cdesc = NULL; dev->config = 0; } /* Figure out what config number to use. */ - r = usbd_get_config_desc(dev, index, &cd); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_config_desc(dev, index, &cd); + if (err) + return (err); len = UGETW(cd.wTotalLength); cdp = malloc(len, M_USB, M_NOWAIT); - if (cdp == 0) + if (cdp == NULL) return (USBD_NOMEM); - r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); + if (err) goto bad; if (cdp->bDescriptorType != UDESC_CONFIG) { DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n", cdp->bDescriptorType)); - r = USBD_INVAL; + err = USBD_INVAL; goto bad; } selfpowered = 0; @@ -594,13 +602,12 @@ usbd_set_config_index(dev, index, msg) /* May be self powered. */ if (cdp->bmAttributes & UC_BUS_POWERED) { /* Must ask device. */ - r = usbd_get_device_status(dev, &ds); - if (r == USBD_NORMAL_COMPLETION && - (UGETW(ds.wStatus) & UDS_SELF_POWERED)) + err = usbd_get_device_status(dev, &ds); + if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED)) selfpowered = 1; DPRINTF(("usbd_set_config_index: status=0x%04x, " "error=%s\n", - UGETW(ds.wStatus), usbd_errstr(r))); + UGETW(ds.wStatus), usbd_errstr(err))); } else selfpowered = 1; } @@ -609,7 +616,7 @@ usbd_set_config_index(dev, index, msg) dev->address, cdp->bmAttributes, selfpowered, cdp->bMaxPower * 2)); #ifdef USB_DEBUG - if (!dev->powersrc) { + if (dev->powersrc == NULL) { DPRINTF(("usbd_set_config_index: No power source?\n")); return (USBD_IOERROR); } @@ -623,7 +630,7 @@ usbd_set_config_index(dev, index, msg) USBDEVNAME(dev->bus->bdev), dev->address, cdp->bConfigurationValue, power, dev->powersrc->power); - r = USBD_NO_POWER; + err = USBD_NO_POWER; goto bad; } dev->power = power; @@ -631,11 +638,11 @@ usbd_set_config_index(dev, index, msg) DPRINTF(("usbd_set_config_index: set config %d\n", cdp->bConfigurationValue)); - r = usbd_set_config(dev, cdp->bConfigurationValue); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_config(dev, cdp->bConfigurationValue); + if (err) { DPRINTF(("usbd_set_config_index: setting config=%d failed, " "error=%s\n", - cdp->bConfigurationValue, usbd_errstr(r))); + cdp->bConfigurationValue, usbd_errstr(err))); goto bad; } DPRINTF(("usbd_set_config_index: setting new config %d\n", @@ -643,16 +650,16 @@ usbd_set_config_index(dev, index, msg) nifc = cdp->bNumInterface; dev->ifaces = malloc(nifc * sizeof(struct usbd_interface), M_USB, M_NOWAIT); - if (dev->ifaces == 0) { - r = USBD_NOMEM; + if (dev->ifaces == NULL) { + err = USBD_NOMEM; goto bad; } DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp)); dev->cdesc = cdp; dev->config = cdp->bConfigurationValue; for (ifcidx = 0; ifcidx < nifc; ifcidx++) { - r = usbd_fill_iface_data(dev, ifcidx, 0); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_fill_iface_data(dev, ifcidx, 0); + if (err) { while (--ifcidx >= 0) usbd_free_iface_data(dev, ifcidx); goto bad; @@ -663,42 +670,44 @@ usbd_set_config_index(dev, index, msg) bad: free(cdp, M_USB); - return (r); + return (err); } /* XXX add function for alternate settings */ usbd_status -usbd_setup_pipe(dev, iface, ep, pipe) +usbd_setup_pipe(dev, iface, ep, ival, pipe) usbd_device_handle dev; usbd_interface_handle iface; struct usbd_endpoint *ep; + int ival; usbd_pipe_handle *pipe; { usbd_pipe_handle p; - usbd_status r; + usbd_status err; DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n", dev, iface, ep, pipe)); p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT); - if (p == 0) + if (p == NULL) return (USBD_NOMEM); p->device = dev; p->iface = iface; p->endpoint = ep; ep->refcnt++; p->refcnt = 1; - p->intrreqh = 0; + p->intrxfer = 0; p->running = 0; p->repeat = 0; + p->interval = ival; SIMPLEQ_INIT(&p->queue); - r = dev->bus->methods->open_pipe(p); - if (r != USBD_NORMAL_COMPLETION) { + err = dev->bus->methods->open_pipe(p); + if (err) { DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" "%s\n", - ep->edesc->bEndpointAddress, usbd_errstr(r))); + ep->edesc->bEndpointAddress, usbd_errstr(err))); free(p, M_USB); - return (r); + return (err); } /* Clear any stall and make sure DATA0 toggle will be used next. */ if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT) @@ -739,7 +748,8 @@ usbd_probe_and_attach(parent, dev, port, addr) { struct usb_attach_arg uaa; usb_device_descriptor_t *dd = &dev->ddesc; - int r, found, i, confi, nifaces; + int found, i, confi, nifaces; + usbd_status err; device_ptr_t dv; usbd_interface_handle ifaces[256]; /* 256 is the absolute max */ @@ -770,10 +780,11 @@ usbd_probe_and_attach(parent, dev, port, addr) uaa.release = UGETW(dd->bcdDevice); /* First try with device specific drivers. */ + DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n")); dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch); - if (dv) { + if (dv != NULL) { dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT); - if (dev->subdevs == 0) + if (dev->subdevs == NULL) return (USBD_NOMEM); dev->subdevs[0] = dv; dev->subdevs[1] = 0; @@ -782,16 +793,18 @@ usbd_probe_and_attach(parent, dev, port, addr) DPRINTF(("usbd_probe_and_attach: no device specific driver found\n")); + DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n", + dd->bNumConfigurations)); /* Next try with interface drivers. */ for (confi = 0; confi < dd->bNumConfigurations; confi++) { DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n", confi)); - r = usbd_set_config_index(dev, confi, 1); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_config_index(dev, confi, 1); + if (err) { #ifdef USB_DEBUG DPRINTF(("%s: port %d, set config at addr %d failed, " "error=%s\n", USBDEVPTRNAME(parent), port, - addr, usbd_errstr(r))); + addr, usbd_errstr(err))); #else printf("%s: port %d, set config at addr %d failed\n", USBDEVPTRNAME(parent), port, addr); @@ -800,7 +813,7 @@ usbd_probe_and_attach(parent, dev, port, addr) device_delete_child(parent, bdev); #endif - return (r); + return (err); } nifaces = dev->cdesc->bNumInterface; uaa.configno = dev->cdesc->bConfigurationValue; @@ -809,7 +822,7 @@ usbd_probe_and_attach(parent, dev, port, addr) uaa.ifaces = ifaces; uaa.nifaces = nifaces; dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT); - if (dev->subdevs == 0) { + if (dev->subdevs == NULL) { #if defined(__FreeBSD__) device_delete_child(parent, bdev); #endif @@ -906,12 +919,13 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) { usbd_device_handle dev; usb_device_descriptor_t *dd; - usbd_status r; + usbd_status err; int addr; int i; DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n", bus, depth, lowspeed)); + addr = usbd_getnewaddr(bus); if (addr < 0) { printf("%s: No free USB addresses, new device ignored.\n", @@ -920,7 +934,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) } dev = malloc(sizeof *dev, M_USB, M_NOWAIT); - if (dev == 0) + if (dev == NULL) return (USBD_NOMEM); memset(dev, 0, sizeof(*dev)); @@ -946,29 +960,29 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) dev->langid = USBD_NOLANG; dev->cookie.cookie = ++usb_cookie_no; - /* Establish the the default pipe. */ - r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe); - if (r != USBD_NORMAL_COMPLETION) { + /* Establish the default pipe. */ + err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, + &dev->default_pipe); + if (err) { usbd_remove_device(dev, up); - return (r); + return (err); } up->device = dev; dd = &dev->ddesc; /* Try a few times in case the device is slow (i.e. outside specs.) */ - for (i = 0; i < 5; i++) { + for (i = 0; i < 3; i++) { /* Get the first 8 bytes of the device descriptor. */ - r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); - if (r == USBD_NORMAL_COMPLETION) + err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); + if (!err) break; usbd_delay_ms(dev, 200); } - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " - "failed\n", - addr)); + "failed\n", addr)); usbd_remove_device(dev, up); - return (r); + return (err); } DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " @@ -994,24 +1008,22 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); /* Get the full device descriptor. */ - r = usbd_get_device_desc(dev, dd); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_reload_device_desc(dev); + if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc " "failed\n", addr)); usbd_remove_device(dev, up); - return (r); + return (err); } - /* Figure out what's wrong with this device. */ - dev->quirks = usbd_find_quirk(dd); - /* Set the address */ - r = usbd_set_address(dev, addr); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr)); - r = USBD_SET_ADDR_FAILED; + err = usbd_set_address(dev, addr); + DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr)); + if (err) { + DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr)); + err = USBD_SET_ADDR_FAILED; usbd_remove_device(dev, up); - return (r); + return (err); } /* Allow device time to set new address */ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); @@ -1026,16 +1038,34 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", addr, dev, parent)); - r = usbd_probe_and_attach(parent, dev, port, addr); - if (r != USBD_NORMAL_COMPLETION) { + usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev); + + err = usbd_probe_and_attach(parent, dev, port, addr); + if (err) { usbd_remove_device(dev, up); - return (r); + return (err); } - - usbd_add_event(USB_EVENT_ATTACH, dev); + return (USBD_NORMAL_COMPLETION); } +usbd_status +usbd_reload_device_desc(dev) + usbd_device_handle dev; +{ + usbd_status err; + + /* Get the full device descriptor. */ + err = usbd_get_device_desc(dev, &dev->ddesc); + if (err) + return (err); + + /* Figure out what's wrong with this device. */ + dev->quirks = usbd_find_quirk(&dev->ddesc); + + return (USBD_NORMAL_COMPLETION); +} + void usbd_remove_device(dev, up) usbd_device_handle dev; @@ -1043,7 +1073,7 @@ usbd_remove_device(dev, up) { DPRINTF(("usbd_remove_device: %p\n", dev)); - if (dev->default_pipe) + if (dev->default_pipe != NULL) usbd_kill_pipe(dev->default_pipe); up->device = 0; dev->bus->devices[dev->address] = 0; @@ -1138,17 +1168,35 @@ usbd_fill_deviceinfo(dev, di) struct usb_device_info *di; { struct usbd_port *p; - int i, r, s; + int i, err, s; - di->config = dev->config; + di->bus = USBDEVUNIT(dev->bus->bdev); + di->addr = dev->address; + di->cookie = dev->cookie; usbd_devinfo_vp(dev, di->vendor, di->product); usbd_printBCD(di->release, UGETW(dev->ddesc.bcdDevice)); di->vendorNo = UGETW(dev->ddesc.idVendor); di->productNo = UGETW(dev->ddesc.idProduct); + di->releaseNo = UGETW(dev->ddesc.bcdDevice); di->class = dev->ddesc.bDeviceClass; + di->subclass = dev->ddesc.bDeviceSubClass; + di->protocol = dev->ddesc.bDeviceProtocol; + di->config = dev->config; di->power = dev->self_powered ? 0 : dev->power; di->lowspeed = dev->lowspeed; - di->addr = dev->address; + + if (dev->subdevs != NULL) { + for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) { + strncpy(di->devnames[i], USBDEVPTRNAME(dev->subdevs[i]), + USB_MAX_DEVNAMELEN); + di->devnames[i][USB_MAX_DEVNAMELEN-1] = '\0'; + } + } else { + i = 0; + } + for (/* i is set */; i < USB_MAX_DEVNAMES; i++) + di->devnames[i][0] = 0; /* empty */ + if (dev->hub) { for (i = 0; i < sizeof(di->ports) / sizeof(di->ports[0]) && @@ -1156,19 +1204,19 @@ usbd_fill_deviceinfo(dev, di) i++) { p = &dev->hub->ports[i]; if (p->device) - r = p->device->address; + err = p->device->address; else { s = UGETW(p->status.wPortStatus); if (s & UPS_PORT_ENABLED) - r = USB_PORT_ENABLED; + err = USB_PORT_ENABLED; else if (s & UPS_SUSPEND) - r = USB_PORT_SUSPENDED; + err = USB_PORT_SUSPENDED; else if (s & UPS_PORT_POWER) - r = USB_PORT_POWERED; + err = USB_PORT_POWERED; else - r = USB_PORT_DISABLED; + err = USB_PORT_DISABLED; } - di->ports[i] = r; + di->ports[i] = err; } di->nports = dev->hub->hubdesc.bNbrPorts; } else @@ -1181,17 +1229,17 @@ usb_free_device(dev) { int ifcidx, nifc; - if (dev->default_pipe) + if (dev->default_pipe != NULL) usbd_kill_pipe(dev->default_pipe); - if (dev->ifaces) { + if (dev->ifaces != NULL) { nifc = dev->cdesc->bNumInterface; for (ifcidx = 0; ifcidx < nifc; ifcidx++) usbd_free_iface_data(dev, ifcidx); free(dev->ifaces, M_USB); } - if (dev->cdesc) + if (dev->cdesc != NULL) free(dev->cdesc, M_USB); - if (dev->subdevs) + if (dev->subdevs != NULL) free(dev->subdevs, M_USB); free(dev, M_USB); } @@ -1226,36 +1274,33 @@ usb_disconnect_port(up, parent) up, dev, up->portno)); #ifdef DIAGNOSTIC - if (!dev) { + if (dev == NULL) { printf("usb_disconnect_port: no device\n"); return; } #endif - if (!dev->cdesc) { - /* Partially attached device, just drop it. */ - dev->bus->devices[dev->address] = 0; - up->device = 0; - return; - } - - if (dev->subdevs) { + if (dev->subdevs != NULL) { + DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n")); for (i = 0; dev->subdevs[i]; i++) { - if (!dev->subdevs[i]) /* skip empty elements */ - continue; - printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]), hubname); if (up->portno != 0) printf(" port %d", up->portno); printf(" (addr %d) disconnected\n", dev->address); +#if defined(__NetBSD__) || defined(__OpenBSD__) config_detach(dev->subdevs[i], DETACH_FORCE); +#elif defined(__FreeBSD__) + device_delete_child(device_get_parent(dev->subdevs[i]), + dev->subdevs[i]); +#endif + } } - usbd_add_event(USB_EVENT_DETACH, dev); - dev->bus->devices[dev->address] = 0; - up->device = 0; + usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev); + dev->bus->devices[dev->address] = NULL; + up->device = NULL; usb_free_device(dev); } diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index f37596c2392..2765d7b4b07 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi.c,v 1.7 1999/11/07 21:30:20 fgsch Exp $ */ -/* $NetBSD: usbdi.c,v 1.47 1999/10/13 23:46:10 augustss Exp $ */ +/* $OpenBSD: usbdi.c,v 1.8 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usbdi.c,v 1.65 2000/03/08 15:34:10 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -40,14 +40,17 @@ #include #include -#include #if defined(__NetBSD__) || defined(__OpenBSD__) +#include #include #elif defined(__FreeBSD__) #include #include #include #include "usb_if.h" +#if defined(DIAGNOSTIC) && defined(__i386__) +#include +#endif #endif #include #include @@ -60,6 +63,10 @@ #include #include +#if defined(__FreeBSD__) +#include "usb_if.h" +#endif + #ifdef USB_DEBUG #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x @@ -71,11 +78,10 @@ extern int usbdebug; static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe)); void usbd_do_request_async_cb - __P((usbd_request_handle, usbd_private_handle, usbd_status)); + __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); void usbd_start_next __P((usbd_pipe_handle pipe)); - -static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests = - SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests); +usbd_status usbd_open_pipe_ival + __P((usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int)); static int usbd_nbuses = 0; @@ -88,29 +94,18 @@ usbd_init() void usbd_finish() { - usbd_request_handle reqh; - - if (--usbd_nbuses == 0) { - /* Last controller is gone, free all requests. */ - for (;;) { - reqh = SIMPLEQ_FIRST(&usbd_free_requests); - if (reqh == NULL) - break; - SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next); - free(reqh, M_USB); - } - } + --usbd_nbuses; } -static __inline int usbd_reqh_isread __P((usbd_request_handle reqh)); +static __inline int usbd_xfer_isread __P((usbd_xfer_handle xfer)); static __inline int -usbd_reqh_isread(reqh) - usbd_request_handle reqh; +usbd_xfer_isread(xfer) + usbd_xfer_handle xfer; { - if (reqh->rqflags & URQ_REQUEST) - return (reqh->request.bmRequestType & UT_READ); + if (xfer->rqflags & URQ_REQUEST) + return (xfer->request.bmRequestType & UT_READ); else - return (reqh->pipe->endpoint->edesc->bEndpointAddress & + return (xfer->pipe->endpoint->edesc->bEndpointAddress & UE_DIR_IN); } @@ -121,13 +116,13 @@ void usbd_dump_queue(pipe) usbd_pipe_handle pipe; { - usbd_request_handle reqh; + usbd_xfer_handle xfer; printf("usbd_dump_queue: pipe=%p\n", pipe); - for (reqh = SIMPLEQ_FIRST(&pipe->queue); - reqh; - reqh = SIMPLEQ_NEXT(reqh, next)) { - printf(" reqh=%p\n", reqh); + for (xfer = SIMPLEQ_FIRST(&pipe->queue); + xfer; + xfer = SIMPLEQ_NEXT(xfer, next)) { + printf(" xfer=%p\n", xfer); } } #endif @@ -139,69 +134,90 @@ usbd_open_pipe(iface, address, flags, pipe) u_int8_t flags; usbd_pipe_handle *pipe; { + return (usbd_open_pipe_ival(iface, address, flags, pipe, + USBD_DEFAULT_INTERVAL)); +} + +usbd_status +usbd_open_pipe_ival(iface, address, flags, pipe, ival) + usbd_interface_handle iface; + u_int8_t address; + u_int8_t flags; + usbd_pipe_handle *pipe; + int ival; +{ usbd_pipe_handle p; struct usbd_endpoint *ep; - usbd_status r; + usbd_status err; int i; + DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n", + iface, address, flags)); + for (i = 0; i < iface->idesc->bNumEndpoints; i++) { ep = &iface->endpoints[i]; + if (ep->edesc == NULL) + return (USBD_IOERROR); if (ep->edesc->bEndpointAddress == address) goto found; } return (USBD_BAD_ADDRESS); found: - if ((flags & USBD_EXCLUSIVE_USE) && - ep->refcnt != 0) + if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0) return (USBD_IN_USE); - r = usbd_setup_pipe(iface->device, iface, ep, &p); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_setup_pipe(iface->device, iface, ep, ival, &p); + if (err) + return (err); LIST_INSERT_HEAD(&iface->pipes, p, next); *pipe = p; return (USBD_NORMAL_COMPLETION); } usbd_status -usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb) +usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, len, cb, ival) usbd_interface_handle iface; u_int8_t address; u_int8_t flags; usbd_pipe_handle *pipe; usbd_private_handle priv; void *buffer; - u_int32_t length; + u_int32_t len; usbd_callback cb; + int ival; { - usbd_status r; - usbd_request_handle reqh; + usbd_status err; + usbd_xfer_handle xfer; usbd_pipe_handle ipipe; - r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe); - if (r != USBD_NORMAL_COMPLETION) - return (r); - reqh = usbd_alloc_request(iface->device); - if (reqh == 0) { - r = USBD_NOMEM; + DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n", + address, flags, len)); + + err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE, + &ipipe, ival); + if (err) + return (err); + xfer = usbd_alloc_xfer(iface->device); + if (xfer == NULL) { + err = USBD_NOMEM; goto bad1; } - usbd_setup_request(reqh, ipipe, priv, buffer, length, flags, + usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags, USBD_NO_TIMEOUT, cb); - ipipe->intrreqh = reqh; + ipipe->intrxfer = xfer; ipipe->repeat = 1; - r = usbd_transfer(reqh); + err = usbd_transfer(xfer); *pipe = ipipe; - if (r != USBD_IN_PROGRESS) + if (err != USBD_IN_PROGRESS) goto bad2; return (USBD_NORMAL_COMPLETION); bad2: - ipipe->intrreqh = 0; + ipipe->intrxfer = 0; ipipe->repeat = 0; - usbd_free_request(reqh); + usbd_free_xfer(xfer); bad1: usbd_close_pipe(ipipe); - return r; + return (err); } usbd_status @@ -209,7 +225,7 @@ usbd_close_pipe(pipe) usbd_pipe_handle pipe; { #ifdef DIAGNOSTIC - if (pipe == 0) { + if (pipe == NULL) { printf("usbd_close_pipe: pipe==NULL\n"); return (USBD_NORMAL_COMPLETION); } @@ -222,185 +238,197 @@ usbd_close_pipe(pipe) LIST_REMOVE(pipe, next); pipe->endpoint->refcnt--; pipe->methods->close(pipe); - if (pipe->intrreqh) - usbd_free_request(pipe->intrreqh); + if (pipe->intrxfer != NULL) + usbd_free_xfer(pipe->intrxfer); free(pipe, M_USB); return (USBD_NORMAL_COMPLETION); } usbd_status -usbd_transfer(reqh) - usbd_request_handle reqh; +usbd_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; - usb_dma_t *dmap = &reqh->dmabuf; - usbd_status r; + usbd_pipe_handle pipe = xfer->pipe; + usb_dma_t *dmap = &xfer->dmabuf; + usbd_status err; u_int size; int s; - DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n", - reqh, reqh->flags, pipe, pipe->running)); + DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n", + xfer, xfer->flags, pipe, pipe->running)); #ifdef USB_DEBUG if (usbdebug > 5) usbd_dump_queue(pipe); #endif - reqh->done = 0; + xfer->done = 0; - size = reqh->length; + size = xfer->length; /* If there is no buffer, allocate one. */ - if (!(reqh->rqflags & URQ_DEV_DMABUF) && size != 0) { + if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) { struct usbd_bus *bus = pipe->device->bus; #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_AUTO_DMABUF) + if (xfer->rqflags & URQ_AUTO_DMABUF) printf("usbd_transfer: has old buffer!\n"); #endif - r = bus->methods->allocm(bus, dmap, size); - if (r != USBD_NORMAL_COMPLETION) - return (r); - reqh->rqflags |= URQ_AUTO_DMABUF; + err = bus->methods->allocm(bus, dmap, size); + if (err) + return (err); + xfer->rqflags |= URQ_AUTO_DMABUF; } /* Copy data if going out. */ - if (!(reqh->flags & USBD_NO_COPY) && size != 0 && - !usbd_reqh_isread(reqh)) - memcpy(KERNADDR(dmap), reqh->buffer, size); + if (!(xfer->flags & USBD_NO_COPY) && size != 0 && + !usbd_xfer_isread(xfer)) + memcpy(KERNADDR(dmap), xfer->buffer, size); - r = pipe->methods->transfer(reqh); + err = pipe->methods->transfer(xfer); - if (r != USBD_IN_PROGRESS && r != USBD_NORMAL_COMPLETION) { + if (err != USBD_IN_PROGRESS && err) { /* The transfer has not been queued, so free buffer. */ - if (reqh->rqflags & URQ_AUTO_DMABUF) { + if (xfer->rqflags & URQ_AUTO_DMABUF) { struct usbd_bus *bus = pipe->device->bus; - bus->methods->freem(bus, &reqh->dmabuf); - reqh->rqflags &= ~URQ_AUTO_DMABUF; + bus->methods->freem(bus, &xfer->dmabuf); + xfer->rqflags &= ~URQ_AUTO_DMABUF; } } - if (!(reqh->flags & USBD_SYNCHRONOUS)) - return (r); + if (!(xfer->flags & USBD_SYNCHRONOUS)) + return (err); /* Sync transfer, wait for completion. */ - if (r != USBD_IN_PROGRESS) - return (r); + if (err != USBD_IN_PROGRESS) + return (err); s = splusb(); - if (!reqh->done) { + if (!xfer->done) { if (pipe->device->bus->use_polling) panic("usbd_transfer: not done\n"); - tsleep(reqh, PRIBIO, "usbsyn", 0); + /* XXX Temporary hack XXX */ + if (xfer->flags & USBD_NO_TSLEEP) { + int i; + usbd_bus_handle bus = pipe->device->bus; + int to = xfer->timeout * 1000; + for (i = 0; i < to; i += 10) { + delay(10); + bus->methods->do_poll(bus); + if (xfer->done) + break; + } + if (!xfer->done) { + pipe->methods->abort(xfer); + xfer->status = USBD_TIMEOUT; + } + } else + /* XXX End hack XXX */ + tsleep(xfer, PRIBIO, "usbsyn", 0); } splx(s); - return (reqh->status); + return (xfer->status); } /* Like usbd_transfer(), but waits for completion. */ usbd_status -usbd_sync_transfer(reqh) - usbd_request_handle reqh; +usbd_sync_transfer(xfer) + usbd_xfer_handle xfer; { - reqh->flags |= USBD_SYNCHRONOUS; - return (usbd_transfer(reqh)); + xfer->flags |= USBD_SYNCHRONOUS; + return (usbd_transfer(xfer)); } void * -usbd_alloc_buffer(reqh, size) - usbd_request_handle reqh; +usbd_alloc_buffer(xfer, size) + usbd_xfer_handle xfer; u_int32_t size; { - struct usbd_bus *bus = reqh->device->bus; - usbd_status r; + struct usbd_bus *bus = xfer->device->bus; + usbd_status err; - r = bus->methods->allocm(bus, &reqh->dmabuf, size); - if (r != USBD_NORMAL_COMPLETION) + err = bus->methods->allocm(bus, &xfer->dmabuf, size); + if (err) return (0); - reqh->rqflags |= URQ_DEV_DMABUF; - return (KERNADDR(&reqh->dmabuf)); + xfer->rqflags |= URQ_DEV_DMABUF; + return (KERNADDR(&xfer->dmabuf)); } void -usbd_free_buffer(reqh) - usbd_request_handle reqh; +usbd_free_buffer(xfer) + usbd_xfer_handle xfer; { #ifdef DIAGNOSTIC - if (!(reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) { + if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) { printf("usbd_free_buffer: no buffer\n"); return; } #endif - reqh->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF); - reqh->device->bus->methods->freem(reqh->device->bus, &reqh->dmabuf); + xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF); + xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf); } void * -usbd_get_buffer(reqh) - usbd_request_handle reqh; +usbd_get_buffer(xfer) + usbd_xfer_handle xfer; { - if (!(reqh->rqflags & URQ_DEV_DMABUF)) + if (!(xfer->rqflags & URQ_DEV_DMABUF)) return (0); - return (KERNADDR(&reqh->dmabuf)); + return (KERNADDR(&xfer->dmabuf)); } -usbd_request_handle -usbd_alloc_request(dev) +usbd_xfer_handle +usbd_alloc_xfer(dev) usbd_device_handle dev; { - usbd_request_handle reqh; - - reqh = SIMPLEQ_FIRST(&usbd_free_requests); - if (reqh) - SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next); - else - reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT); - if (!reqh) - return (0); - memset(reqh, 0, sizeof *reqh); - reqh->device = dev; - DPRINTFN(5,("usbd_alloc_request() = %p\n", reqh)); - return (reqh); + usbd_xfer_handle xfer; + + xfer = dev->bus->methods->allocx(dev->bus); + if (!xfer) + return (NULL); + xfer->device = dev; + DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer)); + return (xfer); } usbd_status -usbd_free_request(reqh) - usbd_request_handle reqh; +usbd_free_xfer(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(5,("usbd_free_request: %p\n", reqh)); - if (reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) - usbd_free_buffer(reqh); - SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next); + DPRINTFN(5,("usbd_free_xfer: %p\n", xfer)); + if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) + usbd_free_buffer(xfer); + xfer->device->bus->methods->freex(xfer->device->bus, xfer); return (USBD_NORMAL_COMPLETION); } void -usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback) - usbd_request_handle reqh; +usbd_setup_xfer(xfer, pipe, priv, buffer, length, flags, timeout, callback) + usbd_xfer_handle xfer; usbd_pipe_handle pipe; usbd_private_handle priv; void *buffer; u_int32_t length; u_int16_t flags; u_int32_t timeout; - void (*callback) __P((usbd_request_handle, + void (*callback) __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); { - reqh->pipe = pipe; - reqh->priv = priv; - reqh->buffer = buffer; - reqh->length = length; - reqh->actlen = 0; - reqh->flags = flags; - reqh->timeout = timeout; - reqh->status = USBD_NOT_STARTED; - reqh->callback = callback; - reqh->rqflags &= ~URQ_REQUEST; - reqh->nframes = 0; + xfer->pipe = pipe; + xfer->priv = priv; + xfer->buffer = buffer; + xfer->length = length; + xfer->actlen = 0; + xfer->flags = flags; + xfer->timeout = timeout; + xfer->status = USBD_NOT_STARTED; + xfer->callback = callback; + xfer->rqflags &= ~URQ_REQUEST; + xfer->nframes = 0; } void -usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer, +usbd_setup_default_xfer(xfer, dev, priv, timeout, req, buffer, length, flags, callback) - usbd_request_handle reqh; + usbd_xfer_handle xfer; usbd_device_handle dev; usbd_private_handle priv; u_int32_t timeout; @@ -408,27 +436,27 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer, void *buffer; u_int32_t length; u_int16_t flags; - void (*callback) __P((usbd_request_handle, + void (*callback) __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); { - reqh->pipe = dev->default_pipe; - reqh->priv = priv; - reqh->buffer = buffer; - reqh->length = length; - reqh->actlen = 0; - reqh->flags = flags; - reqh->timeout = timeout; - reqh->status = USBD_NOT_STARTED; - reqh->callback = callback; - reqh->request = *req; - reqh->rqflags |= URQ_REQUEST; - reqh->nframes = 0; + xfer->pipe = dev->default_pipe; + xfer->priv = priv; + xfer->buffer = buffer; + xfer->length = length; + xfer->actlen = 0; + xfer->flags = flags; + xfer->timeout = timeout; + xfer->status = USBD_NOT_STARTED; + xfer->callback = callback; + xfer->request = *req; + xfer->rqflags |= URQ_REQUEST; + xfer->nframes = 0; } void -usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback) - usbd_request_handle reqh; +usbd_setup_isoc_xfer(xfer, pipe, priv, frlengths, nframes, flags, callback) + usbd_xfer_handle xfer; usbd_pipe_handle pipe; usbd_private_handle priv; u_int16_t *frlengths; @@ -436,42 +464,48 @@ usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback) u_int16_t flags; usbd_callback callback; { - reqh->pipe = pipe; - reqh->priv = priv; - reqh->buffer = 0; - reqh->length = 0; - reqh->actlen = 0; - reqh->flags = flags; - reqh->timeout = USBD_NO_TIMEOUT; - reqh->status = USBD_NOT_STARTED; - reqh->callback = callback; - reqh->rqflags &= ~URQ_REQUEST; - reqh->frlengths = frlengths; - reqh->nframes = nframes; + xfer->pipe = pipe; + xfer->priv = priv; + xfer->buffer = 0; + xfer->length = 0; + xfer->actlen = 0; + xfer->flags = flags; + xfer->timeout = USBD_NO_TIMEOUT; + xfer->status = USBD_NOT_STARTED; + xfer->callback = callback; + xfer->rqflags &= ~URQ_REQUEST; + xfer->frlengths = frlengths; + xfer->nframes = nframes; } void -usbd_get_request_status(reqh, priv, buffer, count, status) - usbd_request_handle reqh; +usbd_get_xfer_status(xfer, priv, buffer, count, status) + usbd_xfer_handle xfer; usbd_private_handle *priv; void **buffer; u_int32_t *count; usbd_status *status; { - if (priv) - *priv = reqh->priv; - if (buffer) - *buffer = reqh->buffer; - if (count) - *count = reqh->actlen; - if (status) - *status = reqh->status; + if (priv != NULL) + *priv = xfer->priv; + if (buffer != NULL) + *buffer = xfer->buffer; + if (count != NULL) + *count = xfer->actlen; + if (status != NULL) + *status = xfer->status; } usb_config_descriptor_t * usbd_get_config_descriptor(dev) usbd_device_handle dev; { +#ifdef DIAGNOSTIC + if (dev == NULL) { + printf("usbd_get_config_descriptor: dev == NULL\n"); + return (NULL); + } +#endif return (dev->cdesc); } @@ -479,6 +513,12 @@ usb_interface_descriptor_t * usbd_get_interface_descriptor(iface) usbd_interface_handle iface; { +#ifdef DIAGNOSTIC + if (iface == NULL) { + printf("usbd_get_interface_descriptor: dev == NULL\n"); + return (NULL); + } +#endif return (iface->idesc); } @@ -503,19 +543,19 @@ usbd_status usbd_abort_pipe(pipe) usbd_pipe_handle pipe; { - usbd_status r; + usbd_status err; int s; #ifdef DIAGNOSTIC - if (pipe == 0) { + if (pipe == NULL) { printf("usbd_close_pipe: pipe==NULL\n"); return (USBD_NORMAL_COMPLETION); } #endif s = splusb(); - r = usbd_ar_pipe(pipe); + err = usbd_ar_pipe(pipe); splx(s); - return (r); + return (err); } usbd_status @@ -524,7 +564,7 @@ usbd_clear_endpoint_stall(pipe) { usbd_device_handle dev = pipe->device; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); @@ -539,15 +579,15 @@ usbd_clear_endpoint_stall(pipe) USETW(req.wValue, UF_ENDPOINT_HALT); USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); USETW(req.wLength, 0); - r = usbd_do_request(dev, &req, 0); + err = usbd_do_request(dev, &req, 0); #if 0 XXX should we do this? - if (r == USBD_NORMAL_COMPLETION) { + if (!err) { pipe->state = USBD_PIPE_ACTIVE; /* XXX activate pipe */ } #endif - return (r); + return (err); } usbd_status @@ -556,7 +596,7 @@ usbd_clear_endpoint_stall_async(pipe) { usbd_device_handle dev = pipe->device; usb_device_request_t req; - usbd_status r; + usbd_status err; pipe->methods->cleartoggle(pipe); @@ -565,8 +605,16 @@ usbd_clear_endpoint_stall_async(pipe) USETW(req.wValue, UF_ENDPOINT_HALT); USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); USETW(req.wLength, 0); - r = usbd_do_request_async(dev, &req, 0); - return (r); + err = usbd_do_request_async(dev, &req, 0); + return (err); +} + +void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */ +void +usbd_clear_endpoint_toggle(pipe) + usbd_pipe_handle pipe; +{ + pipe->methods->cleartoggle(pipe); } usbd_status @@ -583,7 +631,7 @@ usbd_interface_count(dev, count) usbd_device_handle dev; u_int8_t *count; { - if (!dev->cdesc) + if (dev->cdesc == NULL) return (USBD_NOT_CONFIGURED); *count = dev->cdesc->bNumInterface; return (USBD_NORMAL_COMPLETION); @@ -604,7 +652,7 @@ usbd_device2interface_handle(dev, ifaceno, iface) u_int8_t ifaceno; usbd_interface_handle *iface; { - if (!dev->cdesc) + if (dev->cdesc == NULL) return (USBD_NOT_CONFIGURED); if (ifaceno >= dev->cdesc->bNumInterface) return (USBD_INVAL); @@ -626,7 +674,7 @@ usbd_set_interface(iface, altidx) int altidx; { usb_device_request_t req; - usbd_status r; + usbd_status err; if (LIST_FIRST(&iface->pipes) != 0) return (USBD_IN_USE); @@ -636,16 +684,16 @@ usbd_set_interface(iface, altidx) iface->endpoints = 0; iface->idesc = 0; - r = usbd_fill_iface_data(iface->device, iface->index, altidx); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_fill_iface_data(iface->device, iface->index, altidx); + if (err) + return (err); req.bmRequestType = UT_WRITE_INTERFACE; req.bRequest = UR_SET_INTERFACE; USETW(req.wValue, iface->idesc->bAlternateSetting); USETW(req.wIndex, iface->idesc->bInterfaceNumber); USETW(req.wLength, 0); - return usbd_do_request(iface->device, &req, 0); + return (usbd_do_request(iface->device, &req, 0)); } int @@ -687,7 +735,7 @@ usbd_get_interface(iface, aiface) USETW(req.wValue, 0); USETW(req.wIndex, iface->idesc->bInterfaceNumber); USETW(req.wLength, 1); - return usbd_do_request(iface->device, &req, aiface); + return (usbd_do_request(iface->device, &req, aiface)); } /*** Internal routines ***/ @@ -697,7 +745,7 @@ static usbd_status usbd_ar_pipe(pipe) usbd_pipe_handle pipe; { - usbd_request_handle reqh; + usbd_xfer_handle xfer; SPLUSBCHECK; @@ -707,11 +755,11 @@ usbd_ar_pipe(pipe) usbd_dump_queue(pipe); #endif pipe->repeat = 0; - while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) { - DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n", - pipe, reqh, pipe->methods)); + while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) { + DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", + pipe, xfer, pipe->methods)); /* Make the HC abort it (and invoke the callback). */ - pipe->methods->abort(reqh); + pipe->methods->abort(xfer); /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ } return (USBD_NORMAL_COMPLETION); @@ -719,22 +767,22 @@ usbd_ar_pipe(pipe) /* Called at splusb() */ void -usb_transfer_complete(reqh) - usbd_request_handle reqh; +usb_transfer_complete(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; - usb_dma_t *dmap = &reqh->dmabuf; + usbd_pipe_handle pipe = xfer->pipe; + usb_dma_t *dmap = &xfer->dmabuf; int repeat = pipe->repeat; int polling; SPLUSBCHECK; - DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p status=%d actlen=%d\n", - pipe, reqh, reqh->status, reqh->actlen)); + DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d actlen=%d\n", + pipe, xfer, xfer->status, xfer->actlen)); #ifdef DIAGNOSTIC - if (!pipe) { - printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh); + if (pipe == NULL) { + printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); return; } #endif @@ -743,63 +791,71 @@ usb_transfer_complete(reqh) if (polling) pipe->running = 0; - if (!(reqh->flags & USBD_NO_COPY) && reqh->actlen != 0 && - usbd_reqh_isread(reqh)) { + if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 && + usbd_xfer_isread(xfer)) { #ifdef DIAGNOSTIC - if (reqh->actlen > reqh->length) { + if (xfer->actlen > xfer->length) { printf("usb_transfer_complete: actlen > len %d > %d\n", - reqh->actlen, reqh->length); - reqh->actlen = reqh->length; + xfer->actlen, xfer->length); + xfer->actlen = xfer->length; } #endif - memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen); + memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen); } /* if we allocated the buffer in usbd_transfer() we free it here. */ - if (reqh->rqflags & URQ_AUTO_DMABUF) { + if (xfer->rqflags & URQ_AUTO_DMABUF) { if (!repeat) { struct usbd_bus *bus = pipe->device->bus; bus->methods->freem(bus, dmap); - reqh->rqflags &= ~URQ_AUTO_DMABUF; + xfer->rqflags &= ~URQ_AUTO_DMABUF; } } - if (pipe->methods->done) - pipe->methods->done(reqh); - if (!repeat) { /* Remove request from queue. */ #ifdef DIAGNOSTIC - if (reqh != SIMPLEQ_FIRST(&pipe->queue)) + if (xfer != SIMPLEQ_FIRST(&pipe->queue)) printf("usb_transfer_complete: bad dequeue %p != %p\n", - reqh, SIMPLEQ_FIRST(&pipe->queue)); + xfer, SIMPLEQ_FIRST(&pipe->queue)); #endif - SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next); + SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next); } + DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n", + repeat, SIMPLEQ_FIRST(&pipe->queue))); /* Count completed transfers. */ ++pipe->device->bus->stats.requests [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; - reqh->done = 1; - if (reqh->status == USBD_NORMAL_COMPLETION && - reqh->actlen < reqh->length && - !(reqh->flags & USBD_SHORT_XFER_OK)) { + xfer->done = 1; + if (xfer->status && xfer->actlen < xfer->length && + !(xfer->flags & USBD_SHORT_XFER_OK)) { DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n", - reqh->actlen, reqh->length)); - reqh->status = USBD_SHORT_XFER; + xfer->actlen, xfer->length)); + xfer->status = USBD_SHORT_XFER; } - if (reqh->callback) - reqh->callback(reqh, reqh->priv, reqh->status); + if (xfer->callback) + xfer->callback(xfer, xfer->priv, xfer->status); + +#ifdef DIAGNOSTIC + if (pipe->methods->done != NULL) + pipe->methods->done(xfer); + else + printf("usb_transfer_complete: pipe->methods->done == NULL\n"); +#else + pipe->methods->done(xfer); +#endif - if ((reqh->flags & USBD_SYNCHRONOUS) && !polling) - wakeup(reqh); + if ((xfer->flags & USBD_SYNCHRONOUS) && !polling) + wakeup(xfer); if (!repeat) { /* XXX should we stop the queue on all errors? */ - if (reqh->status == USBD_CANCELLED || - reqh->status == USBD_TIMEOUT) + if ((xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) && + pipe->iface != NULL) /* not control pipe */ pipe->running = 0; else usbd_start_next(pipe); @@ -807,25 +863,25 @@ usb_transfer_complete(reqh) } usbd_status -usb_insert_transfer(reqh) - usbd_request_handle reqh; +usb_insert_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; - usbd_status r; + usbd_pipe_handle pipe = xfer->pipe; + usbd_status err; int s; DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", - pipe, pipe->running, reqh->timeout)); + pipe, pipe->running, xfer->timeout)); s = splusb(); - SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next); + SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); if (pipe->running) - r = USBD_IN_PROGRESS; + err = USBD_IN_PROGRESS; else { pipe->running = 1; - r = USBD_NORMAL_COMPLETION; + err = USBD_NORMAL_COMPLETION; } splx(s); - return (r); + return (err); } /* Called at splusb() */ @@ -833,33 +889,31 @@ void usbd_start_next(pipe) usbd_pipe_handle pipe; { - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; SPLUSBCHECK; - DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe)); - #ifdef DIAGNOSTIC - if (!pipe) { - printf("usbd_start_next: pipe == 0\n"); + if (pipe == NULL) { + printf("usbd_start_next: pipe == NULL\n"); return; } - if (!pipe->methods || !pipe->methods->start) { - printf("usbd_start_next: no start method\n"); + if (pipe->methods == NULL || pipe->methods->start == NULL) { + printf("usbd_start_next: pipe=%p no start method\n", pipe); return; } #endif /* Get next request in queue. */ - reqh = SIMPLEQ_FIRST(&pipe->queue); - DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh)); - if (!reqh) + xfer = SIMPLEQ_FIRST(&pipe->queue); + DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); + if (xfer == NULL) { pipe->running = 0; - else { - r = pipe->methods->start(reqh); - if (r != USBD_IN_PROGRESS) { - printf("usbd_start_next: error=%d\n", r); + } else { + err = pipe->methods->start(xfer); + if (err != USBD_IN_PROGRESS) { + printf("usbd_start_next: error=%d\n", err); pipe->running = 0; /* XXX do what? */ } @@ -883,35 +937,39 @@ usbd_do_request_flags(dev, req, data, flags, actlen) u_int16_t flags; int *actlen; { - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; #ifdef DIAGNOSTIC +#if defined(__i386__) && defined(__FreeBSD__) + KASSERT(intr_nesting_level == 0, + ("usbd_do_request: in interrupt context")); +#endif if (dev->bus->intr_context) { printf("usbd_do_request: not in process context\n"); return (USBD_INVAL); } #endif - reqh = usbd_alloc_request(dev); - if (reqh == 0) + xfer = usbd_alloc_xfer(dev); + if (xfer == NULL) return (USBD_NOMEM); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, + usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, UGETW(req->wLength), flags, 0); - r = usbd_sync_transfer(reqh); + err = usbd_sync_transfer(xfer); #if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (reqh->actlen > reqh->length) + if (xfer->actlen > xfer->length) DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - dev->address, reqh->request.bmRequestType, - reqh->request.bRequest, UGETW(reqh->request.wValue), - UGETW(reqh->request.wIndex), - UGETW(reqh->request.wLength), - reqh->length, reqh->actlen)); + dev->address, xfer->request.bmRequestType, + xfer->request.bRequest, UGETW(xfer->request.wValue), + UGETW(xfer->request.wIndex), + UGETW(xfer->request.wLength), + xfer->length, xfer->actlen)); #endif - if (actlen) - *actlen = reqh->actlen; - if (r == USBD_STALLED) { + if (actlen != NULL) + *actlen = xfer->actlen; + if (err == USBD_STALLED) { /* * The control endpoint has stalled. Control endpoints * should not halt, but some may do so anyway so clear @@ -920,18 +978,18 @@ usbd_do_request_flags(dev, req, data, flags, actlen) usb_device_request_t treq; usb_status_t status; u_int16_t s; - usbd_status nr; + usbd_status nerr; treq.bmRequestType = UT_READ_ENDPOINT; treq.bRequest = UR_GET_STATUS; USETW(treq.wValue, 0); USETW(treq.wIndex, 0); USETW(treq.wLength, sizeof(usb_status_t)); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, + usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,sizeof(usb_status_t), 0, 0); - nr = usbd_sync_transfer(reqh); - if (nr != USBD_NORMAL_COMPLETION) + nerr = usbd_sync_transfer(xfer); + if (nerr) goto bad; s = UGETW(status.wStatus); DPRINTF(("usbd_do_request: status = 0x%04x\n", s)); @@ -942,36 +1000,36 @@ usbd_do_request_flags(dev, req, data, flags, actlen) USETW(treq.wValue, UF_ENDPOINT_HALT); USETW(treq.wIndex, 0); USETW(treq.wLength, 0); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, + usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status, 0, 0, 0); - nr = usbd_sync_transfer(reqh); - if (nr != USBD_NORMAL_COMPLETION) + nerr = usbd_sync_transfer(xfer); + if (nerr) goto bad; } bad: - usbd_free_request(reqh); - return (r); + usbd_free_xfer(xfer); + return (err); } void -usbd_do_request_async_cb(reqh, priv, status) - usbd_request_handle reqh; +usbd_do_request_async_cb(xfer, priv, status) + usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { #if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (reqh->actlen > reqh->length) + if (xfer->actlen > xfer->length) DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - reqh->pipe->device->address, - reqh->request.bmRequestType, - reqh->request.bRequest, UGETW(reqh->request.wValue), - UGETW(reqh->request.wIndex), - UGETW(reqh->request.wLength), - reqh->length, reqh->actlen)); + xfer->pipe->device->address, + xfer->request.bmRequestType, + xfer->request.bRequest, UGETW(xfer->request.wValue), + UGETW(xfer->request.wIndex), + UGETW(xfer->request.wLength), + xfer->length, xfer->actlen)); #endif - usbd_free_request(reqh); + usbd_free_xfer(xfer); } /* @@ -984,19 +1042,19 @@ usbd_do_request_async(dev, req, data) usb_device_request_t *req; void *data; { - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; - reqh = usbd_alloc_request(dev); - if (reqh == 0) + xfer = usbd_alloc_xfer(dev); + if (xfer == NULL) return (USBD_NOMEM); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, + usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, UGETW(req->wLength), 0, usbd_do_request_async_cb); - r = usbd_transfer(reqh); - if (r != USBD_IN_PROGRESS) { - usbd_free_request(reqh); - return (r); + err = usbd_transfer(xfer); + if (err != USBD_IN_PROGRESS) { + usbd_free_xfer(xfer); + return (err); } return (USBD_NORMAL_COMPLETION); } @@ -1021,14 +1079,14 @@ usbd_dopoll(iface) } void -usbd_set_polling(iface, on) - usbd_interface_handle iface; +usbd_set_polling(dev, on) + usbd_device_handle dev; int on; { if (on) - iface->device->bus->use_polling++; + dev->bus->use_polling++; else - iface->device->bus->use_polling--; + dev->bus->use_polling--; } @@ -1048,6 +1106,21 @@ usbd_get_endpoint_descriptor(iface, address) return (0); } +/* + * usbd_ratecheck() can limit the number of error messages that occurs. + * When a device is unplugged it may take up to 0.25s for the hub driver + * to notice it. If the driver continuously tries to do I/O operations + * this can generate a large number of messages. + */ +int +usbd_ratecheck(last) + struct timeval *last; +{ + struct timeval errinterval = { 0, 250000 }; /* 0.25s */ + + return (ratecheck(last, &errinterval)); +} + #if defined(__FreeBSD__) int usbd_driver_load(module_t mod, int what, void *arg) diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 7efe8acf65d..29f969c58cc 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi.h,v 1.6 1999/11/07 21:30:20 fgsch Exp $ */ -/* $NetBSD: usbdi.h,v 1.31 1999/10/13 08:10:58 augustss Exp $ */ +/* $OpenBSD: usbdi.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usbdi.h,v 1.31 2000/03/02 12:37:51 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ typedef struct usbd_bus *usbd_bus_handle; typedef struct usbd_device *usbd_device_handle; typedef struct usbd_interface *usbd_interface_handle; typedef struct usbd_pipe *usbd_pipe_handle; -typedef struct usbd_request *usbd_request_handle; +typedef struct usbd_xfer *usbd_xfer_handle; typedef void *usbd_private_handle; typedef enum { /* keep in sync with usbd_status_msgs */ @@ -70,18 +70,23 @@ typedef enum { /* keep in sync with usbd_status_msgs */ USBD_ERROR_MAX, /* must be last */ } usbd_status; -typedef int usbd_lock_token; - -typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle, +typedef void (*usbd_callback) __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); /* Open flags */ #define USBD_EXCLUSIVE_USE 0x01 +/* Use default (specified by ep. desc.) interval on interrupt pipe */ +#define USBD_DEFAULT_INTERVAL (-1) + /* Request flags */ #define USBD_NO_COPY 0x01 /* do not copy data to DMA buffer */ #define USBD_SYNCHRONOUS 0x02 /* wait for completion */ /* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */ +#define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */ + +/* XXX Temporary hack XXX */ +#define USBD_NO_TSLEEP 0x80 /* XXX use busy wait */ #define USBD_NO_TIMEOUT 0 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */ @@ -94,25 +99,25 @@ usbd_status usbd_open_pipe __P((usbd_interface_handle iface, u_int8_t address, u_int8_t flags, usbd_pipe_handle *pipe)); usbd_status usbd_close_pipe __P((usbd_pipe_handle pipe)); -usbd_status usbd_transfer __P((usbd_request_handle req)); -usbd_request_handle usbd_alloc_request __P((usbd_device_handle)); -usbd_status usbd_free_request __P((usbd_request_handle reqh)); -void usbd_setup_request - __P((usbd_request_handle reqh, usbd_pipe_handle pipe, +usbd_status usbd_transfer __P((usbd_xfer_handle req)); +usbd_xfer_handle usbd_alloc_xfer __P((usbd_device_handle)); +usbd_status usbd_free_xfer __P((usbd_xfer_handle xfer)); +void usbd_setup_xfer + __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, usbd_private_handle priv, void *buffer, u_int32_t length, u_int16_t flags, u_int32_t timeout, usbd_callback)); -void usbd_setup_default_request - __P((usbd_request_handle reqh, usbd_device_handle dev, +void usbd_setup_default_xfer + __P((usbd_xfer_handle xfer, usbd_device_handle dev, usbd_private_handle priv, u_int32_t timeout, usb_device_request_t *req, void *buffer, u_int32_t length, u_int16_t flags, usbd_callback)); -void usbd_setup_isoc_request - __P((usbd_request_handle reqh, usbd_pipe_handle pipe, +void usbd_setup_isoc_xfer + __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, usbd_private_handle priv, u_int16_t *frlengths, u_int32_t nframes, u_int16_t flags, usbd_callback)); -void usbd_get_request_status - __P((usbd_request_handle reqh, usbd_private_handle *priv, +void usbd_get_xfer_status + __P((usbd_xfer_handle xfer, usbd_private_handle *priv, void **buffer, u_int32_t *count, usbd_status *status)); usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor __P((usbd_interface_handle iface, u_int8_t address)); @@ -129,15 +134,15 @@ usbd_status usbd_device2interface_handle __P((usbd_device_handle dev, u_int8_t ifaceno, usbd_interface_handle *iface)); usbd_device_handle usbd_pipe2device_handle __P((usbd_pipe_handle)); -void *usbd_alloc_buffer __P((usbd_request_handle req, u_int32_t size)); -void usbd_free_buffer __P((usbd_request_handle req)); -void *usbd_get_buffer __P((usbd_request_handle reqh)); -usbd_status usbd_sync_transfer __P((usbd_request_handle req)); +void *usbd_alloc_buffer __P((usbd_xfer_handle req, u_int32_t size)); +void usbd_free_buffer __P((usbd_xfer_handle req)); +void *usbd_get_buffer __P((usbd_xfer_handle xfer)); +usbd_status usbd_sync_transfer __P((usbd_xfer_handle req)); usbd_status usbd_open_pipe_intr __P((usbd_interface_handle iface, u_int8_t address, u_int8_t flags, usbd_pipe_handle *pipe, usbd_private_handle priv, void *buffer, - u_int32_t length, usbd_callback)); + u_int32_t length, usbd_callback, int)); usbd_status usbd_do_request __P((usbd_device_handle pipe, usb_device_request_t *req, void *data)); usbd_status usbd_do_request_async @@ -166,11 +171,21 @@ usb_endpoint_descriptor_t *usbd_find_edesc int endptidx)); void usbd_dopoll __P((usbd_interface_handle)); -void usbd_set_polling __P((usbd_interface_handle iface, int on)); +void usbd_set_polling __P((usbd_device_handle iface, int on)); const char *usbd_errstr __P((usbd_status err)); -void usbd_add_event __P((int, usbd_device_handle)); +void usbd_add_dev_event __P((int, usbd_device_handle)); +void usbd_add_drv_event __P((int, usbd_device_handle, device_ptr_t)); + +void usbd_devinfo __P((usbd_device_handle, int, char *)); +struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle)); +usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor + __P((usbd_interface_handle iface, u_int8_t address)); + +usbd_status usbd_reload_device_desc __P((usbd_device_handle)); + +int usbd_ratecheck __P((struct timeval *last)); /* NetBSD attachment information */ @@ -231,17 +246,19 @@ struct usb_attach_arg { #endif -void usbd_devinfo __P((usbd_device_handle, int, char *)); -struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle)); -usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor - __P((usbd_interface_handle iface, u_int8_t address)); - #if defined(__FreeBSD__) int usbd_driver_load __P((module_t mod, int what, void *arg)); #endif +/* + * XXX + * splusb MUST be the lowest level interrupt so that within USB callbacks + * the level can be raised the appropriate level. + * XXX Should probably use a softsplusb. + */ /* XXX */ #define splusb splbio +#define splhardusb splbio #define IPL_USB IPL_BIO /* XXX */ diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c index 52a55f047e5..152e81db2fa 100644 --- a/sys/dev/usb/usbdi_util.c +++ b/sys/dev/usb/usbdi_util.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi_util.c,v 1.5 1999/11/07 21:30:20 fgsch Exp $ */ -/* $NetBSD: usbdi_util.c,v 1.22 1999/10/13 08:10:59 augustss Exp $ */ +/* $OpenBSD: usbdi_util.c,v 1.6 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usbdi_util.c,v 1.28 2000/02/22 11:25:06 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,9 +42,8 @@ #include #include #include -#include -#include #if defined(__NetBSD__) || defined(__OpenBSD__) +#include #include #elif defined(__FreeBSD__) #include @@ -74,6 +73,9 @@ usbd_get_desc(dev, type, index, len, desc) { usb_device_request_t req; + DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n", + type, index, len)); + req.bmRequestType = UT_READ_DEVICE; req.bRequest = UR_GET_DESCRIPTOR; USETW2(req.wValue, type, index); @@ -83,21 +85,22 @@ usbd_get_desc(dev, type, index, len, desc) } usbd_status -usbd_get_config_desc(dev, conf, d) +usbd_get_config_desc(dev, confidx, d) usbd_device_handle dev; - int conf; + int confidx; usb_config_descriptor_t *d; { - usbd_status r; + usbd_status err; - DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf)); - r = usbd_get_desc(dev, UDESC_CONFIG, conf, - USB_CONFIG_DESCRIPTOR_SIZE, d); - if (r != USBD_NORMAL_COMPLETION) - return (r); + DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx)); + err = usbd_get_desc(dev, UDESC_CONFIG, confidx, + USB_CONFIG_DESCRIPTOR_SIZE, d); + if (err) + return (err); if (d->bDescriptorType != UDESC_CONFIG) { - DPRINTFN(-1,("usbd_get_config_desc: conf %d, bad desc %d\n", - conf, d->bDescriptorType)); + DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc ", + "len=%d type=%d\n", + confidx, d->bLength, d->bDescriptorType)); return (USBD_INVAL); } return (USBD_NORMAL_COMPLETION); @@ -254,17 +257,15 @@ usbd_set_protocol(iface, report) usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n", iface, report, id->bInterfaceNumber)); - if (!id) + if (id == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!id) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_PROTOCOL; USETW(req.wValue, report); @@ -284,16 +285,14 @@ usbd_set_report(iface, type, id, data, len) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (!ifd) + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); @@ -313,16 +312,14 @@ usbd_set_report_async(iface, type, id, data, len) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len)); - if (!ifd) + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); @@ -342,16 +339,14 @@ usbd_get_report(iface, type, id, data, len) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; - DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (!id) + DPRINTFN(4, ("usbd_get_report: len=%d\n", len)); + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); @@ -369,16 +364,14 @@ usbd_set_idle(iface, duration, id) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id)); - if (!ifd) + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_IDLE; USETW2(req.wValue, duration, id); @@ -414,12 +407,12 @@ usbd_get_hid_descriptor(ifc) usb_config_descriptor_t *cdesc; usb_hid_descriptor_t *hd; char *p, *end; - usbd_status r; + usbd_status err; - if (!idesc) + if (idesc == NULL) return (0); - r = usbd_interface2device_handle(ifc, &dev); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_interface2device_handle(ifc, &dev); + if (err) return (0); cdesc = usbd_get_config_descriptor(dev); @@ -451,27 +444,27 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem) usb_interface_descriptor_t *id; usb_hid_descriptor_t *hid; usbd_device_handle dev; - usbd_status r; + usbd_status err; - r = usbd_interface2device_handle(ifc, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_interface2device_handle(ifc, &dev); + if (err) + return (err); id = usbd_get_interface_descriptor(ifc); - if (!id) + if (id == NULL) return (USBD_INVAL); hid = usbd_get_hid_descriptor(ifc); - if (!hid) + if (hid == NULL) return (USBD_IOERROR); *sizep = UGETW(hid->descrs[0].wDescriptorLength); *descp = malloc(*sizep, mem, M_NOWAIT); - if (!*descp) + if (*descp == NULL) return (USBD_NOMEM); /* XXX should not use 0 Report ID */ - r = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0, + err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0, *sizep, *descp); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { free(*descp, mem); - return (r); + return (err); } return (USBD_NORMAL_COMPLETION); } @@ -491,20 +484,20 @@ usbd_get_config(dev, conf) return (usbd_do_request(dev, &req, conf)); } -static void usbd_bulk_transfer_cb __P((usbd_request_handle reqh, +static void usbd_bulk_transfer_cb __P((usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)); static void -usbd_bulk_transfer_cb(reqh, priv, status) - usbd_request_handle reqh; +usbd_bulk_transfer_cb(xfer, priv, status) + usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { - wakeup(reqh); + wakeup(xfer); } usbd_status -usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl) - usbd_request_handle reqh; +usbd_bulk_transfer(xfer, pipe, flags, timeout, buf, size, lbl) + usbd_xfer_handle xfer; usbd_pipe_handle pipe; u_int16_t flags; u_int32_t timeout; @@ -512,32 +505,32 @@ usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl) u_int32_t *size; char *lbl; { - usbd_status r; + usbd_status err; int s, error; - usbd_setup_request(reqh, pipe, 0, buf, *size, - flags, timeout, usbd_bulk_transfer_cb); + usbd_setup_xfer(xfer, pipe, 0, buf, *size, + flags, timeout, usbd_bulk_transfer_cb); DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size)); s = splusb(); /* don't want callback until tsleep() */ - r = usbd_transfer(reqh); - if (r != USBD_IN_PROGRESS) { + err = usbd_transfer(xfer); + if (err != USBD_IN_PROGRESS) { splx(s); - return (r); + return (err); } - error = tsleep((caddr_t)reqh, PZERO | PCATCH, lbl, 0); + error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0); splx(s); if (error) { DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error)); usbd_abort_pipe(pipe); return (USBD_INTERRUPTED); } - usbd_get_request_status(reqh, 0, 0, size, &r); + usbd_get_xfer_status(xfer, NULL, NULL, size, &err); DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size)); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("usbd_bulk_transfer: error=%d\n", r)); + if (err != USBD_NORMAL_COMPLETION) { + DPRINTF(("usbd_bulk_transfer: error=%d\n", err)); usbd_clear_endpoint_stall(pipe); } - return (r); + return (err); } void diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h index e3c055e36d0..098316bac4d 100644 --- a/sys/dev/usb/usbdi_util.h +++ b/sys/dev/usb/usbdi_util.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi_util.h,v 1.3 1999/09/27 18:03:56 fgsch Exp $ */ -/* $NetBSD: usbdi_util.h,v 1.17 1999/09/05 19:32:19 augustss Exp $ */ +/* $OpenBSD: usbdi_util.h,v 1.4 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usbdi_util.h,v 1.19 1999/11/18 23:32:37 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ usbd_status usbd_set_config_index __P((usbd_device_handle dev, int index, int msg)); usbd_status usbd_bulk_transfer - __P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags, + __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, char *lbl)); void usb_detach_wait __P((device_ptr_t)); diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index 9fd4931567e..ad013bedc34 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdivar.h,v 1.6 1999/11/07 21:30:20 fgsch Exp $ */ -/* $NetBSD: usbdivar.h,v 1.38 1999/10/25 10:51:46 augustss Exp $ */ +/* $OpenBSD: usbdivar.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usbdivar.h,v 1.47 2000/02/22 11:30:56 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ /* From usb_mem.h */ DECLARE_USB_DMA_T; -struct usbd_request; +struct usbd_xfer; struct usbd_pipe; struct usbd_endpoint { @@ -51,19 +51,23 @@ struct usbd_endpoint { struct usbd_bus_methods { usbd_status (*open_pipe)__P((struct usbd_pipe *pipe)); + void (*soft_intr)__P((struct usbd_bus *)); void (*do_poll)__P((struct usbd_bus *)); usbd_status (*allocm)__P((struct usbd_bus *, usb_dma_t *, u_int32_t bufsize)); void (*freem)__P((struct usbd_bus *, usb_dma_t *)); + struct usbd_xfer * (*allocx)__P((struct usbd_bus *)); + void (*freex)__P((struct usbd_bus *, + struct usbd_xfer *)); }; struct usbd_pipe_methods { - usbd_status (*transfer)__P((usbd_request_handle reqh)); - usbd_status (*start)__P((usbd_request_handle reqh)); - void (*abort)__P((usbd_request_handle reqh)); + usbd_status (*transfer)__P((usbd_xfer_handle xfer)); + usbd_status (*start)__P((usbd_xfer_handle xfer)); + void (*abort)__P((usbd_xfer_handle xfer)); void (*close)__P((usbd_pipe_handle pipe)); void (*cleartoggle)__P((usbd_pipe_handle pipe)); - void (*done)__P((usbd_request_handle reqh)); + void (*done)__P((usbd_xfer_handle xfer)); }; struct usbd_port { @@ -101,31 +105,38 @@ struct usbd_bus { struct usb_device_stats stats; int intr_context; u_int no_intrs; + int usbrev; /* USB revision */ +#define USBREV_UNKNOWN 0 +#define USBREV_PRE_1_0 1 +#define USBREV_1_0 2 +#define USBREV_1_1 3 +#define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1" } + #if defined(__NetBSD__) || defined(__OpenBSD__) bus_dma_tag_t dmatag; /* DMA tag */ #endif }; struct usbd_device { - struct usbd_bus *bus; - struct usbd_pipe *default_pipe; - u_int8_t address; - u_int8_t depth; - u_int8_t lowspeed; - u_int16_t power; - u_int8_t self_powered; - int config; - int langid; /* language to use for strings */ + struct usbd_bus *bus; /* our controller */ + struct usbd_pipe *default_pipe; /* pipe 0 */ + u_int8_t address; /* device address */ + u_int8_t config; /* current configuration # */ + u_int8_t depth; /* distance from root hub */ + u_int8_t lowspeed; /* lowspeed flag */ + u_int8_t self_powered; /* flag for self powered */ + u_int16_t power; /* mA the device uses */ + int16_t langid; /* language for strings */ #define USBD_NOLANG (-1) - usb_event_cookie_t cookie; /* unique connection id */ - struct usbd_port *powersrc; - struct usbd_endpoint def_ep; /* for pipe 0 */ - usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ - struct usbd_interface *ifaces; - usb_device_descriptor_t ddesc; - usb_config_descriptor_t *cdesc; /* full config descr */ - struct usbd_quirks *quirks; - struct usbd_hub *hub; /* only if this is a hub */ + usb_event_cookie_t cookie; /* unique connection id */ + struct usbd_port *powersrc; /* upstream hub port, or 0 */ + struct usbd_endpoint def_ep; /* for pipe 0 */ + usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ + struct usbd_interface *ifaces; /* array of all interfaces */ + usb_device_descriptor_t ddesc; /* device descriptor */ + usb_config_descriptor_t *cdesc; /* full config descr */ + struct usbd_quirks *quirks; /* device quirks, always set */ + struct usbd_hub *hub; /* only if this is a hub */ device_ptr_t *subdevs; /* sub-devices, 0 terminated */ }; @@ -145,17 +156,18 @@ struct usbd_pipe { struct usbd_endpoint *endpoint; int refcnt; char running; - SIMPLEQ_HEAD(, usbd_request) queue; + SIMPLEQ_HEAD(, usbd_xfer) queue; LIST_ENTRY(usbd_pipe) next; - usbd_request_handle intrreqh; /* used for repeating requests */ + usbd_xfer_handle intrxfer; /* used for repeating requests */ char repeat; + int interval; /* Filled by HC driver. */ struct usbd_pipe_methods *methods; }; -struct usbd_request { +struct usbd_xfer { struct usbd_pipe *pipe; void *priv; void *buffer; @@ -183,10 +195,10 @@ struct usbd_request { #define URQ_AUTO_DMABUF 0x10 #define URQ_DEV_DMABUF 0x20 - SIMPLEQ_ENTRY(usbd_request) next; + SIMPLEQ_ENTRY(usbd_xfer) next; void *hcpriv; /* private use by the HC driver */ - int hcprivint; /* ditto */ + int hcprivint; #if defined(__FreeBSD__) struct callout_handle timo_handle; @@ -204,7 +216,7 @@ usbd_status usbd_reset_port __P((usbd_device_handle dev, int port, usb_port_status_t *ps)); usbd_status usbd_setup_pipe __P((usbd_device_handle dev, usbd_interface_handle iface, - struct usbd_endpoint *, + struct usbd_endpoint *, int, usbd_pipe_handle *pipe)); usbd_status usbd_new_device __P((device_ptr_t parent, usbd_bus_handle bus, int depth, @@ -217,13 +229,13 @@ usbd_status usbd_fill_iface_data __P((usbd_device_handle dev, int i, int a)); void usb_free_device __P((usbd_device_handle)); -usbd_status usb_insert_transfer __P((usbd_request_handle reqh)); -void usb_transfer_complete __P((usbd_request_handle reqh)); +usbd_status usb_insert_transfer __P((usbd_xfer_handle xfer)); +void usb_transfer_complete __P((usbd_xfer_handle xfer)); void usb_disconnect_port __P((struct usbd_port *up, device_ptr_t)); /* Routines from usb.c */ -int usb_bus_count __P((void)); void usb_needs_explore __P((usbd_bus_handle)); +void usb_schedsoftintr __P((struct usbd_bus *)); #ifdef DIAGNOSTIC #define SPLUSBCHECK \ @@ -231,6 +243,7 @@ void usb_needs_explore __P((usbd_bus_handle)); extern int cold; \ if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \ _s, _su, __FILE__, __LINE__); \ + splx(_s); \ } while (0) #else #define SPLUSBCHECK