diff options
-rw-r--r-- | sys/dev/usb/TODO | 4 | ||||
-rw-r--r-- | sys/dev/usb/ohci.c | 439 | ||||
-rw-r--r-- | sys/dev/usb/ohcireg.h | 6 | ||||
-rw-r--r-- | sys/dev/usb/ohcivar.h | 13 | ||||
-rw-r--r-- | sys/dev/usb/ugen.c | 50 | ||||
-rw-r--r-- | sys/dev/usb/uhci.c | 514 | ||||
-rw-r--r-- | sys/dev/usb/uhcireg.h | 16 | ||||
-rw-r--r-- | sys/dev/usb/uhcivar.h | 46 | ||||
-rw-r--r-- | sys/dev/usb/uhid.c | 15 | ||||
-rw-r--r-- | sys/dev/usb/uhub.c | 27 | ||||
-rw-r--r-- | sys/dev/usb/usb.h | 12 | ||||
-rw-r--r-- | sys/dev/usb/usb_mem.c | 16 | ||||
-rw-r--r-- | sys/dev/usb/usb_mem.h | 8 | ||||
-rw-r--r-- | sys/dev/usb/usb_subr.c | 114 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.c | 164 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 13 | ||||
-rw-r--r-- | sys/dev/usb/usbdi_util.c | 11 | ||||
-rw-r--r-- | sys/dev/usb/usbdi_util.h | 4 | ||||
-rw-r--r-- | sys/dev/usb/usbdivar.h | 14 |
19 files changed, 765 insertions, 721 deletions
diff --git a/sys/dev/usb/TODO b/sys/dev/usb/TODO index d4b43d3a58e..7c5458c7eb5 100644 --- a/sys/dev/usb/TODO +++ b/sys/dev/usb/TODO @@ -24,3 +24,7 @@ memory allocator from an interrupt context. Move memory allocation and copying to HC independent code. Use a TD chain in ohci.c to allow transfers > 8K. + +Document device driver API. + +Document HC driver API. diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 503d1a50e33..7892a19c232 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ohci.c,v 1.4 1999/08/19 08:18:38 fgsch Exp $ */ +/* $OpenBSD: ohci.c,v 1.5 1999/08/27 09:00:28 fgsch Exp $ */ /* $NetBSD: ohci.c,v 1.33 1999/06/30 06:44:23 augustss Exp $ */ /* @@ -65,8 +65,8 @@ #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> -#include <dev/usb/usb_quirks.h> #include <dev/usb/usb_mem.h> +#include <dev/usb/usb_quirks.h> #include <dev/usb/ohcireg.h> #include <dev/usb/ohcivar.h> @@ -108,11 +108,6 @@ 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_idone __P((ohci_softc_t *, usbd_request_handle)); -void ohci_done __P((ohci_softc_t *, usbd_request_handle)); -void ohci_ctrl_done __P((ohci_softc_t *, usbd_request_handle)); -void ohci_intr_done __P((ohci_softc_t *, usbd_request_handle)); -void ohci_bulk_done __P((ohci_softc_t *, usbd_request_handle)); usbd_status ohci_device_request __P((usbd_request_handle reqh)); void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); @@ -130,21 +125,26 @@ 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)); void ohci_root_intr_close __P((usbd_pipe_handle)); +void ohci_root_intr_done __P((usbd_request_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)); void ohci_device_ctrl_close __P((usbd_pipe_handle)); +void ohci_device_ctrl_done __P((usbd_request_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)); void ohci_device_bulk_close __P((usbd_pipe_handle)); +void ohci_device_bulk_done __P((usbd_request_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)); void ohci_device_intr_close __P((usbd_pipe_handle)); +void ohci_device_intr_done __P((usbd_request_handle)); + usbd_status ohci_device_setintr __P((ohci_softc_t *sc, struct ohci_pipe *pipe, int ival)); @@ -155,7 +155,9 @@ 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_request __P((usbd_request_handle reqh)); +void ohci_abort_req __P((usbd_request_handle reqh, + usbd_status status)); +void ohci_abort_req_end __P((void *)); void ohci_device_clear_toggle __P((usbd_pipe_handle pipe)); void ohci_noop __P((usbd_pipe_handle pipe)); @@ -216,6 +218,7 @@ struct usbd_methods ohci_root_ctrl_methods = { ohci_root_ctrl_close, ohci_noop, 0, + 0, }; struct usbd_methods ohci_root_intr_methods = { @@ -224,6 +227,7 @@ struct usbd_methods ohci_root_intr_methods = { ohci_root_intr_abort, ohci_root_intr_close, ohci_noop, + ohci_root_intr_done, 0, }; @@ -233,6 +237,7 @@ struct usbd_methods ohci_device_ctrl_methods = { ohci_device_ctrl_abort, ohci_device_ctrl_close, ohci_noop, + ohci_device_ctrl_done, 0, }; @@ -242,6 +247,7 @@ struct usbd_methods ohci_device_intr_methods = { ohci_device_intr_abort, ohci_device_intr_close, ohci_device_clear_toggle, + ohci_device_intr_done, 0, }; @@ -251,6 +257,7 @@ struct usbd_methods ohci_device_bulk_methods = { ohci_device_bulk_abort, ohci_device_bulk_close, ohci_device_clear_toggle, + ohci_device_bulk_done, 0, }; @@ -265,30 +272,23 @@ ohci_alloc_sed(sc) if (!sc->sc_freeeds) { DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n")); - sed = malloc(sizeof(ohci_soft_ed_t) * OHCI_ED_CHUNK, - M_USBHC, M_NOWAIT); - if (!sed) - return 0; - r = usb_allocmem(sc->sc_dmatag, OHCI_ED_SIZE * OHCI_ED_CHUNK, + r = usb_allocmem(sc->sc_dmatag, OHCI_SED_SIZE * OHCI_SED_CHUNK, OHCI_ED_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) { - free(sed, M_USBHC); - return 0; - } - for(i = 0; i < OHCI_ED_CHUNK; i++, sed++) { - offs = i * OHCI_ED_SIZE; + if (r != USBD_NORMAL_COMPLETION) + return (0); + for(i = 0; i < OHCI_SED_CHUNK; i++) { + offs = i * OHCI_SED_SIZE; + sed = (ohci_soft_ed_t *)((char *)KERNADDR(&dma) +offs); sed->physaddr = DMAADDR(&dma) + offs; - sed->ed = (ohci_ed_t *) - ((char *)KERNADDR(&dma) + offs); sed->next = sc->sc_freeeds; sc->sc_freeeds = sed; } } sed = sc->sc_freeeds; sc->sc_freeeds = sed->next; - memset(sed->ed, 0, OHCI_ED_SIZE); + memset(&sed->ed, 0, sizeof(ohci_ed_t)); sed->next = 0; - return sed; + return (sed); } void @@ -311,28 +311,21 @@ ohci_alloc_std(sc) if (!sc->sc_freetds) { DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); - std = malloc(sizeof(ohci_soft_td_t) * OHCI_TD_CHUNK, - M_USBHC, M_NOWAIT); - if (!std) - return 0; - r = usb_allocmem(sc->sc_dmatag, OHCI_TD_SIZE * OHCI_TD_CHUNK, + r = usb_allocmem(sc->sc_dmatag, OHCI_STD_SIZE * OHCI_STD_CHUNK, OHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) { - free(std, M_USBHC); - return 0; - } - for(i = 0; i < OHCI_TD_CHUNK; i++, std++) { - offs = i * OHCI_TD_SIZE; + if (r != USBD_NORMAL_COMPLETION) + return (0); + for(i = 0; i < OHCI_STD_CHUNK; i++) { + offs = i * OHCI_STD_SIZE; + std = (ohci_soft_td_t *)((char *)KERNADDR(&dma) +offs); std->physaddr = DMAADDR(&dma) + offs; - std->td = (ohci_td_t *) - ((char *)KERNADDR(&dma) + offs); std->nexttd = sc->sc_freetds; sc->sc_freetds = std; } } std = sc->sc_freetds; sc->sc_freetds = std->nexttd; - memset(std->td, 0, OHCI_TD_SIZE); + memset(&std->td, 0, sizeof(ohci_td_t)); std->nexttd = 0; return (std); } @@ -359,7 +352,7 @@ ohci_init(sc) DPRINTF(("ohci_init: start\n")); rev = OREAD4(sc, OHCI_REVISION); #if defined(__OpenBSD__) - printf(", version %d.%d%s", + printf(" version %d.%d%s", #else printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev), #endif @@ -397,14 +390,14 @@ ohci_init(sc) r = USBD_NOMEM; goto bad1; } - sc->sc_ctrl_head->ed->ed_flags |= LE(OHCI_ED_SKIP); + sc->sc_ctrl_head->ed.ed_flags |= LE(OHCI_ED_SKIP); sc->sc_bulk_head = ohci_alloc_sed(sc); if (!sc->sc_bulk_head) { r = USBD_NOMEM; goto bad2; } - sc->sc_bulk_head->ed->ed_flags |= LE(OHCI_ED_SKIP); + sc->sc_bulk_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++) { @@ -417,11 +410,11 @@ ohci_init(sc) } /* All ED fields are set to 0. */ sc->sc_eds[i] = sed; - sed->ed->ed_flags |= LE(OHCI_ED_SKIP); + sed->ed.ed_flags |= LE(OHCI_ED_SKIP); if (i != 0) { psed = sc->sc_eds[(i-1) / 2]; sed->next = psed; - sed->ed->ed_nexted = LE(psed->physaddr); + sed->ed.ed_nexted = LE(psed->physaddr); } } /* @@ -728,7 +721,7 @@ ohci_process_done(sc, done) 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 = 0; done; done = LE(std->td.td_nexttd)) { std = ohci_hash_find_td(sc, done); std->dnext = sdone; sdone = std; @@ -745,30 +738,32 @@ ohci_process_done(sc, done) reqh = std->reqh; DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n", std, reqh, reqh->hcpriv)); - cc = OHCI_TD_GET_CC(LE(std->td->td_flags)); + 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) { DPRINTF(("ohci_process_done: cancel/timeout %p\n", reqh)); - ohci_idone(sc, reqh); + /* Handled by abort routine. */ + continue; } 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; + if (std->td.td_cbp != 0) + len -= LE(std->td.td_be) - + LE(std->td.td_cbp) + 1; if (std->flags & OHCI_SET_LEN) reqh->actlen = len; if (std->flags & OHCI_CALL_DONE) { reqh->status = USBD_NORMAL_COMPLETION; - ohci_idone(sc, reqh); + usb_transfer_complete(reqh); } } else { ohci_soft_td_t *p, *n; struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; DPRINTFN(-1,("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))])); + OHCI_TD_GET_CC(LE(std->td.td_flags)), + ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))])); /* * Endpoint is halted. First unlink all the TDs * belonging to the failed transfer, and then restart @@ -780,14 +775,14 @@ ohci_process_done(sc, done) ohci_free_std(sc, p); } /* clear halt */ - opipe->sed->ed->ed_headp = LE(p->physaddr); + opipe->sed->ed.ed_headp = LE(p->physaddr); OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); if (cc == OHCI_CC_STALL) reqh->status = USBD_STALLED; else reqh->status = USBD_IOERROR; - ohci_idone(sc, reqh); + usb_transfer_complete(reqh); } ohci_hash_rem_td(sc, std); ohci_free_std(sc, std); @@ -795,65 +790,22 @@ ohci_process_done(sc, done) } void -ohci_idone(sc, reqh) - ohci_softc_t *sc; - usbd_request_handle reqh; -{ - ohci_done(sc, reqh); - if (reqh->pipe->intrreqh != reqh) - usb_start_next(reqh->pipe); -} - -void -ohci_done(sc, reqh) - ohci_softc_t *sc; - usbd_request_handle reqh; -{ - usbd_pipe_handle pipe = reqh->pipe; - -#ifdef DIAGNOSTIC - if (!reqh->hcpriv) - printf("ohci_done: reqh=%p, no hcpriv\n", reqh); -#endif - reqh->hcpriv = 0; - - switch (pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) { - case UE_CONTROL: - ohci_ctrl_done(sc, reqh); - break; - case UE_INTERRUPT: - ohci_intr_done(sc, reqh); - break; - case UE_BULK: - ohci_bulk_done(sc, reqh); - break; - case UE_ISOCHRONOUS: - printf("ohci_process_done: ISO done?\n"); - break; - } - - /* Remove request from queue. */ - SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next); - - /* And finally execute callback. */ - reqh->xfercb(reqh); -} - -void -ohci_ctrl_done(sc, reqh) - ohci_softc_t *sc; +ohci_device_ctrl_done(reqh) usbd_request_handle reqh; { struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; u_int len = opipe->u.ctl.length; usb_dma_t *dma; DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh)); +#ifdef DIAGNOSTIC if (!reqh->isreq) { panic("ohci_ctrl_done: not a request\n"); - return; } +#endif + reqh->hcpriv = 0; if (len != 0) { dma = &opipe->u.ctl.datadma; @@ -861,15 +813,14 @@ ohci_ctrl_done(sc, reqh) memcpy(reqh->buffer, KERNADDR(dma), len); usb_freemem(sc->sc_dmatag, dma); } - usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); } void -ohci_intr_done(sc, reqh) - ohci_softc_t *sc; +ohci_device_intr_done(reqh) usbd_request_handle reqh; { struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; usb_dma_t *dma; ohci_soft_ed_t *sed = opipe->sed; ohci_soft_td_t *xfer, *tail; @@ -878,10 +829,12 @@ ohci_intr_done(sc, reqh) DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n", reqh, reqh->actlen)); + reqh->hcpriv = 0; + dma = &opipe->u.intr.datadma; memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen); - if (reqh->pipe->intrreqh == reqh) { + if (reqh->pipe->repeat) { xfer = opipe->tail; tail = ohci_alloc_std(sc); /* XXX should reuse TD */ if (!tail) { @@ -890,22 +843,22 @@ ohci_intr_done(sc, reqh) } tail->reqh = 0; - xfer->td->td_flags = LE( + xfer->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) - xfer->td->td_flags |= LE(OHCI_TD_R); - xfer->td->td_cbp = LE(DMAADDR(dma)); + xfer->td.td_flags |= LE(OHCI_TD_R); + xfer->td.td_cbp = LE(DMAADDR(dma)); xfer->nexttd = tail; - xfer->td->td_nexttd = LE(tail->physaddr); - xfer->td->td_be = LE(LE(xfer->td->td_cbp) + reqh->length - 1); + xfer->td.td_nexttd = LE(tail->physaddr); + xfer->td.td_be = LE(LE(xfer->td.td_cbp) + reqh->length - 1); xfer->len = reqh->length; xfer->reqh = reqh; xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN; reqh->hcpriv = xfer; ohci_hash_add_td(sc, xfer); - sed->ed->ed_tailp = LE(tail->physaddr); + sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail = tail; } else { usb_freemem(sc->sc_dmatag, dma); @@ -913,23 +866,23 @@ ohci_intr_done(sc, reqh) } void -ohci_bulk_done(sc, reqh) - ohci_softc_t *sc; +ohci_device_bulk_done(reqh) usbd_request_handle reqh; { struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; u_int len = opipe->u.bulk.length; usb_dma_t *dma; - DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n", reqh, reqh->actlen)); + reqh->hcpriv = 0; + dma = &opipe->u.bulk.datadma; if (opipe->u.bulk.isread) memcpy(reqh->buffer, KERNADDR(dma), len); usb_freemem(sc->sc_dmatag, dma); - usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); } void @@ -965,13 +918,21 @@ ohci_rhsc(sc, reqh) DPRINTF(("ohci_rhsc: change=0x%02x\n", *p)); reqh->actlen = reqh->length; reqh->status = USBD_NORMAL_COMPLETION; - reqh->xfercb(reqh); - if (reqh->pipe->intrreqh != reqh) { - sc->sc_intrreqh = 0; + usb_transfer_complete(reqh); +} + +void +ohci_root_intr_done(reqh) + usbd_request_handle reqh; +{ + struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; + + reqh->hcpriv = 0; + + if (!reqh->pipe->repeat) usb_freemem(sc->sc_dmatag, &opipe->u.intr.datadma); - usb_start_next(reqh->pipe); - } } /* @@ -1007,7 +968,7 @@ ohci_waitintr(sc, reqh) /* Timeout */ DPRINTF(("ohci_waitintr: timeout\n")); reqh->status = USBD_TIMEOUT; - ohci_idone(sc, reqh); + usb_transfer_complete(reqh); /* XXX should free TD */ } @@ -1066,8 +1027,8 @@ ohci_device_request(reqh) /* 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. */ - sed->ed->ed_flags = LE( - (LE(sed->ed->ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) | + 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))); @@ -1081,14 +1042,14 @@ ohci_device_request(reqh) r = usb_allocmem(sc->sc_dmatag, len, 0, dmap); if (r != USBD_NORMAL_COMPLETION) goto bad4; - xfer->td->td_flags = LE( + xfer->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)); - xfer->td->td_cbp = LE(DMAADDR(dmap)); + xfer->td.td_cbp = LE(DMAADDR(dmap)); xfer->nexttd = stat; - xfer->td->td_nexttd = LE(stat->physaddr); - xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1); + xfer->td.td_nexttd = LE(stat->physaddr); + xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1); xfer->len = len; xfer->reqh = reqh; xfer->flags = OHCI_SET_LEN; @@ -1104,24 +1065,24 @@ ohci_device_request(reqh) if (!isread && len != 0) memcpy(KERNADDR(dmap), reqh->buffer, len); - setup->td->td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC | + setup->td.td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC | OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR); - setup->td->td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma)); + setup->td.td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma)); setup->nexttd = next; - setup->td->td_nexttd = LE(next->physaddr); - setup->td->td_be = LE(LE(setup->td->td_cbp) + sizeof *req - 1); + 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->flags = 0; reqh->hcpriv = setup; - stat->td->td_flags = LE( + stat->td.td_flags = LE( (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->td.td_cbp = 0; stat->nexttd = tail; - stat->td->td_nexttd = LE(tail->physaddr); - stat->td->td_be = 0; + stat->td.td_nexttd = LE(tail->physaddr); + stat->td.td_be = 0; stat->len = 0; stat->reqh = reqh; @@ -1139,7 +1100,7 @@ ohci_device_request(reqh) if (len != 0) ohci_hash_add_td(sc, xfer); ohci_hash_add_td(sc, stat); - sed->ed->ed_tailp = LE(tail->physaddr); + sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail = tail; OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); if (reqh->timeout && !sc->sc_bus.use_polling) { @@ -1179,9 +1140,9 @@ ohci_add_ed(sed, head) ohci_soft_ed_t *head; { sed->next = head->next; - sed->ed->ed_nexted = head->ed->ed_nexted; + sed->ed.ed_nexted = head->ed.ed_nexted; head->next = sed; - head->ed->ed_nexted = LE(sed->physaddr); + head->ed.ed_nexted = LE(sed->physaddr); } /* @@ -1200,7 +1161,7 @@ ohci_rem_ed(sed, head) if (!p) panic("ohci_rem_ed: ED not found\n"); p->next = sed->next; - p->ed->ed_nexted = sed->ed->ed_nexted; + p->ed.ed_nexted = sed->ed.ed_nexted; } /* @@ -1254,16 +1215,10 @@ void ohci_timeout(addr) void *addr; { -#if 0 - usbd_request_handle *reqh = addr; - int s; + usbd_request_handle reqh = addr; DPRINTF(("ohci_timeout: reqh=%p\n", reqh)); - s = splusb(); - /* XXX need to inactivate TD before calling interrupt routine */ - ohci_XXX_done(reqh); - splx(s); -#endif + ohci_abort_req(reqh, USBD_TIMEOUT); } #ifdef USB_DEBUG @@ -1282,13 +1237,13 @@ ohci_dump_td(std) printf("TD(%p) at %08lx: %b delay=%d ec=%d cc=%d\ncbp=0x%08lx " "nexttd=0x%08lx be=0x%08lx\n", std, (u_long)std->physaddr, - (int)LE(std->td->td_flags), + (int)LE(std->td.td_flags), "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE", - OHCI_TD_GET_DI(LE(std->td->td_flags)), - OHCI_TD_GET_EC(LE(std->td->td_flags)), - OHCI_TD_GET_CC(LE(std->td->td_flags)), - (u_long)LE(std->td->td_cbp), - (u_long)LE(std->td->td_nexttd), (u_long)LE(std->td->td_be)); + OHCI_TD_GET_DI(LE(std->td.td_flags)), + OHCI_TD_GET_EC(LE(std->td.td_flags)), + OHCI_TD_GET_CC(LE(std->td.td_flags)), + (u_long)LE(std->td.td_cbp), + (u_long)LE(std->td.td_nexttd), (u_long)LE(std->td.td_be)); } void @@ -1298,14 +1253,14 @@ ohci_dump_ed(sed) printf("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx " "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)), - OHCI_ED_GET_MAXP(LE(sed->ed->ed_flags)), - (int)LE(sed->ed->ed_flags), + OHCI_ED_GET_FA(LE(sed->ed.ed_flags)), + OHCI_ED_GET_EN(LE(sed->ed.ed_flags)), + OHCI_ED_GET_MAXP(LE(sed->ed.ed_flags)), + (int)LE(sed->ed.ed_flags), "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO", - (u_long)LE(sed->ed->ed_tailp), - (u_long)LE(sed->ed->ed_headp), "\20\1HALT\2CARRY", - (u_long)LE(sed->ed->ed_nexted)); + (u_long)LE(sed->ed.ed_tailp), + (u_long)LE(sed->ed.ed_headp), "\20\1HALT\2CARRY", + (u_long)LE(sed->ed.ed_nexted)); } #endif @@ -1345,7 +1300,7 @@ ohci_open(pipe) goto bad1; opipe->sed = sed; opipe->tail = std; - sed->ed->ed_flags = LE( + sed->ed.ed_flags = LE( OHCI_ED_SET_FA(addr) | OHCI_ED_SET_EN(ed->bEndpointAddress) | OHCI_ED_DIR_TD | @@ -1353,7 +1308,7 @@ ohci_open(pipe) ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ? OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) | 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 = LE(std->physaddr); switch (ed->bmAttributes & UE_XFERTYPE) { case UE_CONTROL: @@ -1408,10 +1363,10 @@ 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))) { - ohci_physaddr_t td = sed->ed->ed_headp; + sed->ed.ed_flags |= LE(OHCI_ED_SKIP); + if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != + (sed->ed.ed_headp & LE(OHCI_TAILMASK))) { + 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; @@ -1420,11 +1375,11 @@ ohci_close_pipe(pipe, head) break; printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " "tl=0x%x pipe=%p, std=%p\n", sed, - (int)LE(sed->ed->ed_headp), (int)LE(sed->ed->ed_tailp), + (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_TAILMASK)) != + (sed->ed.ed_headp & LE(OHCI_TAILMASK))) printf("ohci_close_pipe: pipe still not empty\n"); } #endif @@ -1445,57 +1400,65 @@ ohci_close_pipe(pipe, head) * interrupt processing to process it. */ void -ohci_abort_request(reqh) +ohci_abort_req(reqh, status) usbd_request_handle reqh; + usbd_status status; { struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; ohci_soft_ed_t *sed; - ohci_soft_td_t *p, *n; - int s; - DPRINTF(("ohci_abort_request: reqh=%p pipe=%p\n", reqh, opipe)); - s = splusb(); + DPRINTF(("ohci_abort_req: reqh=%p pipe=%p\n", reqh, opipe)); - reqh->status = USBD_CANCELLED; /* mark as cancelled */ + reqh->status = status; - if (!reqh->hcpriv) { - /* Not scheduled */ - reqh->xfercb(reqh); - return; - } + usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); sed = opipe->sed; - DPRINTFN(1,("ohci_abort_request: stop ed=%p\n", sed)); - sed->ed->ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */ - delay(10); /* give HC hardware a little time */ - - /* if already processed by hardware let interrupt routine handle it */ - if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) == - (sed->ed->ed_headp & LE(OHCI_TAILMASK))) { - DPRINTF(("ohci_abort_request: request processed\n")); - usb_delay_ms(dev->bus, 2); + DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed)); + sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */ + + if (curproc) { + usb_delay_ms(opipe->pipe.device->bus, 1); + ohci_abort_req_end(reqh); } else { - p = reqh->hcpriv; + timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + } +} + +void +ohci_abort_req_end(v) + void *v; +{ + usbd_request_handle reqh = v; + struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; + ohci_soft_ed_t *sed; + ohci_soft_td_t *p, *n; + int s; + + s = splusb(); + + p = reqh->hcpriv; #ifdef DIAGNOSTIC - if (!p) { - printf("ohci_abort_request: hcpriv==0\n"); - return; - } + if (!p) { + printf("ohci_abort_req: hcpriv==0\n"); + return; + } #endif - ohci_done(sc, reqh); - for (; p->reqh == reqh; p = n) { - n = p->nexttd; - ohci_hash_rem_td(sc, p); - ohci_free_std(sc, p); - } - DPRINTFN(2,("ohci_abort_request: set hd=%x, tl=%x\n", - (int)LE(p->physaddr), (int)LE(sed->ed->ed_tailp))); - sed->ed->ed_headp = p->physaddr; /* unlink TDs */ + for (; p->reqh == reqh; p = n) { + n = p->nexttd; + ohci_hash_rem_td(sc, p); + ohci_free_std(sc, p); } - sed->ed->ed_flags &= LE(~OHCI_ED_SKIP); /* remove hardware skip */ + sed = opipe->sed; + DPRINTFN(2,("ohci_abort_req: 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); + splx(s); } @@ -1885,10 +1848,8 @@ ohci_root_ctrl_start(reqh) reqh->actlen = totlen; r = USBD_NORMAL_COMPLETION; ret: - SIMPLEQ_REMOVE_HEAD(&reqh->pipe->queue, reqh, next); reqh->status = r; - reqh->xfercb(reqh); - usb_start_next(reqh->pipe); + usb_transfer_complete(reqh); return (USBD_IN_PROGRESS); } @@ -2015,7 +1976,7 @@ ohci_device_ctrl_abort(reqh) usbd_request_handle reqh; { DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh)); - ohci_abort_request(reqh); + ohci_abort_req(reqh, USBD_CANCELLED); } /* Close a device control pipe. */ @@ -2037,7 +1998,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_tailp &= LE(~OHCI_TOGGLECARRY); } void @@ -2108,20 +2069,20 @@ ohci_device_bulk_start(reqh) tail->reqh = 0; /* Update device address */ - sed->ed->ed_flags = LE( - (LE(sed->ed->ed_flags) & ~OHCI_ED_ADDRMASK) | + sed->ed.ed_flags = LE( + (LE(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) | OHCI_ED_SET_FA(addr)); /* Set up data transaction */ xfer = opipe->tail; - xfer->td->td_flags = LE( + xfer->td.td_flags = LE( (isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC | OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY | (reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0)); - xfer->td->td_cbp = LE(DMAADDR(dmap)); + xfer->td.td_cbp = LE(DMAADDR(dmap)); xfer->nexttd = tail; - xfer->td->td_nexttd = LE(tail->physaddr); - xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1); + xfer->td.td_nexttd = LE(tail->physaddr); + xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1); xfer->len = len; xfer->reqh = reqh; xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN; @@ -2132,8 +2093,8 @@ ohci_device_bulk_start(reqh) DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " "td_cbp=0x%08x td_be=0x%08x\n", - (int)LE(sed->ed->ed_flags), (int)LE(xfer->td->td_flags), - (int)LE(xfer->td->td_cbp), (int)LE(xfer->td->td_be))); + (int)LE(sed->ed.ed_flags), (int)LE(xfer->td.td_flags), + (int)LE(xfer->td.td_cbp), (int)LE(xfer->td.td_be))); #ifdef USB_DEBUG if (ohcidebug > 4) { @@ -2145,9 +2106,9 @@ ohci_device_bulk_start(reqh) /* Insert ED in schedule */ s = splusb(); ohci_hash_add_td(sc, xfer); - sed->ed->ed_tailp = LE(tail->physaddr); + sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail = tail; - sed->ed->ed_flags &= LE(~OHCI_ED_SKIP); + 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, @@ -2179,7 +2140,7 @@ ohci_device_bulk_abort(reqh) usbd_request_handle reqh; { DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh)); - ohci_abort_request(reqh); + ohci_abort_req(reqh, USBD_CANCELLED); } /* @@ -2251,15 +2212,15 @@ ohci_device_intr_start(reqh) if (r != USBD_NORMAL_COMPLETION) goto ret2; - xfer->td->td_flags = LE( + xfer->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) - xfer->td->td_flags |= LE(OHCI_TD_R); - xfer->td->td_cbp = LE(DMAADDR(dmap)); + xfer->td.td_flags |= LE(OHCI_TD_R); + xfer->td.td_cbp = LE(DMAADDR(dmap)); xfer->nexttd = tail; - xfer->td->td_nexttd = LE(tail->physaddr); - xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1); + xfer->td.td_nexttd = LE(tail->physaddr); + xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1); xfer->len = len; xfer->reqh = reqh; xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN; @@ -2276,15 +2237,9 @@ ohci_device_intr_start(reqh) /* Insert ED in schedule */ s = splusb(); ohci_hash_add_td(sc, xfer); - sed->ed->ed_tailp = LE(tail->physaddr); + sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail = tail; -#if 0 - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(ohci_timeout, reqh, - MS_TO_TICKS(reqh->timeout), reqh->timo_handle); - } -#endif - sed->ed->ed_flags &= LE(~OHCI_ED_SKIP); + sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); #ifdef USB_DEBUG if (ohcidebug > 5) { @@ -2314,7 +2269,7 @@ ohci_device_intr_abort(reqh) DPRINTF(("ohci_device_intr_abort: remove\n")); reqh->pipe->intrreqh = 0; } - ohci_abort_request(reqh); + ohci_abort_req(reqh, USBD_CANCELLED); } /* Close a device interrupt pipe. */ @@ -2333,9 +2288,9 @@ ohci_device_intr_close(pipe) DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n", 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))) + sed->ed.ed_flags |= LE(OHCI_ED_SKIP); + if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != + (sed->ed.ed_headp & LE(OHCI_TAILMASK))) usb_delay_ms(&sc->sc_bus, 2); for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) @@ -2343,7 +2298,7 @@ ohci_device_intr_close(pipe) if (!p) panic("ohci_device_intr_close: ED not found\n"); p->next = sed->next; - p->ed->ed_nexted = sed->ed->ed_nexted; + p->ed.ed_nexted = sed->ed.ed_nexted; splx(s); for (j = 0; j < nslots; j++) @@ -2404,9 +2359,9 @@ ohci_device_setintr(sc, opipe, ival) s = splusb(); hsed = sc->sc_eds[best]; sed->next = hsed->next; - sed->ed->ed_nexted = hsed->ed->ed_nexted; + sed->ed.ed_nexted = hsed->ed.ed_nexted; hsed->next = sed; - hsed->ed->ed_nexted = LE(sed->physaddr); + hsed->ed.ed_nexted = LE(sed->physaddr); splx(s); for (j = 0; j < nslots; j++) diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h index 877a0db6bd0..d054fd5a56a 100644 --- a/sys/dev/usb/ohcireg.h +++ b/sys/dev/usb/ohcireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ohcireg.h,v 1.1 1999/08/13 05:28:04 fgsch Exp $ */ +/* $OpenBSD: ohcireg.h,v 1.2 1999/08/27 09:00:28 fgsch Exp $ */ /* $NetBSD: ohcireg.h,v 1.7 1998/12/10 23:16:47 augustss Exp $ */ /* @@ -165,7 +165,7 @@ typedef struct { ohci_physaddr_t ed_headp; ohci_physaddr_t ed_nexted; } ohci_ed_t; -#define OHCI_ED_SIZE 16 +/* #define OHCI_ED_SIZE 16 */ #define OHCI_ED_ALIGN 16 typedef struct { @@ -188,7 +188,7 @@ typedef struct { ohci_physaddr_t td_nexttd; /* Next TD */ ohci_physaddr_t td_be; /* Buffer End */ } ohci_td_t; -#define OHCI_TD_SIZE 16 +/* #define OHCI_TD_SIZE 16 */ #define OHCI_TD_ALIGN 16 #define OHCI_CC_NO_ERROR 0 diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index 601619a4199..ffa75a6b072 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ohcivar.h,v 1.3 1999/08/19 08:18:38 fgsch Exp $ */ +/* $OpenBSD: ohcivar.h,v 1.4 1999/08/27 09:00:28 fgsch Exp $ */ /* $NetBSD: ohcivar.h,v 1.6 1999/08/14 14:49:31 augustss Exp $ */ /* @@ -39,26 +39,27 @@ */ typedef struct ohci_soft_ed { - ohci_ed_t *ed; + ohci_ed_t ed; struct ohci_soft_ed *next; ohci_physaddr_t physaddr; } ohci_soft_ed_t; -#define OHCI_ED_CHUNK 256 +#define OHCI_SED_SIZE ((sizeof (struct ohci_soft_ed) + OHCI_ED_ALIGN - 1) / OHCI_ED_ALIGN * OHCI_ED_ALIGN) +#define OHCI_SED_CHUNK 128 typedef struct ohci_soft_td { - ohci_td_t *td; + ohci_td_t td; struct ohci_soft_td *nexttd; /* mirrors nexttd in TD */ struct ohci_soft_td *dnext; /* next in done list */ ohci_physaddr_t physaddr; LIST_ENTRY(ohci_soft_td) hnext; - /*ohci_soft_ed_t *sed;*/ usbd_request_handle reqh; u_int16_t len; u_int16_t flags; #define OHCI_CALL_DONE 0x0001 #define OHCI_SET_LEN 0x0002 } ohci_soft_td_t; -#define OHCI_TD_CHUNK 256 +#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN) +#define OHCI_STD_CHUNK 128 #define OHCI_NO_EDS (2*OHCI_NO_INTRS-1) diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index 968078fc9bb..62e9d262951 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ugen.c,v 1.2 1999/08/16 22:08:48 fgsch Exp $ */ -/* $NetBSD: ugen.c,v 1.13 1999/08/02 19:32:56 augustss Exp $ */ +/* $OpenBSD: ugen.c,v 1.3 1999/08/27 09:00:28 fgsch Exp $ */ +/* $NetBSD: ugen.c,v 1.18 1999/08/23 22:55:14 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -86,6 +86,7 @@ struct ugen_endpoint { struct clist q; struct selinfo rsel; void *ibuf; + u_int32_t timeout; }; #define UGEN_CHUNK 128 /* chunk size for read */ @@ -287,6 +288,7 @@ ugenopen(dev, flag, mode, p) continue; sce = &sc->sc_endpoints[endpt][dir]; sce->state = 0; + sce->timeout = USBD_NO_TIMEOUT; DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", sc, endpt, dir, sce)); edesc = sce->edesc; @@ -469,10 +471,12 @@ ugen_do_read(sc, endpt, uio, flag) reqh, sce->pipeh, sce->state & UGEN_SHORT_OK ? USBD_SHORT_XFER_OK : 0, - buf, &tn, "ugenrb"); + sce->timeout, buf, &tn, "ugenrb"); if (r != USBD_NORMAL_COMPLETION) { if (r == USBD_INTERRUPTED) error = EINTR; + else if (r == USBD_TIMEOUT) + error = ETIMEDOUT; else error = EIO; break; @@ -515,7 +519,7 @@ ugen_do_write(sc, endpt, uio, flag) int flag; { struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; - size_t n; + u_int32_t n; int error = 0; char buf[UGEN_BBSIZE]; usbd_request_handle reqh; @@ -546,8 +550,8 @@ ugen_do_write(sc, endpt, uio, flag) if (error) break; DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf, - &n, "ugenwb"); + r = usbd_bulk_transfer(reqh, sce->pipeh, 0, + sce->timeout, buf, &n,"ugenwb"); if (r != USBD_NORMAL_COMPLETION) { if (r == USBD_INTERRUPTED) error = EINTR; @@ -586,6 +590,17 @@ ugen_activate(self, act) struct device *self; enum devact act; { + struct ugen_softc *sc = (struct ugen_softc *)self; + + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: + sc->sc_dying = 1; + break; + } return (0); } @@ -642,10 +657,7 @@ ugenintr(reqh, addr, status) { struct ugen_endpoint *sce = addr; /*struct ugen_softc *sc = sce->sc;*/ - usbd_private_handle priv; - void *buffer; u_int32_t count; - usbd_status xstatus; u_char *ibuf; if (status == USBD_CANCELLED) @@ -657,11 +669,11 @@ ugenintr(reqh, addr, status) return; } - (void)usbd_get_request_status(reqh, &priv, &buffer, &count, &xstatus); + usbd_get_request_status(reqh, 0, 0, &count, 0); ibuf = sce->ibuf; DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n", - reqh, xstatus, count)); + reqh, status, count)); DPRINTFN(5, (" data = %02x %02x %02x\n", ibuf[0], ibuf[1], ibuf[2])); @@ -816,7 +828,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) sce = &sc->sc_endpoints[endpt][IN]; #ifdef DIAGNOSTIC if (!sce->pipeh) { - printf("ugenioctl: no pipe\n"); + printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); return (EIO); } #endif @@ -825,6 +837,16 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) else sce->state &= ~UGEN_SHORT_OK; return (0); + case USB_SET_TIMEOUT: + sce = &sc->sc_endpoints[endpt][IN]; +#ifdef DIAGNOSTIC + if (!sce->pipeh) { + printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n"); + return (EIO); + } +#endif + sce->timeout = *(int *)addr; + return (0); default: break; } @@ -956,11 +978,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = p; -#if defined(__OpenBSD__) error = uiomove((caddr_t)cdesc, len, &uio); -#else - error = uiomove(cdesc, len, &uio); -#endif free(cdesc, M_TEMP); return (error); } diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 9296c686491..6f523d43cfd 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhci.c,v 1.3 1999/08/19 08:18:38 fgsch Exp $ */ -/* $NetBSD: uhci.c,v 1.34 1999/08/02 23:35:55 augustss Exp $ */ +/* $OpenBSD: uhci.c,v 1.4 1999/08/27 09:00:28 fgsch Exp $ */ +/* $NetBSD: uhci.c,v 1.43 1999/08/22 23:41:00 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -66,6 +66,7 @@ #include <machine/bus_pio.h> #endif #include <machine/bus.h> +#include <machine/endian.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -90,6 +91,16 @@ struct cfdriver uhci_cd = { }; #endif +/* + * The UHCI controller is little endian, so on big endian machines + * the data strored in memory needs to be swapped. + */ +#if BYTE_ORDER == BIG_ENDIAN +#define LE(x) (bswap32(x)) +#else +#define LE(x) (x) +#endif + struct uhci_pipe { struct usbd_pipe pipe; uhci_intr_info_t *iinfo; @@ -158,8 +169,8 @@ void uhci_timo __P((void *)); void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle)); void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *)); void uhci_idone __P((uhci_intr_info_t *)); -void uhci_done __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_timeout __P((void *)); void uhci_wakeup_ctrl __P((void *, int, int, void *, int)); void uhci_lock_frames __P((uhci_softc_t *)); @@ -176,42 +187,47 @@ 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)); void uhci_device_ctrl_close __P((usbd_pipe_handle)); +void uhci_device_ctrl_done __P((usbd_request_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)); void uhci_device_intr_close __P((usbd_pipe_handle)); +void uhci_device_intr_done __P((usbd_request_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)); void uhci_device_bulk_close __P((usbd_pipe_handle)); +void uhci_device_bulk_done __P((usbd_request_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)); void uhci_device_isoc_close __P((usbd_pipe_handle)); +void uhci_device_isoc_done __P((usbd_request_handle)); usbd_status uhci_device_isoc_setbuf __P((usbd_pipe_handle, u_int, u_int)); 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)); void uhci_root_ctrl_close __P((usbd_pipe_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)); void uhci_root_intr_close __P((usbd_pipe_handle)); +void uhci_root_intr_done __P((usbd_request_handle)); usbd_status uhci_open __P((usbd_pipe_handle)); void uhci_poll __P((struct usbd_bus *)); usbd_status uhci_device_request __P((usbd_request_handle reqh)); -void uhci_ctrl_done __P((uhci_intr_info_t *ii)); -void uhci_bulk_done __P((uhci_intr_info_t *ii)); 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 *)); usbd_status uhci_device_setintr __P((uhci_softc_t *sc, struct uhci_pipe *pipe, int ival)); -void uhci_intr_done __P((uhci_intr_info_t *ii)); -void uhci_isoc_done __P((uhci_intr_info_t *ii)); void uhci_device_clear_toggle __P((usbd_pipe_handle pipe)); void uhci_noop __P((usbd_pipe_handle pipe)); @@ -246,6 +262,7 @@ struct usbd_methods uhci_root_ctrl_methods = { uhci_root_ctrl_close, uhci_noop, 0, + 0, }; struct usbd_methods uhci_root_intr_methods = { @@ -254,6 +271,7 @@ struct usbd_methods uhci_root_intr_methods = { uhci_root_intr_abort, uhci_root_intr_close, uhci_noop, + uhci_root_intr_done, 0, }; @@ -263,6 +281,7 @@ struct usbd_methods uhci_device_ctrl_methods = { uhci_device_ctrl_abort, uhci_device_ctrl_close, uhci_noop, + uhci_device_ctrl_done, 0, }; @@ -272,6 +291,7 @@ struct usbd_methods uhci_device_intr_methods = { uhci_device_intr_abort, uhci_device_intr_close, uhci_device_clear_toggle, + uhci_device_intr_done, 0, }; @@ -281,6 +301,7 @@ struct usbd_methods uhci_device_bulk_methods = { uhci_device_bulk_abort, uhci_device_bulk_close, uhci_device_clear_toggle, + uhci_device_bulk_done, 0, }; @@ -290,6 +311,7 @@ struct usbd_methods uhci_device_isoc_methods = { uhci_device_isoc_abort, uhci_device_isoc_close, uhci_noop, + uhci_device_isoc_done, uhci_device_isoc_setbuf, }; @@ -331,23 +353,23 @@ uhci_init(sc) return (r); 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 */ + 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) return (USBD_NOMEM); - bsqh->qh->qh_hlink = UHCI_PTR_T; /* end of QH chain */ - bsqh->qh->qh_elink = UHCI_PTR_T; + bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */ + bsqh->qh.qh_elink = LE(UHCI_PTR_T); sc->sc_bulk_start = sc->sc_bulk_end = bsqh; /* Allocate the dummy QH where control traffic will be queued. */ csqh = uhci_alloc_sqh(sc); if (!csqh) return (USBD_NOMEM); - csqh->qh->hlink = bsqh; - csqh->qh->qh_hlink = bsqh->physaddr | UHCI_PTR_Q; - csqh->qh->qh_elink = UHCI_PTR_T; + csqh->hlink = bsqh; + csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q); + csqh->qh.qh_elink = LE(UHCI_PTR_T); sc->sc_ctl_start = sc->sc_ctl_end = csqh; /* @@ -360,15 +382,15 @@ uhci_init(sc) sqh = uhci_alloc_sqh(sc); if (!std || !sqh) return (USBD_NOMEM); - std->td->link.sqh = sqh; - std->td->td_link = sqh->physaddr | UHCI_PTR_Q; - std->td->td_status = UHCI_TD_IOS; /* iso, inactive */ - std->td->td_token = 0; - std->td->td_buffer = 0; - sqh->qh->hlink = csqh; - sqh->qh->qh_hlink = csqh->physaddr | UHCI_PTR_Q; - sqh->qh->elink = 0; - sqh->qh->qh_elink = UHCI_PTR_T; + std->link.sqh = sqh; + std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q); + std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */ + std->td.td_token = LE(0); + std->td.td_buffer = LE(0); + sqh->hlink = csqh; + sqh->qh.qh_hlink = LE(csqh->physaddr | UHCI_PTR_Q); + sqh->elink = 0; + sqh->qh.qh_elink = LE(UHCI_PTR_T); sc->sc_vframes[i].htd = std; sc->sc_vframes[i].etd = std; sc->sc_vframes[i].hqh = sqh; @@ -376,7 +398,7 @@ uhci_init(sc) for (j = i; j < UHCI_FRAMELIST_COUNT; j += UHCI_VFRAMELIST_COUNT) - sc->sc_pframes[j] = std->physaddr; + sc->sc_pframes[j] = LE(std->physaddr); } LIST_INIT(&sc->sc_intrhead); @@ -402,9 +424,9 @@ uhci_init(sc) /* * Handle suspend/resume. * - * Must use delay() here since we are called from an interrupt - * context, but since we are close to being inactive anyway - * it doesn't matter. + * We need to switch to polling mode here, because this routine is + * called from an intterupt context. This is all right since we + * are almost suspended anyway. */ void uhci_power(why, v) @@ -429,9 +451,10 @@ uhci_power(why, v) if (sc->sc_has_timo) usb_untimeout(uhci_timo, sc->sc_has_timo, sc->sc_has_timo->timo_handle); + sc->sc_bus.use_polling = 1; uhci_run(sc, 0); /* stop the controller */ UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ - delay(USB_RESUME_WAIT * 1000); + usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); sc->sc_suspend = why; DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); } else { @@ -444,12 +467,13 @@ uhci_power(why, v) if (cmd & UHCI_CMD_RS) uhci_run(sc, 0); /* in case BIOS has started it */ UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ - delay(USB_RESUME_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */ uhci_run(sc, 1); /* and start traffic again */ - delay(USB_RESUME_RECOVERY * 1000); + usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); + sc->sc_bus.use_polling = 0; if (sc->sc_has_timo) usb_timeout(uhci_timo, sc->sc_has_timo, sc->sc_ival, sc->sc_has_timo->timo_handle); @@ -489,25 +513,25 @@ uhci_dump_td(p) printf("TD(%p) at %08lx = link=0x%08lx status=0x%08lx " "token=0x%08lx buffer=0x%08lx\n", p, (long)p->physaddr, - (long)p->td->td_link, - (long)p->td->td_status, - (long)p->td->td_token, - (long)p->td->td_buffer); + (long)LE(p->td.td_link), + (long)LE(p->td.td_status), + (long)LE(p->td.td_token), + (long)LE(p->td.td_buffer)); if (uhci_longtd) printf(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d," "D=%d,maxlen=%d\n", - (int)p->td->td_link, + (int)LE(p->td.td_link), "\20\1T\2Q\3VF", - (int)p->td->td_status, + (int)LE(p->td.td_status), "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD", - UHCI_TD_GET_ERRCNT(p->td->td_status), - UHCI_TD_GET_ACTLEN(p->td->td_status), - UHCI_TD_GET_PID(p->td->td_token), - UHCI_TD_GET_DEVADDR(p->td->td_token), - UHCI_TD_GET_ENDPT(p->td->td_token), - UHCI_TD_GET_DT(p->td->td_token), - UHCI_TD_GET_MAXLEN(p->td->td_token)); + UHCI_TD_GET_ERRCNT(LE(p->td.td_status)), + UHCI_TD_GET_ACTLEN(LE(p->td.td_status)), + UHCI_TD_GET_PID(LE(p->td.td_token)), + UHCI_TD_GET_DEVADDR(LE(p->td.td_token)), + UHCI_TD_GET_ENDPT(LE(p->td.td_token)), + UHCI_TD_GET_DT(LE(p->td.td_token)), + UHCI_TD_GET_MAXLEN(LE(p->td.td_token))); } void @@ -515,7 +539,7 @@ uhci_dump_qh(p) uhci_soft_qh_t *p; { printf("QH(%p) at %08x: hlink=%08x elink=%08x\n", p, (int)p->physaddr, - p->qh->qh_hlink, p->qh->qh_elink); + LE(p->qh.qh_hlink), LE(p->qh.qh_elink)); } @@ -528,7 +552,7 @@ uhci_dump() uhci_dumpregs(sc); printf("intrs=%d\n", sc->sc_intrs); printf("framelist[i].link = %08x\n", sc->sc_framelist[0].link); - uhci_dump_qh(sc->sc_ctl_start->qh->hlink); + uhci_dump_qh(sc->sc_ctl_start->qh.hlink); } #endif @@ -538,7 +562,7 @@ uhci_dump_tds(std) { uhci_soft_td_t *p; - for(p = std; p; p = p->td->link.std) + for(p = std; p; p = p->link.std) uhci_dump_td(p); } #endif @@ -560,27 +584,36 @@ uhci_timo(addr) DPRINTFN(15, ("uhci_timo\n")); + usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); + p = KERNADDR(&upipe->u.intr.datadma); p[0] = 0; if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) p[0] |= 1<<1; if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) p[0] |= 1<<2; + if (p[0] == 0) + /* No change, try again in a while */ + return; + + reqh->actlen = 1; + reqh->status = USBD_NORMAL_COMPLETION; s = splusb(); + reqh->hcpriv = 0; + usb_transfer_complete(reqh); + splx(s); +} + +void +uhci_root_intr_done(reqh) + usbd_request_handle reqh; +{ + usbd_pipe_handle pipe = reqh->pipe; + uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; + struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; + if (!reqh->pipe->repeat) - SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next); - if (p[0] != 0) { - reqh->actlen = 1; - reqh->status = USBD_NORMAL_COMPLETION; - reqh->xfercb(reqh); - } - if (reqh->pipe->repeat) { - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); - } else { usb_freemem(sc->sc_dmatag, &upipe->u.intr.datadma); - usb_start_next(reqh->pipe); - } - splx(s); } @@ -641,14 +674,14 @@ uhci_add_ctrl(sc, sqh) uhci_softc_t *sc; uhci_soft_qh_t *sqh; { - uhci_qh_t *eqh; + uhci_soft_qh_t *eqh; DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh)); - eqh = sc->sc_ctl_end->qh; - sqh->qh->hlink = eqh->hlink; - sqh->qh->qh_hlink = eqh->qh_hlink; - eqh->hlink = sqh; - eqh->qh_hlink = sqh->physaddr | UHCI_PTR_Q; + eqh = sc->sc_ctl_end; + sqh->hlink = eqh->hlink; + sqh->qh.qh_hlink = eqh->qh.qh_hlink; + eqh->hlink = sqh; + eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q); sc->sc_ctl_end = sqh; } @@ -661,17 +694,17 @@ uhci_remove_ctrl(sc, sqh) uhci_soft_qh_t *pqh; DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh)); - for (pqh = sc->sc_ctl_start; pqh->qh->hlink != sqh; pqh=pqh->qh->hlink) + for (pqh = sc->sc_ctl_start; pqh->hlink != sqh; pqh=pqh->hlink) #if defined(DIAGNOSTIC) || defined(USB_DEBUG) - if (pqh->qh->qh_hlink & UHCI_PTR_T) { + if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) { printf("uhci_remove_ctrl: QH not found\n"); return; } #else ; #endif - pqh->qh->hlink = sqh->qh->hlink; - pqh->qh->qh_hlink = sqh->qh->qh_hlink; + pqh->hlink = sqh->hlink; + pqh->qh.qh_hlink = sqh->qh.qh_hlink; if (sc->sc_ctl_end == sqh) sc->sc_ctl_end = pqh; } @@ -682,14 +715,14 @@ uhci_add_bulk(sc, sqh) uhci_softc_t *sc; uhci_soft_qh_t *sqh; { - uhci_qh_t *eqh; + uhci_soft_qh_t *eqh; DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); - eqh = sc->sc_bulk_end->qh; - sqh->qh->hlink = eqh->hlink; - sqh->qh->qh_hlink = eqh->qh_hlink; - eqh->hlink = sqh; - eqh->qh_hlink = sqh->physaddr | UHCI_PTR_Q; + eqh = sc->sc_bulk_end; + sqh->hlink = eqh->hlink; + sqh->qh.qh_hlink = eqh->qh.qh_hlink; + eqh->hlink = sqh; + eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q); sc->sc_bulk_end = sqh; } @@ -702,19 +735,17 @@ uhci_remove_bulk(sc, sqh) uhci_soft_qh_t *pqh; DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh)); - for (pqh = sc->sc_bulk_start; - pqh->qh->hlink != sqh; - pqh = pqh->qh->hlink) + for (pqh = sc->sc_bulk_start; pqh->hlink != sqh; pqh = pqh->hlink) #if defined(DIAGNOSTIC) || defined(USB_DEBUG) - if (pqh->qh->qh_hlink & UHCI_PTR_T) { + if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) { printf("uhci_remove_bulk: QH not found\n"); return; } #else ; #endif - pqh->qh->hlink = sqh->qh->hlink; - pqh->qh->qh_hlink = sqh->qh->qh_hlink; + pqh->hlink = sqh->hlink; + pqh->qh.qh_hlink = sqh->qh.qh_hlink; if (sc->sc_bulk_end == sqh) sc->sc_bulk_end = pqh; } @@ -792,7 +823,6 @@ uhci_check_intr(sc, ii) uhci_softc_t *sc; uhci_intr_info_t *ii; { - struct uhci_pipe *upipe; uhci_soft_td_t *std, *lstd; u_int32_t status; @@ -817,10 +847,10 @@ uhci_check_intr(sc, ii) * is a an error somewhere in the middle, or whether there was a * short packet (SPD and not ACTIVE). */ - if (lstd->td->td_status & UHCI_TD_ACTIVE) { + if (LE(lstd->td.td_status) & UHCI_TD_ACTIVE) { DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii)); - for (std = ii->stdstart; std != lstd; std = std->td->link.std){ - status = std->td->td_status; + 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) @@ -832,7 +862,6 @@ uhci_check_intr(sc, ii) } done: usb_untimeout(uhci_timeout, ii, ii->timeout_handle); - upipe = (struct uhci_pipe *)ii->reqh->pipe; uhci_idone(ii); } @@ -874,16 +903,17 @@ 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->td->link.std) { - status = std->td->td_status; + for (std = ii->stdstart; std; std = std->link.std) { + status = LE(std->td.td_status); if (status & UHCI_TD_ACTIVE) break; - if (UHCI_TD_GET_PID(std->td->td_token) != UHCI_TD_PID_SETUP) + 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) - upipe->nexttoggle = UHCI_TD_GET_DT(std->td->td_token); + 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", @@ -905,41 +935,8 @@ uhci_idone(ii) } else { reqh->status = USBD_NORMAL_COMPLETION; } - - uhci_done(ii); - if (ii->reqh->pipe->intrreqh != ii->reqh) - usb_start_next(ii->reqh->pipe); -} - -void -uhci_done(ii) - uhci_intr_info_t *ii; -{ - usbd_request_handle reqh = ii->reqh; - usbd_pipe_handle pipe = reqh->pipe; - - DPRINTFN(5, ("uhci_ii_finish: calling handler ii=%p\n", ii)); - - switch (pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) { - case UE_CONTROL: - uhci_ctrl_done(ii); - break; - case UE_ISOCHRONOUS: - uhci_isoc_done(ii); - break; - case UE_BULK: - uhci_bulk_done(ii); - break; - case UE_INTERRUPT: - uhci_intr_done(ii); - break; - } - - /* Remove request from queue. */ - SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next); - - /* And finally execute callback. */ - reqh->xfercb(reqh); + reqh->hcpriv = ii; + usb_transfer_complete(reqh); } /* @@ -988,10 +985,11 @@ uhci_waitintr(sc, reqh) ii && ii->reqh != reqh; ii = LIST_NEXT(ii, list)) ; - if (ii) - uhci_idone(ii); - else +#ifdef DIAGNOSTIC + if (!ii) panic("uhci_waitintr: lost intr_info\n"); +#endif + uhci_idone(ii); } void @@ -1067,32 +1065,26 @@ uhci_alloc_std(sc) { uhci_soft_td_t *std; usbd_status r; - int i; + int i, offs; usb_dma_t dma; if (!sc->sc_freetds) { DPRINTFN(2,("uhci_alloc_std: allocating chunk\n")); - std = malloc(sizeof(uhci_soft_td_t) * UHCI_TD_CHUNK, - M_USBHC, M_NOWAIT); - if (!std) - return (0); - r = usb_allocmem(sc->sc_dmatag, UHCI_TD_SIZE * UHCI_TD_CHUNK, + r = usb_allocmem(sc->sc_dmatag, UHCI_STD_SIZE * UHCI_STD_CHUNK, UHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) { - free(std, M_USBHC); + if (r != USBD_NORMAL_COMPLETION) return (0); - } - for(i = 0; i < UHCI_TD_CHUNK; i++, std++) { - std->physaddr = DMAADDR(&dma) + i * UHCI_TD_SIZE; - std->td = (uhci_td_t *) - ((char *)KERNADDR(&dma) + i * UHCI_TD_SIZE); - std->td->link.std = sc->sc_freetds; + for(i = 0; i < UHCI_STD_CHUNK; i++) { + offs = i * UHCI_STD_SIZE; + std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) +offs); + std->physaddr = DMAADDR(&dma) + offs; + std->link.std = sc->sc_freetds; sc->sc_freetds = std; } } std = sc->sc_freetds; - sc->sc_freetds = std->td->link.std; - memset(std->td, 0, UHCI_TD_SIZE); + sc->sc_freetds = std->link.std; + memset(&std->td, 0, sizeof(uhci_td_t)); return std; } @@ -1103,13 +1095,13 @@ uhci_free_std(sc, std) { #ifdef DIAGNOSTIC #define TD_IS_FREE 0x12345678 - if (std->td->td_token == TD_IS_FREE) { + if (LE(std->td.td_token) == TD_IS_FREE) { printf("uhci_free_std: freeing free TD %p\n", std); return; } - std->td->td_token = TD_IS_FREE; + std->td.td_token = LE(TD_IS_FREE); #endif - std->td->link.std = sc->sc_freetds; + std->link.std = sc->sc_freetds; sc->sc_freetds = std; } @@ -1124,28 +1116,21 @@ uhci_alloc_sqh(sc) if (!sc->sc_freeqhs) { DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n")); - sqh = malloc(sizeof(uhci_soft_qh_t) * UHCI_QH_CHUNK, - M_USBHC, M_NOWAIT); - if (!sqh) - return 0; - r = usb_allocmem(sc->sc_dmatag, UHCI_QH_SIZE * UHCI_QH_CHUNK, + r = usb_allocmem(sc->sc_dmatag, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, UHCI_QH_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) { - free(sqh, M_USBHC); + if (r != USBD_NORMAL_COMPLETION) return 0; - } - for(i = 0; i < UHCI_QH_CHUNK; i++, sqh++) { - offs = i * UHCI_QH_SIZE; + for(i = 0; i < UHCI_SQH_CHUNK; i++) { + offs = i * UHCI_SQH_SIZE; + sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma) +offs); sqh->physaddr = DMAADDR(&dma) + offs; - sqh->qh = (uhci_qh_t *) - ((char *)KERNADDR(&dma) + offs); - sqh->qh->hlink = sc->sc_freeqhs; + sqh->hlink = sc->sc_freeqhs; sc->sc_freeqhs = sqh; } } sqh = sc->sc_freeqhs; - sc->sc_freeqhs = sqh->qh->hlink; - memset(sqh->qh, 0, UHCI_QH_SIZE); + sc->sc_freeqhs = sqh->hlink; + memset(&sqh->qh, 0, sizeof(uhci_qh_t)); return (sqh); } @@ -1154,7 +1139,7 @@ uhci_free_sqh(sc, sqh) uhci_softc_t *sc; uhci_soft_qh_t *sqh; { - sqh->qh->hlink = sc->sc_freeqhs; + sqh->hlink = sc->sc_freeqhs; sc->sc_freeqhs = sqh; } @@ -1183,7 +1168,7 @@ uhci_free_std_chain(sc, std, stdend) uhci_soft_td_t *p; for (; std != stdend; std = p) { - p = std->td->link.std; + p = std->link.std; uhci_free_std(sc, std); } } @@ -1217,6 +1202,7 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) return (USBD_INVAL); } ntd = (len + maxp - 1) / maxp; + DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd)); tog = upipe->nexttoggle; if (ntd % 2 == 0) tog ^= 1; @@ -1235,11 +1221,11 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) uhci_free_std_chain(sc, lastp, 0); return (USBD_NOMEM); } - p->td->link.std = lastp; - p->td->td_link = lastlink; + p->link.std = lastp; + p->td.td_link = LE(lastlink); lastp = p; lastlink = p->physaddr; - p->td->td_status = status; + p->td.td_status = LE(status); if (i == ntd) { /* last TD */ l = len % maxp; @@ -1247,10 +1233,10 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) *ep = p; } else l = maxp; - p->td->td_token = - rd ? UHCI_TD_IN (l, endpt, addr, tog) : - UHCI_TD_OUT(l, endpt, addr, tog); - p->td->td_buffer = DMAADDR(dma) + i * maxp; + p->td.td_token = + LE(rd ? UHCI_TD_IN (l, endpt, addr, tog) : + UHCI_TD_OUT(l, endpt, addr, tog)); + p->td.td_buffer = LE(DMAADDR(dma) + i * maxp); tog ^= 1; } *sp = lastp; @@ -1327,7 +1313,7 @@ uhci_device_bulk_start(reqh) dmap, &xfer, &xferend); if (r != USBD_NORMAL_COMPLETION) goto ret2; - xferend->td->td_status |= UHCI_TD_IOC; + xferend->td.td_status |= LE(UHCI_TD_IOC); if (!isread && len != 0) memcpy(KERNADDR(dmap), reqh->buffer, len); @@ -1347,8 +1333,8 @@ uhci_device_bulk_start(reqh) ii->isdone = 0; #endif - sqh->qh->elink = xfer; - sqh->qh->qh_elink = xfer->physaddr; + sqh->elink = xfer; + sqh->qh.qh_elink = LE(xfer->physaddr); sqh->intr_info = ii; s = splusb(); @@ -1397,20 +1383,39 @@ uhci_abort_req(reqh, status) struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *std; - int s; /* Make interrupt routine ignore it, */ - reqh->status = USBD_CANCELLED; + reqh->status = status; + + /* don't timeout, */ + usb_untimeout(uhci_timeout, ii, ii->timeout_handle); /* make hardware ignore it, */ - for (std = ii->stdstart; std != 0; std = std->td->link.std) - std->td->td_status &= ~UHCI_TD_ACTIVE; + for (std = ii->stdstart; std != 0; std = std->link.std) + std->td.td_status &= LE(~UHCI_TD_ACTIVE); + + reqh->hcpriv = ii; + /* make sure hardware has completed, */ - usb_delay_ms(reqh->pipe->device->bus, 1); + if (curproc) { + usb_delay_ms(reqh->pipe->device->bus, 1); + /* and call final part of interrupt handler. */ + uhci_abort_req_end(reqh); + } else { + /* We have no process context, so we can't use tsleep(). */ + timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + } +} + +void +uhci_abort_req_end(v) + void *v; +{ + usbd_request_handle reqh = v; + int s; - /* and call final part of interrupt handler. */ s = splusb(); - uhci_done(ii); + usb_transfer_complete(reqh); splx(s); } @@ -1514,7 +1519,7 @@ uhci_device_intr_start(reqh) dmap, &xfer, &xferend); if (r != USBD_NORMAL_COMPLETION) goto ret2; - xferend->td->td_status |= UHCI_TD_IOC; + xferend->td.td_status |= LE(UHCI_TD_IOC); #ifdef USB_DEBUG if (uhcidebug > 10) { @@ -1537,8 +1542,8 @@ uhci_device_intr_start(reqh) upipe->u.intr.qhs[0])); for (i = 0; i < upipe->u.intr.npoll; i++) { sqh = upipe->u.intr.qhs[i]; - sqh->qh->elink = xfer; - sqh->qh->qh_elink = xfer->physaddr; + sqh->elink = xfer; + sqh->qh.qh_elink = LE(xfer->physaddr); } splx(s); @@ -1676,8 +1681,8 @@ uhci_device_request(reqh) if (r != USBD_NORMAL_COMPLETION) goto ret2; next = xfer; - xferend->td->link.std = stat; - xferend->td->td_link = stat->physaddr; + xferend->link.std = stat; + xferend->td.td_link = LE(stat->physaddr); } else { next = stat; } @@ -1687,27 +1692,25 @@ uhci_device_request(reqh) if (!isread && len != 0) memcpy(KERNADDR(dmap), reqh->buffer, len); - setup->td->link.std = next; - setup->td->td_link = next->physaddr; - setup->td->td_status = UHCI_TD_SET_ERRCNT(2) | ls | UHCI_TD_ACTIVE; - setup->td->td_token = UHCI_TD_SETUP(sizeof *req, endpt, addr); - setup->td->td_buffer = DMAADDR(&upipe->u.ctl.reqdma); - - stat->td->link.std = 0; - stat->td->td_link = UHCI_PTR_T; - stat->td->td_status = UHCI_TD_SET_ERRCNT(2) | ls | - UHCI_TD_ACTIVE | UHCI_TD_IOC; - stat->td->td_token = - isread ? UHCI_TD_OUT(0, endpt, addr, 1) : - UHCI_TD_IN (0, endpt, addr, 1); - stat->td->td_buffer = 0; + setup->link.std = next; + setup->td.td_link = LE(next->physaddr); + 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)); + + stat->link.std = 0; + stat->td.td_link = LE(UHCI_PTR_T); + stat->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | + UHCI_TD_ACTIVE | UHCI_TD_IOC); + stat->td.td_token = + LE(isread ? UHCI_TD_OUT(0, endpt, addr, 1) : + UHCI_TD_IN (0, endpt, addr, 1)); + stat->td.td_buffer = LE(0); #ifdef USB_DEBUG if (uhcidebug > 20) { - printf("uhci_device_request: setup\n"); - uhci_dump_td(setup); - printf("uhci_device_request: stat\n"); - uhci_dump_td(stat); + printf("uhci_device_request: before transfer\n"); + uhci_dump_tds(setup); } #endif @@ -1719,8 +1722,8 @@ uhci_device_request(reqh) ii->isdone = 0; #endif - sqh->qh->elink = setup; - sqh->qh->qh_elink = setup->physaddr; + sqh->elink = setup; + sqh->qh.qh_elink = LE(setup->physaddr); sqh->intr_info = ii; s = splusb(); @@ -1736,20 +1739,20 @@ uhci_device_request(reqh) printf("uhci_enter_ctl_q: follow from [0]\n"); for (std = sc->sc_vframes[0].htd, link = 0; (link & UHCI_PTR_Q) == 0; - std = std->td->link.std) { - link = std->td->td_link; + std = std->link.std) { + link = LE(std->td.td_link); uhci_dump_td(std); } for (sxqh = xqh = (uhci_soft_qh_t *)std; xqh; - xqh = (maxqh++ == 5 || xqh->qh->hlink==sxqh || - xqh->qh->hlink==xqh ? NULL : xqh->qh->hlink)) { + xqh = (maxqh++ == 5 || xqh->hlink==sxqh || + xqh->hlink==xqh ? NULL : xqh->hlink)) { uhci_dump_qh(xqh); uhci_dump_qh(sxqh); } printf("Enqueued QH:\n"); uhci_dump_qh(sqh); - uhci_dump_tds(sqh->qh->elink); + uhci_dump_tds(sqh->elink); } #endif if (reqh->timeout && !sc->sc_bus.use_polling) { @@ -1818,7 +1821,7 @@ uhci_device_isoc_close(pipe) iso = &upipe->u.iso; for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) - iso->stds[i]->td->td_status &= ~UHCI_TD_ACTIVE; + iso->stds[i]->td.td_status &= LE(~UHCI_TD_ACTIVE); usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */ uhci_lock_frames(sc); @@ -1827,8 +1830,8 @@ uhci_device_isoc_close(pipe) std = iso->stds[i]; for (vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd; - vstd && vstd->td->link.std != std; - vstd = vstd->td->link.std) + vstd && vstd->link.std != std; + vstd = vstd->link.std) ; if (!vstd) { /*panic*/ @@ -1836,8 +1839,8 @@ uhci_device_isoc_close(pipe) uhci_unlock_frames(sc); return; } - vstd->td->link = std->td->link; - vstd->td->td_link = std->td->td_link; + vstd->link = std->link; + vstd->td.td_link = std->td.td_link; uhci_free_std(sc, std); } uhci_unlock_frames(sc); @@ -1907,17 +1910,17 @@ uhci_device_isoc_setbuf(pipe, bufsize, nbuf) uhci_soft_td_t *std, *vstd; std = iso->stds[i]; - std->td->td_status = UHCI_TD_IOS; /* iso, inactive */ - std->td->td_token = - rd ? UHCI_TD_IN (0, endpt, addr, 0) : - UHCI_TD_OUT(0, endpt, addr, 0); - std->td->td_buffer = DMAADDR(&iso->bufs[i % nbuf]); + std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */ + std->td.td_token = + LE(rd ? UHCI_TD_IN (0, endpt, addr, 0) : + UHCI_TD_OUT(0, endpt, addr, 0)); + std->td.td_buffer = LE(DMAADDR(&iso->bufs[i % nbuf])); vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd; - std->td->link = vstd->td->link; - std->td->td_link = vstd->td->td_link; - vstd->td->link.std = std; - vstd->td->td_link = std->physaddr; + std->link = vstd->link; + std->td.td_link = vstd->td.td_link; + vstd->link.std = std; + vstd->td.td_link = LE(std->physaddr); } uhci_unlock_frames(sc); @@ -1935,17 +1938,18 @@ uhci_device_isoc_setbuf(pipe, bufsize, nbuf) } void -uhci_isoc_done(ii) - uhci_intr_info_t *ii; +uhci_device_isoc_done(reqh) + usbd_request_handle reqh; { + /*uhci_intr_info_t *ii = v;*/ } void -uhci_intr_done(ii) - uhci_intr_info_t *ii; +uhci_device_intr_done(reqh) + usbd_request_handle reqh; { + uhci_intr_info_t *ii = reqh->hcpriv; uhci_softc_t *sc = ii->sc; - usbd_request_handle reqh = ii->reqh; struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; usb_dma_t *dma; uhci_soft_qh_t *sqh; @@ -1958,8 +1962,8 @@ uhci_intr_done(ii) npoll = upipe->u.intr.npoll; for(i = 0; i < npoll; i++) { sqh = upipe->u.intr.qhs[i]; - sqh->qh->elink = 0; - sqh->qh->qh_elink = UHCI_PTR_T; + sqh->elink = 0; + sqh->qh.qh_elink = LE(UHCI_PTR_T); } uhci_free_std_chain(sc, ii->stdstart, 0); @@ -1971,7 +1975,7 @@ uhci_intr_done(ii) uhci_alloc_std_chain(upipe, sc, reqh->length, 1, reqh->flags & USBD_SHORT_XFER_OK, dma, &xfer, &xferend); - xferend->td->td_status |= UHCI_TD_IOC; + xferend->td.td_status |= LE(UHCI_TD_IOC); #ifdef USB_DEBUG if (uhcidebug > 10) { @@ -1988,8 +1992,8 @@ uhci_intr_done(ii) #endif for (i = 0; i < npoll; i++) { sqh = upipe->u.intr.qhs[i]; - sqh->qh->elink = xfer; - sqh->qh->qh_elink = xfer->physaddr; + sqh->elink = xfer; + sqh->qh.qh_elink = LE(xfer->physaddr); } } else { usb_freemem(sc->sc_dmatag, dma); @@ -1999,15 +2003,14 @@ uhci_intr_done(ii) /* Deallocate request data structures */ void -uhci_ctrl_done(ii) - uhci_intr_info_t *ii; +uhci_device_ctrl_done(reqh) + usbd_request_handle reqh; { + uhci_intr_info_t *ii = reqh->hcpriv; uhci_softc_t *sc = ii->sc; - usbd_request_handle reqh = ii->reqh; struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; u_int len = upipe->u.ctl.length; usb_dma_t *dma; - uhci_td_t *htd = ii->stdstart->td; #ifdef DIAGNOSTIC if (!reqh->isreq) @@ -2022,7 +2025,7 @@ uhci_ctrl_done(ii) dma = &upipe->u.ctl.datadma; if (reqh->request.bmRequestType & UT_READ) memcpy(reqh->buffer, KERNADDR(dma), len); - uhci_free_std_chain(sc, htd->link.std, ii->stdend); + uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend); usb_freemem(sc->sc_dmatag, dma); } DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen)); @@ -2030,11 +2033,11 @@ uhci_ctrl_done(ii) /* Deallocate request data structures */ void -uhci_bulk_done(ii) - uhci_intr_info_t *ii; +uhci_device_bulk_done(reqh) + usbd_request_handle reqh; { + uhci_intr_info_t *ii = reqh->hcpriv; uhci_softc_t *sc = ii->sc; - usbd_request_handle reqh = ii->reqh; struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; u_int datalen = upipe->u.bulk.length; usb_dma_t *dma; @@ -2061,14 +2064,14 @@ uhci_add_intr(sc, n, sqh) uhci_soft_qh_t *sqh; { struct uhci_vframe *vf = &sc->sc_vframes[n]; - uhci_qh_t *eqh; + uhci_soft_qh_t *eqh; DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", n, sqh)); - eqh = vf->eqh->qh; - sqh->qh->hlink = eqh->hlink; - sqh->qh->qh_hlink = eqh->qh_hlink; - eqh->hlink = sqh; - eqh->qh_hlink = sqh->physaddr | UHCI_PTR_Q; + eqh = vf->eqh; + sqh->hlink = eqh->hlink; + sqh->qh.qh_hlink = eqh->qh.qh_hlink; + eqh->hlink = sqh; + eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q); vf->eqh = sqh; vf->bandwidth++; } @@ -2085,17 +2088,17 @@ uhci_remove_intr(sc, n, sqh) DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", n, sqh)); - for (pqh = vf->hqh; pqh->qh->hlink != sqh; pqh = pqh->qh->hlink) + for (pqh = vf->hqh; pqh->hlink != sqh; pqh = pqh->hlink) #if defined(DIAGNOSTIC) || defined(USB_DEBUG) - if (pqh->qh->qh_hlink & UHCI_PTR_T) { + if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) { printf("uhci_remove_intr: QH not found\n"); return; } #else ; #endif - pqh->qh->hlink = sqh->qh->hlink; - pqh->qh->qh_hlink = sqh->qh->qh_hlink; + pqh->hlink = sqh->hlink; + pqh->qh.qh_hlink = sqh->qh.qh_hlink; if (vf->eqh == sqh) vf->eqh = pqh; vf->bandwidth--; @@ -2144,8 +2147,8 @@ uhci_device_setintr(sc, upipe, ival) upipe->iinfo->stdstart = 0; for(i = 0; i < npoll; i++) { upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc); - sqh->qh->elink = 0; - sqh->qh->qh_elink = UHCI_PTR_T; + sqh->elink = 0; + sqh->qh.qh_elink = LE(UHCI_PTR_T); sqh->pos = MOD(i * ival + bestoffs); sqh->intr_info = upipe->iinfo; } @@ -2658,10 +2661,9 @@ uhci_root_ctrl_start(reqh) reqh->actlen = totlen; r = USBD_NORMAL_COMPLETION; ret: - SIMPLEQ_REMOVE_HEAD(&reqh->pipe->queue, reqh, next); reqh->status = r; - reqh->xfercb(reqh); - usb_start_next(reqh->pipe); + reqh->hcpriv = 0; + usb_transfer_complete(reqh); return (USBD_IN_PROGRESS); } diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h index 29ac0b6607d..a49c9c31c3c 100644 --- a/sys/dev/usb/uhcireg.h +++ b/sys/dev/usb/uhcireg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uhcireg.h,v 1.1 1999/08/13 05:28:04 fgsch Exp $ */ -/* $NetBSD: uhcireg.h,v 1.6 1999/04/03 19:01:20 augustss Exp $ */ +/* $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 $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -116,11 +116,6 @@ typedef u_int32_t uhci_physaddr_t; #define UHCI_PTR_Q 0x00000002 #define UHCI_PTR_VF 0x00000004 -typedef union { - struct uhci_soft_qh *sqh; - struct uhci_soft_td *std; -} uhci_soft_td_qh_t; - /* * The Queue Heads and Transfer Descriptors and accessed * by both the CPU and the USB controller which runs @@ -166,10 +161,7 @@ typedef struct { #define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff) #define UHCI_TD_MAXLEN_MASK 0xffe00000 u_int32_t td_buffer; - uhci_soft_td_qh_t link; /* soft version of the td_link field */ - /* padding to 32 bytes */ } uhci_td_t; -#define UHCI_TD_SIZE 32 #define UHCI_TD_ERROR (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED) @@ -185,10 +177,6 @@ typedef struct { typedef struct { uhci_physaddr_t qh_hlink; uhci_physaddr_t qh_elink; - struct uhci_soft_qh *hlink; /* soft version of qh_hlink */ - struct uhci_soft_td *elink; /* soft version of qh_elink */ - /* padding to 32 bytes */ } uhci_qh_t; -#define UHCI_QH_SIZE 32 #endif /* _DEV_PCI_UHCIREG_H_ */ diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index d81af2589af..6e3215ba2e3 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uhcivar.h,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */ -/* $NetBSD: uhcivar.h,v 1.7 1999/06/26 08:30:18 augustss Exp $ */ +/* $OpenBSD: uhcivar.h,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */ +/* $NetBSD: uhcivar.h,v 1.12 1999/08/22 23:41:00 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -56,6 +56,11 @@ typedef struct uhci_soft_qh uhci_soft_qh_t; typedef struct uhci_soft_td uhci_soft_td_t; +typedef union { + struct uhci_soft_qh *sqh; + struct uhci_soft_td *std; +} uhci_soft_td_qh_t; + /* * An interrupt info struct contains the information needed to * execute a requested routine when the controller generates an @@ -81,28 +86,34 @@ typedef struct uhci_intr_info { * Extra information that we need for a TD. */ struct uhci_soft_td { - uhci_td_t *td; /* The real TD */ - uhci_physaddr_t physaddr; /* and its physical address. */ + uhci_td_t td; /* The real TD, must be first */ + uhci_soft_td_qh_t link; /* soft version of the td_link field */ + uhci_physaddr_t physaddr; /* TD's physical address. */ }; -#define UHCI_TD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/ +/* + * 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 + * aligned. + * NOTE: Minimum size is 32 bytes. + */ +#define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN) +#define UHCI_STD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/ /* * Extra information that we need for a QH. */ struct uhci_soft_qh { - uhci_qh_t *qh; /* The real QH */ - uhci_physaddr_t physaddr; /* and its physical address. */ + uhci_qh_t qh; /* The real QH, must be first */ + uhci_soft_qh_t *hlink; /* soft version of qh_hlink */ + uhci_soft_td_t *elink; /* soft version of qh_elink */ + uhci_physaddr_t physaddr; /* QH's physical address. */ int pos; /* Timeslot position */ uhci_intr_info_t *intr_info; /* Who to call on completion. */ +/* XXX should try to shrink with 4 bytes to fit into 32 bytes */ }; -#define UHCI_QH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/ - -/* Only used for buffer free list. */ -struct uhci_buffer { - struct uhci_buffer *next; -}; -#define UHCI_BUFFER_SIZE 64 -#define UHCI_BUFFER_CHUNK 64 /*(PAGE_SIZE / UHCI_BUFFER_SIZE)*/ +/* See comment about UHCI_STD_SIZE. */ +#define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN) +#define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/ /* * Information about an entry in the virtial frame list. @@ -137,7 +148,6 @@ typedef struct uhci_softc { uhci_soft_td_t *sc_freetds; uhci_soft_qh_t *sc_freeqhs; - struct uhci_buffer *sc_freebuffers; u_int8_t sc_addr; /* device address */ u_int8_t sc_conf; /* device configuration */ @@ -157,10 +167,6 @@ typedef struct uhci_softc { #define UHCI_HAS_LOCK 1 #define UHCI_WANT_LOCK 2 -#if defined(__NetBSD__) || defined(__OpenBSD__) - usb_dma_t *sc_mallocs; -#endif - char sc_vendor[16]; int sc_id_vendor; } uhci_softc_t; diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index c8069545114..74feaaca1d7 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhid.c,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */ -/* $NetBSD: uhid.c,v 1.18 1999/06/30 06:44:23 augustss Exp $ */ +/* $OpenBSD: uhid.c,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */ +/* $NetBSD: uhid.c,v 1.21 1999/08/23 22:55:14 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -243,6 +243,17 @@ uhid_activate(self, act) struct device *self; enum devact act; { + struct uhid_softc *sc = (struct uhid_softc *)self; + + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: + sc->sc_dying = 1; + break; + } return (0); } diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index af333fa22e4..fd80037ef55 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhub.c,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */ -/* $NetBSD: uhub.c,v 1.18 1999/06/30 06:44:23 augustss Exp $ */ +/* $OpenBSD: uhub.c,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */ +/* $NetBSD: uhub.c,v 1.23 1999/08/23 22:55:14 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -63,7 +63,6 @@ #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x extern int usbdebug; -extern char *usbd_error_strs[]; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -127,8 +126,8 @@ USB_ATTACH(uhub) r = usbd_set_config_index(dev, 0, 1); if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("%s: configuration failed, error=%d(%s)\n", - USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r])); + DPRINTF(("%s: configuration failed, error=%s\n", + USBDEVNAME(sc->sc_dev), usbd_errstr(r))); USB_ATTACH_ERROR_RETURN; } @@ -152,8 +151,8 @@ USB_ATTACH(uhub) r = usbd_do_request(dev, &req, &hubdesc); } if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("%s: getting hub descriptor failed, error=%d(%s)\n", - USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r])); + DPRINTF(("%s: getting hub descriptor failed, error=%s\n", + USBDEVNAME(sc->sc_dev), usbd_errstr(r))); USB_ATTACH_ERROR_RETURN; } @@ -328,8 +327,8 @@ uhub_explore(dev) r = usbd_get_port_status(dev, port, &up->status); if (r != USBD_NORMAL_COMPLETION) { DPRINTF(("uhub_explore: get port status failed, " - "error=%d(%s)\n", - r, usbd_error_strs[r])); + "error=%s\n", + usbd_errstr(r))); continue; } status = UGETW(up->status.wPortStatus); @@ -403,7 +402,7 @@ uhub_explore(dev) /* XXX retry a few times? */ if (r != USBD_NORMAL_COMPLETION) { DPRINTFN(-1,("uhub_explore: usb_new_device failed, " - "error=%d(%s)\n", r, usbd_error_strs[r])); + "error=%s\n", usbd_errstr(r))); /* Avoid addressing problems by disabling. */ /* usbd_reset_port(dev, port, &up->status); */ /* XXX @@ -492,6 +491,14 @@ uhub_activate(self, act) struct device *self; enum devact act; { + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: + break; + } return (0); } diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index a466a7bae82..e0a1e6ca5f2 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usb.h,v 1.2 1999/08/19 08:18:39 fgsch Exp $ */ +/* $OpenBSD: usb.h,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */ /* $NetBSD: usb.h,v 1.27 1999/08/18 07:55:19 augustss Exp $ */ /* @@ -45,9 +45,7 @@ #include <sys/types.h> #if defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/ioctl.h> -#endif -#if defined(__NetBSD__) || defined(__OpenBSD__) #if defined(_KERNEL) #include <dev/usb/usb_port.h> #endif /* _KERNEL */ @@ -223,6 +221,7 @@ typedef struct { #define UE_ADDR 0x0f #define UE_GET_ADDR(a) ((a) & UE_ADDR) #define UE_GET_IN(a) (((a) >> 7) & 1) +#define UE_GET_DIR(a) ((a) & 0x80) uByte bmAttributes; #define UE_XFERTYPE 0x03 #define UE_CONTROL 0x00 @@ -356,8 +355,10 @@ typedef struct { #define USUBCLASS_UFI 4 #define USUBCLASS_SFF8070I 5 #define USUBCLASS_SCSI 6 -#define UPROTO_MASS_CBI_C 0 -#define UPROTO_MASS_CBI_NC 1 +#define UPROTO_MASS_CBI_I 0 +#define UPROTO_MASS_CBI 1 +#define UPROTO_MASS_BULK 80 +#define UPROTO_MASS_BULK2 2 #define UCLASS_HUB 9 #define USUBCLASS_HUB 0 #define UCLASS_DATA 10 @@ -509,6 +510,7 @@ struct usb_device_stats { #define USB_DO_REQUEST _IOWR('U', 111, struct usb_ctl_request) #define USB_GET_DEVICEINFO _IOR ('U', 112, struct usb_device_info) #define USB_SET_SHORT_XFER _IOW ('U', 113, int) +#define USB_SET_TIMEOUT _IOW ('U', 114, int) /* Modem device */ #define USB_GET_CM_OVER_DATA _IOR ('U', 130, int) diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c index 805877dcbae..fee0b823a82 100644 --- a/sys/dev/usb/usb_mem.c +++ b/sys/dev/usb/usb_mem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_mem.c,v 1.3 1999/08/19 08:18:39 fgsch Exp $ */ +/* $OpenBSD: usb_mem.c,v 1.4 1999/08/27 09:00:29 fgsch Exp $ */ /* $NetBSD: usb_mem.c,v 1.9 1999/08/16 20:19:55 augustss Exp $ */ /* @@ -64,7 +64,7 @@ #ifdef USB_DEBUG #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x -extern int usbdebug; +int usbdebug; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -83,12 +83,14 @@ struct usb_frag_dma { usbd_status usb_block_allocmem __P((bus_dma_tag_t, size_t, size_t, usb_dma_block_t **)); +#if 0 void usb_block_real_freemem __P((usb_dma_block_t *)); +#endif void usb_block_freemem __P((usb_dma_block_t *)); -LIST_HEAD(, usb_block_dma) usb_blk_freelist = +LIST_HEAD(, usb_dma_block) usb_blk_freelist = LIST_HEAD_INITIALIZER(usb_blk_freelist); -/* XXX should have different free list for different tags */ +/* XXX should have different free list for different tags (for speed) */ LIST_HEAD(, usb_frag_dma) usb_frag_freelist = LIST_HEAD_INITIALIZER(usb_frag_freelist); @@ -107,8 +109,8 @@ usb_block_allocmem(tag, size, align, dmap) #ifdef DIAGNOSTIC if (!curproc) { - printf("usb_block_allocmem: in interrupt context, size=%u\n", - size); + printf("usb_block_allocmem: in interrupt context, size=%lu\n", + (unsigned long) size); } #endif @@ -173,6 +175,7 @@ free: return (USBD_NOMEM); } +#if 0 void usb_block_real_freemem(p) usb_dma_block_t *p; @@ -189,6 +192,7 @@ usb_block_real_freemem(p) bus_dmamem_free(p->tag, p->segs, p->nsegs); free(p, M_USB); } +#endif /* * Do not free the memory unconditionally since we might be called diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h index 041127807bb..9c5ae8f435c 100644 --- a/sys/dev/usb/usb_mem.h +++ b/sys/dev/usb/usb_mem.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_mem.h,v 1.1 1999/08/13 05:28:04 fgsch Exp $ */ +/* $OpenBSD: usb_mem.h,v 1.2 1999/08/27 09:00:30 fgsch Exp $ */ /* $NetBSD: usb_mem.h,v 1.4 1999/01/09 12:16:54 augustss Exp $ */ /* @@ -39,7 +39,7 @@ */ #if defined(__NetBSD__) || defined(__OpenBSD__) -typedef struct usb_block_dma { +typedef struct usb_dma_block { bus_dma_tag_t tag; bus_dmamap_t map; caddr_t kaddr; @@ -48,11 +48,11 @@ typedef struct usb_block_dma { size_t size; size_t align; int fullblock; - LIST_ENTRY(usb_block_dma) next; + LIST_ENTRY(usb_dma_block) next; } usb_dma_block_t; typedef struct { - usb_dma_block_t *block; + struct usb_dma_block *block; u_int offs; } usb_dma_t; diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index a26022ee9ad..981663dd903 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_subr.c,v 1.3 1999/08/19 08:18:39 fgsch Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.4 1999/08/27 09:00:30 fgsch Exp $ */ /* $NetBSD: usb_subr.c,v 1.38 1999/08/17 20:59:04 augustss Exp $ */ /* @@ -131,6 +131,33 @@ char *usbd_error_strs[] = { }; #endif +char * +usbd_errstr(err) + usbd_status err; +{ + static char buffer[5]; + +#ifdef USB_DEBUG + if ( err < USBD_ERROR_MAX ) { + return usbd_error_strs[err]; + } else { +#if !defined(__OpenBSD__) + snprintf(buffer, sizeof buffer, "%d", err); +#else + sprintf(buffer, "%d", err); +#endif /* !defined(__OpenBSD__) */ + return buffer; + } +#else +#if !defined(__OpenBSD__) + snprintf(buffer, sizeof buffer, "%d", err); +#else + sprintf(buffer, "%d", err); +#endif /* !defined(__OpenBSD__) */ + return buffer; +#endif +} + usbd_status usbd_get_string_desc(dev, sindex, langid, sdesc) usbd_device_handle dev; @@ -313,8 +340,8 @@ usbd_reset_port(dev, port, ps) USETW(req.wIndex, port); USETW(req.wLength, 0); r = usbd_do_request(dev, &req, 0); - DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n", - port, r, usbd_error_strs[r])); + DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n", + port, usbd_errstr(r))); if (r != USBD_NORMAL_COMPLETION) return (r); n = 10; @@ -574,8 +601,8 @@ usbd_set_config_index(dev, index, msg) (UGETW(ds.wStatus) & UDS_SELF_POWERED)) selfpowered = 1; DPRINTF(("usbd_set_config_index: status=0x%04x, " - "error=%d(%s)\n", - UGETW(ds.wStatus), r, usbd_error_strs[r])); + "error=%s\n", + UGETW(ds.wStatus), usbd_errstr(r))); } else selfpowered = 1; } @@ -609,8 +636,8 @@ usbd_set_config_index(dev, index, msg) r = usbd_set_config(dev, cdp->bConfigurationValue); if (r != USBD_NORMAL_COMPLETION) { DPRINTF(("usbd_set_config_index: setting config=%d failed, " - "error=%d(%s)\n", - cdp->bConfigurationValue, r, usbd_error_strs[r])); + "error=%s\n", + cdp->bConfigurationValue, usbd_errstr(r))); goto bad; } DPRINTF(("usbd_set_config_index: setting new config %d\n", @@ -669,9 +696,9 @@ usbd_setup_pipe(dev, iface, ep, pipe) SIMPLEQ_INIT(&p->queue); r = dev->bus->open_pipe(p); if (r != USBD_NORMAL_COMPLETION) { - DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=%d" - "(%s)\n", - ep->edesc->bEndpointAddress, r, usbd_error_strs[r])); + DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" + "%s\n", + ep->edesc->bEndpointAddress, usbd_errstr(r))); free(p, M_USB); return (r); } @@ -764,8 +791,8 @@ usbd_probe_and_attach(parent, dev, port, addr) if (r != USBD_NORMAL_COMPLETION) { #ifdef USB_DEBUG DPRINTF(("%s: port %d, set config at addr %d failed, " - "error=%d(%s)\n", USBDEVNAME(*parent), port, - addr, r, usbd_error_strs[r])); + "error=%s\n", USBDEVNAME(*parent), port, + addr, usbd_errstr(r))); #else printf("%s: port %d, set config at addr %d failed\n", USBDEVNAME(*parent), port, addr); @@ -926,6 +953,12 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) return (r); } + DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " + "subclass=%d, protocol=%d, maxpacket=%d, len=%d, ls=%d\n", + addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, + dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, + dev->lowspeed)); + if (dd->bDescriptorType != UDESC_DEVICE) { /* Illegal device descriptor */ DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n", @@ -934,10 +967,11 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) return (USBD_INVAL); } - DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " - "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n", - addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, - dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed)); + if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) { + DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength)); + usbd_remove_device(dev, up); + return (USBD_INVAL); + } USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); @@ -1086,54 +1120,6 @@ usbd_bus_print_child(device_t bus, device_t dev) } #endif -usbd_status -usb_insert_transfer(reqh) - usbd_request_handle reqh; -{ - usbd_pipe_handle pipe = reqh->pipe; - - SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next); - if (pipe->running) - return (USBD_IN_PROGRESS); - pipe->running = 1; - return (USBD_NORMAL_COMPLETION); -} - -void -usb_start_next(pipe) - usbd_pipe_handle pipe; -{ - usbd_request_handle reqh; - usbd_status r; - - DPRINTFN(10, ("usb_start_next: pipe=%p\n", pipe)); - -#ifdef DIAGNOSTIC - if (!pipe) { - printf("usb_start_next: pipe == 0\n"); - return; - } - if (!pipe->methods || !pipe->methods->start) { - printf("usb_start_next: no start method\n"); - return; - } -#endif - - /* Get next request in queue. */ - reqh = SIMPLEQ_FIRST(&pipe->queue); - DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh)); - if (!reqh) - pipe->running = 0; - else { - r = pipe->methods->start(reqh); - if (r != USBD_IN_PROGRESS) { - printf("usb_start_next: error=%d\n", r); - pipe->running = 0; - /* XXX do what? */ - } - } -} - void usbd_fill_deviceinfo(dev, di) usbd_device_handle dev; diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 48708c75cd6..319c555f52a 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi.c,v 1.3 1999/08/19 08:18:39 fgsch Exp $ */ -/* $NetBSD: usbdi.c,v 1.30 1999/08/17 20:59:04 augustss Exp $ */ +/* $OpenBSD: usbdi.c,v 1.4 1999/08/27 09:00:30 fgsch Exp $ */ +/* $NetBSD: usbdi.c,v 1.32 1999/08/23 22:55:14 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -71,11 +71,9 @@ extern int usbdebug; #endif static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe)); -static void usbd_transfer_cb __P((usbd_request_handle reqh)); -static void usbd_sync_transfer_cb __P((usbd_request_handle reqh)); -static usbd_status usbd_do_transfer __P((usbd_request_handle reqh)); void usbd_do_request_async_cb __P((usbd_request_handle, usbd_private_handle, usbd_status)); +void usbd_start_next __P((usbd_pipe_handle pipe)); static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests; @@ -229,27 +227,46 @@ usbd_close_pipe(pipe) return (USBD_NORMAL_COMPLETION); } -usbd_status +usbd_status usbd_transfer(reqh) usbd_request_handle reqh; { - reqh->xfercb = usbd_transfer_cb; - return (usbd_do_transfer(reqh)); -} - -static usbd_status -usbd_do_transfer(reqh) - usbd_request_handle reqh; -{ usbd_pipe_handle pipe = reqh->pipe; + usbd_status r; + int s; - DPRINTFN(5,("usbd_do_transfer: reqh=%p\n", reqh)); + DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n", + reqh, reqh->flags, pipe, pipe->running)); #ifdef USB_DEBUG if (usbdebug > 5) usbd_dump_queue(pipe); #endif reqh->done = 0; - return (pipe->methods->transfer(reqh)); + + r = pipe->methods->transfer(reqh); + if (!(reqh->flags & USBD_SYNCHRONOUS)) + return r; + + /* Sync transfer, wait for completion. */ + if (r != USBD_IN_PROGRESS) + return (r); + s = splusb(); + if (!reqh->done) { + if (reqh->pipe->device->bus->use_polling) + panic("usbd_transfer: not done\n"); + tsleep(reqh, PRIBIO, "usbsyn", 0); + } + splx(s); + return (reqh->status); +} + +/* Like usbd_transfer(), but waits for completion. */ +usbd_status +usbd_sync_transfer(reqh) + usbd_request_handle reqh; +{ + reqh->flags |= USBD_SYNCHRONOUS; + return (usbd_transfer(reqh)); } usbd_request_handle @@ -300,7 +317,6 @@ usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback) reqh->timeout = timeout; reqh->status = USBD_NOT_STARTED; reqh->callback = callback; - reqh->retries = 1; reqh->isreq = 0; return (USBD_NORMAL_COMPLETION); } @@ -330,12 +346,11 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer, reqh->status = USBD_NOT_STARTED; reqh->callback = callback; reqh->request = *req; - reqh->retries = 1; reqh->isreq = 1; return (USBD_NORMAL_COMPLETION); } -usbd_status +void usbd_get_request_status(reqh, priv, buffer, count, status) usbd_request_handle reqh; usbd_private_handle *priv; @@ -343,11 +358,14 @@ usbd_get_request_status(reqh, priv, buffer, count, status) u_int32_t *count; usbd_status *status; { - *priv = reqh->priv; - *buffer = reqh->buffer; - *count = reqh->actlen; - *status = reqh->status; - return (USBD_NORMAL_COMPLETION); + if (priv) + *priv = reqh->priv; + if (buffer) + *buffer = reqh->buffer; + if (count) + *count = reqh->actlen; + if (status) + *status = reqh->status; } usb_config_descriptor_t * @@ -601,23 +619,37 @@ usbd_init() } } -static void -usbd_transfer_cb(reqh) +void +usb_transfer_complete(reqh) usbd_request_handle reqh; { usbd_pipe_handle pipe = reqh->pipe; + int polling; + + DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p actlen=%d\n", + pipe, reqh, reqh->actlen)); - DPRINTFN(10, ("usbd_transfer_cb: reqh=%p\n", reqh)); - /* Count completed transfers. */ #ifdef DIAGNOSTIC - if (!pipe) + if (!pipe) { printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh); - else + return; + } #endif + polling = reqh->pipe->device->bus->use_polling; + /* XXXX */ + if (polling) + pipe->running = 0; + + if (reqh->pipe->methods->done) + reqh->pipe->methods->done(reqh); + + /* Remove request from queue. */ + SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next); + + /* Count completed transfers. */ ++pipe->device->bus->stats.requests [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; - /* XXX check retry count */ reqh->done = 1; if (reqh->status == USBD_NORMAL_COMPLETION && reqh->actlen < reqh->length && @@ -626,40 +658,66 @@ usbd_transfer_cb(reqh) reqh->actlen, reqh->length)); reqh->status = USBD_SHORT_XFER; } + if (reqh->callback) reqh->callback(reqh, reqh->priv, reqh->status); -} -static void -usbd_sync_transfer_cb(reqh) - usbd_request_handle reqh; -{ - DPRINTFN(10, ("usbd_sync_transfer_cb: reqh=%p\n", reqh)); - usbd_transfer_cb(reqh); - if (!reqh->pipe->device->bus->use_polling) + if ((reqh->flags & USBD_SYNCHRONOUS) && !polling) wakeup(reqh); + + if (!pipe->repeat && + reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT) + usbd_start_next(pipe); } -/* Like usbd_transfer(), but waits for completion. */ usbd_status -usbd_sync_transfer(reqh) +usb_insert_transfer(reqh) usbd_request_handle reqh; { + usbd_pipe_handle pipe = reqh->pipe; + + DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe, + pipe->running)); + SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next); + if (pipe->running) + return (USBD_IN_PROGRESS); + pipe->running = 1; + return (USBD_NORMAL_COMPLETION); +} + +void +usbd_start_next(pipe) + usbd_pipe_handle pipe; +{ + usbd_request_handle reqh; usbd_status r; - int s; - reqh->xfercb = usbd_sync_transfer_cb; - r = usbd_do_transfer(reqh); - if (r != USBD_IN_PROGRESS) - return (r); - s = splusb(); - if (!reqh->done) { - if (reqh->pipe->device->bus->use_polling) - panic("usbd_sync_transfer: not done\n"); - tsleep(reqh, PRIBIO, "usbsyn", 0); + DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe)); + +#ifdef DIAGNOSTIC + if (!pipe) { + printf("usbd_start_next: pipe == 0\n"); + return; + } + if (!pipe->methods || !pipe->methods->start) { + printf("usbd_start_next: no start method\n"); + 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) + pipe->running = 0; + else { + r = pipe->methods->start(reqh); + if (r != USBD_IN_PROGRESS) { + printf("usbd_start_next: error=%d\n", r); + pipe->running = 0; + /* XXX do what? */ + } } - splx(s); - return (reqh->status); } usbd_status diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 335c019eab0..b169b4fccfa 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi.h,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */ +/* $OpenBSD: usbdi.h,v 1.3 1999/08/27 09:00:30 fgsch Exp $ */ /* $NetBSD: usbdi.h,v 1.20 1999/06/30 06:44:23 augustss Exp $ */ /* @@ -46,7 +46,7 @@ typedef struct usbd_request *usbd_request_handle; typedef void *usbd_private_handle; typedef enum { - USBD_NORMAL_COMPLETION = 0, + USBD_NORMAL_COMPLETION = 0, /* must be 0 */ USBD_IN_PROGRESS, /* errors */ USBD_PENDING_REQUESTS, @@ -68,6 +68,8 @@ typedef enum { USBD_INTERRUPTED, USBD_XXX, + + USBD_ERROR_MAX, /* must be last */ } usbd_status; typedef int usbd_lock_token; @@ -81,7 +83,8 @@ typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle, /* Request flags */ #define USBD_XFER_OUT 0x01 #define USBD_XFER_IN 0x02 -#define USBD_SHORT_XFER_OK 0x04 +#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ +#define USBD_SYNCHRONOUS 0x08 /* wait for completion */ #define USBD_NO_TIMEOUT 0 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */ @@ -103,7 +106,7 @@ usbd_status usbd_setup_default_request 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)); -usbd_status usbd_get_request_status +void usbd_get_request_status __P((usbd_request_handle reqh, usbd_private_handle *priv, void **buffer, u_int32_t *count, usbd_status *status)); usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor @@ -161,6 +164,8 @@ usb_endpoint_descriptor_t *usbd_find_edesc void usbd_dopoll __P((usbd_interface_handle)); void usbd_set_polling __P((usbd_interface_handle iface, int on)); +char *usbd_errstr __P((usbd_status err)); + /* NetBSD attachment information */ /* Attach data */ diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c index 8ed127df125..688c1c48f89 100644 --- a/sys/dev/usb/usbdi_util.c +++ b/sys/dev/usb/usbdi_util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi_util.c,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */ +/* $OpenBSD: usbdi_util.c,v 1.3 1999/08/27 09:00:30 fgsch Exp $ */ /* $NetBSD: usbdi_util.c,v 1.16 1999/08/07 23:14:17 augustss Exp $ */ /* @@ -501,21 +501,20 @@ usbd_bulk_transfer_cb(reqh, priv, status) } usbd_status -usbd_bulk_transfer(reqh, pipe, flags, buf, size, lbl) +usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl) usbd_request_handle reqh; usbd_pipe_handle pipe; u_int16_t flags; + u_int32_t timeout; void *buf; u_int32_t *size; char *lbl; { - usbd_private_handle priv; - void *buffer; usbd_status r; int s, error; r = usbd_setup_request(reqh, pipe, 0, buf, *size, - flags, USBD_NO_TIMEOUT, usbd_bulk_transfer_cb); + flags, timeout, usbd_bulk_transfer_cb); if (r != USBD_NORMAL_COMPLETION) return (r); DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size)); @@ -532,7 +531,7 @@ usbd_bulk_transfer(reqh, pipe, flags, buf, size, lbl) usbd_abort_pipe(pipe); return (USBD_INTERRUPTED); } - usbd_get_request_status(reqh, &priv, &buffer, size, &r); + usbd_get_request_status(reqh, 0, 0, size, &r); DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size)); if (r != USBD_NORMAL_COMPLETION) { DPRINTF(("usbd_bulk_transfer: error=%d\n", r)); diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h index 9146a9365d3..f77b789d522 100644 --- a/sys/dev/usb/usbdi_util.h +++ b/sys/dev/usb/usbdi_util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi_util.h,v 1.1 1999/08/13 05:28:05 fgsch Exp $ */ +/* $OpenBSD: usbdi_util.h,v 1.2 1999/08/27 09:00:30 fgsch Exp $ */ /* $NetBSD: usbdi_util.h,v 1.14 1999/08/07 23:14:17 augustss Exp $ */ /* @@ -91,7 +91,7 @@ usbd_status usbd_set_config_index usbd_status usbd_bulk_transfer __P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags, - void *buf, u_int32_t *size, char *lbl)); + u_int32_t timeout, void *buf, u_int32_t *size, char *lbl)); void usb_detach_wait __P((bdevice *)); void usb_detach_wakeup __P((bdevice *)); diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index 2ccaa846f54..a40975d1420 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdivar.h,v 1.2 1999/08/19 08:18:39 fgsch Exp $ */ +/* $OpenBSD: usbdivar.h,v 1.3 1999/08/27 09:00:30 fgsch Exp $ */ /* $NetBSD: usbdivar.h,v 1.24 1999/08/17 20:59:04 augustss Exp $ */ /* @@ -46,14 +46,13 @@ struct usbd_endpoint { int refcnt; }; -typedef void (*usbd_xfercb)__P((usbd_request_handle req)); - struct usbd_methods { usbd_status (*transfer)__P((usbd_request_handle reqh)); usbd_status (*start)__P((usbd_request_handle reqh)); void (*abort)__P((usbd_request_handle reqh)); void (*close)__P((usbd_pipe_handle pipe)); void (*cleartoggle)__P((usbd_pipe_handle pipe)); + void (*done)__P((usbd_request_handle reqh)); usbd_status (*isobuf)__P((usbd_pipe_handle pipe, u_int32_t bufsize,u_int32_t nbuf)); }; @@ -152,12 +151,10 @@ struct usbd_request { u_int32_t timeout; usbd_status status; usbd_callback callback; - usbd_xfercb xfercb; - u_int32_t retries; char done; usb_device_request_t request; - u_int8_t isreq; + char isreq; SIMPLEQ_ENTRY(usbd_request) next; @@ -187,12 +184,13 @@ usbd_status usbd_new_device __P((bdevice *parent, void usbd_remove_device __P((usbd_device_handle, struct usbd_port *)); int usbd_printBCD __P((char *cp, int bcd)); -usbd_status usb_insert_transfer __P((usbd_request_handle reqh)); -void usb_start_next __P((usbd_pipe_handle pipe)); 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)); + /* Routines from usb.c */ int usb_bus_count __P((void)); void usb_needs_explore __P((usbd_bus_handle)); |