diff options
Diffstat (limited to 'sys/dev/usb/uhci.c')
-rw-r--r-- | sys/dev/usb/uhci.c | 1138 |
1 files changed, 642 insertions, 496 deletions
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index ba8b15e..db8726a 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.49 1999/09/11 08:19:26 augustss Exp $ */ +/* $NetBSD: uhci.c,v 1.63 1999/11/12 00:34:57 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -58,13 +58,14 @@ #elif defined(__FreeBSD__) #include <sys/module.h> #include <sys/bus.h> +#include <machine/bus_pio.h> +#if defined(DIAGNOSTIC) && defined(__i386__) +#include <machine/cpu.h> +#endif #endif #include <sys/proc.h> #include <sys/queue.h> -#if defined(__FreeBSD__) -#include <machine/bus_pio.h> -#endif #include <machine/bus.h> #include <machine/endian.h> @@ -83,6 +84,14 @@ #define delay(d) DELAY(d) #endif +#define MS_TO_TICKS(ms) ((ms) * hz / 1000) + +#if defined(__OpenBSD__) +struct cfdriver uhci_cd = { + NULL, "uhci", DV_DULL +}; +#endif + #ifdef UHCI_DEBUG #define DPRINTF(x) if (uhcidebug) printf x #define DPRINTFN(n,x) if (uhcidebug>(n)) printf x @@ -92,15 +101,6 @@ int uhcidebug = 0; #define DPRINTFN(n,x) #endif - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#if defined(__OpenBSD__) -struct cfdriver uhci_cd = { - NULL, "uhci", DV_DULL -}; -#endif - /* * The UHCI controller is little endian, so on big endian machines * the data strored in memory needs to be swapped. @@ -149,104 +149,108 @@ struct uhci_pipe { */ LIST_HEAD(, uhci_intr_info) uhci_ii_free; -void uhci_busreset __P((uhci_softc_t *)); -void uhci_power __P((int, void *)); -usbd_status uhci_run __P((uhci_softc_t *, int run)); -uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *)); -void uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *)); -uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *)); -void uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *)); -uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *)); -void uhci_free_intr_info __P((uhci_intr_info_t *ii)); +static void uhci_busreset __P((uhci_softc_t *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) +static void uhci_power __P((int, void *)); +#endif +static usbd_status uhci_run __P((uhci_softc_t *, int run)); +static uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *)); +static void uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *)); +static uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *)); +static void uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *)); +static uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *)); +static void uhci_free_intr_info __P((uhci_intr_info_t *ii)); #if 0 -void uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *, - uhci_intr_info_t *)); -void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *)); +static void uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *, + uhci_intr_info_t *)); +static void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *)); #endif -void uhci_free_std_chain __P((uhci_softc_t *, - uhci_soft_td_t *, uhci_soft_td_t *)); -usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *, - int, int, int, usb_dma_t *, - uhci_soft_td_t **, - uhci_soft_td_t **)); -void uhci_timo __P((void *)); -void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle)); -void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *)); -void uhci_idone __P((uhci_intr_info_t *)); -void uhci_abort_req __P((usbd_request_handle, usbd_status status)); -void uhci_abort_req_end __P((void *v)); -void uhci_timeout __P((void *)); -void uhci_wakeup_ctrl __P((void *, int, int, void *, int)); -void uhci_lock_frames __P((uhci_softc_t *)); -void uhci_unlock_frames __P((uhci_softc_t *)); -void uhci_add_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *)); -void uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *)); -void uhci_remove_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *)); -void uhci_remove_bulk __P((uhci_softc_t *, uhci_soft_qh_t *)); -int uhci_str __P((usb_string_descriptor_t *, int, char *)); -usbd_status uhci_setup_isoc __P((usbd_pipe_handle pipe)); -void uhci_device_isoc_enter __P((usbd_request_handle)); - -void uhci_wakeup_cb __P((usbd_request_handle reqh)); - -usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t)); -void uhci_freem __P((struct usbd_bus *, usb_dma_t *)); - -usbd_status uhci_device_ctrl_transfer __P((usbd_request_handle)); -usbd_status uhci_device_ctrl_start __P((usbd_request_handle)); -void uhci_device_ctrl_abort __P((usbd_request_handle)); -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_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_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_device_clear_toggle __P((usbd_pipe_handle pipe)); -void uhci_noop __P((usbd_pipe_handle pipe)); +static void uhci_free_std_chain __P((uhci_softc_t *, + uhci_soft_td_t *, uhci_soft_td_t *)); +static usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, + uhci_softc_t *, int, int, int, usb_dma_t *, + uhci_soft_td_t **, uhci_soft_td_t **)); +static void uhci_timo __P((void *)); +static void uhci_waitintr __P((uhci_softc_t *, + usbd_xfer_handle)); +static void uhci_check_intr __P((uhci_softc_t *, + uhci_intr_info_t *)); +static void uhci_idone __P((uhci_intr_info_t *)); +static void uhci_abort_req __P((usbd_xfer_handle, + usbd_status status)); +static void uhci_abort_req_end __P((void *v)); +static void uhci_timeout __P((void *)); +static void uhci_lock_frames __P((uhci_softc_t *)); +static void uhci_unlock_frames __P((uhci_softc_t *)); +static void uhci_add_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *)); +static void uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *)); +static void uhci_remove_ctrl __P((uhci_softc_t *,uhci_soft_qh_t *)); +static void uhci_remove_bulk __P((uhci_softc_t *,uhci_soft_qh_t *)); +static int uhci_str __P((usb_string_descriptor_t *, int, char *)); +static usbd_status uhci_setup_isoc __P((usbd_pipe_handle pipe)); +static void uhci_device_isoc_enter __P((usbd_xfer_handle)); + +static usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *, + u_int32_t)); +static void uhci_freem __P((struct usbd_bus *, usb_dma_t *)); + +static usbd_status uhci_device_ctrl_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_ctrl_start __P((usbd_xfer_handle)); +static void uhci_device_ctrl_abort __P((usbd_xfer_handle)); +static void uhci_device_ctrl_close __P((usbd_pipe_handle)); +static void uhci_device_ctrl_done __P((usbd_xfer_handle)); + +static usbd_status uhci_device_intr_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_intr_start __P((usbd_xfer_handle)); +static void uhci_device_intr_abort __P((usbd_xfer_handle)); +static void uhci_device_intr_close __P((usbd_pipe_handle)); +static void uhci_device_intr_done __P((usbd_xfer_handle)); + +static usbd_status uhci_device_bulk_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_bulk_start __P((usbd_xfer_handle)); +static void uhci_device_bulk_abort __P((usbd_xfer_handle)); +static void uhci_device_bulk_close __P((usbd_pipe_handle)); +static void uhci_device_bulk_done __P((usbd_xfer_handle)); + +static usbd_status uhci_device_isoc_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_isoc_start __P((usbd_xfer_handle)); +static void uhci_device_isoc_abort __P((usbd_xfer_handle)); +static void uhci_device_isoc_close __P((usbd_pipe_handle)); +static void uhci_device_isoc_done __P((usbd_xfer_handle)); + +static usbd_status uhci_root_ctrl_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_root_ctrl_start __P((usbd_xfer_handle)); +static void uhci_root_ctrl_abort __P((usbd_xfer_handle)); +static void uhci_root_ctrl_close __P((usbd_pipe_handle)); + +static usbd_status uhci_root_intr_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_root_intr_start __P((usbd_xfer_handle)); +static void uhci_root_intr_abort __P((usbd_xfer_handle)); +static void uhci_root_intr_close __P((usbd_pipe_handle)); +static void uhci_root_intr_done __P((usbd_xfer_handle)); + +static usbd_status uhci_open __P((usbd_pipe_handle)); +static void uhci_poll __P((struct usbd_bus *)); + +static usbd_status uhci_device_request __P((usbd_xfer_handle xfer)); + +static void uhci_add_intr __P((uhci_softc_t *, int, + uhci_soft_qh_t *)); +static void uhci_remove_intr __P((uhci_softc_t *, int, + uhci_soft_qh_t *)); +static usbd_status uhci_device_setintr __P((uhci_softc_t *sc, + struct uhci_pipe *pipe, int ival)); + +static void uhci_device_clear_toggle __P((usbd_pipe_handle pipe)); +static void uhci_noop __P((usbd_pipe_handle pipe)); #ifdef UHCI_DEBUG -static void uhci_dumpregs __P((uhci_softc_t *)); -void uhci_dump_tds __P((uhci_soft_td_t *)); -void uhci_dump_qh __P((uhci_soft_qh_t *)); -void uhci_dump __P((void)); -void uhci_dump_td __P((uhci_soft_td_t *)); +static void uhci_dumpregs __P((uhci_softc_t *)); +static void uhci_dump_qhs __P((uhci_soft_qh_t *)); +static void uhci_dump_qh __P((uhci_soft_qh_t *)); +static void uhci_dump_tds __P((uhci_soft_td_t *)); +static void uhci_dump_td __P((uhci_soft_td_t *)); #endif #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) @@ -338,7 +342,7 @@ usbd_status uhci_init(sc) uhci_softc_t *sc; { - usbd_status r; + usbd_status err; int i, j; uhci_soft_qh_t *csqh, *bsqh, *sqh; uhci_soft_td_t *std; @@ -356,18 +360,18 @@ uhci_init(sc) uhci_busreset(sc); /* Allocate and initialize real frame array. */ - r = usb_allocmem(sc->sc_dmatag, - UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), - UHCI_FRAMELIST_ALIGN, &sc->sc_dma); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_allocmem(&sc->sc_bus, + UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), + UHCI_FRAMELIST_ALIGN, &sc->sc_dma); + if (err) + return (err); sc->sc_pframes = KERNADDR(&sc->sc_dma); UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */ UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/ /* Allocate the dummy QH where bulk traffic will be queued. */ bsqh = uhci_alloc_sqh(sc); - if (!bsqh) + if (bsqh == NULL) return (USBD_NOMEM); bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */ bsqh->qh.qh_elink = LE(UHCI_PTR_T); @@ -375,7 +379,7 @@ uhci_init(sc) /* Allocate the dummy QH where control traffic will be queued. */ csqh = uhci_alloc_sqh(sc); - if (!csqh) + if (csqh == NULL) return (USBD_NOMEM); csqh->hlink = bsqh; csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q); @@ -390,7 +394,7 @@ uhci_init(sc) for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = uhci_alloc_std(sc); sqh = uhci_alloc_sqh(sc); - if (!std || !sqh) + if (std == NULL || sqh == NULL) return (USBD_NOMEM); std->link.sqh = sqh; std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q); @@ -417,10 +421,8 @@ uhci_init(sc) sc->sc_bus.methods = &uhci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct uhci_pipe); -#if defined(__NetBSD__) sc->sc_suspend = PWR_RESUME; - powerhook_establish(uhci_power, sc); -#endif + sc->sc_powerhook = powerhook_establish(uhci_power, sc); DPRINTFN(1,("uhci_init: enabling\n")); UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | @@ -429,17 +431,56 @@ uhci_init(sc) return (uhci_run(sc, 1)); /* and here we go... */ } +#if defined(__NetBSD__) || defined(__OpenBSD__) +int +uhci_activate(self, act) + device_ptr_t self; + enum devact act; +{ + struct uhci_softc *sc = (struct uhci_softc *)self; + int rv = 0; + + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: + if (sc->sc_child != NULL) + rv = config_deactivate(sc->sc_child); + break; + } + return (rv); +} + +int +uhci_detach(sc, flags) + struct uhci_softc *sc; + int flags; +{ + int rv = 0; + + if (sc->sc_child != NULL) + rv = config_detach(sc->sc_child, flags); + + if (rv != 0) + return (rv); + + powerhook_disestablish(sc->sc_powerhook); + /* free data structures XXX */ + + return (rv); +} +#endif + usbd_status uhci_allocm(bus, dma, size) struct usbd_bus *bus; usb_dma_t *dma; u_int32_t size; { -#if defined(__NetBSD__) || defined(__OpenBSD__) - struct uhci_softc *sc = (struct uhci_softc *)bus; -#endif - - return (usb_allocmem(sc->sc_dmatag, size, 0, dma)); + return (usb_allocmem(&((struct uhci_softc *)bus)->sc_bus, size, 0, + dma)); } void @@ -447,11 +488,7 @@ uhci_freem(bus, dma) struct usbd_bus *bus; usb_dma_t *dma; { -#if defined(__NetBSD__) || defined(__OpenBSD__) - struct uhci_softc *sc = (struct uhci_softc *)bus; -#endif - - usb_freemem(sc->sc_dmatag, dma); + usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma); } #if defined(__NetBSD__) @@ -485,11 +522,12 @@ 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; + sc->sc_bus.use_polling++; uhci_run(sc, 0); /* stop the controller */ UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); sc->sc_suspend = why; + sc->sc_bus.use_polling--; DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); } else { /* @@ -497,6 +535,11 @@ uhci_power(why, v) * controller registers have been lost and BIOS has * not restored them. */ +#ifdef DIAGNOSTIC + if (sc->sc_suspend == PWR_RESUME) + printf("uhci_power: weird, resume without suspend.\n"); +#endif + sc->sc_bus.use_polling++; sc->sc_suspend = why; if (cmd & UHCI_CMD_RS) uhci_run(sc, 0); /* in case BIOS has started it */ @@ -507,7 +550,7 @@ uhci_power(why, v) UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */ uhci_run(sc, 1); /* and start traffic again */ usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_bus.use_polling = 0; + sc->sc_bus.use_polling--; if (sc->sc_has_timo) usb_timeout(uhci_timo, sc->sc_has_timo, sc->sc_ival, sc->sc_has_timo->timo_handle); @@ -518,7 +561,7 @@ uhci_power(why, v) } splx(s); } -#endif /* !defined(__OpenBSD__) */ +#endif /* defined(__NetBSD__) */ #ifdef UHCI_DEBUG static void @@ -566,11 +609,11 @@ uhci_dump_td(p) } void -uhci_dump_qh(p) - uhci_soft_qh_t *p; +uhci_dump_qh(sqh) + uhci_soft_qh_t *sqh; { - DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", p, - (int)p->physaddr, LE(p->qh.qh_hlink), LE(p->qh.qh_elink))); + DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh, + (int)sqh->physaddr, LE(sqh->qh.qh_hlink), LE(sqh->qh.qh_elink))); } @@ -581,20 +624,63 @@ uhci_dump() uhci_softc_t *sc = uhci; uhci_dumpregs(sc); - printf("intrs=%d\n", sc->sc_intrs); + printf("intrs=%d\n", sc->sc_bus.no_intrs); printf("framelist[i].link = %08x\n", sc->sc_framelist[0].link); uhci_dump_qh(sc->sc_ctl_start->qh.hlink); } #endif + +void +uhci_dump_qhs(sqh) + uhci_soft_qh_t *sqh; +{ + uhci_dump_qh(sqh); + + /* uhci_dump_qhs displays all the QHs and TDs from the given QH onwards + * Traverses sideways first, then down. + * + * QH1 + * QH2 + * No QH + * TD2.1 + * TD2.2 + * TD1.1 + * etc. + * + * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1. + */ + + + if (sqh->hlink != NULL && !(sqh->qh.qh_hlink & UHCI_PTR_T)) + uhci_dump_qhs(sqh->hlink); + else + DPRINTF(("No QH\n")); + + if (sqh->elink != NULL && !(sqh->qh.qh_elink & UHCI_PTR_T)) + uhci_dump_tds(sqh->elink); + else + DPRINTF(("No TD\n")); +} + void uhci_dump_tds(std) uhci_soft_td_t *std; { - uhci_soft_td_t *p; + uhci_soft_td_t *td; + + for(td = std; td != NULL; td = td->link.std) { + uhci_dump_td(td); - for(p = std; p; p = p->link.std) - uhci_dump_td(p); + /* Check whether the link pointer in this TD marks + * the link pointer as end of queue. This avoids + * printing the free list in case the queue/TD has + * already been moved there (seatbelt). + */ + if (td->td.td_link & UHCI_PTR_T || + td->td.td_link == 0) + break; + } } #endif @@ -606,17 +692,17 @@ void uhci_timo(addr) void *addr; { - usbd_request_handle reqh = addr; - usbd_pipe_handle pipe = reqh->pipe; + usbd_xfer_handle xfer = addr; + usbd_pipe_handle pipe = xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; int s; u_char *p; - DPRINTFN(15, ("uhci_timo\n")); + DPRINTFN(20, ("uhci_timo\n")); - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); + usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle); - p = KERNADDR(&reqh->dmabuf); + p = KERNADDR(&xfer->dmabuf); p[0] = 0; if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) p[0] |= 1<<1; @@ -626,17 +712,19 @@ uhci_timo(addr) /* No change, try again in a while */ return; - reqh->actlen = 1; - reqh->status = USBD_NORMAL_COMPLETION; + xfer->actlen = 1; + xfer->status = USBD_NORMAL_COMPLETION; s = splusb(); - reqh->hcpriv = 0; - usb_transfer_complete(reqh); + xfer->hcpriv = 0; + xfer->device->bus->intr_context++; + usb_transfer_complete(xfer); + xfer->device->bus->intr_context--; splx(s); } void -uhci_root_intr_done(reqh) - usbd_request_handle reqh; +uhci_root_intr_done(xfer) + usbd_xfer_handle xfer; { } @@ -646,6 +734,7 @@ uhci_lock_frames(sc) uhci_softc_t *sc; { int s = splusb(); + while (sc->sc_vflock) { sc->sc_vflock |= UHCI_WANT_LOCK; tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0); @@ -659,6 +748,7 @@ uhci_unlock_frames(sc) uhci_softc_t *sc; { int s = splusb(); + sc->sc_vflock &= ~UHCI_HAS_LOCK; if (sc->sc_vflock & UHCI_WANT_LOCK) wakeup(&sc->sc_vflock); @@ -704,6 +794,8 @@ uhci_add_ctrl(sc, sqh) { uhci_soft_qh_t *eqh; + SPLUSBCHECK; + DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh)); eqh = sc->sc_ctl_end; sqh->hlink = eqh->hlink; @@ -721,6 +813,8 @@ uhci_remove_ctrl(sc, sqh) { uhci_soft_qh_t *pqh; + SPLUSBCHECK; + DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh)); for (pqh = sc->sc_ctl_start; pqh->hlink != sqh; pqh=pqh->hlink) #if defined(DIAGNOSTIC) || defined(UHCI_DEBUG) @@ -745,6 +839,8 @@ uhci_add_bulk(sc, sqh) { uhci_soft_qh_t *eqh; + SPLUSBCHECK; + DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); eqh = sc->sc_bulk_end; sqh->hlink = eqh->hlink; @@ -762,6 +858,8 @@ uhci_remove_bulk(sc, sqh) { uhci_soft_qh_t *pqh; + SPLUSBCHECK; + DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh)); for (pqh = sc->sc_bulk_start; pqh->hlink != sqh; pqh = pqh->hlink) #if defined(DIAGNOSTIC) || defined(UHCI_DEBUG) @@ -787,8 +885,6 @@ uhci_intr(arg) int ack; uhci_intr_info_t *ii; - sc->sc_intrs++; - #ifdef UHCI_DEBUG if (uhcidebug > 15) { DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev))); @@ -796,12 +892,15 @@ uhci_intr(arg) } #endif + status = UREAD2(sc, UHCI_STS); + if (status == 0) /* The interrupt was not for us. */ + return (0); + #if defined(DIAGNOSTIC) && defined(__NetBSD__) if (sc->sc_suspend != PWR_RESUME) printf("uhci_intr: suspended sts=0x%x\n", status); #endif - status = UREAD2(sc, UHCI_STS); ack = 0; if (status & UHCI_STS_USBINT) ack |= UHCI_STS_USBINT; @@ -831,6 +930,9 @@ uhci_intr(arg) else /* nothing to acknowledge */ return (0); + sc->sc_bus.intr_context++; + sc->sc_bus.no_intrs++; + /* * Interrupts on UHCI really suck. When the host controller * interrupts because a transfer is completed there is no @@ -845,7 +947,9 @@ uhci_intr(arg) for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) uhci_check_intr(sc, ii); - DPRINTFN(10, ("uhci_intr: exit\n")); + DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev))); + + sc->sc_bus.intr_context--; return (1); } @@ -861,16 +965,16 @@ uhci_check_intr(sc, ii) DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii)); #ifdef DIAGNOSTIC - if (!ii) { + if (ii == NULL) { printf("uhci_check_intr: no ii? %p\n", ii); return; } #endif - if (!ii->stdstart) + if (ii->stdstart == NULL) return; lstd = ii->stdend; #ifdef DIAGNOSTIC - if (!lstd) { + if (lstd == NULL) { printf("uhci_check_intr: std==0\n"); return; } @@ -898,14 +1002,15 @@ uhci_check_intr(sc, ii) uhci_idone(ii); } +/* Called at splusb() */ void uhci_idone(ii) uhci_intr_info_t *ii; { - usbd_request_handle reqh = ii->reqh; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + usbd_xfer_handle xfer = ii->xfer; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_soft_td_t *std; - u_int32_t status = 0; + u_int32_t status = 0, nstatus; int actlen; #ifdef DIAGNOSTIC @@ -921,22 +1026,22 @@ uhci_idone(ii) } #endif - if (reqh->status == USBD_CANCELLED || - reqh->status == USBD_TIMEOUT) { - DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh)); + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) { + DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer)); return; } - if (reqh->nframes) { + if (xfer->nframes != 0) { /* Isoc transfer, do things differently. */ uhci_soft_td_t **stds = upipe->u.iso.stds; int i, n, nframes; DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii)); - nframes = reqh->nframes; + nframes = xfer->nframes; actlen = 0; - n = reqh->hcprivint; + n = xfer->hcprivint; for (i = 0; i < nframes; i++) { std = stds[n]; #ifdef UHCI_DEBUG @@ -951,10 +1056,10 @@ uhci_idone(ii) actlen += UHCI_TD_GET_ACTLEN(status); } upipe->u.iso.inuse -= nframes; - reqh->actlen = actlen; - reqh->status = USBD_NORMAL_COMPLETION; - reqh->hcpriv = ii; - usb_transfer_complete(reqh); + xfer->actlen = actlen; + xfer->status = USBD_NORMAL_COMPLETION; + xfer->hcpriv = ii; + usb_transfer_complete(xfer); return; } @@ -965,43 +1070,42 @@ uhci_idone(ii) #endif /* The transfer is done, compute actual length and status. */ - /* XXX Is this correct for control xfers? */ actlen = 0; - status = 0; - for (std = ii->stdstart; std; std = std->link.std) { - if (LE(std->td.td_status) & UHCI_TD_ACTIVE) + for (std = ii->stdstart; std != NULL; std = std->link.std) { + nstatus = LE(std->td.td_status); + if (nstatus & UHCI_TD_ACTIVE) break; - status = LE(std->td.td_status); + status = nstatus; if (UHCI_TD_GET_PID(LE(std->td.td_token)) != UHCI_TD_PID_SETUP) actlen += UHCI_TD_GET_ACTLEN(status); } /* If there are left over TDs we need to update the toggle. */ - if (std) + if (std != NULL) upipe->nexttoggle = UHCI_TD_GET_DT(LE(std->td.td_token)); status &= UHCI_TD_ERROR; DPRINTFN(10, ("uhci_check_intr: actlen=%d, status=0x%x\n", actlen, status)); - reqh->actlen = actlen; + xfer->actlen = actlen; if (status != 0) { DPRINTFN((status&UHCI_TD_STALLED)*10, ("uhci_idone: error, addr=%d, endpt=0x%02x, " "status 0x%b\n", - reqh->pipe->device->address, - reqh->pipe->endpoint->edesc->bEndpointAddress, + xfer->pipe->device->address, + xfer->pipe->endpoint->edesc->bEndpointAddress, (int)status, "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" "STALLED\30ACTIVE")); if (status == UHCI_TD_STALLED) - reqh->status = USBD_STALLED; + xfer->status = USBD_STALLED; else - reqh->status = USBD_IOERROR; /* more info XXX */ + xfer->status = USBD_IOERROR; /* more info XXX */ } else { - reqh->status = USBD_NORMAL_COMPLETION; + xfer->status = USBD_NORMAL_COMPLETION; } - reqh->hcpriv = ii; - usb_transfer_complete(reqh); + xfer->hcpriv = ii; + usb_transfer_complete(xfer); } /* @@ -1014,7 +1118,15 @@ uhci_timeout(addr) uhci_intr_info_t *ii = addr; DPRINTF(("uhci_timeout: ii=%p\n", ii)); - uhci_abort_req(ii->reqh, USBD_TIMEOUT); + +#ifdef UHCI_DEBUG + if (uhcidebug > 10) + uhci_dump_tds(ii->stdstart); +#endif + + ii->xfer->device->bus->intr_context++; + uhci_abort_req(ii->xfer, USBD_TIMEOUT); + ii->xfer->device->bus->intr_context--; } /* @@ -1024,22 +1136,22 @@ uhci_timeout(addr) * Only used during boot when interrupts are not enabled yet. */ void -uhci_waitintr(sc, reqh) +uhci_waitintr(sc, xfer) uhci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { - int timo = reqh->timeout; + int timo = xfer->timeout; uhci_intr_info_t *ii; DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo)); - reqh->status = USBD_IN_PROGRESS; + xfer->status = USBD_IN_PROGRESS; for (; timo >= 0; timo--) { usb_delay_ms(&sc->sc_bus, 1); DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS))); if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) { uhci_intr(sc); - if (reqh->status != USBD_IN_PROGRESS) + if (xfer->status != USBD_IN_PROGRESS) return; } } @@ -1047,11 +1159,11 @@ uhci_waitintr(sc, reqh) /* Timeout */ DPRINTF(("uhci_waitintr: timeout\n")); for (ii = LIST_FIRST(&sc->sc_intrhead); - ii && ii->reqh != reqh; + ii != NULL && ii->xfer != xfer; ii = LIST_NEXT(ii, list)) ; #ifdef DIAGNOSTIC - if (!ii) + if (ii == NULL) panic("uhci_waitintr: lost intr_info\n"); #endif uhci_idone(ii); @@ -1129,19 +1241,19 @@ uhci_alloc_std(sc) uhci_softc_t *sc; { uhci_soft_td_t *std; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freetds) { + if (sc->sc_freetds == NULL) { DPRINTFN(2,("uhci_alloc_std: allocating chunk\n")); - r = usb_allocmem(sc->sc_dmatag, UHCI_STD_SIZE * UHCI_STD_CHUNK, - UHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK, + UHCI_TD_ALIGN, &dma); + if (err) return (0); for(i = 0; i < UHCI_STD_CHUNK; i++) { offs = i * UHCI_STD_SIZE; - std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) +offs); + std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) + offs); std->physaddr = DMAADDR(&dma) + offs; std->link.std = sc->sc_freetds; sc->sc_freetds = std; @@ -1160,7 +1272,7 @@ uhci_free_std(sc, std) { #ifdef DIAGNOSTIC #define TD_IS_FREE 0x12345678 - if (LE(std->td.td_token) == TD_IS_FREE) { + if (std->td.td_token == LE(TD_IS_FREE)) { printf("uhci_free_std: freeing free TD %p\n", std); return; } @@ -1175,16 +1287,16 @@ uhci_alloc_sqh(sc) uhci_softc_t *sc; { uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freeqhs) { + if (sc->sc_freeqhs == NULL) { DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n")); - r = usb_allocmem(sc->sc_dmatag, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, - UHCI_QH_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) - return 0; + err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, + UHCI_QH_ALIGN, &dma); + if (err) + return (0); for(i = 0; i < UHCI_SQH_CHUNK; i++) { offs = i * UHCI_SQH_SIZE; sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma) +offs); @@ -1282,20 +1394,12 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) status |= UHCI_TD_SPD; for (i = ntd; i >= 0; i--) { p = uhci_alloc_std(sc); - if (!p) { + if (p == NULL) { uhci_free_std_chain(sc, lastp, 0); return (USBD_NOMEM); } p->link.std = lastp; - /* The if statement might be necessary to avoid confusing the - * VIA chipset. It doesn't like extra bits when UHCI_PTR_T - * is set. - */ - if (lastlink != UHCI_PTR_T) - p->td.td_link = LE(lastlink|UHCI_PTR_VF); - else - p->td.td_link = LE(lastlink); - + p->td.td_link = LE(lastlink); lastp = p; lastlink = p->physaddr; p->td.td_status = LE(status); @@ -1333,66 +1437,70 @@ uhci_noop(pipe) } usbd_status -uhci_device_bulk_transfer(reqh) - usbd_request_handle reqh; +uhci_device_bulk_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_device_bulk_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_bulk_start(reqh) - usbd_request_handle reqh; +uhci_device_bulk_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_intr_info_t *ii = upipe->iinfo; - uhci_soft_td_t *xfer, *xferend; + uhci_soft_td_t *data, *dataend; uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int len, isread, endpt; int s; - DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3, ("uhci_device_bulk_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("uhci_device_bulk_transfer: a request\n"); #endif - len = reqh->length; - endpt = reqh->pipe->endpoint->edesc->bEndpointAddress; + len = xfer->length; + endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sqh = upipe->u.bulk.sqh; upipe->u.bulk.isread = isread; upipe->u.bulk.length = len; - r = uhci_alloc_std_chain(upipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - if (r != USBD_NORMAL_COMPLETION) - return (r); - xferend->td.td_status |= LE(UHCI_TD_IOC); + err = uhci_alloc_std_chain(upipe, sc, len, isread, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); + dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG if (uhcidebug > 8) { - DPRINTF(("uhci_device_bulk_transfer: xfer(1)\n")); - uhci_dump_tds(xfer); + DPRINTF(("uhci_device_bulk_transfer: data(1)\n")); + uhci_dump_tds(data); } #endif /* Set up interrupt info. */ - ii->reqh = reqh; - ii->stdstart = xfer; - ii->stdend = xferend; + ii->xfer = xfer; + ii->stdstart = data; + ii->stdend = dataend; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif @@ -1400,53 +1508,53 @@ uhci_device_bulk_start(reqh) ii->isdone = 0; #endif - sqh->elink = xfer; - sqh->qh.qh_elink = LE(xfer->physaddr); + sqh->elink = data; + sqh->qh.qh_elink = LE(data->physaddr); sqh->intr_info = ii; s = splusb(); uhci_add_bulk(sc, sqh); LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout), + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(uhci_timeout, ii, MS_TO_TICKS(xfer->timeout), ii->timeout_handle); } splx(s); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("uhci_device_bulk_transfer: xfer(2)\n")); - uhci_dump_tds(xfer); + DPRINTF(("uhci_device_bulk_transfer: data(2)\n")); + uhci_dump_tds(data); } #endif if (sc->sc_bus.use_polling) - uhci_waitintr(sc, reqh); + uhci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } /* Abort a device bulk request. */ void -uhci_device_bulk_abort(reqh) - usbd_request_handle reqh; +uhci_device_bulk_abort(xfer) + usbd_xfer_handle xfer; { DPRINTF(("uhci_device_bulk_abort:\n")); - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_req(xfer, USBD_CANCELLED); } void -uhci_abort_req(reqh, status) - usbd_request_handle reqh; +uhci_abort_req(xfer, status) + usbd_xfer_handle xfer; usbd_status status; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *std; /* Make interrupt routine ignore it, */ - reqh->status = status; + xfer->status = status; /* don't timeout, */ usb_untimeout(uhci_timeout, ii, ii->timeout_handle); @@ -1455,16 +1563,20 @@ uhci_abort_req(reqh, status) for (std = ii->stdstart; std != 0; std = std->link.std) std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - reqh->hcpriv = ii; + xfer->hcpriv = ii; /* make sure hardware has completed, */ - if (curproc) { - usb_delay_ms(reqh->pipe->device->bus, 1); - /* and call final part of interrupt handler. */ - uhci_abort_req_end(reqh); - } else { + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(uhci_abort_req_end, xfer, hz / USB_FRAMES_PER_SECOND); + } else { +#if defined(DIAGNOSTIC) && defined(__i386__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif + usb_delay_ms(xfer->pipe->device->bus, 1); + /* and call final part of interrupt handler. */ + uhci_abort_req_end(xfer); } } @@ -1472,11 +1584,11 @@ void uhci_abort_req_end(v) void *v; { - usbd_request_handle reqh = v; + usbd_xfer_handle xfer = v; int s; s = splusb(); - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); } @@ -1495,93 +1607,101 @@ uhci_device_bulk_close(pipe) } usbd_status -uhci_device_ctrl_transfer(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_device_ctrl_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_ctrl_start(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_start(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; - usbd_status r; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; + usbd_status err; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_device_ctrl_transfer: not a request\n"); #endif - r = uhci_device_request(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uhci_device_request(xfer); + if (err) + return (err); if (sc->sc_bus.use_polling) - uhci_waitintr(sc, reqh); + uhci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } usbd_status -uhci_device_intr_transfer(reqh) - usbd_request_handle reqh; +uhci_device_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_device_intr_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_intr_start(reqh) - usbd_request_handle reqh; +uhci_device_intr_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_intr_info_t *ii = upipe->iinfo; - uhci_soft_td_t *xfer, *xferend; + uhci_soft_td_t *data, *dataend; uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int i, s; - DPRINTFN(3,("uhci_device_intr_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("uhci_device_intr_transfer: a request\n"); #endif - r = uhci_alloc_std_chain(upipe, sc, reqh->length, 1, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - if (r != USBD_NORMAL_COMPLETION) - return (r); - xferend->td.td_status |= LE(UHCI_TD_IOC); + err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); + dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_transfer: xfer(1)\n")); - uhci_dump_tds(xfer); + DPRINTF(("uhci_device_intr_transfer: data(1)\n")); + uhci_dump_tds(data); uhci_dump_qh(upipe->u.intr.qhs[0]); } #endif s = splusb(); /* Set up interrupt info. */ - ii->reqh = reqh; - ii->stdstart = xfer; - ii->stdend = xferend; + ii->xfer = xfer; + ii->stdstart = data; + ii->stdend = dataend; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif @@ -1593,15 +1713,15 @@ 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->elink = xfer; - sqh->qh.qh_elink = LE(xfer->physaddr); + sqh->elink = data; + sqh->qh.qh_elink = LE(data->physaddr); } splx(s); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_transfer: xfer(2)\n")); - uhci_dump_tds(xfer); + DPRINTF(("uhci_device_intr_transfer: data(2)\n")); + uhci_dump_tds(data); uhci_dump_qh(upipe->u.intr.qhs[0]); } #endif @@ -1611,11 +1731,11 @@ uhci_device_intr_start(reqh) /* Abort a device control request. */ void -uhci_device_ctrl_abort(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_abort(xfer) + usbd_xfer_handle xfer; { DPRINTF(("uhci_device_ctrl_abort:\n")); - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_req(xfer, USBD_CANCELLED); } /* Close a device control pipe. */ @@ -1626,20 +1746,20 @@ uhci_device_ctrl_close(pipe) struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; uhci_free_intr_info(upipe->iinfo); - /* XXX free other resources */ + /* XXX free other resources? */ } /* Abort a device interrupt request. */ void -uhci_device_intr_abort(reqh) - usbd_request_handle reqh; +uhci_device_intr_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(1,("uhci_device_intr_abort: reqh=%p\n", reqh)); - if (reqh->pipe->intrreqh == reqh) { + DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer)); + if (xfer->pipe->intrxfer == xfer) { DPRINTFN(1,("uhci_device_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = 0; } - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_req(xfer, USBD_CANCELLED); } /* Close a device interrupt pipe. */ @@ -1680,21 +1800,21 @@ uhci_device_intr_close(pipe) } usbd_status -uhci_device_request(reqh) - usbd_request_handle reqh; +uhci_device_request(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; - usb_device_request_t *req = &reqh->request; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; + usb_device_request_t *req = &xfer->request; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; int addr = dev->address; int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; uhci_intr_info_t *ii = upipe->iinfo; - uhci_soft_td_t *setup, *xfer, *stat, *next, *xferend; + uhci_soft_td_t *setup, *data, *stat, *next, *dataend; uhci_soft_qh_t *sqh; int len; u_int32_t ls; - usbd_status r; + usbd_status err; int isread; int s; @@ -1715,14 +1835,14 @@ uhci_device_request(reqh) /* Set up data transaction */ if (len != 0) { upipe->nexttoggle = 1; - r = uhci_alloc_std_chain(upipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - if (r != USBD_NORMAL_COMPLETION) - return (r); - next = xfer; - xferend->link.std = stat; - xferend->td.td_link = LE(stat->physaddr|UHCI_PTR_VF); + err = uhci_alloc_std_chain(upipe, sc, len, isread, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); + next = data; + dataend->link.std = stat; + dataend->td.td_link = LE(stat->physaddr); } else { next = stat; } @@ -1731,7 +1851,7 @@ uhci_device_request(reqh) memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req); setup->link.std = next; - setup->td.td_link = LE(next->physaddr|UHCI_PTR_VF); + 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)); @@ -1746,16 +1866,19 @@ uhci_device_request(reqh) stat->td.td_buffer = LE(0); #ifdef UHCI_DEBUG - if (uhcidebug > 20) { + if (uhcidebug > 10) { DPRINTF(("uhci_device_request: before transfer\n")); uhci_dump_tds(setup); } #endif /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = setup; ii->stdend = stat; +#if defined(__FreeBSD__) + callout_handle_init(&ii->timeout_handle); +#endif #ifdef DIAGNOSTIC ii->isdone = 0; #endif @@ -1781,21 +1904,22 @@ uhci_device_request(reqh) link = LE(std->td.td_link); uhci_dump_td(std); } - for (sxqh = xqh = (uhci_soft_qh_t *)std; - xqh; + sxqh = (uhci_soft_qh_t *)std; + uhci_dump_qh(sxqh); + for (xqh = sxqh; + xqh != NULL; xqh = (maxqh++ == 5 || xqh->hlink==sxqh || xqh->hlink==xqh ? NULL : xqh->hlink)) { uhci_dump_qh(xqh); - uhci_dump_qh(sxqh); } DPRINTF(("Enqueued QH:\n")); uhci_dump_qh(sqh); uhci_dump_tds(sqh->elink); } #endif - if (reqh->timeout && !sc->sc_bus.use_polling) { + if (xfer->timeout && !sc->sc_bus.use_polling) { usb_timeout(uhci_timeout, ii, - MS_TO_TICKS(reqh->timeout), ii->timeout_handle); + MS_TO_TICKS(xfer->timeout), ii->timeout_handle); } splx(s); @@ -1803,37 +1927,37 @@ uhci_device_request(reqh) } usbd_status -uhci_device_isoc_transfer(reqh) - usbd_request_handle reqh; +uhci_device_isoc_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - DPRINTFN(5,("uhci_device_isoc_transfer: reqh=%p\n", reqh)); + DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer)); /* Put it on our queue, */ - r = usb_insert_transfer(reqh); + err = usb_insert_transfer(xfer); /* bail out on error, */ - if (r != USBD_NORMAL_COMPLETION && r != USBD_IN_PROGRESS) - return (r); + if (err && err != USBD_IN_PROGRESS) + return (err); /* XXX should check inuse here */ /* insert into schedule, */ - uhci_device_isoc_enter(reqh); + uhci_device_isoc_enter(xfer); /* and put on interrupt list if the pipe wasn't running */ - if (r == USBD_NORMAL_COMPLETION) - uhci_device_isoc_start(reqh); + if (!err) + uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); - return (r); + return (err); } void -uhci_device_isoc_enter(reqh) - usbd_request_handle reqh; +uhci_device_isoc_enter(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; struct iso *iso = &upipe->u.iso; @@ -1841,11 +1965,11 @@ uhci_device_isoc_enter(reqh) u_int32_t buf, len, status; int s, i, next, nframes; - DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d reqh=%p " + DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p " "nframes=%d\n", - iso->inuse, iso->next, reqh, reqh->nframes)); + iso->inuse, iso->next, xfer, xfer->nframes)); - if (reqh->status == USBD_IN_PROGRESS) { + if (xfer->status == USBD_IN_PROGRESS) { /* This request has already been entered into the frame list */ } @@ -1861,20 +1985,20 @@ uhci_device_isoc_enter(reqh) DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next)); } - reqh->status = USBD_IN_PROGRESS; - reqh->hcprivint = next; + xfer->status = USBD_IN_PROGRESS; + xfer->hcprivint = next; - buf = DMAADDR(&reqh->dmabuf); + buf = DMAADDR(&xfer->dmabuf); status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | UHCI_TD_ACTIVE | UHCI_TD_IOS)); - nframes = reqh->nframes; + nframes = xfer->nframes; s = splusb(); for (i = 0; i < nframes; i++) { std = iso->stds[next]; if (++next >= UHCI_VFRAMELIST_COUNT) next = 0; - len = reqh->frlengths[i]; + len = xfer->frlengths[i]; std->td.td_buffer = LE(buf); if (i == nframes - 1) status |= LE(UHCI_TD_IOC); @@ -1890,28 +2014,28 @@ uhci_device_isoc_enter(reqh) buf += len; } iso->next = next; - iso->inuse += reqh->nframes; + iso->inuse += xfer->nframes; splx(s); } usbd_status -uhci_device_isoc_start(reqh) - usbd_request_handle reqh; +uhci_device_isoc_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *end; int s, i; #ifdef DIAGNOSTIC - if (reqh->status != USBD_IN_PROGRESS) - printf("uhci_device_isoc_start: not in progress %p\n", reqh); + if (xfer->status != USBD_IN_PROGRESS) + printf("uhci_device_isoc_start: not in progress %p\n", xfer); #endif /* Find the last TD */ - i = reqh->hcprivint + reqh->nframes; + i = xfer->hcprivint + xfer->nframes; if (i >= UHCI_VFRAMELIST_COUNT) i -= UHCI_VFRAMELIST_COUNT; end = upipe->u.iso.stds[i]; @@ -1919,9 +2043,12 @@ uhci_device_isoc_start(reqh) s = splusb(); /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = end; ii->stdend = end; +#if defined(__FreeBSD__) + callout_handle_init(&ii->timeout_handle); +#endif #ifdef DIAGNOSTIC ii->isdone = 0; #endif @@ -1933,21 +2060,21 @@ uhci_device_isoc_start(reqh) } void -uhci_device_isoc_abort(reqh) - usbd_request_handle reqh; +uhci_device_isoc_abort(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t **stds = upipe->u.iso.stds; uhci_soft_td_t *std; int i, n, nframes; /* Make interrupt routine ignore it, */ - reqh->status = USBD_CANCELLED; + xfer->status = USBD_CANCELLED; /* make hardware ignore it, */ - nframes = reqh->nframes; - n = reqh->hcprivint; + nframes = xfer->nframes; + n = xfer->hcprivint; for (i = 0; i < nframes; i++) { std = stds[n]; std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); @@ -1955,16 +2082,16 @@ uhci_device_isoc_abort(reqh) n = 0; } - reqh->hcpriv = ii; + xfer->hcpriv = ii; /* make sure hardware has completed, */ - if (curproc) { - usb_delay_ms(reqh->pipe->device->bus, 1); - /* and call final part of interrupt handler. */ - uhci_abort_req_end(reqh); - } else { + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(uhci_abort_req_end, xfer, hz / USB_FRAMES_PER_SECOND); + } else { + usb_delay_ms(xfer->pipe->device->bus, 1); + /* and call final part of interrupt handler. */ + uhci_abort_req_end(xfer); } } @@ -1995,10 +2122,10 @@ uhci_device_isoc_close(pipe) for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = iso->stds[i]; for (vstd = sc->sc_vframes[i].htd; - vstd && vstd->link.std != std; + vstd != NULL && vstd->link.std != std; vstd = vstd->link.std) ; - if (!vstd) { + if (vstd == NULL) { /*panic*/ printf("uhci_device_isoc_close: %p not found\n", std); uhci_unlock_frames(sc); @@ -2070,12 +2197,12 @@ uhci_setup_isoc(pipe) } void -uhci_device_isoc_done(reqh) - usbd_request_handle reqh; +uhci_device_isoc_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; - DPRINTFN(4, ("uhci_isoc_done: length=%d\n", reqh->actlen)); + DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen)); /* Turn off the interrupt since it is active even if the TD is not. */ ii->stdend->td.td_status &= LE(~UHCI_TD_IOC); @@ -2084,16 +2211,16 @@ uhci_device_isoc_done(reqh) } void -uhci_device_intr_done(reqh) - usbd_request_handle reqh; +uhci_device_intr_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_soft_qh_t *sqh; int i, npoll; - DPRINTFN(5, ("uhci_intr_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_intr_done: length=%d\n", xfer->actlen)); npoll = upipe->u.intr.npoll; for(i = 0; i < npoll; i++) { @@ -2104,32 +2231,35 @@ uhci_device_intr_done(reqh) uhci_free_std_chain(sc, ii->stdstart, 0); /* XXX Wasteful. */ - if (reqh->pipe->repeat) { - uhci_soft_td_t *xfer, *xferend; + if (xfer->pipe->repeat) { + uhci_soft_td_t *data, *dataend; /* This alloc cannot fail since we freed the chain above. */ - uhci_alloc_std_chain(upipe, sc, reqh->length, 1, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - xferend->td.td_status |= LE(UHCI_TD_IOC); + uhci_alloc_std_chain(upipe, sc, xfer->length, 1, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_done: xfer(1)\n")); - uhci_dump_tds(xfer); + DPRINTF(("uhci_device_intr_done: data(1)\n")); + uhci_dump_tds(data); uhci_dump_qh(upipe->u.intr.qhs[0]); } #endif - ii->stdstart = xfer; - ii->stdend = xferend; + ii->stdstart = data; + ii->stdend = dataend; +#if defined(__FreeBSD__) + callout_handle_init(&ii->timeout_handle); +#endif #ifdef DIAGNOSTIC ii->isdone = 0; #endif for (i = 0; i < npoll; i++) { sqh = upipe->u.intr.qhs[i]; - sqh->elink = xfer; - sqh->qh.qh_elink = LE(xfer->physaddr); + sqh->elink = data; + sqh->qh.qh_elink = LE(data->physaddr); } } else { ii->stdstart = 0; /* mark as inactive */ @@ -2138,15 +2268,15 @@ uhci_device_intr_done(reqh) /* Deallocate request data structures */ void -uhci_device_ctrl_done(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_ctrl_done: not a request\n"); #endif @@ -2157,17 +2287,17 @@ uhci_device_ctrl_done(reqh) if (upipe->u.ctl.length != 0) uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend); - DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", xfer->actlen)); } /* Deallocate request data structures */ void -uhci_device_bulk_done(reqh) - usbd_request_handle reqh; +uhci_device_bulk_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; LIST_REMOVE(ii, list); /* remove from active list */ @@ -2175,7 +2305,7 @@ uhci_device_bulk_done(reqh) uhci_free_std_chain(sc, ii->stdstart, 0); - DPRINTFN(5, ("uhci_bulk_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen)); } /* Add interrupt QH, called with vflock. */ @@ -2299,7 +2429,7 @@ uhci_open(pipe) uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - usbd_status r; + usbd_status err; DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", pipe, pipe->device->address, @@ -2323,23 +2453,23 @@ uhci_open(pipe) case UE_CONTROL: pipe->methods = &uhci_device_ctrl_methods; upipe->u.ctl.sqh = uhci_alloc_sqh(sc); - if (upipe->u.ctl.sqh == 0) + if (upipe->u.ctl.sqh == NULL) goto bad; upipe->u.ctl.setup = uhci_alloc_std(sc); - if (upipe->u.ctl.setup == 0) { + if (upipe->u.ctl.setup == NULL) { uhci_free_sqh(sc, upipe->u.ctl.sqh); goto bad; } upipe->u.ctl.stat = uhci_alloc_std(sc); - if (upipe->u.ctl.stat == 0) { + if (upipe->u.ctl.stat == NULL) { uhci_free_sqh(sc, upipe->u.ctl.sqh); uhci_free_std(sc, upipe->u.ctl.setup); goto bad; } - r = usb_allocmem(sc->sc_dmatag, - sizeof(usb_device_request_t), - 0, &upipe->u.ctl.reqdma); - if (r != USBD_NORMAL_COMPLETION) { + err = usb_allocmem(&sc->sc_bus, + sizeof(usb_device_request_t), + 0, &upipe->u.ctl.reqdma); + if (err) { uhci_free_sqh(sc, upipe->u.ctl.sqh); uhci_free_std(sc, upipe->u.ctl.setup); uhci_free_std(sc, upipe->u.ctl.stat); @@ -2355,7 +2485,7 @@ uhci_open(pipe) case UE_BULK: pipe->methods = &uhci_device_bulk_methods; upipe->u.bulk.sqh = uhci_alloc_sqh(sc); - if (upipe->u.bulk.sqh == 0) + if (upipe->u.bulk.sqh == NULL) goto bad; break; } @@ -2451,35 +2581,39 @@ uhci_str(p, l, s) * Simulate a hardware hub by handling all the necessary requests. */ usbd_status -uhci_root_ctrl_transfer(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_root_ctrl_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_root_ctrl_start(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_start(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; usb_device_request_t *req; void *buf = NULL; int port, x; - int len, value, index, status, change, l, totlen = 0; + int s, len, value, index, status, change, l, totlen = 0; usb_port_status_t ps; - usbd_status r; + usbd_status err; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_root_ctrl_transfer: not a request\n"); #endif - req = &reqh->request; + req = &xfer->request; DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); @@ -2489,7 +2623,7 @@ uhci_root_ctrl_start(reqh) index = UGETW(req->wIndex); if (len != 0) - buf = KERNADDR(&reqh->dmabuf); + buf = KERNADDR(&xfer->dmabuf); #define C(x,y) ((x) | ((y) << 8)) switch(C(req->bRequest, req->bmRequestType)) { @@ -2512,7 +2646,7 @@ uhci_root_ctrl_start(reqh) switch(value >> 8) { case UDESC_DEVICE: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); @@ -2521,7 +2655,7 @@ uhci_root_ctrl_start(reqh) break; case UDESC_CONFIG: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); @@ -2552,7 +2686,7 @@ uhci_root_ctrl_start(reqh) } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -2577,14 +2711,14 @@ uhci_root_ctrl_start(reqh) break; case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): if (value >= USB_MAX_DEVICES) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_addr = value; break; case C(UR_SET_CONFIG, UT_WRITE_DEVICE): if (value != 0 && value != 1) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_conf = value; @@ -2594,7 +2728,7 @@ uhci_root_ctrl_start(reqh) case C(UR_SET_FEATURE, UT_WRITE_DEVICE): case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): break; @@ -2612,7 +2746,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -2642,7 +2776,7 @@ uhci_root_ctrl_start(reqh) break; case UHF_C_PORT_RESET: sc->sc_isreset = 0; - r = USBD_NORMAL_COMPLETION; + err = USBD_NORMAL_COMPLETION; goto ret; case UHF_PORT_CONNECTION: case UHF_PORT_OVER_CURRENT: @@ -2650,7 +2784,7 @@ uhci_root_ctrl_start(reqh) case UHF_PORT_LOW_SPEED: case UHF_C_PORT_SUSPEND: default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -2660,7 +2794,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len > 0) { @@ -2672,7 +2806,7 @@ uhci_root_ctrl_start(reqh) break; case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): if (value != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } l = min(len, USB_HUB_DESCRIPTOR_SIZE); @@ -2681,7 +2815,7 @@ uhci_root_ctrl_start(reqh) break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } memset(buf, 0, len); @@ -2693,11 +2827,11 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } x = UREAD2(sc, port); @@ -2728,7 +2862,7 @@ uhci_root_ctrl_start(reqh) totlen = l; break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): break; @@ -2738,7 +2872,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -2773,27 +2907,29 @@ uhci_root_ctrl_start(reqh) case UHF_C_PORT_SUSPEND: case UHF_C_PORT_RESET: default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } - reqh->actlen = totlen; - r = USBD_NORMAL_COMPLETION; + xfer->actlen = totlen; + err = USBD_NORMAL_COMPLETION; ret: - reqh->status = r; - reqh->hcpriv = 0; - usb_transfer_complete(reqh); + xfer->status = err; + xfer->hcpriv = 0; + s = splusb(); + usb_transfer_complete(xfer); + splx(s); return (USBD_IN_PROGRESS); } /* Abort a root control request. */ void -uhci_root_ctrl_abort(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_abort(xfer) + usbd_xfer_handle xfer; { /* Nothing to do, all transfers are syncronous. */ } @@ -2811,42 +2947,53 @@ uhci_root_ctrl_close(pipe) /* Abort a root interrupt request. */ void -uhci_root_intr_abort(reqh) - usbd_request_handle reqh; +uhci_root_intr_abort(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usb_untimeout(uhci_timo, reqh, reqh->timo_handle); + usb_untimeout(uhci_timo, xfer, xfer->timo_handle); sc->sc_has_timo = 0; + + if (xfer->pipe->intrxfer == xfer) { + DPRINTF(("uhci_root_intr_abort: remove\n")); + xfer->pipe->intrxfer = 0; + } + xfer->status = USBD_CANCELLED; + usb_transfer_complete(xfer); } usbd_status -uhci_root_intr_transfer(reqh) - usbd_request_handle reqh; +uhci_root_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_root_intr_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } /* Start a transfer on the root interrupt pipe */ usbd_status -uhci_root_intr_start(reqh) - usbd_request_handle reqh; +uhci_root_intr_start(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; + usbd_pipe_handle pipe = xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3, ("uhci_root_intr_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); - sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval); - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); - sc->sc_has_timo = reqh; + sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); + usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle); + sc->sc_has_timo = xfer; return (USBD_IN_PROGRESS); } @@ -2857,8 +3004,7 @@ uhci_root_intr_close(pipe) { uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle); + usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle); sc->sc_has_timo = 0; DPRINTF(("uhci_root_intr_close\n")); } - |