diff options
Diffstat (limited to 'sys/dev/usb/controller')
-rw-r--r-- | sys/dev/usb/controller/xhci.c | 70 | ||||
-rw-r--r-- | sys/dev/usb/controller/xhci.h | 2 |
2 files changed, 52 insertions, 20 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 6faba7f..f32e89a 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -2045,7 +2045,9 @@ xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop) struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); struct usb_page_search buf_inp; struct xhci_input_dev_ctx *pinp; + uint32_t temp; uint8_t index; + uint8_t x; index = udev->controller_slot_id; @@ -2060,6 +2062,24 @@ xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop) } else { xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0); xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask); + + /* find most significant set bit */ + for (x = 31; x != 1; x--) { + if (mask & (1 << x)) + break; + } + + /* adjust */ + x--; + + /* figure out maximum */ + if (x > sc->sc_hw.devs[index].context_num) { + sc->sc_hw.devs[index].context_num = x; + temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0); + temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31); + temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1); + xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp); + } } return (0); } @@ -2311,16 +2331,9 @@ xhci_configure_device(struct usb_device *udev) DPRINTF("Route=0x%08x\n", route); - temp = XHCI_SCTX_0_ROUTE_SET(route); - - switch (sc->sc_hw.devs[index].state) { - case XHCI_ST_CONFIGURED: - temp |= XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1); - break; - default: - temp |= XHCI_SCTX_0_CTX_NUM_SET(1); - break; - } + temp = XHCI_SCTX_0_ROUTE_SET(route) | + XHCI_SCTX_0_CTX_NUM_SET( + sc->sc_hw.devs[index].context_num + 1); switch (udev->speed) { case USB_SPEED_LOW: @@ -2464,8 +2477,9 @@ xhci_alloc_device_ext(struct usb_device *udev) if (usb_pc_alloc_mem(pc, pg, sc->sc_ctx_is_64_byte ? (2 * sizeof(struct xhci_input_dev_ctx)) : - sizeof(struct xhci_input_dev_ctx), XHCI_PAGE_SIZE)) + sizeof(struct xhci_input_dev_ctx), XHCI_PAGE_SIZE)) { goto error; + } pc = &sc->sc_hw.devs[index].endpoint_pc; pg = &sc->sc_hw.devs[index].endpoint_pg; @@ -2473,15 +2487,18 @@ xhci_alloc_device_ext(struct usb_device *udev) /* need to initialize the page cache */ pc->tag_parent = sc->sc_bus.dma_parent_tag; - if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_dev_endpoint_trbs), XHCI_PAGE_SIZE)) + if (usb_pc_alloc_mem(pc, pg, + sizeof(struct xhci_dev_endpoint_trbs), XHCI_PAGE_SIZE)) { goto error; + } /* initialise all endpoint LINK TRBs */ for (i = 0; i != XHCI_MAX_ENDPOINTS; i++) { /* lookup endpoint TRB ring */ - usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[i][0], &buf_ep); + usbd_get_page(pc, (uintptr_t)& + ((struct xhci_dev_endpoint_trbs *)0)->trb[i][0], &buf_ep); /* get TRB pointer */ trb = buf_ep.buffer; @@ -2568,8 +2585,10 @@ xhci_endpoint_doorbell(struct usb_xfer *xfer) epno = XHCI_EPNO2EPID(epno); index = xfer->xroot->udev->controller_slot_id; - if (xfer->xroot->udev->flags.self_suspended == 0) - XWRITE4(sc, door, XHCI_DOORBELL(index), epno | XHCI_DB_SID_SET(0)); + if (xfer->xroot->udev->flags.self_suspended == 0) { + XWRITE4(sc, door, XHCI_DOORBELL(index), + epno | XHCI_DB_SID_SET(xfer->stream_id)); + } } static void @@ -3584,7 +3603,7 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer) * endpoint context state diagram in the XHCI specification: */ - xhci_configure_mask(udev, 1U << epno, 0); + xhci_configure_mask(udev, (1U << epno) | 1U, 0); err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index); @@ -3858,6 +3877,7 @@ xhci_device_resume(struct usb_device *udev) struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); uint8_t index; uint8_t n; + uint8_t p; DPRINTF("\n"); @@ -3873,8 +3893,12 @@ xhci_device_resume(struct usb_device *udev) USB_BUS_LOCK(udev->bus); - for (n = 1; n != XHCI_MAX_ENDPOINTS; n++) - XWRITE4(sc, door, XHCI_DOORBELL(index), n | XHCI_DB_SID_SET(0)); + for (n = 1; n != XHCI_MAX_ENDPOINTS; n++) { + for (p = 0; p != XHCI_MAX_STREAMS; p++) { + XWRITE4(sc, door, XHCI_DOORBELL(index), + n | XHCI_DB_SID_SET(p)); + } + } USB_BUS_UNLOCK(udev->bus); @@ -3948,8 +3972,12 @@ xhci_device_state_change(struct usb_device *udev) if (sc->sc_hw.devs[index].state == XHCI_ST_DEFAULT) break; + /* set default state */ sc->sc_hw.devs[index].state = XHCI_ST_DEFAULT; + /* reset number of contexts */ + sc->sc_hw.devs[index].context_num = 0; + err = xhci_cmd_reset_dev(sc, index); if (err != 0) { @@ -3976,11 +4004,15 @@ xhci_device_state_change(struct usb_device *udev) if (sc->sc_hw.devs[index].state == XHCI_ST_CONFIGURED) break; + /* set configured state */ sc->sc_hw.devs[index].state = XHCI_ST_CONFIGURED; + /* reset number of contexts */ + sc->sc_hw.devs[index].context_num = 0; + usbd_get_page(&sc->sc_hw.devs[index].input_pc, 0, &buf_inp); - xhci_configure_mask(udev, 1, 0); + xhci_configure_mask(udev, 3, 0); err = xhci_configure_device(udev); if (err != 0) { diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h index a7e4f74..01e60ee 100644 --- a/sys/dev/usb/controller/xhci.h +++ b/sys/dev/usb/controller/xhci.h @@ -394,7 +394,7 @@ struct xhci_hw_dev { uint8_t state; uint8_t nports; uint8_t tt; - uint8_t reserved; + uint8_t context_num; }; struct xhci_hw_softc { |