Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/usb/ehci.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/usb/ehci.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.234 retrieving revision 1.234.2.27 diff -u -p -r1.234 -r1.234.2.27 --- src/sys/dev/usb/ehci.c 2014/09/22 08:13:02 1.234 +++ src/sys/dev/usb/ehci.c 2015/01/02 08:45:05 1.234.2.27 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.234 2014/09/22 08:13:02 skrll Exp $ */ +/* $NetBSD: ehci.c,v 1.234.2.27 2015/01/02 08:45:05 skrll Exp $ */ /* * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234 2014/09/22 08:13:02 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.27 2015/01/02 08:45:05 skrll Exp $"); #include "ohci.h" #include "uhci.h" @@ -81,10 +81,10 @@ __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.2 #include #include #include -#include #include #include +#include #ifdef USB_DEBUG @@ -131,6 +131,7 @@ struct ehci_pipe { union { ehci_soft_qtd_t *qtd; /* ehci_soft_itd_t *itd; */ + /* ehci_soft_sitd_t *sitd; */ } tail; union { /* Control pipe */ @@ -161,6 +162,7 @@ Static void ehci_waitintr(ehci_softc_t Static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *); Static void ehci_check_qh_intr(ehci_softc_t *, struct ehci_xfer *); Static void ehci_check_itd_intr(ehci_softc_t *, struct ehci_xfer *); +Static void ehci_check_sitd_intr(ehci_softc_t *, struct ehci_xfer *); Static void ehci_idone(struct ehci_xfer *); Static void ehci_timeout(void *); Static void ehci_timeout_task(void *); @@ -168,18 +170,11 @@ Static void ehci_intrlist_timeout(void Static void ehci_doorbell(void *); Static void ehci_pcd(void *); -Static usbd_status ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -Static void ehci_freem(struct usbd_bus *, usb_dma_t *); - Static usbd_xfer_handle ehci_allocx(struct usbd_bus *); Static void ehci_freex(struct usbd_bus *, usbd_xfer_handle); Static void ehci_get_lock(struct usbd_bus *, kmutex_t **); - -Static usbd_status ehci_root_ctrl_transfer(usbd_xfer_handle); -Static usbd_status ehci_root_ctrl_start(usbd_xfer_handle); -Static void ehci_root_ctrl_abort(usbd_xfer_handle); -Static void ehci_root_ctrl_close(usbd_pipe_handle); -Static void ehci_root_ctrl_done(usbd_xfer_handle); +Static int ehci_roothub_ctrl(struct usbd_bus *, + usb_device_request_t *, void *, int); Static usbd_status ehci_root_intr_transfer(usbd_xfer_handle); Static usbd_status ehci_root_intr_start(usbd_xfer_handle); @@ -211,8 +206,14 @@ Static void ehci_device_isoc_abort(usbd Static void ehci_device_isoc_close(usbd_pipe_handle); Static void ehci_device_isoc_done(usbd_xfer_handle); -Static void ehci_device_clear_toggle(usbd_pipe_handle pipe); -Static void ehci_noop(usbd_pipe_handle pipe); +Static usbd_status ehci_device_fs_isoc_transfer(usbd_xfer_handle); +Static usbd_status ehci_device_fs_isoc_start(usbd_xfer_handle); +Static void ehci_device_fs_isoc_abort(usbd_xfer_handle); +Static void ehci_device_fs_isoc_close(usbd_pipe_handle); +Static void ehci_device_fs_isoc_done(usbd_xfer_handle); + +Static void ehci_device_clear_toggle(usbd_pipe_handle); +Static void ehci_noop(usbd_pipe_handle); Static void ehci_disown(ehci_softc_t *, int, int); @@ -227,17 +228,21 @@ Static usbd_status ehci_alloc_sqtd_chain Static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qtd_t *, ehci_soft_qtd_t *); -Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *sc); -Static void ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd); -Static void ehci_rem_free_itd_chain(ehci_softc_t *sc, - struct ehci_xfer *exfer); -Static void ehci_abort_isoc_xfer(usbd_xfer_handle xfer, - usbd_status status); +Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *); +Static ehci_soft_sitd_t *ehci_alloc_sitd(ehci_softc_t *); +Static void ehci_free_itd(ehci_softc_t *, ehci_soft_itd_t *); +Static void ehci_free_sitd(ehci_softc_t *, ehci_soft_sitd_t *); +Static void ehci_rem_free_itd_chain(ehci_softc_t *, + struct ehci_xfer *); +Static void ehci_rem_free_sitd_chain(ehci_softc_t *, + struct ehci_xfer *); +Static void ehci_abort_isoc_xfer(usbd_xfer_handle, + usbd_status); -Static usbd_status ehci_device_request(usbd_xfer_handle xfer); +Static usbd_status ehci_device_request(usbd_xfer_handle); Static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *, - int ival); + int); Static void ehci_add_qh(ehci_softc_t *, ehci_soft_qh_t *, ehci_soft_qh_t *); @@ -260,88 +265,84 @@ Static void ehci_dump_sqtds(ehci_soft_q Static void ehci_dump_sqtd(ehci_soft_qtd_t *); Static void ehci_dump_qtd(ehci_qtd_t *); Static void ehci_dump_sqh(ehci_soft_qh_t *); -Static void ehci_dump_sitd(struct ehci_soft_itd *itd); +Static void ehci_dump_sitd(struct ehci_soft_itd *); Static void ehci_dump_itd(struct ehci_soft_itd *); Static void ehci_dump_exfer(struct ehci_xfer *); #endif #define EHCI_NULL htole32(EHCI_LINK_TERMINATE) -#define EHCI_INTR_ENDPT 1 - #define ehci_add_intr_list(sc, ex) \ - TAILQ_INSERT_TAIL(&(sc)->sc_intrhead, (ex), inext); + TAILQ_INSERT_TAIL(&(sc)->sc_intrhead, (ex), ex_next); #define ehci_del_intr_list(sc, ex) \ do { \ - TAILQ_REMOVE(&sc->sc_intrhead, (ex), inext); \ - (ex)->inext.tqe_prev = NULL; \ + TAILQ_REMOVE(&sc->sc_intrhead, (ex), ex_next); \ + (ex)->ex_next.tqe_prev = NULL; \ } while (0) -#define ehci_active_intr_list(ex) ((ex)->inext.tqe_prev != NULL) +#define ehci_active_intr_list(ex) ((ex)->ex_next.tqe_prev != NULL) Static const struct usbd_bus_methods ehci_bus_methods = { - .open_pipe = ehci_open, - .soft_intr = ehci_softintr, - .do_poll = ehci_poll, - .allocm = ehci_allocm, - .freem = ehci_freem, - .allocx = ehci_allocx, - .freex = ehci_freex, - .get_lock = ehci_get_lock, - .new_device = NULL, -}; - -Static const struct usbd_pipe_methods ehci_root_ctrl_methods = { - .transfer = ehci_root_ctrl_transfer, - .start = ehci_root_ctrl_start, - .abort = ehci_root_ctrl_abort, - .close = ehci_root_ctrl_close, - .cleartoggle = ehci_noop, - .done = ehci_root_ctrl_done, + .ubm_open = ehci_open, + .ubm_softint = ehci_softintr, + .ubm_dopoll = ehci_poll, + .ubm_allocx = ehci_allocx, + .ubm_freex = ehci_freex, + .ubm_getlock = ehci_get_lock, + .ubm_rhctrl = ehci_roothub_ctrl, }; Static const struct usbd_pipe_methods ehci_root_intr_methods = { - .transfer = ehci_root_intr_transfer, - .start = ehci_root_intr_start, - .abort = ehci_root_intr_abort, - .close = ehci_root_intr_close, - .cleartoggle = ehci_noop, - .done = ehci_root_intr_done, + .upm_transfer = ehci_root_intr_transfer, + .upm_start = ehci_root_intr_start, + .upm_abort = ehci_root_intr_abort, + .upm_close = ehci_root_intr_close, + .upm_cleartoggle = ehci_noop, + .upm_done = ehci_root_intr_done, }; Static const struct usbd_pipe_methods ehci_device_ctrl_methods = { - .transfer = ehci_device_ctrl_transfer, - .start = ehci_device_ctrl_start, - .abort = ehci_device_ctrl_abort, - .close = ehci_device_ctrl_close, - .cleartoggle = ehci_noop, - .done = ehci_device_ctrl_done, + .upm_transfer = ehci_device_ctrl_transfer, + .upm_start = ehci_device_ctrl_start, + .upm_abort = ehci_device_ctrl_abort, + .upm_close = ehci_device_ctrl_close, + .upm_cleartoggle = ehci_noop, + .upm_done = ehci_device_ctrl_done, }; Static const struct usbd_pipe_methods ehci_device_intr_methods = { - .transfer = ehci_device_intr_transfer, - .start = ehci_device_intr_start, - .abort = ehci_device_intr_abort, - .close = ehci_device_intr_close, - .cleartoggle = ehci_device_clear_toggle, - .done = ehci_device_intr_done, + .upm_transfer = ehci_device_intr_transfer, + .upm_start = ehci_device_intr_start, + .upm_abort = ehci_device_intr_abort, + .upm_close = ehci_device_intr_close, + .upm_cleartoggle = ehci_device_clear_toggle, + .upm_done = ehci_device_intr_done, }; Static const struct usbd_pipe_methods ehci_device_bulk_methods = { - .transfer = ehci_device_bulk_transfer, - .start = ehci_device_bulk_start, - .abort = ehci_device_bulk_abort, - .close = ehci_device_bulk_close, - .cleartoggle = ehci_device_clear_toggle, - .done = ehci_device_bulk_done, + .upm_transfer = ehci_device_bulk_transfer, + .upm_start = ehci_device_bulk_start, + .upm_abort = ehci_device_bulk_abort, + .upm_close = ehci_device_bulk_close, + .upm_cleartoggle = ehci_device_clear_toggle, + .upm_done = ehci_device_bulk_done, }; Static const struct usbd_pipe_methods ehci_device_isoc_methods = { - .transfer = ehci_device_isoc_transfer, - .start = ehci_device_isoc_start, - .abort = ehci_device_isoc_abort, - .close = ehci_device_isoc_close, - .cleartoggle = ehci_noop, - .done = ehci_device_isoc_done, + .upm_transfer = ehci_device_isoc_transfer, + .upm_start = ehci_device_isoc_start, + .upm_abort = ehci_device_isoc_abort, + .upm_close = ehci_device_isoc_close, + .upm_cleartoggle = ehci_noop, + .upm_done = ehci_device_isoc_done, +}; + +Static const struct usbd_pipe_methods ehci_device_fs_isoc_methods = { + .upm_transfer = ehci_device_fs_isoc_transfer, + .upm_start = ehci_device_fs_isoc_start, + .upm_abort = ehci_device_fs_isoc_abort, + .upm_close = ehci_device_fs_isoc_close, + .upm_cleartoggle = ehci_noop, + .upm_done = ehci_device_fs_isoc_done, }; static const uint8_t revbits[EHCI_MAX_POLLRATE] = { @@ -355,10 +356,10 @@ static const uint8_t revbits[EHCI_MAX_PO 0x07,0x47,0x27,0x67,0x17,0x57,0x37,0x77,0x0f,0x4f,0x2f,0x6f,0x1f,0x5f,0x3f,0x7f, }; -usbd_status +int ehci_init(ehci_softc_t *sc) { - u_int32_t vers, sparams, cparams, hcr; + uint32_t vers, sparams, cparams, hcr; u_int i; usbd_status err; ehci_soft_qh_t *sqh; @@ -424,10 +425,9 @@ ehci_init(ehci_softc_t *sc) EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); } - sc->sc_bus.usbrev = USBREV_2_0; - - usb_setup_reserve(sc->sc_dev, &sc->sc_dma_reserve, sc->sc_bus.dmatag, - USB_MEM_RESERVE); + sc->sc_bus.ub_revision = USBREV_2_0; + sc->sc_bus.ub_usedma = true; + sc->sc_bus.ub_dmaflags = USBMALLOC_MULTISEG; /* Reset the controller */ USBHIST_LOG(ehcidebug, "resetting", 0, 0, 0, 0); @@ -442,7 +442,7 @@ ehci_init(ehci_softc_t *sc) } if (hcr) { aprint_error("%s: reset timeout\n", device_xname(sc->sc_dev)); - return (USBD_IOERROR); + return EIO; } if (sc->sc_vendor_init) sc->sc_vendor_init(sc); @@ -466,12 +466,12 @@ ehci_init(ehci_softc_t *sc) case 0: sc->sc_flsize = 1024; break; case 1: sc->sc_flsize = 512; break; case 2: sc->sc_flsize = 256; break; - case 3: return (USBD_IOERROR); + case 3: return EIO; } err = usb_allocmem(&sc->sc_bus, sc->sc_flsize * sizeof(ehci_link_t), EHCI_FLALIGN_ALIGN, &sc->sc_fldma); if (err) - return (err); + return err; USBHIST_LOG(ehcidebug, "flsize=%d", sc->sc_flsize, 0, 0, 0); sc->sc_flist = KERNADDR(&sc->sc_fldma, 0); @@ -486,11 +486,12 @@ ehci_init(ehci_softc_t *sc) if (sc->sc_softitds == NULL) return ENOMEM; LIST_INIT(&sc->sc_freeitds); + LIST_INIT(&sc->sc_freesitds); TAILQ_INIT(&sc->sc_intrhead); /* Set up the bus struct. */ - sc->sc_bus.methods = &ehci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ehci_pipe); + sc->sc_bus.ub_methods = &ehci_bus_methods; + sc->sc_bus.ub_pipesize= sizeof(struct ehci_pipe); sc->sc_eintrs = EHCI_NORMAL_INTRS; @@ -501,7 +502,7 @@ ehci_init(ehci_softc_t *sc) for (i = 0; i < EHCI_INTRQHS; i++) { sqh = ehci_alloc_sqh(sc); if (sqh == NULL) { - err = USBD_NOMEM; + err = ENOMEM; goto bad1; } sc->sc_islots[i].sqh = sqh; @@ -544,7 +545,7 @@ ehci_init(ehci_softc_t *sc) /* Allocate dummy QH that starts the async list. */ sqh = ehci_alloc_sqh(sc); if (sqh == NULL) { - err = USBD_NOMEM; + err = ENOMEM; goto bad1; } /* Fill the QH */ @@ -590,14 +591,14 @@ ehci_init(ehci_softc_t *sc) } if (hcr) { aprint_error("%s: run timeout\n", device_xname(sc->sc_dev)); - return (USBD_IOERROR); + return EIO; } /* Enable interrupts */ USBHIST_LOG(ehcidebug, "enabling interupts", 0, 0, 0, 0); EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - return (USBD_NORMAL_COMPLETION); + return 0; #if 0 bad2: @@ -605,7 +606,7 @@ ehci_init(ehci_softc_t *sc) #endif bad1: usb_freemem(&sc->sc_bus, &sc->sc_fldma); - return (err); + return err; } int @@ -625,15 +626,13 @@ ehci_intr(void *v) goto done; /* If we get an interrupt while polling, then just ignore it. */ - if (sc->sc_bus.use_polling) { - u_int32_t intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); + if (sc->sc_bus.ub_usepolling) { + uint32_t intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); if (intrs) EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ -#ifdef DIAGNOSTIC USBHIST_LOGN(ehcidebug, 16, "ignored interrupt while polling", 0, 0, 0, 0); -#endif goto done; } @@ -647,7 +646,7 @@ done: Static int ehci_intr1(ehci_softc_t *sc) { - u_int32_t intrs, eintrs; + uint32_t intrs, eintrs; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -656,23 +655,22 @@ ehci_intr1(ehci_softc_t *sc) #ifdef DIAGNOSTIC printf("ehci_intr1: sc == NULL\n"); #endif - return (0); + return 0; } KASSERT(mutex_owned(&sc->sc_intr_lock)); intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); if (!intrs) - return (0); + return 0; eintrs = intrs & sc->sc_eintrs; USBHIST_LOG(ehcidebug, "sc=%p intrs=%#x(%#x) eintrs=%#x", sc, intrs, EOREAD4(sc, EHCI_USBSTS), eintrs); if (!eintrs) - return (0); + return 0; EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ - sc->sc_bus.no_intrs++; if (eintrs & EHCI_STS_IAA) { USBHIST_LOG(ehcidebug, "door bell", 0, 0, 0, 0); kpreempt_disable(); @@ -709,7 +707,7 @@ ehci_intr1(ehci_softc_t *sc) device_xname(sc->sc_dev), eintrs); } - return (1); + return 1; } Static void @@ -740,9 +738,9 @@ ehci_pcd(void *addr) goto done; } - p = KERNADDR(&xfer->dmabuf, 0); - m = min(sc->sc_noport, xfer->length * 8 - 1); - memset(p, 0, xfer->length); + p = xfer->ux_buf; + m = min(sc->sc_noport, xfer->ux_length * 8 - 1); + memset(p, 0, xfer->ux_length); for (i = 1; i <= m; i++) { /* Pick out CHANGE bits from the status reg. */ if (EOREAD4(sc, EHCI_PORTSC(i)) & EHCI_PS_CLEAR) @@ -751,8 +749,8 @@ ehci_pcd(void *addr) USBHIST_LOG(ehcidebug, "change(%d)=0x%02x", i / 8, p[i/8], 0, 0); } - xfer->actlen = xfer->length; - xfer->status = USBD_NORMAL_COMPLETION; + xfer->ux_actlen = xfer->ux_length; + xfer->ux_status = USBD_NORMAL_COMPLETION; usb_transfer_complete(xfer); @@ -764,10 +762,10 @@ Static void ehci_softintr(void *v) { struct usbd_bus *bus = v; - ehci_softc_t *sc = bus->hci_private; + ehci_softc_t *sc = bus->ub_hcpriv; struct ehci_xfer *ex, *nextex; - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -778,7 +776,7 @@ ehci_softintr(void *v) * clue what, so we need to scan through all active transfers. :-( */ for (ex = TAILQ_FIRST(&sc->sc_intrhead); ex; ex = nextex) { - nextex = TAILQ_NEXT(ex, inext); + nextex = TAILQ_NEXT(ex, ex_next); ehci_check_intr(sc, ex); } @@ -798,17 +796,21 @@ ehci_softintr(void *v) Static void ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex) { + usbd_device_handle dev = ex->ex_xfer.ux_pipe->up_dev; int attr; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "ex = %p", ex, 0, 0, 0); - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); - attr = ex->xfer.pipe->endpoint->edesc->bmAttributes; - if (UE_GET_XFERTYPE(attr) == UE_ISOCHRONOUS) - ehci_check_itd_intr(sc, ex); - else + attr = ex->ex_xfer.ux_pipe->up_endpoint->ue_edesc->bmAttributes; + if (UE_GET_XFERTYPE(attr) == UE_ISOCHRONOUS) { + if (dev->ud_speed == USB_SPEED_HIGH) + ehci_check_itd_intr(sc, ex); + else + ehci_check_sitd_intr(sc, ex); + } else ehci_check_qh_intr(sc, ex); return; @@ -818,18 +820,18 @@ Static void ehci_check_qh_intr(ehci_softc_t *sc, struct ehci_xfer *ex) { ehci_soft_qtd_t *sqtd, *lsqtd; - __uint32_t status; + uint32_t status; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); - if (ex->sqtdstart == NULL) { + if (ex->ex_sqtdstart == NULL) { printf("ehci_check_qh_intr: not valid sqtd\n"); return; } - lsqtd = ex->sqtdend; + lsqtd = ex->ex_sqtdend; #ifdef DIAGNOSTIC if (lsqtd == NULL) { printf("ehci_check_qh_intr: lsqtd==0\n"); @@ -851,7 +853,8 @@ ehci_check_qh_intr(ehci_softc_t *sc, str sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD); if (status & EHCI_QTD_ACTIVE) { USBHIST_LOGN(ehcidebug, 10, "active ex=%p", ex, 0, 0, 0); - for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) { + for (sqtd = ex->ex_sqtdstart; sqtd != lsqtd; + sqtd = sqtd->nextqtd) { usb_syncmem(&sqtd->dma, sqtd->offs + offsetof(ehci_qtd_t, qtd_status), sizeof(sqtd->qtd.qtd_status), @@ -868,9 +871,9 @@ ehci_check_qh_intr(ehci_softc_t *sc, str goto done; /* Handle short packets */ if (EHCI_QTD_GET_BYTES(status) != 0) { - usbd_pipe_handle pipe = ex->xfer.pipe; + usbd_pipe_handle pipe = ex->ex_xfer.ux_pipe; usb_endpoint_descriptor_t *ed = - pipe->endpoint->edesc; + pipe->up_endpoint->ue_edesc; uint8_t xt = UE_GET_XFERTYPE(ed->bmAttributes); /* @@ -888,12 +891,12 @@ ehci_check_qh_intr(ehci_softc_t *sc, str } } USBHIST_LOGN(ehcidebug, 10, "ex=%p std=%p still active", - ex, ex->sqtdstart, 0, 0); + ex, ex->ex_sqtdstart, 0, 0); return; } done: USBHIST_LOGN(ehcidebug, 10, "ex=%p done", ex, 0, 0, 0); - callout_stop(&ex->xfer.timeout_handle); + callout_stop(&ex->ex_xfer.ux_callout); ehci_idone(ex); } @@ -907,15 +910,15 @@ ehci_check_itd_intr(ehci_softc_t *sc, st KASSERT(mutex_owned(&sc->sc_lock)); - if (&ex->xfer != SIMPLEQ_FIRST(&ex->xfer.pipe->queue)) + if (&ex->ex_xfer != SIMPLEQ_FIRST(&ex->ex_xfer.ux_pipe->up_queue)) return; - if (ex->itdstart == NULL) { + if (ex->ex_itdstart == NULL) { printf("ehci_check_itd_intr: not valid itd\n"); return; } - itd = ex->itdend; + itd = ex->ex_itdend; #ifdef DIAGNOSTIC if (itd == NULL) { printf("ehci_check_itd_intr: itdend == 0\n"); @@ -941,79 +944,126 @@ ehci_check_itd_intr(ehci_softc_t *sc, st } USBHIST_LOGN(ehcidebug, 10, "ex %p itd %p still active", ex, - ex->itdstart, 0, 0); + ex->ex_itdstart, 0, 0); return; done: USBHIST_LOG(ehcidebug, "ex %p done", ex, 0, 0, 0); - callout_stop(&ex->xfer.timeout_handle); + callout_stop(&ex->ex_xfer.ux_callout); + ehci_idone(ex); +} + +void +ehci_check_sitd_intr(ehci_softc_t *sc, struct ehci_xfer *ex) +{ + ehci_soft_sitd_t *sitd; + + USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); + + KASSERT(mutex_owned(&sc->sc_lock)); + + if (&ex->ex_xfer != SIMPLEQ_FIRST(&ex->ex_xfer.ux_pipe->up_queue)) + return; + + if (ex->ex_sitdstart == NULL) { + printf("ehci_check_sitd_intr: not valid sitd\n"); + return; + } + + sitd = ex->ex_sitdend; +#ifdef DIAGNOSTIC + if (sitd == NULL) { + printf("ehci_check_sitd_intr: sitdend == 0\n"); + return; + } +#endif + + /* + * check no active transfers in last sitd, meaning we're finished + */ + + usb_syncmem(&sitd->dma, sitd->offs + offsetof(ehci_sitd_t, sitd_buffer), + sizeof(sitd->sitd.sitd_buffer), BUS_DMASYNC_POSTWRITE | + BUS_DMASYNC_POSTREAD); + + if (le32toh(sitd->sitd.sitd_trans) & EHCI_SITD_ACTIVE) + return; + + USBHIST_LOGN(ehcidebug, 10, "ex=%p done", ex, 0, 0, 0); + callout_stop(&(ex->ex_xfer.ux_callout)); ehci_idone(ex); } + Static void ehci_idone(struct ehci_xfer *ex) { - usbd_xfer_handle xfer = &ex->xfer; - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - struct ehci_softc *sc = xfer->pipe->device->bus->hci_private; + usbd_xfer_handle xfer = &ex->ex_xfer; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + struct ehci_softc *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; ehci_soft_qtd_t *sqtd, *lsqtd; - u_int32_t status = 0, nstatus = 0; + uint32_t status = 0, nstatus = 0; int actlen; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); USBHIST_LOG(ehcidebug, "ex=%p", ex, 0, 0, 0); #ifdef DIAGNOSTIC - if (ex->isdone) { + if (ex->ex_isdone) { printf("ehci_idone: ex=%p is done!\n", ex); #ifdef EHCI_DEBUG ehci_dump_exfer(ex); #endif return; } - ex->isdone = 1; + ex->ex_isdone = 1; #endif - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { + if (xfer->ux_status == USBD_CANCELLED || + xfer->ux_status == USBD_TIMEOUT) { USBHIST_LOG(ehcidebug, "aborted xfer=%p", xfer, 0, 0, 0); return; } USBHIST_LOG(ehcidebug, "xfer=%p, pipe=%p ready", xfer, epipe, 0, 0); #ifdef EHCI_DEBUG - ehci_dump_sqtds(ex->sqtdstart); + ehci_dump_sqtds(ex->ex_sqtdstart); #endif /* The transfer is done, compute actual length and status. */ - if (UE_GET_XFERTYPE(xfer->pipe->endpoint->edesc->bmAttributes) - == UE_ISOCHRONOUS) { - /* Isoc transfer */ + u_int xfertype, speed; + + xfertype = UE_GET_XFERTYPE(xfer->ux_pipe->up_endpoint->ue_edesc->bmAttributes); + speed = xfer->ux_pipe->up_dev->ud_speed; + if (xfertype == UE_ISOCHRONOUS && speed == USB_SPEED_HIGH) { + /* HS isoc transfer */ + struct ehci_soft_itd *itd; int i, nframes, len, uframes; nframes = 0; actlen = 0; - i = xfer->pipe->endpoint->edesc->bInterval; + i = xfer->ux_pipe->up_endpoint->ue_edesc->bInterval; uframes = min(1 << (i - 1), USB_UFRAMES_PER_FRAME); - for (itd = ex->itdstart; itd != NULL; itd = itd->xfer_next) { + for (itd = ex->ex_itdstart; itd != NULL; itd = itd->xfer_next) { usb_syncmem(&itd->dma,itd->offs + offsetof(ehci_itd_t,itd_ctl), sizeof(itd->itd.itd_ctl), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); for (i = 0; i < EHCI_ITD_NUFRAMES; i += uframes) { - /* XXX - driver didn't fill in the frame full + /* + * XXX - driver didn't fill in the frame full * of uframes. This leads to scheduling * inefficiencies, but working around * this doubles complexity of tracking * an xfer. */ - if (nframes >= xfer->nframes) + if (nframes >= xfer->ux_nframes) break; status = le32toh(itd->itd.itd_ctl[i]); @@ -1021,24 +1071,73 @@ ehci_idone(struct ehci_xfer *ex) if (EHCI_ITD_GET_STATUS(status) != 0) len = 0; /*No valid data on error*/ - xfer->frlengths[nframes++] = len; + xfer->ux_frlengths[nframes++] = len; actlen += len; } - if (nframes >= xfer->nframes) + if (nframes >= xfer->ux_nframes) break; } - xfer->actlen = actlen; - xfer->status = USBD_NORMAL_COMPLETION; + xfer->ux_actlen = actlen; + xfer->ux_status = USBD_NORMAL_COMPLETION; goto end; } + if (xfertype == UE_ISOCHRONOUS && speed == USB_SPEED_FULL) { + /* FS isoc transfer */ + struct ehci_soft_sitd *sitd; + int nframes, len; + + nframes = 0; + actlen = 0; + + for (sitd = ex->ex_sitdstart; sitd != NULL; sitd = sitd->xfer_next) { + usb_syncmem(&sitd->dma,sitd->offs + offsetof(ehci_sitd_t, sitd_buffer), + sizeof(sitd->sitd.sitd_buffer), BUS_DMASYNC_POSTWRITE | + BUS_DMASYNC_POSTREAD); + + /* + * XXX - driver didn't fill in the frame full + * of uframes. This leads to scheduling + * inefficiencies, but working around + * this doubles complexity of tracking + * an xfer. + */ + if (nframes >= xfer->ux_nframes) + break; + + status = le32toh(sitd->sitd.sitd_trans); + len = EHCI_SITD_GET_LEN(status); + if (status & (EHCI_SITD_ERR|EHCI_SITD_BUFERR| + EHCI_SITD_BABBLE|EHCI_SITD_XACTERR|EHCI_SITD_MISS)) { + /* No valid data on error */ + len = xfer->ux_frlengths[nframes]; + } + + /* + * frlengths[i]: # of bytes to send + * len: # of bytes host didn't send + */ + xfer->ux_frlengths[nframes] -= len; + /* frlengths[i]: # of bytes host sent */ + actlen += xfer->ux_frlengths[nframes++]; + + if (nframes >= xfer->ux_nframes) + break; + } + + xfer->ux_actlen = actlen; + xfer->ux_status = USBD_NORMAL_COMPLETION; + goto end; + } + KASSERT(xfertype != UE_ISOCHRONOUS); + /* Continue processing xfers using queue heads */ - lsqtd = ex->sqtdend; + lsqtd = ex->ex_sqtdend; actlen = 0; - for (sqtd = ex->sqtdstart; sqtd != lsqtd->nextqtd; + for (sqtd = ex->ex_sqtdstart; sqtd != lsqtd->nextqtd; sqtd = sqtd->nextqtd) { usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); @@ -1060,25 +1159,25 @@ ehci_idone(struct ehci_xfer *ex) * packets within the qTD. */ if ((sqtd != lsqtd->nextqtd || EHCI_QTD_GET_BYTES(status)) && - xfer->pipe->device->default_pipe != xfer->pipe) { + xfer->ux_pipe->up_dev->ud_pipe0 != xfer->ux_pipe) { USBHIST_LOG(ehcidebug, "toggle update status=0x%08x nstatus=0x%08x", status, nstatus, 0, 0); #if 0 ehci_dump_sqh(epipe->sqh); - ehci_dump_sqtds(ex->sqtdstart); + ehci_dump_sqtds(ex->ex_sqtdstart); #endif epipe->nexttoggle = EHCI_QTD_GET_TOGGLE(nstatus); } - USBHIST_LOG(ehcidebug, "len=%d actlen=%d status=0x%08x", xfer->length, + USBHIST_LOG(ehcidebug, "len=%d actlen=%d status=0x%08x", xfer->ux_length, actlen, status, 0); - xfer->actlen = actlen; + xfer->ux_actlen = actlen; if (status & EHCI_QTD_HALTED) { #ifdef EHCI_DEBUG USBHIST_LOG(ehcidebug, "halted addr=%d endpt=0x%02x", - xfer->pipe->device->address, - xfer->pipe->endpoint->edesc->bEndpointAddress, 0, 0); + xfer->ux_pipe->up_dev->ud_addr, + xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress, 0, 0); USBHIST_LOG(ehcidebug, "cerr=%d pid=%d stat=%#x", EHCI_QTD_GET_CERR(status), EHCI_QTD_GET_PID(status), status, 0); @@ -1097,7 +1196,7 @@ ehci_idone(struct ehci_xfer *ex) status & EHCI_QTD_PINGSTATE ? 1 : 0); ehci_dump_sqh(epipe->sqh); - ehci_dump_sqtds(ex->sqtdstart); + ehci_dump_sqtds(ex->ex_sqtdstart); #endif /* low&full speed has an extra error flag */ if (EHCI_QH_GET_EPS(epipe->sqh->qh.qh_endp) != @@ -1106,9 +1205,9 @@ ehci_idone(struct ehci_xfer *ex) else status &= EHCI_QTD_STATERRS; if (status == 0) /* no other errors means a stall */ { - xfer->status = USBD_STALLED; + xfer->ux_status = USBD_STALLED; } else { - xfer->status = USBD_IOERROR; /* more info XXX */ + xfer->ux_status = USBD_IOERROR; /* more info XXX */ } /* XXX need to reset TT on missed microframe */ if (status & EHCI_QTD_MISSEDMICRO) { @@ -1117,13 +1216,15 @@ ehci_idone(struct ehci_xfer *ex) device_xname(sc->sc_dev)); } } else { - xfer->status = USBD_NORMAL_COMPLETION; + xfer->ux_status = USBD_NORMAL_COMPLETION; } end: - /* XXX transfer_complete memcpys out transfer data (for in endpoints) + /* + * XXX transfer_complete memcpys out transfer data (for in endpoints) * during this call, before methods->done is called: dma sync required - * beforehand? */ + * beforehand? + */ usb_transfer_complete(xfer); USBHIST_LOG(ehcidebug, "ex=%p done", ex, 0, 0, 0); } @@ -1137,12 +1238,12 @@ Static void ehci_waitintr(ehci_softc_t *sc, usbd_xfer_handle xfer) { int timo; - u_int32_t intrs; + uint32_t intrs; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); - xfer->status = USBD_IN_PROGRESS; - for (timo = xfer->timeout; timo >= 0; timo--) { + xfer->ux_status = USBD_IN_PROGRESS; + for (timo = xfer->ux_timeout; timo >= 0; timo--) { usb_delay_ms(&sc->sc_bus, 1); if (sc->sc_dying) break; @@ -1157,14 +1258,14 @@ ehci_waitintr(ehci_softc_t *sc, usbd_xfe mutex_spin_enter(&sc->sc_intr_lock); ehci_intr1(sc); mutex_spin_exit(&sc->sc_intr_lock); - if (xfer->status != USBD_IN_PROGRESS) + if (xfer->ux_status != USBD_IN_PROGRESS) return; } } /* Timeout */ USBHIST_LOG(ehcidebug, "timeout", 0, 0, 0, 0); - xfer->status = USBD_TIMEOUT; + xfer->ux_status = USBD_TIMEOUT; mutex_enter(&sc->sc_lock); usb_transfer_complete(xfer); mutex_exit(&sc->sc_lock); @@ -1174,7 +1275,7 @@ ehci_waitintr(ehci_softc_t *sc, usbd_xfe Static void ehci_poll(struct usbd_bus *bus) { - ehci_softc_t *sc = bus->hci_private; + ehci_softc_t *sc = bus->ub_hcpriv; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -1215,7 +1316,7 @@ ehci_detach(struct ehci_softc *sc, int f rv = config_detach(sc->sc_child, flags); if (rv != 0) - return (rv); + return rv; callout_halt(&sc->sc_tmo_intrlist, NULL); callout_destroy(&sc->sc_tmo_intrlist); @@ -1241,7 +1342,7 @@ ehci_detach(struct ehci_softc *sc, int f EOWRITE4(sc, EHCI_CONFIGFLAG, 0); - return (rv); + return rv; } @@ -1279,7 +1380,7 @@ ehci_suspend(device_t dv, const pmf_qual USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); mutex_spin_enter(&sc->sc_intr_lock); - sc->sc_bus.use_polling++; + sc->sc_bus.ub_usepolling++; mutex_spin_exit(&sc->sc_intr_lock); for (i = 1; i <= sc->sc_noport; i++) { @@ -1317,7 +1418,7 @@ ehci_suspend(device_t dv, const pmf_qual printf("%s: config timeout\n", device_xname(dv)); mutex_spin_enter(&sc->sc_intr_lock); - sc->sc_bus.use_polling--; + sc->sc_bus.ub_usepolling--; mutex_spin_exit(&sc->sc_intr_lock); return true; @@ -1395,70 +1496,35 @@ ehci_shutdown(device_t self, int flags) return true; } -Static usbd_status -ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - struct ehci_softc *sc = bus->hci_private; - usbd_status err; - - err = usb_allocmem_flags(&sc->sc_bus, size, 0, dma, USBMALLOC_MULTISEG); -#ifdef EHCI_DEBUG - if (err) - printf("ehci_allocm: usb_allocmem_flags()= %s (%d)\n", - usbd_errstr(err), err); -#endif - if (err == USBD_NOMEM) - err = usb_reserve_allocm(&sc->sc_dma_reserve, dma, size); -#ifdef EHCI_DEBUG - if (err) - printf("ehci_allocm: usb_reserve_allocm()= %s (%d)\n", - usbd_errstr(err), err); -#endif - return (err); -} - -Static void -ehci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - struct ehci_softc *sc = bus->hci_private; - - if (dma->block->flags & USB_DMA_RESERVE) { - usb_reserve_freem(&sc->sc_dma_reserve, - dma); - return; - } - usb_freemem(&sc->sc_bus, dma); -} - Static usbd_xfer_handle ehci_allocx(struct usbd_bus *bus) { - struct ehci_softc *sc = bus->hci_private; + struct ehci_softc *sc = bus->ub_hcpriv; usbd_xfer_handle xfer; xfer = pool_cache_get(sc->sc_xferpool, PR_NOWAIT); if (xfer != NULL) { memset(xfer, 0, sizeof(struct ehci_xfer)); #ifdef DIAGNOSTIC - EXFER(xfer)->isdone = 1; - xfer->busy_free = XFER_BUSY; + EXFER(xfer)->ex_isdone = 1; + xfer->ux_state = XFER_BUSY; #endif } - return (xfer); + return xfer; } Static void ehci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) { - struct ehci_softc *sc = bus->hci_private; + struct ehci_softc *sc = bus->ub_hcpriv; #ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { + if (xfer->ux_state != XFER_BUSY) { printf("ehci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); + xfer->ux_state); } - xfer->busy_free = XFER_FREE; - if (!EXFER(xfer)->isdone) { + xfer->ux_state = XFER_FREE; + if (!EXFER(xfer)->ex_isdone) { printf("ehci_freex: !isdone\n"); } #endif @@ -1468,7 +1534,7 @@ ehci_freex(struct usbd_bus *bus, usbd_xf Static void ehci_get_lock(struct usbd_bus *bus, kmutex_t **lock) { - struct ehci_softc *sc = bus->hci_private; + struct ehci_softc *sc = bus->ub_hcpriv; *lock = &sc->sc_lock; } @@ -1654,7 +1720,7 @@ ehci_dump_sqh(ehci_soft_qh_t *sqh) ehci_qh_t *qh = &sqh->qh; ehci_link_t link; #endif - u_int32_t endp, endphub; + uint32_t endp, endphub; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); usb_syncmem(&sqh->dma, sqh->offs, @@ -1751,20 +1817,21 @@ ehci_dump_exfer(struct ehci_xfer *ex) USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "ex = %p sqtdstart = %p end = %p", - ex, ex->sqtdstart, ex->sqtdend, 0); + ex, ex->ex_sqtdstart, ex->ex_sqtdend, 0); USBHIST_LOG(ehcidebug, " itdstart = %p end = %p isdone = %d", - ex->itdstart, ex->itdend, ex->isdone, 0); + ex->ex_itdstart, ex->ex_itdend, ex->ex_isdone, 0); } #endif Static usbd_status ehci_open(usbd_pipe_handle pipe) { - usbd_device_handle dev = pipe->device; - ehci_softc_t *sc = dev->bus->hci_private; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - u_int8_t addr = dev->address; - u_int8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); + usbd_device_handle dev = pipe->up_dev; + ehci_softc_t *sc = dev->ud_bus->ub_hcpriv; + usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc; + uint8_t rhaddr = dev->ud_bus->ub_rhaddr; + uint8_t addr = dev->ud_addr; + uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; ehci_soft_qh_t *sqh; usbd_status err; @@ -1774,64 +1841,57 @@ ehci_open(usbd_pipe_handle pipe) USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "pipe=%p, addr=%d, endpt=%d (%d)", - pipe, addr, ed->bEndpointAddress, sc->sc_addr); + pipe, addr, ed->bEndpointAddress, rhaddr); - if (dev->myhsport) { + if (dev->ud_myhsport) { /* * When directly attached FS/LS device while doing embedded * transaction translations and we are the hub, set the hub * address to 0 (us). */ if (!(sc->sc_flags & EHCIF_ETTF) - || (dev->myhsport->parent->address != sc->sc_addr)) { - hshubaddr = dev->myhsport->parent->address; + || (dev->ud_myhsport->up_parent->ud_addr != rhaddr)) { + hshubaddr = dev->ud_myhsport->up_parent->ud_addr; } else { hshubaddr = 0; } - hshubport = dev->myhsport->portno; + hshubport = dev->ud_myhsport->up_portno; } else { hshubaddr = 0; hshubport = 0; } if (sc->sc_dying) - return (USBD_IOERROR); + return USBD_IOERROR; /* toggle state needed for bulk endpoints */ - epipe->nexttoggle = pipe->endpoint->datatoggle; + epipe->nexttoggle = pipe->up_endpoint->ue_toggle; - if (addr == sc->sc_addr) { + if (addr == rhaddr) { switch (ed->bEndpointAddress) { case USB_CONTROL_ENDPOINT: - pipe->methods = &ehci_root_ctrl_methods; + pipe->up_methods = &roothub_ctrl_methods; break; - case UE_DIR_IN | EHCI_INTR_ENDPT: - pipe->methods = &ehci_root_intr_methods; + case UE_DIR_IN | USBROOTHUB_INTR_ENDPT: + pipe->up_methods = &ehci_root_intr_methods; break; default: USBHIST_LOG(ehcidebug, "bad bEndpointAddress 0x%02x", ed->bEndpointAddress, 0, 0, 0); - return (USBD_INVAL); + return USBD_INVAL; } - return (USBD_NORMAL_COMPLETION); + return USBD_NORMAL_COMPLETION; } /* XXX All this stuff is only valid for async. */ - switch (dev->speed) { + switch (dev->ud_speed) { case USB_SPEED_LOW: speed = EHCI_QH_SPEED_LOW; break; case USB_SPEED_FULL: speed = EHCI_QH_SPEED_FULL; break; case USB_SPEED_HIGH: speed = EHCI_QH_SPEED_HIGH; break; - default: panic("ehci_open: bad device speed %d", dev->speed); + default: panic("ehci_open: bad device speed %d", dev->ud_speed); } - if (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_ISOCHRONOUS) { - aprint_error_dev(sc->sc_dev, "error opening low/full speed " - "isoc endpoint.\n"); - aprint_normal_dev(sc->sc_dev, "a low/full speed device is " - "attached to a USB2 hub, and transaction translations are " - "not yet supported.\n"); - aprint_normal_dev(sc->sc_dev, "reattach the device to the " - "root hub instead.\n"); + if (speed == EHCI_QH_SPEED_LOW && xfertype == UE_ISOCHRONOUS) { USBHIST_LOG(ehcidebug, "hshubaddr=%d hshubport=%d", hshubaddr, hshubport, 0, 0); return USBD_INVAL; @@ -1849,7 +1909,7 @@ ehci_open(usbd_pipe_handle pipe) if (xfertype != UE_ISOCHRONOUS) { sqh = ehci_alloc_sqh(sc); if (sqh == NULL) - return (USBD_NOMEM); + return USBD_NOMEM; /* qh_link filled when the QH is added */ sqh->qh.qh_endp = htole32( EHCI_QH_SET_ADDR(addr) | @@ -1894,20 +1954,20 @@ ehci_open(usbd_pipe_handle pipe) #endif if (err) goto bad; - pipe->methods = &ehci_device_ctrl_methods; + pipe->up_methods = &ehci_device_ctrl_methods; mutex_enter(&sc->sc_lock); ehci_add_qh(sc, sqh, sc->sc_async_head); mutex_exit(&sc->sc_lock); break; case UE_BULK: - pipe->methods = &ehci_device_bulk_methods; + pipe->up_methods = &ehci_device_bulk_methods; mutex_enter(&sc->sc_lock); ehci_add_qh(sc, sqh, sc->sc_async_head); mutex_exit(&sc->sc_lock); break; case UE_INTERRUPT: - pipe->methods = &ehci_device_intr_methods; - ival = pipe->interval; + pipe->up_methods = &ehci_device_intr_methods; + ival = pipe->up_interval; if (ival == USBD_DEFAULT_INTERVAL) { if (speed == EHCI_QH_SPEED_HIGH) { if (ed->bInterval > 16) { @@ -1927,7 +1987,10 @@ ehci_open(usbd_pipe_handle pipe) goto bad; break; case UE_ISOCHRONOUS: - pipe->methods = &ehci_device_isoc_methods; + if (speed == EHCI_QH_SPEED_HIGH) + pipe->up_methods = &ehci_device_isoc_methods; + else + pipe->up_methods = &ehci_device_fs_isoc_methods; if (ed->bInterval == 0 || ed->bInterval > 16) { printf("ehci: opening pipe with invalid bInterval\n"); err = USBD_INVAL; @@ -1946,12 +2009,12 @@ ehci_open(usbd_pipe_handle pipe) err = USBD_INVAL; goto bad; } - return (USBD_NORMAL_COMPLETION); + return USBD_NORMAL_COMPLETION; bad: if (sqh != NULL) ehci_free_sqh(sc, sqh); - return (err); + return err; } /* @@ -2014,7 +2077,7 @@ Static void ehci_set_qh_qtd(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd) { int i; - u_int32_t status; + uint32_t status; /* Save toggle bit and ping status. */ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), @@ -2086,10 +2149,10 @@ ehci_rem_free_itd_chain(ehci_softc_t *sc prev = NULL; - if (exfer->itdstart == NULL || exfer->itdend == NULL) + if (exfer->ex_itdstart == NULL || exfer->ex_itdend == NULL) panic("ehci isoc xfer being freed, but with no itd chain\n"); - for (itd = exfer->itdstart; itd != NULL; itd = itd->xfer_next) { + for (itd = exfer->ex_itdstart; itd != NULL; itd = itd->xfer_next) { prev = itd->u.frame_list.prev; /* Unlink itd from hardware chain, or frame array */ if (prev == NULL) { /* We're at the table head */ @@ -2097,7 +2160,7 @@ ehci_rem_free_itd_chain(ehci_softc_t *sc sc->sc_flist[itd->slot] = itd->itd.itd_next; usb_syncmem(&sc->sc_fldma, sizeof(ehci_link_t) * itd->slot, - sizeof(ehci_link_t), + sizeof(ehci_link_t), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); if (itd->u.frame_list.next != NULL) @@ -2107,7 +2170,7 @@ ehci_rem_free_itd_chain(ehci_softc_t *sc prev->itd.itd_next = itd->itd.itd_next; usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_next), - sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE); + sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE); prev->u.frame_list.next = itd->u.frame_list.next; if (itd->u.frame_list.next != NULL) @@ -2116,136 +2179,83 @@ ehci_rem_free_itd_chain(ehci_softc_t *sc } prev = NULL; - for (itd = exfer->itdstart; itd != NULL; itd = itd->xfer_next) { + for (itd = exfer->ex_itdstart; itd != NULL; itd = itd->xfer_next) { if (prev != NULL) ehci_free_itd(sc, prev); prev = itd; } if (prev) ehci_free_itd(sc, prev); - exfer->itdstart = NULL; - exfer->itdend = NULL; + exfer->ex_itdstart = NULL; + exfer->ex_itdend = NULL; } -/***********/ - -/* - * Data structures and routines to emulate the root hub. - */ -Static usb_device_descriptor_t ehci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x02}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_HSHUBSTT, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -Static const usb_device_qualifier_t ehci_odevd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE_QUALIFIER, /* type */ - {0x00, 0x02}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - 1, /* # of configurations */ - 0 -}; - -Static const usb_config_descriptor_t ehci_confd = { - USB_CONFIG_DESCRIPTOR_SIZE, - UDESC_CONFIG, - {USB_CONFIG_DESCRIPTOR_SIZE + - USB_INTERFACE_DESCRIPTOR_SIZE + - USB_ENDPOINT_DESCRIPTOR_SIZE}, - 1, - 1, - 0, - UC_ATTR_MBO | UC_SELF_POWERED, - 0 /* max power */ -}; - -Static const usb_interface_descriptor_t ehci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_HSHUBSTT, - 0 -}; +Static void +ehci_rem_free_sitd_chain(ehci_softc_t *sc, struct ehci_xfer *exfer) +{ + struct ehci_soft_sitd *sitd, *prev; -Static const usb_endpoint_descriptor_t ehci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | EHCI_INTR_ENDPT, - UE_INTERRUPT, - {8, 0}, /* max packet */ - 12 -}; + prev = NULL; -Static const usb_hub_descriptor_t ehci_hubd = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 0, - {0,0}, - 0, - 0, - {""}, - {""}, -}; + if (exfer->ex_sitdstart == NULL || exfer->ex_sitdend == NULL) + panic("ehci isoc xfer being freed, but with no sitd chain\n"); -/* - * Simulate a hardware hub by handling all the necessary requests. - */ -Static usbd_status -ehci_root_ctrl_transfer(usbd_xfer_handle xfer) -{ - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; - usbd_status err; + for (sitd = exfer->ex_sitdstart; sitd != NULL; sitd = sitd->xfer_next) { + prev = sitd->u.frame_list.prev; + /* Unlink sitd from hardware chain, or frame array */ + if (prev == NULL) { /* We're at the table head */ + sc->sc_softsitds[sitd->slot] = sitd->u.frame_list.next; + sc->sc_flist[sitd->slot] = sitd->sitd.sitd_next; + usb_syncmem(&sc->sc_fldma, + sizeof(ehci_link_t) * sitd->slot, + sizeof(ehci_link_t), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - /* Insert last in queue. */ - mutex_enter(&sc->sc_lock); - err = usb_insert_transfer(xfer); - mutex_exit(&sc->sc_lock); - if (err) - return (err); + if (sitd->u.frame_list.next != NULL) + sitd->u.frame_list.next->u.frame_list.prev = NULL; + } else { + /* XXX this part is untested... */ + prev->sitd.sitd_next = sitd->sitd.sitd_next; + usb_syncmem(&sitd->dma, + sitd->offs + offsetof(ehci_sitd_t, sitd_next), + sizeof(sitd->sitd.sitd_next), BUS_DMASYNC_PREWRITE); + + prev->u.frame_list.next = sitd->u.frame_list.next; + if (sitd->u.frame_list.next != NULL) + sitd->u.frame_list.next->u.frame_list.prev = prev; + } + } - /* Pipe isn't running, start first */ - return (ehci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); + prev = NULL; + for (sitd = exfer->ex_sitdstart; sitd != NULL; sitd = sitd->xfer_next) { + if (prev != NULL) + ehci_free_sitd(sc, prev); + prev = sitd; + } + if (prev) + ehci_free_sitd(sc, prev); + exfer->ex_sitdstart = NULL; + exfer->ex_sitdend = NULL; } -Static usbd_status -ehci_root_ctrl_start(usbd_xfer_handle xfer) +/***********/ + +Static int +ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, + void *buf, int buflen) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; - usb_device_request_t *req; - void *buf = NULL; - int port, i; - int len, value, index, l, totlen = 0; - usb_port_status_t ps; + ehci_softc_t *sc = bus->ub_hcpriv; usb_hub_descriptor_t hubd; - usbd_status err; - u_int32_t v; + usb_port_status_t ps; + uint16_t len, value, index; + int l, totlen = 0; + int port, i; + uint32_t v; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - /* XXX panic */ - return (USBD_INVAL); -#endif - req = &xfer->request; + return -1; USBHIST_LOG(ehcidebug, "type=0x%02x request=%02x", req->bmRequestType, req->bRequest, 0, 0); @@ -2254,142 +2264,37 @@ ehci_root_ctrl_start(usbd_xfer_handle xf value = UGETW(req->wValue); index = UGETW(req->wIndex); - if (len != 0) - buf = KERNADDR(&xfer->dmabuf, 0); - #define C(x,y) ((x) | ((y) << 8)) - switch(C(req->bRequest, req->bmRequestType)) { - case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): - case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): - case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* - * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops - * for the integrated root hub. - */ - break; - case C(UR_GET_CONFIG, UT_READ_DEVICE): - if (len > 0) { - *(u_int8_t *)buf = sc->sc_conf; - totlen = 1; - } - break; + switch (C(req->bRequest, req->bmRequestType)) { case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): - USBHIST_LOG(ehcidebug, "wValue=0x%04x", value, 0, 0, 0); if (len == 0) break; - switch(value >> 8) { - case UDESC_DEVICE: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - USETW(ehci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &ehci_devd, l); + switch (value) { + case C(0, UDESC_DEVICE): { + usb_device_descriptor_t devd; + totlen = min(buflen, sizeof(devd)); + memcpy(&devd, buf, totlen); + USETW(devd.idVendor, sc->sc_id_vendor); + memcpy(buf, &devd, totlen); break; - /* - * We can't really operate at another speed, but the spec says - * we need this descriptor. - */ - case UDESC_DEVICE_QUALIFIER: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - memcpy(buf, &ehci_odevd, l); + + } +#define sd ((usb_string_descriptor_t *)buf) + case C(1, UDESC_STRING): + /* Vendor */ + totlen = usb_makestrdesc(sd, len, sc->sc_vendor); break; - /* - * We can't really operate at another speed, but the spec says - * we need this descriptor. - */ - case UDESC_OTHER_SPEED_CONFIGURATION: - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &ehci_confd, l); - ((usb_config_descriptor_t *)buf)->bDescriptorType = - value >> 8; - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ehci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ehci_endpd, l); + case C(2, UDESC_STRING): + /* Product */ + totlen = usb_makestrdesc(sd, len, "EHCI root hub"); break; - case UDESC_STRING: -#define sd ((usb_string_descriptor_t *)buf) - switch (value & 0xff) { - case 0: /* Language table */ - totlen = usb_makelangtbl(sd, len); - break; - case 1: /* Vendor */ - totlen = usb_makestrdesc(sd, len, - sc->sc_vendor); - break; - case 2: /* Product */ - totlen = usb_makestrdesc(sd, len, - "EHCI root hub"); - break; - } #undef sd - break; default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_INTERFACE, UT_READ_INTERFACE): - if (len > 0) { - *(u_int8_t *)buf = 0; - totlen = 1; - } - break; - case C(UR_GET_STATUS, UT_READ_DEVICE): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED); - totlen = 2; + /* default from usbroothub */ + return buflen; } break; - case C(UR_GET_STATUS, UT_READ_INTERFACE): - case C(UR_GET_STATUS, UT_READ_ENDPOINT): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus, 0); - totlen = 2; - } - break; - case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): - if (value >= USB_MAX_DEVICES) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_addr = value; - break; - case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - if (value != 0 && value != 1) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_conf = value; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_DEVICE): - case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): - case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): - break; - case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): - break; + /* Hub requests */ case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): break; @@ -2398,14 +2303,13 @@ ehci_root_ctrl_start(usbd_xfer_handle xf "UR_CLEAR_PORT_FEATURE port=%d feature=%d", index, value, 0, 0); if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; + return -1; } port = EHCI_PORTSC(index); v = EOREAD4(sc, port); USBHIST_LOG(ehcidebug, "portsc=0x%08x", v, 0, 0, 0); v &= ~EHCI_PS_CLEAR; - switch(value) { + switch (value) { case UHF_PORT_ENABLE: EOWRITE4(sc, port, v &~ EHCI_PS_PE); break; @@ -2453,8 +2357,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xf sc->sc_isreset[index] = 0; break; default: - err = USBD_IOERROR; - goto ret; + return -1; } #if 0 switch(value) { @@ -2472,10 +2375,10 @@ ehci_root_ctrl_start(usbd_xfer_handle xf if (len == 0) break; if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; + return -1; } - hubd = ehci_hubd; + totlen = min(buflen, sizeof(hubd)); + memcpy(&hubd, buf, totlen); hubd.bNbrPorts = sc->sc_noport; v = EOREAD4(sc, EHCI_HCSPARAMS); USETW(hubd.wHubCharacteristics, @@ -2486,14 +2389,12 @@ ehci_root_ctrl_start(usbd_xfer_handle xf for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8) hubd.DeviceRemovable[i++] = 0; /* XXX can't find out? */ hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i; - l = min(len, hubd.bDescLength); - totlen = l; - memcpy(buf, &hubd, l); + totlen = min(totlen, hubd.bDescLength); + memcpy(buf, &hubd, totlen); break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): if (len != 4) { - err = USBD_IOERROR; - goto ret; + return -1; } memset(buf, 0, len); /* ? XXX */ totlen = len; @@ -2501,12 +2402,10 @@ ehci_root_ctrl_start(usbd_xfer_handle xf case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): USBHIST_LOG(ehcidebug, "get port status i=%d", index, 0, 0, 0); if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; + return -1; } if (len != 4) { - err = USBD_IOERROR; - goto ret; + return -1; } v = EOREAD4(sc, EHCI_PORTSC(index)); USBHIST_LOG(ehcidebug, "port status=0x%04x", v, 0, 0, 0); @@ -2536,19 +2435,16 @@ ehci_root_ctrl_start(usbd_xfer_handle xf if (v & EHCI_PS_OCC) i |= UPS_C_OVERCURRENT_INDICATOR; if (sc->sc_isreset[index]) i |= UPS_C_PORT_RESET; USETW(ps.wPortChange, i); - l = min(len, sizeof ps); - memcpy(buf, &ps, l); - totlen = l; + totlen = min(len, sizeof(ps)); + memcpy(buf, &ps, totlen); break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - err = USBD_IOERROR; - goto ret; + return -1; case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): break; case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; + return -1; } port = EHCI_PORTSC(index); v = EOREAD4(sc, port); @@ -2579,8 +2475,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xf /* Wait for reset to complete. */ usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY); if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; + return -1; } /* * An embedded transaction translator will automatically @@ -2595,8 +2490,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xf usb_delay_ms(&sc->sc_bus, EHCI_PORT_RESET_COMPLETE); if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; + return -1; } } @@ -2606,7 +2500,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xf if (v & EHCI_PS_PR) { printf("%s: port reset timeout\n", device_xname(sc->sc_dev)); - return (USBD_TIMEOUT); + return USBD_TIMEOUT; } if (!(v & EHCI_PS_PE)) { /* Not a high speed device, give up ownership.*/ @@ -2635,8 +2529,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xf EOWRITE4(sc, port, v | EHCI_PS_PIC); break; default: - err = USBD_IOERROR; - goto ret; + return -1; } break; case C(UR_CLEAR_TT_BUFFER, UT_WRITE_CLASS_OTHER): @@ -2645,24 +2538,18 @@ ehci_root_ctrl_start(usbd_xfer_handle xf case C(UR_STOP_TT, UT_WRITE_CLASS_OTHER): break; default: - err = USBD_IOERROR; - goto ret; + /* default from usbroothub */ + return buflen; } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - mutex_enter(&sc->sc_lock); - xfer->status = err; - usb_transfer_complete(xfer); - mutex_exit(&sc->sc_lock); - return (USBD_IN_PROGRESS); + + return totlen; } Static void ehci_disown(ehci_softc_t *sc, int index, int lowspeed) { int port; - u_int32_t v; + uint32_t v; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -2688,31 +2575,10 @@ ehci_disown(ehci_softc_t *sc, int index, EOWRITE4(sc, port, v | EHCI_PS_PO); } -/* Abort a root control request. */ -Static void -ehci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -Static void -ehci_root_ctrl_close(usbd_pipe_handle pipe) -{ - USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); - /* Nothing to do. */ -} - -Static void -ehci_root_ctrl_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - Static usbd_status ehci_root_intr_transfer(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; usbd_status err; /* Insert last in queue. */ @@ -2720,40 +2586,40 @@ ehci_root_intr_transfer(usbd_xfer_handle err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); if (err) - return (err); + return err; /* Pipe isn't running, start first */ - return (ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); + return ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); } Static usbd_status ehci_root_intr_start(usbd_xfer_handle xfer) { - usbd_pipe_handle pipe = xfer->pipe; - ehci_softc_t *sc = pipe->device->bus->hci_private; + usbd_pipe_handle pipe = xfer->ux_pipe; + ehci_softc_t *sc = pipe->up_dev->ud_bus->ub_hcpriv; if (sc->sc_dying) - return (USBD_IOERROR); + return USBD_IOERROR; mutex_enter(&sc->sc_lock); sc->sc_intrxfer = xfer; mutex_exit(&sc->sc_lock); - return (USBD_IN_PROGRESS); + return USBD_IN_PROGRESS; } /* Abort a root interrupt request. */ Static void ehci_root_intr_abort(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; KASSERT(mutex_owned(&sc->sc_lock)); - KASSERT(xfer->pipe->intrxfer == xfer); + KASSERT(xfer->ux_pipe->up_intrxfer == xfer); sc->sc_intrxfer = NULL; - xfer->status = USBD_CANCELLED; + xfer->ux_status = USBD_CANCELLED; usb_transfer_complete(xfer); } @@ -2761,7 +2627,7 @@ ehci_root_intr_abort(usbd_xfer_handle xf Static void ehci_root_intr_close(usbd_pipe_handle pipe) { - ehci_softc_t *sc = pipe->device->bus->hci_private; + ehci_softc_t *sc = pipe->up_dev->ud_bus->ub_hcpriv; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -2773,7 +2639,7 @@ ehci_root_intr_close(usbd_pipe_handle pi Static void ehci_root_intr_done(usbd_xfer_handle xfer) { - xfer->hcpriv = NULL; + xfer->ux_hcpriv = NULL; } /************************/ @@ -2797,7 +2663,7 @@ ehci_alloc_sqh(ehci_softc_t *sc) printf("ehci_alloc_sqh: usb_allocmem()=%d\n", err); #endif if (err) - return (NULL); + return NULL; for(i = 0; i < EHCI_SQH_CHUNK; i++) { offs = i * EHCI_SQH_SIZE; sqh = KERNADDR(&dma, offs); @@ -2812,7 +2678,7 @@ ehci_alloc_sqh(ehci_softc_t *sc) sc->sc_freeqhs = sqh->next; memset(&sqh->qh, 0, sizeof(ehci_qh_t)); sqh->next = NULL; - return (sqh); + return sqh; } Static void @@ -2863,14 +2729,14 @@ ehci_alloc_sqtd(ehci_softc_t *sc) sqtd->xfer = NULL; done: - return (sqtd); + return sqtd; } Static void ehci_free_sqtd(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd) { - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); sqtd->nextqtd = sc->sc_freeqtds; sc->sc_freeqtds = sqtd; @@ -2883,14 +2749,14 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * { ehci_soft_qtd_t *next, *cur; ehci_physaddr_t nextphys; - u_int32_t qtdstatus; + uint32_t qtdstatus; int len, curlen, mps; int i, tog; int pages, pageoffs; bus_size_t curoffs; vaddr_t va, va_offs; - usb_dma_t *dma = &xfer->dmabuf; - u_int16_t flags = xfer->flags; + usb_dma_t *dma = &xfer->ux_dmabuf; + uint16_t flags = xfer->ux_flags; paddr_t a; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -2904,7 +2770,7 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * /* IOC set below */ /* BYTES set below */ ; - mps = UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); + mps = UGETW(epipe->pipe.up_endpoint->ue_edesc->wMaxPacketSize); tog = epipe->nexttoggle; qtdstatus |= EHCI_QTD_SET_TOGGLE(tog); @@ -2931,10 +2797,7 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * curlen -= curlen % mps; USBHIST_LOG(ehcidebug, "multiple QTDs, " "curlen=%d", curlen, 0, 0, 0); -#ifdef DIAGNOSTIC - if (curlen == 0) - panic("ehci_alloc_sqtd_chain: curlen == 0"); -#endif + KASSERT(curlen != 0); } USBHIST_LOG(ehcidebug, "len=%d curlen=%d curoffs=%zu", len, curlen, (size_t)curoffs, 0); @@ -2982,8 +2845,10 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * USBHIST_LOG(ehcidebug, "cbp=0x%08zx end=0x%08zx", (size_t)curoffs, (size_t)(curoffs + curlen), 0, 0); - /* adjust the toggle based on the number of packets in this - qtd */ + /* + * adjust the toggle based on the number of packets in this + * qtd + */ if (((curlen + mps - 1) / mps) & 1) { tog ^= 1; qtdstatus ^= EHCI_QTD_TOGGLE_MASK; @@ -3006,12 +2871,12 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * USBHIST_LOG(ehcidebug, "return sqtd=%p sqtdend=%p", *sp, *ep, 0, 0); - return (USBD_NORMAL_COMPLETION); + return USBD_NORMAL_COMPLETION; nomem: /* XXX free chain */ USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); - return (USBD_NOMEM); + return USBD_NOMEM; } Static void @@ -3044,10 +2909,12 @@ ehci_alloc_itd(ehci_softc_t *sc) mutex_enter(&sc->sc_lock); - /* Find an itd that wasn't freed this frame or last frame. This can + /* + * Find an itd that wasn't freed this frame or last frame. This can * discard itds that were freed before frindex wrapped around * XXX - can this lead to thrashing? Could fix by enabling wrap-around - * interrupt and fiddling with list when that happens */ + * interrupt and fiddling with list when that happens + */ frindex = (EOREAD4(sc, EHCI_FRINDEX) + 1) >> 3; previndex = (frindex != 0) ? frindex - 1 : sc->sc_flsize; @@ -3088,8 +2955,8 @@ ehci_alloc_itd(ehci_softc_t *sc) LIST_REMOVE(itd, u.free_list); memset(&itd->itd, 0, sizeof(ehci_itd_t)); usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_next), - sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE | - BUS_DMASYNC_PREREAD); + sizeof(itd->itd.itd_next), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); itd->u.frame_list.next = NULL; itd->u.frame_list.prev = NULL; @@ -3101,6 +2968,77 @@ ehci_alloc_itd(ehci_softc_t *sc) return itd; } +Static ehci_soft_sitd_t * +ehci_alloc_sitd(ehci_softc_t *sc) +{ + struct ehci_soft_sitd *sitd, *freesitd; + usbd_status err; + int i, offs, frindex, previndex; + usb_dma_t dma; + + USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); + + mutex_enter(&sc->sc_lock); + + /* + * Find an sitd that wasn't freed this frame or last frame. This can + * discard sitds that were freed before frindex wrapped around + * XXX - can this lead to thrashing? Could fix by enabling wrap-around + * interrupt and fiddling with list when that happens + */ + frindex = (EOREAD4(sc, EHCI_FRINDEX) + 1) >> 3; + previndex = (frindex != 0) ? frindex - 1 : sc->sc_flsize; + + freesitd = NULL; + LIST_FOREACH(sitd, &sc->sc_freesitds, u.free_list) { + if (sitd == NULL) + break; + if (sitd->slot != frindex && sitd->slot != previndex) { + freesitd = sitd; + break; + } + } + + if (freesitd == NULL) { + USBHIST_LOG(ehcidebug, "allocating chunk", 0, 0, 0, 0); + err = usb_allocmem(&sc->sc_bus, EHCI_SITD_SIZE * EHCI_SITD_CHUNK, + EHCI_PAGE_SIZE, &dma); + + if (err) { + USBHIST_LOG(ehcidebug, + "alloc returned %d", err, 0, 0, 0); + mutex_exit(&sc->sc_lock); + return NULL; + } + + for (i = 0; i < EHCI_SITD_CHUNK; i++) { + offs = i * EHCI_SITD_SIZE; + sitd = KERNADDR(&dma, offs); + sitd->physaddr = DMAADDR(&dma, offs); + sitd->dma = dma; + sitd->offs = offs; + LIST_INSERT_HEAD(&sc->sc_freesitds, sitd, u.free_list); + } + freesitd = LIST_FIRST(&sc->sc_freesitds); + } + + sitd = freesitd; + LIST_REMOVE(sitd, u.free_list); + memset(&sitd->sitd, 0, sizeof(ehci_sitd_t)); + usb_syncmem(&sitd->dma, sitd->offs + offsetof(ehci_sitd_t, sitd_next), + sizeof(sitd->sitd.sitd_next), BUS_DMASYNC_PREWRITE | + BUS_DMASYNC_PREREAD); + + sitd->u.frame_list.next = NULL; + sitd->u.frame_list.prev = NULL; + sitd->xfer_next = NULL; + sitd->slot = 0; + + mutex_exit(&sc->sc_lock); + + return sitd; +} + Static void ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd) { @@ -3110,6 +3048,15 @@ ehci_free_itd(ehci_softc_t *sc, ehci_sof LIST_INSERT_HEAD(&sc->sc_freeitds, itd, u.free_list); } +Static void +ehci_free_sitd(ehci_softc_t *sc, ehci_soft_sitd_t *sitd) +{ + + KASSERT(mutex_owned(&sc->sc_lock)); + + LIST_INSERT_HEAD(&sc->sc_freesitds, sitd, u.free_list); +} + /****************/ /* @@ -3120,7 +3067,7 @@ Static void ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head) { struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - ehci_softc_t *sc = pipe->device->bus->hci_private; + ehci_softc_t *sc = pipe->up_dev->ud_bus->ub_hcpriv; ehci_soft_qh_t *sqh = epipe->sqh; KASSERT(mutex_owned(&sc->sc_lock)); @@ -3145,12 +3092,12 @@ Static void ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) { #define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - ehci_softc_t *sc = epipe->pipe.device->bus->hci_private; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + ehci_softc_t *sc = epipe->pipe.up_dev->ud_bus->ub_hcpriv; ehci_soft_qh_t *sqh = epipe->sqh; ehci_soft_qtd_t *sqtd; ehci_physaddr_t cur; - u_int32_t qhstatus; + uint32_t qhstatus; int hit; int wake; @@ -3159,44 +3106,42 @@ ehci_abort_xfer(usbd_xfer_handle xfer, u USBHIST_LOG(ehcidebug, "xfer=%p pipe=%p", xfer, epipe, 0, 0); KASSERT(mutex_owned(&sc->sc_lock)); + ASSERT_SLEEPABLE(); if (sc->sc_dying) { /* If we're dying, just do the software part. */ - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); + xfer->ux_status = status; /* make software ignore it */ + callout_stop(&xfer->ux_callout); usb_transfer_complete(xfer); return; } - if (cpu_intr_p() || cpu_softintr_p()) - panic("ehci_abort_xfer: not in process context"); - /* * If an abort is already in progress then just wait for it to * complete and return. */ - if (xfer->hcflags & UXFER_ABORTING) { + if (xfer->ux_hcflags & UXFER_ABORTING) { USBHIST_LOG(ehcidebug, "already aborting", 0, 0, 0, 0); #ifdef DIAGNOSTIC if (status == USBD_TIMEOUT) printf("ehci_abort_xfer: TIMEOUT while aborting\n"); #endif /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; + xfer->ux_status = status; USBHIST_LOG(ehcidebug, "waiting for abort to finish", 0, 0, 0, 0); - xfer->hcflags |= UXFER_ABORTWAIT; - while (xfer->hcflags & UXFER_ABORTING) - cv_wait(&xfer->hccv, &sc->sc_lock); + xfer->ux_hcflags |= UXFER_ABORTWAIT; + while (xfer->ux_hcflags & UXFER_ABORTING) + cv_wait(&xfer->ux_hccv, &sc->sc_lock); return; } - xfer->hcflags |= UXFER_ABORTING; + xfer->ux_hcflags |= UXFER_ABORTING; /* * Step 1: Make interrupt routine and hardware ignore xfer. */ - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); + xfer->ux_status = status; /* make software ignore it */ + callout_stop(&xfer->ux_callout); usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status), @@ -3208,7 +3153,7 @@ ehci_abort_xfer(usbd_xfer_handle xfer, u sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status), sizeof(sqh->qh.qh_qtd.qtd_status), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) { + for (sqtd = exfer->ex_sqtdstart; ; sqtd = sqtd->nextqtd) { usb_syncmem(&sqtd->dma, sqtd->offs + offsetof(ehci_qtd_t, qtd_status), sizeof(sqtd->qtd.qtd_status), @@ -3218,7 +3163,7 @@ ehci_abort_xfer(usbd_xfer_handle xfer, u sqtd->offs + offsetof(ehci_qtd_t, qtd_status), sizeof(sqtd->qtd.qtd_status), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - if (sqtd == exfer->sqtdend) + if (sqtd == exfer->ex_sqtdend) break; } @@ -3246,9 +3191,9 @@ ehci_abort_xfer(usbd_xfer_handle xfer, u BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd)); hit = 0; - for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) { + for (sqtd = exfer->ex_sqtdstart; ; sqtd = sqtd->nextqtd) { hit |= cur == sqtd->physaddr; - if (sqtd == exfer->sqtdend) + if (sqtd == exfer->ex_sqtdend) break; } sqtd = sqtd->nextqtd; @@ -3273,13 +3218,13 @@ ehci_abort_xfer(usbd_xfer_handle xfer, u * Step 4: Execute callback. */ #ifdef DIAGNOSTIC - exfer->isdone = 1; + exfer->ex_isdone = 1; #endif - wake = xfer->hcflags & UXFER_ABORTWAIT; - xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT); + wake = xfer->ux_hcflags & UXFER_ABORTWAIT; + xfer->ux_hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT); usb_transfer_complete(xfer); if (wake) { - cv_broadcast(&xfer->hccv); + cv_broadcast(&xfer->ux_hccv); } KASSERT(mutex_owned(&sc->sc_lock)); @@ -3294,26 +3239,27 @@ ehci_abort_isoc_xfer(usbd_xfer_handle xf struct ehci_xfer *exfer; ehci_softc_t *sc; struct ehci_soft_itd *itd; + struct ehci_soft_sitd *sitd; int i, wake; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); - epipe = (struct ehci_pipe *) xfer->pipe; + epipe = (struct ehci_pipe *) xfer->ux_pipe; exfer = EXFER(xfer); - sc = epipe->pipe.device->bus->hci_private; + sc = epipe->pipe.up_dev->ud_bus->ub_hcpriv; USBHIST_LOG(ehcidebug, "xfer %p pipe %p", xfer, epipe, 0, 0); KASSERT(mutex_owned(&sc->sc_lock)); if (sc->sc_dying) { - xfer->status = status; - callout_stop(&xfer->timeout_handle); + xfer->ux_status = status; + callout_stop(&xfer->ux_callout); usb_transfer_complete(xfer); return; } - if (xfer->hcflags & UXFER_ABORTING) { + if (xfer->ux_hcflags & UXFER_ABORTING) { USBHIST_LOG(ehcidebug, "already aborting", 0, 0, 0, 0); #ifdef DIAGNOSTIC @@ -3321,49 +3267,69 @@ ehci_abort_isoc_xfer(usbd_xfer_handle xf printf("ehci_abort_isoc_xfer: TIMEOUT while aborting\n"); #endif - xfer->status = status; + xfer->ux_status = status; USBHIST_LOG(ehcidebug, "waiting for abort to finish", 0, 0, 0, 0); - xfer->hcflags |= UXFER_ABORTWAIT; - while (xfer->hcflags & UXFER_ABORTING) - cv_wait(&xfer->hccv, &sc->sc_lock); + xfer->ux_hcflags |= UXFER_ABORTWAIT; + while (xfer->ux_hcflags & UXFER_ABORTING) + cv_wait(&xfer->ux_hccv, &sc->sc_lock); goto done; } - xfer->hcflags |= UXFER_ABORTING; + xfer->ux_hcflags |= UXFER_ABORTING; - xfer->status = status; - callout_stop(&xfer->timeout_handle); + xfer->ux_status = status; + callout_stop(&xfer->ux_callout); - for (itd = exfer->itdstart; itd != NULL; itd = itd->xfer_next) { - usb_syncmem(&itd->dma, - itd->offs + offsetof(ehci_itd_t, itd_ctl), - sizeof(itd->itd.itd_ctl), - BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + if (xfer->ux_pipe->up_dev->ud_speed == USB_SPEED_HIGH) { + for (itd = exfer->ex_itdstart; itd != NULL; + itd = itd->xfer_next) { + usb_syncmem(&itd->dma, + itd->offs + offsetof(ehci_itd_t, itd_ctl), + sizeof(itd->itd.itd_ctl), + BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + + for (i = 0; i < 8; i++) { + trans_status = le32toh(itd->itd.itd_ctl[i]); + trans_status &= ~EHCI_ITD_ACTIVE; + itd->itd.itd_ctl[i] = htole32(trans_status); + } - for (i = 0; i < 8; i++) { - trans_status = le32toh(itd->itd.itd_ctl[i]); - trans_status &= ~EHCI_ITD_ACTIVE; - itd->itd.itd_ctl[i] = htole32(trans_status); + usb_syncmem(&itd->dma, + itd->offs + offsetof(ehci_itd_t, itd_ctl), + sizeof(itd->itd.itd_ctl), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); } + } else { + for (sitd = exfer->ex_sitdstart; sitd != NULL; + sitd = sitd->xfer_next) { + usb_syncmem(&sitd->dma, + sitd->offs + offsetof(ehci_sitd_t, sitd_buffer), + sizeof(sitd->sitd.sitd_buffer), + BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); - usb_syncmem(&itd->dma, - itd->offs + offsetof(ehci_itd_t, itd_ctl), - sizeof(itd->itd.itd_ctl), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + trans_status = le32toh(sitd->sitd.sitd_trans); + trans_status &= ~EHCI_SITD_ACTIVE; + sitd->sitd.sitd_trans = htole32(trans_status); + + usb_syncmem(&sitd->dma, + sitd->offs + offsetof(ehci_sitd_t, sitd_buffer), + sizeof(sitd->sitd.sitd_buffer), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + } } - sc->sc_softwake = 1; - usb_schedsoftintr(&sc->sc_bus); + sc->sc_softwake = 1; + usb_schedsoftintr(&sc->sc_bus); cv_wait(&sc->sc_softwake_cv, &sc->sc_lock); #ifdef DIAGNOSTIC - exfer->isdone = 1; + exfer->ex_isdone = 1; #endif - wake = xfer->hcflags & UXFER_ABORTWAIT; - xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT); + wake = xfer->ux_hcflags & UXFER_ABORTWAIT; + xfer->ux_hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT); usb_transfer_complete(xfer); if (wake) { - cv_broadcast(&xfer->hccv); + cv_broadcast(&xfer->ux_hccv); } done: @@ -3375,28 +3341,28 @@ Static void ehci_timeout(void *addr) { struct ehci_xfer *exfer = addr; - struct ehci_pipe *epipe = (struct ehci_pipe *)exfer->xfer.pipe; - ehci_softc_t *sc = epipe->pipe.device->bus->hci_private; + struct ehci_pipe *epipe = (struct ehci_pipe *)exfer->ex_xfer.ux_pipe; + ehci_softc_t *sc = epipe->pipe.up_dev->ud_bus->ub_hcpriv; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "exfer %p", exfer, 0, 0, 0); #ifdef EHCI_DEBUG if (ehcidebug > 1) - usbd_dump_pipe(exfer->xfer.pipe); + usbd_dump_pipe(exfer->ex_xfer.ux_pipe); #endif if (sc->sc_dying) { mutex_enter(&sc->sc_lock); - ehci_abort_xfer(&exfer->xfer, USBD_TIMEOUT); + ehci_abort_xfer(&exfer->ex_xfer, USBD_TIMEOUT); mutex_exit(&sc->sc_lock); return; } /* Execute the abort in a process context. */ - usb_init_task(&exfer->abort_task, ehci_timeout_task, addr, + usb_init_task(&exfer->ex_aborttask, ehci_timeout_task, addr, USB_TASKQ_MPSAFE); - usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task, + usb_add_task(exfer->ex_xfer.ux_pipe->up_dev, &exfer->ex_aborttask, USB_TASKQ_HC); } @@ -3404,7 +3370,7 @@ Static void ehci_timeout_task(void *addr) { usbd_xfer_handle xfer = addr; - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -3420,7 +3386,7 @@ ehci_timeout_task(void *addr) Static usbd_status ehci_device_ctrl_transfer(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; usbd_status err; /* Insert last in queue. */ @@ -3428,47 +3394,41 @@ ehci_device_ctrl_transfer(usbd_xfer_hand err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); if (err) - return (err); + return err; /* Pipe isn't running, start first */ - return (ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); + return ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); } Static usbd_status ehci_device_ctrl_start(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; usbd_status err; if (sc->sc_dying) - return (USBD_IOERROR); + return USBD_IOERROR; -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - /* XXX panic */ - printf("ehci_device_ctrl_transfer: not a request\n"); - return (USBD_INVAL); - } -#endif + KASSERT(xfer->ux_rqflags & URQ_REQUEST); err = ehci_device_request(xfer); if (err) { - return (err); + return err; } - if (sc->sc_bus.use_polling) + if (sc->sc_bus.ub_usepolling) ehci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); + return USBD_IN_PROGRESS; } Static void ehci_device_ctrl_done(usbd_xfer_handle xfer) { struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + usb_device_request_t *req = &xfer->ux_request; int len = UGETW(req->wLength); int rd = req->bmRequestType & UT_READ; @@ -3476,25 +3436,20 @@ ehci_device_ctrl_done(usbd_xfer_handle x USBHIST_LOG(ehcidebug, "xfer=%p", xfer, 0, 0, 0); - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); + KASSERT(xfer->ux_rqflags & URQ_REQUEST); -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - panic("ehci_ctrl_done: not a request"); - } -#endif - - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { + if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(ex)) { ehci_del_intr_list(sc, ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); + ehci_free_sqtd_chain(sc, ex->ex_sqtdstart, NULL); usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_POSTWRITE); if (len) - usb_syncmem(&xfer->dmabuf, 0, len, + usb_syncmem(&xfer->ux_dmabuf, 0, len, rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } - USBHIST_LOG(ehcidebug, "length=%d", xfer->actlen, 0, 0, 0); + USBHIST_LOG(ehcidebug, "length=%d", xfer->ux_actlen, 0, 0, 0); } /* Abort a device control request. */ @@ -3511,7 +3466,7 @@ ehci_device_ctrl_abort(usbd_xfer_handle Static void ehci_device_ctrl_close(usbd_pipe_handle pipe) { - ehci_softc_t *sc = pipe->device->bus->hci_private; + ehci_softc_t *sc = pipe->up_dev->ud_bus->ub_hcpriv; /*struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;*/ USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -3527,10 +3482,10 @@ Static usbd_status ehci_device_request(usbd_xfer_handle xfer) { #define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = epipe->pipe.device; - ehci_softc_t *sc = dev->bus->hci_private; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + usb_device_request_t *req = &xfer->ux_request; + usbd_device_handle dev = epipe->pipe.up_dev; + ehci_softc_t *sc = dev->ud_bus->ub_hcpriv; ehci_soft_qtd_t *setup, *stat, *next; ehci_soft_qh_t *sqh; int isread; @@ -3547,8 +3502,8 @@ ehci_device_request(usbd_xfer_handle xfe req->bmRequestType, req->bRequest, UGETW(req->wValue), UGETW(req->wIndex)); USBHIST_LOG(ehcidebug, "len=%d, addr=%d, endpt=%d", - len, dev->address, - epipe->pipe.endpoint->edesc->bEndpointAddress, 0); + len, dev->ud_addr, + epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress, 0); setup = ehci_alloc_sqtd(sc); if (setup == NULL) { @@ -3565,14 +3520,14 @@ ehci_device_request(usbd_xfer_handle xfe sqh = epipe->sqh; - KASSERTMSG(EHCI_QH_GET_ADDR(le32toh(sqh->qh.qh_endp)) == dev->address, + KASSERTMSG(EHCI_QH_GET_ADDR(le32toh(sqh->qh.qh_endp)) == dev->ud_addr, "address QH %d pipe %d\n", - EHCI_QH_GET_ADDR(le32toh(sqh->qh.qh_endp)), dev->address); + EHCI_QH_GET_ADDR(le32toh(sqh->qh.qh_endp)), dev->ud_addr); KASSERTMSG(EHCI_QH_GET_MPL(le32toh(sqh->qh.qh_endp)) == - UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize), + UGETW(epipe->pipe.up_endpoint->ue_edesc->wMaxPacketSize), "MPS QH %d pipe %d\n", EHCI_QH_GET_MPL(le32toh(sqh->qh.qh_endp)), - UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)); + UGETW(epipe->pipe.up_endpoint->ue_edesc->wMaxPacketSize)); /* Set up data transaction */ if (len != 0) { @@ -3636,23 +3591,23 @@ ehci_device_request(usbd_xfer_handle xfe ehci_dump_sqtds(setup); #endif - exfer->sqtdstart = setup; - exfer->sqtdend = stat; + exfer->ex_sqtdstart = setup; + exfer->ex_sqtdend = stat; #ifdef DIAGNOSTIC - if (!exfer->isdone) { + if (!exfer->ex_isdone) { printf("ehci_device_request: not done, exfer=%p\n", exfer); } - exfer->isdone = 0; + exfer->ex_isdone = 0; #endif /* Insert qTD in QH list. */ ehci_set_qh_qtd(sqh, setup); /* also does usb_syncmem(sqh) */ - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), + if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) { + callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout), ehci_timeout, xfer); } ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; + xfer->ux_status = USBD_IN_PROGRESS; mutex_exit(&sc->sc_lock); #ifdef EHCI_DEBUG @@ -3665,7 +3620,7 @@ ehci_device_request(usbd_xfer_handle xfe ehci_dump_sqtds(setup); #endif - return (USBD_NORMAL_COMPLETION); + return USBD_NORMAL_COMPLETION; bad3: mutex_exit(&sc->sc_lock); @@ -3675,10 +3630,10 @@ ehci_device_request(usbd_xfer_handle xfe bad1: USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); mutex_enter(&sc->sc_lock); - xfer->status = err; + xfer->ux_status = err; usb_transfer_complete(xfer); mutex_exit(&sc->sc_lock); - return (err); + return err; #undef exfer } @@ -3708,7 +3663,7 @@ ehci_intrlist_timeout(void *arg) Static usbd_status ehci_device_bulk_transfer(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; usbd_status err; /* Insert last in queue. */ @@ -3716,19 +3671,19 @@ ehci_device_bulk_transfer(usbd_xfer_hand err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); if (err) - return (err); + return err; /* Pipe isn't running, start first */ - return (ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); + return ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); } Static usbd_status ehci_device_bulk_start(usbd_xfer_handle xfer) { #define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usbd_device_handle dev = epipe->pipe.device; - ehci_softc_t *sc = dev->bus->hci_private; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + usbd_device_handle dev = epipe->pipe.up_dev; + ehci_softc_t *sc = dev->ud_bus->ub_hcpriv; ehci_soft_qtd_t *data, *dataend; ehci_soft_qh_t *sqh; usbd_status err; @@ -3737,20 +3692,17 @@ ehci_device_bulk_start(usbd_xfer_handle USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "xfer=%p len=%d flags=%d", - xfer, xfer->length, xfer->flags, 0); + xfer, xfer->ux_length, xfer->ux_flags, 0); if (sc->sc_dying) - return (USBD_IOERROR); + return USBD_IOERROR; -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_bulk_start: a request"); -#endif + KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); mutex_enter(&sc->sc_lock); - len = xfer->length; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; + len = xfer->ux_length; + endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sqh = epipe->sqh; @@ -3760,10 +3712,10 @@ ehci_device_bulk_start(usbd_xfer_handle &dataend); if (err) { USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); - xfer->status = err; + xfer->ux_status = err; usb_transfer_complete(xfer); mutex_exit(&sc->sc_lock); - return (err); + return err; } #ifdef EHCI_DEBUG @@ -3773,22 +3725,22 @@ ehci_device_bulk_start(usbd_xfer_handle #endif /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; + exfer->ex_sqtdstart = data; + exfer->ex_sqtdend = dataend; #ifdef DIAGNOSTIC - if (!exfer->isdone) { + if (!exfer->ex_isdone) { printf("ehci_device_bulk_start: not done, ex=%p\n", exfer); } - exfer->isdone = 0; + exfer->ex_isdone = 0; #endif ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */ - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), + if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) { + callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout), ehci_timeout, xfer); } ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; + xfer->ux_status = USBD_IN_PROGRESS; mutex_exit(&sc->sc_lock); #ifdef EHCI_DEBUG @@ -3805,10 +3757,10 @@ ehci_device_bulk_start(usbd_xfer_handle ehci_dump_sqtds(data); #endif - if (sc->sc_bus.use_polling) + if (sc->sc_bus.ub_usepolling) ehci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); + return USBD_IN_PROGRESS; #undef exfer } @@ -3827,7 +3779,7 @@ ehci_device_bulk_abort(usbd_xfer_handle Static void ehci_device_bulk_close(usbd_pipe_handle pipe) { - ehci_softc_t *sc = pipe->device->bus->hci_private; + ehci_softc_t *sc = pipe->up_dev->ud_bus->ub_hcpriv; struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -3835,7 +3787,7 @@ ehci_device_bulk_close(usbd_pipe_handle KASSERT(mutex_owned(&sc->sc_lock)); USBHIST_LOG(ehcidebug, "pipe=%p", pipe, 0, 0, 0); - pipe->endpoint->datatoggle = epipe->nexttoggle; + pipe->up_endpoint->ue_toggle = epipe->nexttoggle; ehci_close_pipe(pipe, sc->sc_async_head); } @@ -3843,26 +3795,26 @@ Static void ehci_device_bulk_done(usbd_xfer_handle xfer) { struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - int endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + int endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; int rd = UE_GET_DIR(endpt) == UE_DIR_IN; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "xfer=%p, actlen=%d", - xfer, xfer->actlen, 0, 0); + xfer, xfer->ux_actlen, 0, 0); KASSERT(mutex_owned(&sc->sc_lock)); - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { + if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(ex)) { ehci_del_intr_list(sc, ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - usb_syncmem(&xfer->dmabuf, 0, xfer->length, + ehci_free_sqtd_chain(sc, ex->ex_sqtdstart, NULL); + usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } - USBHIST_LOG(ehcidebug, "length=%d", xfer->actlen, 0, 0, 0); + USBHIST_LOG(ehcidebug, "length=%d", xfer->ux_actlen, 0, 0, 0); } /************************/ @@ -3889,13 +3841,13 @@ ehci_device_setintr(ehci_softc_t *sc, eh ehci_add_qh(sc, sqh, isp->sqh); mutex_exit(&sc->sc_lock); - return (USBD_NORMAL_COMPLETION); + return USBD_NORMAL_COMPLETION; } Static usbd_status ehci_device_intr_transfer(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; usbd_status err; /* Insert last in queue. */ @@ -3903,22 +3855,22 @@ ehci_device_intr_transfer(usbd_xfer_hand err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); if (err) - return (err); + return err; /* * Pipe isn't running (otherwise err would be USBD_INPROG), * so start it first. */ - return (ehci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); + return ehci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); } Static usbd_status ehci_device_intr_start(usbd_xfer_handle xfer) { #define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usbd_device_handle dev = xfer->pipe->device; - ehci_softc_t *sc = dev->bus->hci_private; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; + usbd_device_handle dev = xfer->ux_pipe->up_dev; + ehci_softc_t *sc = dev->ud_bus->ub_hcpriv; ehci_soft_qtd_t *data, *dataend; ehci_soft_qh_t *sqh; usbd_status err; @@ -3927,20 +3879,17 @@ ehci_device_intr_start(usbd_xfer_handle USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "xfer=%p len=%d flags=%d", - xfer, xfer->length, xfer->flags, 0); + xfer, xfer->ux_length, xfer->ux_flags, 0); if (sc->sc_dying) - return (USBD_IOERROR); + return USBD_IOERROR; -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_intr_start: a request"); -#endif + KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); mutex_enter(&sc->sc_lock); - len = xfer->length; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; + len = xfer->ux_length; + endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sqh = epipe->sqh; @@ -3950,10 +3899,10 @@ ehci_device_intr_start(usbd_xfer_handle &dataend); if (err) { USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); - xfer->status = err; + xfer->ux_status = err; usb_transfer_complete(xfer); mutex_exit(&sc->sc_lock); - return (err); + return err; } #ifdef EHCI_DEBUG @@ -3963,22 +3912,22 @@ ehci_device_intr_start(usbd_xfer_handle #endif /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; + exfer->ex_sqtdstart = data; + exfer->ex_sqtdend = dataend; #ifdef DIAGNOSTIC - if (!exfer->isdone) { + if (!exfer->ex_isdone) { printf("ehci_device_intr_start: not done, ex=%p\n", exfer); } - exfer->isdone = 0; + exfer->ex_isdone = 0; #endif ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */ - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), + if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) { + callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout), ehci_timeout, xfer); } ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; + xfer->ux_status = USBD_IN_PROGRESS; mutex_exit(&sc->sc_lock); #ifdef EHCI_DEBUG @@ -3991,10 +3940,10 @@ ehci_device_intr_start(usbd_xfer_handle ehci_dump_sqtds(data); #endif - if (sc->sc_bus.use_polling) + if (sc->sc_bus.ub_usepolling) ehci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); + return USBD_IN_PROGRESS; #undef exfer } @@ -4004,7 +3953,7 @@ ehci_device_intr_abort(usbd_xfer_handle USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "xfer=%p", xfer, 0, 0, 0); - KASSERT(xfer->pipe->intrxfer == xfer); + KASSERT(xfer->ux_pipe->up_intrxfer == xfer); /* * XXX - abort_xfer uses ehci_sync_hc, which syncs via the advance @@ -4017,7 +3966,7 @@ ehci_device_intr_abort(usbd_xfer_handle Static void ehci_device_intr_close(usbd_pipe_handle pipe) { - ehci_softc_t *sc = pipe->device->bus->hci_private; + ehci_softc_t *sc = pipe->up_dev->ud_bus->ub_hcpriv; struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; struct ehci_soft_islot *isp; @@ -4032,8 +3981,8 @@ ehci_device_intr_done(usbd_xfer_handle x { #define exfer EXFER(xfer) struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->ux_pipe; ehci_soft_qtd_t *data, *dataend; ehci_soft_qh_t *sqh; usbd_status err; @@ -4042,18 +3991,18 @@ ehci_device_intr_done(usbd_xfer_handle x USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); USBHIST_LOG(ehcidebug, "xfer=%p, actlen=%d", - xfer, xfer->actlen, 0, 0); + xfer, xfer->ux_actlen, 0, 0); - KASSERT(sc->sc_bus.use_polling || mutex_owned(&sc->sc_lock)); + KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); - if (xfer->pipe->repeat) { - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); + if (xfer->ux_pipe->up_repeat) { + ehci_free_sqtd_chain(sc, ex->ex_sqtdstart, NULL); len = epipe->u.intr.length; - xfer->length = len; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; + xfer->ux_length = len; + endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; - usb_syncmem(&xfer->dmabuf, 0, len, + usb_syncmem(&xfer->ux_dmabuf, 0, len, isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); sqh = epipe->sqh; @@ -4061,36 +4010,36 @@ ehci_device_intr_done(usbd_xfer_handle x &data, &dataend); if (err) { USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); - xfer->status = err; + xfer->ux_status = err; return; } /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; + exfer->ex_sqtdstart = data; + exfer->ex_sqtdend = dataend; #ifdef DIAGNOSTIC - if (!exfer->isdone) { + if (!exfer->ex_isdone) { USBHIST_LOG(ehcidebug, "marked not done, ex = %p", exfer, 0, 0, 0); printf("ehci_device_intr_done: not done, ex=%p\n", exfer); } - exfer->isdone = 0; + exfer->ex_isdone = 0; #endif ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */ - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, - mstohz(xfer->timeout), ehci_timeout, xfer); + if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) { + callout_reset(&xfer->ux_callout, + mstohz(xfer->ux_timeout), ehci_timeout, xfer); } - xfer->status = USBD_IN_PROGRESS; - } else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { + xfer->ux_status = USBD_IN_PROGRESS; + } else if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(ex)) { ehci_del_intr_list(sc, ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; + ehci_free_sqtd_chain(sc, ex->ex_sqtdstart, NULL); + endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; - usb_syncmem(&xfer->dmabuf, 0, xfer->length, + usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } #undef exfer @@ -4099,9 +4048,324 @@ ehci_device_intr_done(usbd_xfer_handle x /************************/ Static usbd_status +ehci_device_fs_isoc_transfer(usbd_xfer_handle xfer) +{ + usbd_status err; + + err = usb_insert_transfer(xfer); + if (err && err != USBD_IN_PROGRESS) + return err; + + return ehci_device_fs_isoc_start(xfer); +} + +Static usbd_status +ehci_device_fs_isoc_start(usbd_xfer_handle xfer) +{ + struct ehci_pipe *epipe; + usbd_device_handle dev; + ehci_softc_t *sc; + struct ehci_xfer *exfer; + ehci_soft_sitd_t *sitd, *prev, *start, *stop; + usb_dma_t *dma_buf; + int i, j, k, frames; + int offs, total_length; + int frindex; + u_int huba, dir; + + USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); + + start = NULL; + prev = NULL; + sitd = NULL; + total_length = 0; + exfer = (struct ehci_xfer *) xfer; + sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + dev = xfer->ux_pipe->up_dev; + epipe = (struct ehci_pipe *)xfer->ux_pipe; + + /* + * To allow continuous transfers, above we start all transfers + * immediately. However, we're still going to get usbd_start_next call + * this when another xfer completes. So, check if this is already + * in progress or not + */ + + if (exfer->ex_sitdstart != NULL) + return USBD_IN_PROGRESS; + + USBHIST_LOG(ehcidebug, "xfer %p len %d flags %d", + xfer, xfer->ux_length, xfer->ux_flags, 0); + + if (sc->sc_dying) + return USBD_IOERROR; + + /* + * To avoid complication, don't allow a request right now that'll span + * the entire frame table. To within 4 frames, to allow some leeway + * on either side of where the hc currently is. + */ + if (epipe->pipe.up_endpoint->ue_edesc->bInterval * + xfer->ux_nframes >= sc->sc_flsize - 4) { + printf("ehci: isoc descriptor requested that spans the entire" + "frametable, too many frames\n"); + return USBD_INVAL; + } + + KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); + +#ifdef DIAGNOSTIC + if (!exfer->ex_isdone) + printf("ehci_device_fs_isoc_start: not done, ex = %p\n", exfer); + exfer->ex_isdone = 0; +#endif + + /* + * Step 1: Allocate and initialize sitds. + */ + + i = epipe->pipe.up_endpoint->ue_edesc->bInterval; + if (i > 16 || i == 0) { + /* Spec page 271 says intervals > 16 are invalid */ + USBHIST_LOG(ehcidebug, "bInterval %d invalid", i, 0, 0, 0); + + return USBD_INVAL; + } + + frames = xfer->ux_nframes; + + if (frames == 0) { + USBHIST_LOG(ehcidebug, "frames == 0", 0, 0, 0, 0); + + return USBD_INVAL; + } + + dma_buf = &xfer->ux_dmabuf; + offs = 0; + + for (i = 0; i < frames; i++) { + sitd = ehci_alloc_sitd(sc); + + if (prev) + prev->xfer_next = sitd; + else + start = sitd; + +#ifdef DIAGNOSTIC + if (xfer->ux_frlengths[i] > 0x3ff) { + printf("ehci: invalid frame length\n"); + xfer->ux_frlengths[i] = 0x3ff; + } +#endif + + sitd->sitd.sitd_trans = htole32(EHCI_SITD_ACTIVE | + EHCI_SITD_SET_LEN(xfer->ux_frlengths[i])); + + /* Set page0 index and offset. */ + sitd->sitd.sitd_buffer[0] = htole32(DMAADDR(dma_buf, offs)); + + total_length += xfer->ux_frlengths[i]; + offs += xfer->ux_frlengths[i]; + + sitd->sitd.sitd_buffer[1] = + htole32(EHCI_SITD_SET_BPTR(DMAADDR(dma_buf, offs - 1))); + + huba = dev->ud_myhsport->up_parent->ud_addr; + +/* if (sc->sc_flags & EHCIF_FREESCALE) { + // Set hub address to 0 if embedded TT is used. + if (huba == sc->sc_addr) + huba = 0; + } +*/ + + k = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; + dir = UE_GET_DIR(k) ? 1 : 0; + sitd->sitd.sitd_endp = + htole32(EHCI_SITD_SET_ENDPT(UE_GET_ADDR(k)) | + EHCI_SITD_SET_DADDR(dev->ud_addr) | + EHCI_SITD_SET_PORT(dev->ud_myhsport->up_portno) | + EHCI_SITD_SET_HUBA(huba) | + EHCI_SITD_SET_DIR(dir)); + + sitd->sitd.sitd_back = htole32(EHCI_LINK_TERMINATE); + + /* XXX */ + u_char sa, sb; + u_int temp, tlen; + sa = 0; + + if (dir == 0) { /* OUT */ + temp = 0; + tlen = xfer->ux_frlengths[i]; + if (tlen <= 188) { + temp |= 1; /* T-count = 1, TP = ALL */ + tlen = 1; + } else { + tlen += 187; + tlen /= 188; + temp |= tlen; /* T-count = [1..6] */ + temp |= 8; /* TP = Begin */ + } + sitd->sitd.sitd_buffer[1] |= htole32(temp); + + tlen += sa; + + if (tlen >= 8) { + sb = 0; + } else { + sb = (1 << tlen); + } + + sa = (1 << sa); + sa = (sb - sa) & 0x3F; + sb = 0; + } else { + sb = (-(4 << sa)) & 0xFE; + sa = (1 << sa) & 0x3F; + sa = 0x01; + sb = 0xfc; + } + + sitd->sitd.sitd_sched = htole32(EHCI_SITD_SET_SMASK(sa) | + EHCI_SITD_SET_CMASK(sb)); + + prev = sitd; + } /* End of frame */ + + sitd->sitd.sitd_trans |= htole32(EHCI_SITD_IOC); + + stop = sitd; + stop->xfer_next = NULL; + + usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, total_length, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + /* + * Part 2: Transfer descriptors have now been set up, now they must + * be scheduled into the periodic frame list. Erk. Not wanting to + * complicate matters, transfer is denied if the transfer spans + * more than the period frame list. + */ + + mutex_enter(&sc->sc_lock); + + /* Start inserting frames */ + if (epipe->u.isoc.cur_xfers > 0) { + frindex = epipe->u.isoc.next_frame; + } else { + frindex = EOREAD4(sc, EHCI_FRINDEX); + frindex = frindex >> 3; /* Erase microframe index */ + frindex += 2; + } + + if (frindex >= sc->sc_flsize) + frindex &= (sc->sc_flsize - 1); + + /* Whats the frame interval? */ + i = epipe->pipe.up_endpoint->ue_edesc->bInterval; + + sitd = start; + for (j = 0; j < frames; j++) { + if (sitd == NULL) + panic("ehci: unexpectedly ran out of isoc sitds\n"); + + sitd->sitd.sitd_next = sc->sc_flist[frindex]; + if (sitd->sitd.sitd_next == 0) + /* FIXME: frindex table gets initialized to NULL + * or EHCI_NULL? */ + sitd->sitd.sitd_next = EHCI_NULL; + + usb_syncmem(&sitd->dma, + sitd->offs + offsetof(ehci_sitd_t, sitd_next), + sizeof(ehci_sitd_t), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + sc->sc_flist[frindex] = + htole32(EHCI_LINK_SITD | sitd->physaddr); + + usb_syncmem(&sc->sc_fldma, + sizeof(ehci_link_t) * frindex, + sizeof(ehci_link_t), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + sitd->u.frame_list.next = sc->sc_softsitds[frindex]; + sc->sc_softsitds[frindex] = sitd; + if (sitd->u.frame_list.next != NULL) + sitd->u.frame_list.next->u.frame_list.prev = sitd; + sitd->slot = frindex; + sitd->u.frame_list.prev = NULL; + + frindex += i; + if (frindex >= sc->sc_flsize) + frindex -= sc->sc_flsize; + + sitd = sitd->xfer_next; + } + + epipe->u.isoc.cur_xfers++; + epipe->u.isoc.next_frame = frindex; + + exfer->ex_sitdstart = start; + exfer->ex_sitdend = stop; + + ehci_add_intr_list(sc, exfer); + xfer->ux_status = USBD_IN_PROGRESS; + xfer->ux_done = 0; + + mutex_exit(&sc->sc_lock); + + if (sc->sc_bus.ub_usepolling) { + printf("Starting ehci isoc xfer with polling. Bad idea?\n"); + ehci_waitintr(sc, xfer); + } + + return USBD_IN_PROGRESS; +} + +Static void +ehci_device_fs_isoc_abort(usbd_xfer_handle xfer) +{ + USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); + + USBHIST_LOG(ehcidebug, "xfer = %p", xfer, 0, 0, 0); + ehci_abort_isoc_xfer(xfer, USBD_CANCELLED); +} + +Static void +ehci_device_fs_isoc_close(usbd_pipe_handle pipe) +{ + USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); + + USBHIST_LOG(ehcidebug, "nothing in the pipe to free?", 0, 0, 0, 0); +} + +Static void +ehci_device_fs_isoc_done(usbd_xfer_handle xfer) +{ + struct ehci_xfer *exfer; + ehci_softc_t *sc; + struct ehci_pipe *epipe; + + exfer = EXFER(xfer); + sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + epipe = (struct ehci_pipe *) xfer->ux_pipe; + + KASSERT(mutex_owned(&sc->sc_lock)); + + epipe->u.isoc.cur_xfers--; + if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(exfer)) { + ehci_del_intr_list(sc, exfer); + ehci_rem_free_sitd_chain(sc, exfer); + } + + usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | + BUS_DMASYNC_POSTREAD); +} +Static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle xfer) { - ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; + ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; usbd_status err; mutex_enter(&sc->sc_lock); @@ -4133,8 +4397,8 @@ ehci_device_isoc_start(usbd_xfer_handle trans_count = 0; total_length = 0; exfer = (struct ehci_xfer *) xfer; - sc = xfer->pipe->device->bus->hci_private; - epipe = (struct ehci_pipe *)xfer->pipe; + sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + epipe = (struct ehci_pipe *)xfer->ux_pipe; /* * To allow continuous transfers, above we start all transfers @@ -4143,11 +4407,11 @@ ehci_device_isoc_start(usbd_xfer_handle * in progress or not */ - if (exfer->itdstart != NULL) + if (exfer->ex_itdstart != NULL) return USBD_IN_PROGRESS; USBHIST_LOG(ehcidebug, "xfer %p len %d flags %d", - xfer, xfer->length, xfer->flags, 0); + xfer, xfer->ux_length, xfer->ux_flags, 0); if (sc->sc_dying) return USBD_IOERROR; @@ -4157,24 +4421,23 @@ ehci_device_isoc_start(usbd_xfer_handle * the entire frame table. To within 4 frames, to allow some leeway * on either side of where the hc currently is. */ - if ((1 << (epipe->pipe.endpoint->edesc->bInterval)) * - xfer->nframes >= (sc->sc_flsize - 4) * 8) { + if ((1 << (epipe->pipe.up_endpoint->ue_edesc->bInterval)) * + xfer->ux_nframes >= (sc->sc_flsize - 4) * 8) { USBHIST_LOG(ehcidebug, "isoc descriptor spans entire frametable", 0, 0, 0, 0); printf("ehci: isoc descriptor requested that spans the entire frametable, too many frames\n"); return USBD_INVAL; } -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_isoc_start: request\n"); + KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); - if (!exfer->isdone) { +#ifdef DIAGNOSTIC + if (!exfer->ex_isdone) { USBHIST_LOG(ehcidebug, "marked not done, ex = %p", exfer, 0, 0, 0); printf("ehci_device_isoc_start: not done, ex = %p\n", exfer); } - exfer->isdone = 0; + exfer->ex_isdone = 0; #endif /* @@ -4183,15 +4446,15 @@ ehci_device_isoc_start(usbd_xfer_handle * multiple microframes per frame. */ - i = epipe->pipe.endpoint->edesc->bInterval; + i = epipe->pipe.up_endpoint->ue_edesc->bInterval; if (i > 16 || i == 0) { /* Spec page 271 says intervals > 16 are invalid */ - USBHIST_LOG(ehcidebug, "bInvertal %d invalid", i, 0, 0, 0); + USBHIST_LOG(ehcidebug, "bInterval %d invalid", i, 0, 0, 0); return USBD_INVAL; } ufrperframe = max(1, USB_UFRAMES_PER_FRAME / (1 << (i - 1))); - frames = (xfer->nframes + (ufrperframe - 1)) / ufrperframe; + frames = (xfer->ux_nframes + (ufrperframe - 1)) / ufrperframe; uframes = USB_UFRAMES_PER_FRAME / ufrperframe; if (frames == 0) { @@ -4199,7 +4462,7 @@ ehci_device_isoc_start(usbd_xfer_handle return USBD_INVAL; } - dma_buf = &xfer->dmabuf; + dma_buf = &xfer->ux_dmabuf; offs = 0; for (i = 0; i < frames; i++) { @@ -4211,7 +4474,7 @@ ehci_device_isoc_start(usbd_xfer_handle htole32(itd->physaddr | EHCI_LINK_ITD); usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_next), - sizeof(itd->itd.itd_next), BUS_DMASYNC_POSTWRITE); + sizeof(itd->itd.itd_next), BUS_DMASYNC_POSTWRITE); prev->xfer_next = itd; } else { @@ -4229,27 +4492,29 @@ ehci_device_isoc_start(usbd_xfer_handle addr = EHCI_PAGE(addr); addr /= EHCI_PAGE_SIZE; - /* This gets the initial offset into the first page, + /* + * This gets the initial offset into the first page, * looks how far further along the current uframe * offset is. Works out how many pages that is. */ itd->itd.itd_ctl[j] = htole32 ( EHCI_ITD_ACTIVE | - EHCI_ITD_SET_LEN(xfer->frlengths[trans_count]) | + EHCI_ITD_SET_LEN(xfer->ux_frlengths[trans_count]) | EHCI_ITD_SET_PG(addr) | EHCI_ITD_SET_OFFS(EHCI_PAGE_OFFSET(DMAADDR(dma_buf,offs)))); - total_length += xfer->frlengths[trans_count]; - offs += xfer->frlengths[trans_count]; + total_length += xfer->ux_frlengths[trans_count]; + offs += xfer->ux_frlengths[trans_count]; trans_count++; - if (trans_count >= xfer->nframes) { /*Set IOC*/ + if (trans_count >= xfer->ux_nframes) { /*Set IOC*/ itd->itd.itd_ctl[j] |= htole32(EHCI_ITD_IOC); break; } } - /* Step 1.75, set buffer pointers. To simplify matters, all + /* + * Step 1.75, set buffer pointers. To simplify matters, all * pointers are filled out for the next 7 hardware pages in * the dma block, so no need to worry what pages to cover * and what to not. @@ -4261,7 +4526,7 @@ ehci_device_isoc_start(usbd_xfer_handle * of buffer */ int page_offs = EHCI_PAGE(froffs + (EHCI_PAGE_SIZE * j)); - if (page_offs >= dma_buf->block->size) + if (page_offs >= dma_buf->udma_block->size) break; unsigned long long page = DMAADDR(dma_buf, page_offs); @@ -4276,13 +4541,13 @@ ehci_device_isoc_start(usbd_xfer_handle * Other special values */ - k = epipe->pipe.endpoint->edesc->bEndpointAddress; + k = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; itd->itd.itd_bufr[0] |= htole32(EHCI_ITD_SET_EP(UE_GET_ADDR(k)) | - EHCI_ITD_SET_DADDR(epipe->pipe.device->address)); + EHCI_ITD_SET_DADDR(epipe->pipe.up_dev->ud_addr)); - k = (UE_GET_DIR(epipe->pipe.endpoint->edesc->bEndpointAddress)) + k = (UE_GET_DIR(epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress)) ? 1 : 0; - j = UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); + j = UGETW(epipe->pipe.up_endpoint->ue_edesc->wMaxPacketSize); itd->itd.itd_bufr[1] |= htole32(EHCI_ITD_SET_DIR(k) | EHCI_ITD_SET_MAXPKT(UE_GET_SIZE(j))); @@ -4292,7 +4557,7 @@ ehci_device_isoc_start(usbd_xfer_handle usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_next), - sizeof(ehci_itd_t), + sizeof(ehci_itd_t), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); prev = itd; @@ -4300,9 +4565,8 @@ ehci_device_isoc_start(usbd_xfer_handle stop = itd; stop->xfer_next = NULL; - exfer->isoc_len = total_length; - usb_syncmem(&exfer->xfer.dmabuf, 0, total_length, + usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, total_length, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* @@ -4327,7 +4591,7 @@ ehci_device_isoc_start(usbd_xfer_handle frindex &= (sc->sc_flsize - 1); /* What's the frame interval? */ - i = (1 << (epipe->pipe.endpoint->edesc->bInterval - 1)); + i = (1 << (epipe->pipe.up_endpoint->ue_edesc->bInterval - 1)); if (i / USB_UFRAMES_PER_FRAME == 0) i = 1; else @@ -4346,14 +4610,14 @@ ehci_device_isoc_start(usbd_xfer_handle usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_next), - sizeof(itd->itd.itd_next), + sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); sc->sc_flist[frindex] = htole32(EHCI_LINK_ITD | itd->physaddr); usb_syncmem(&sc->sc_fldma, sizeof(ehci_link_t) * frindex, - sizeof(ehci_link_t), + sizeof(ehci_link_t), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); itd->u.frame_list.next = sc->sc_softitds[frindex]; @@ -4373,17 +4637,15 @@ ehci_device_isoc_start(usbd_xfer_handle epipe->u.isoc.cur_xfers++; epipe->u.isoc.next_frame = frindex; - exfer->itdstart = start; - exfer->itdend = stop; - exfer->sqtdstart = NULL; - exfer->sqtdend = NULL; + exfer->ex_itdstart = start; + exfer->ex_itdend = stop; ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - xfer->done = 0; + xfer->ux_status = USBD_IN_PROGRESS; + xfer->ux_done = 0; mutex_exit(&sc->sc_lock); - if (sc->sc_bus.use_polling) { + if (sc->sc_bus.ub_usepolling) { printf("Starting ehci isoc xfer with polling. Bad idea?\n"); ehci_waitintr(sc, xfer); } @@ -4416,18 +4678,18 @@ ehci_device_isoc_done(usbd_xfer_handle x struct ehci_pipe *epipe; exfer = EXFER(xfer); - sc = xfer->pipe->device->bus->hci_private; - epipe = (struct ehci_pipe *) xfer->pipe; + sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; + epipe = (struct ehci_pipe *) xfer->ux_pipe; KASSERT(mutex_owned(&sc->sc_lock)); epipe->u.isoc.cur_xfers--; - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(exfer)) { + if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(exfer)) { ehci_del_intr_list(sc, exfer); ehci_rem_free_itd_chain(sc, exfer); } - usb_syncmem(&xfer->dmabuf, 0, xfer->length, BUS_DMASYNC_POSTWRITE | - BUS_DMASYNC_POSTREAD); + usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | + BUS_DMASYNC_POSTREAD); }