version 1.122, 2020/03/14 03:01:36 |
version 1.123, 2020/04/02 11:37:23 |
Line 164 static usbd_status xhci_do_command(struc |
|
Line 164 static usbd_status xhci_do_command(struc |
|
static usbd_status xhci_do_command_locked(struct xhci_softc * const, |
static usbd_status xhci_do_command_locked(struct xhci_softc * const, |
struct xhci_soft_trb * const, int); |
struct xhci_soft_trb * const, int); |
static usbd_status xhci_init_slot(struct usbd_device *, uint32_t); |
static usbd_status xhci_init_slot(struct usbd_device *, uint32_t); |
static void xhci_free_slot(struct xhci_softc *, struct xhci_slot *, int, int); |
static void xhci_free_slot(struct xhci_softc *, struct xhci_slot *); |
static usbd_status xhci_set_address(struct usbd_device *, uint32_t, bool); |
static usbd_status xhci_set_address(struct usbd_device *, uint32_t, bool); |
static usbd_status xhci_enable_slot(struct xhci_softc * const, |
static usbd_status xhci_enable_slot(struct xhci_softc * const, |
uint8_t * const); |
uint8_t * const); |
Line 175 static void xhci_set_dcba(struct xhci_so |
|
Line 175 static void xhci_set_dcba(struct xhci_so |
|
static usbd_status xhci_update_ep0_mps(struct xhci_softc * const, |
static usbd_status xhci_update_ep0_mps(struct xhci_softc * const, |
struct xhci_slot * const, u_int); |
struct xhci_slot * const, u_int); |
static usbd_status xhci_ring_init(struct xhci_softc * const, |
static usbd_status xhci_ring_init(struct xhci_softc * const, |
struct xhci_ring * const, size_t, size_t); |
struct xhci_ring **, size_t, size_t); |
static void xhci_ring_free(struct xhci_softc * const, struct xhci_ring * const); |
static void xhci_ring_free(struct xhci_softc * const, |
|
struct xhci_ring ** const); |
|
|
static void xhci_setup_ctx(struct usbd_pipe *); |
static void xhci_setup_ctx(struct usbd_pipe *); |
static void xhci_setup_route(struct usbd_pipe *, uint32_t *); |
static void xhci_setup_route(struct usbd_pipe *, uint32_t *); |
Line 1194 xhci_init(struct xhci_softc *sc) |
|
Line 1195 xhci_init(struct xhci_softc *sc) |
|
|
|
struct xhci_erste *erst; |
struct xhci_erste *erst; |
erst = KERNADDR(&sc->sc_eventst_dma, 0); |
erst = KERNADDR(&sc->sc_eventst_dma, 0); |
erst[0].erste_0 = htole64(xhci_ring_trbp(&sc->sc_er, 0)); |
erst[0].erste_0 = htole64(xhci_ring_trbp(sc->sc_er, 0)); |
erst[0].erste_2 = htole32(sc->sc_er.xr_ntrb); |
erst[0].erste_2 = htole32(sc->sc_er->xr_ntrb); |
erst[0].erste_3 = htole32(0); |
erst[0].erste_3 = htole32(0); |
usb_syncmem(&sc->sc_eventst_dma, 0, |
usb_syncmem(&sc->sc_eventst_dma, 0, |
XHCI_ERSTE_SIZE * XHCI_EVENT_RING_SEGMENTS, BUS_DMASYNC_PREWRITE); |
XHCI_ERSTE_SIZE * XHCI_EVENT_RING_SEGMENTS, BUS_DMASYNC_PREWRITE); |
|
|
xhci_rt_write_4(sc, XHCI_ERSTSZ(0), XHCI_EVENT_RING_SEGMENTS); |
xhci_rt_write_4(sc, XHCI_ERSTSZ(0), XHCI_EVENT_RING_SEGMENTS); |
xhci_rt_write_8(sc, XHCI_ERSTBA(0), DMAADDR(&sc->sc_eventst_dma, 0)); |
xhci_rt_write_8(sc, XHCI_ERSTBA(0), DMAADDR(&sc->sc_eventst_dma, 0)); |
xhci_rt_write_8(sc, XHCI_ERDP(0), xhci_ring_trbp(&sc->sc_er, 0) | |
xhci_rt_write_8(sc, XHCI_ERDP(0), xhci_ring_trbp(sc->sc_er, 0) | |
XHCI_ERDP_LO_BUSY); |
XHCI_ERDP_LO_BUSY); |
|
|
xhci_op_write_8(sc, XHCI_DCBAAP, DMAADDR(&sc->sc_dcbaa_dma, 0)); |
xhci_op_write_8(sc, XHCI_DCBAAP, DMAADDR(&sc->sc_dcbaa_dma, 0)); |
xhci_op_write_8(sc, XHCI_CRCR, xhci_ring_trbp(&sc->sc_cr, 0) | |
xhci_op_write_8(sc, XHCI_CRCR, xhci_ring_trbp(sc->sc_cr, 0) | |
sc->sc_cr.xr_cs); |
sc->sc_cr->xr_cs); |
|
|
xhci_op_barrier(sc, 0, 4, BUS_SPACE_BARRIER_WRITE); |
xhci_op_barrier(sc, 0, 4, BUS_SPACE_BARRIER_WRITE); |
|
|
Line 1543 xhci_set_dequeue_locked(struct usbd_pipe |
|
Line 1544 xhci_set_dequeue_locked(struct usbd_pipe |
|
struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); |
struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); |
struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; |
struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; |
const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc); |
const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc); |
struct xhci_ring * const xr = &xs->xs_ep[dci].xe_tr; |
struct xhci_ring * const xr = xs->xs_xr[dci]; |
struct xhci_soft_trb trb; |
struct xhci_soft_trb trb; |
usbd_status err; |
usbd_status err; |
|
|
Line 1551 xhci_set_dequeue_locked(struct usbd_pipe |
|
Line 1552 xhci_set_dequeue_locked(struct usbd_pipe |
|
XHCIHIST_CALLARGS("slot %ju dci %ju", xs->xs_idx, dci, 0, 0); |
XHCIHIST_CALLARGS("slot %ju dci %ju", xs->xs_idx, dci, 0, 0); |
|
|
KASSERT(mutex_owned(&sc->sc_lock)); |
KASSERT(mutex_owned(&sc->sc_lock)); |
|
KASSERT(xr != NULL); |
|
|
xhci_host_dequeue(xr); |
xhci_host_dequeue(xr); |
|
|
Line 1588 xhci_open(struct usbd_pipe *pipe) |
|
Line 1590 xhci_open(struct usbd_pipe *pipe) |
|
{ |
{ |
struct usbd_device * const dev = pipe->up_dev; |
struct usbd_device * const dev = pipe->up_dev; |
struct xhci_softc * const sc = XHCI_BUS2SC(dev->ud_bus); |
struct xhci_softc * const sc = XHCI_BUS2SC(dev->ud_bus); |
|
struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; |
usb_endpoint_descriptor_t * const ed = pipe->up_endpoint->ue_edesc; |
usb_endpoint_descriptor_t * const ed = pipe->up_endpoint->ue_edesc; |
|
const u_int dci = xhci_ep_get_dci(ed); |
const uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); |
const uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); |
|
usbd_status err; |
|
|
XHCIHIST_FUNC(); |
XHCIHIST_FUNC(); |
XHCIHIST_CALLARGS("addr %jd depth %jd port %jd speed %jd", dev->ud_addr, |
XHCIHIST_CALLARGS("addr %jd depth %jd port %jd speed %jd", dev->ud_addr, |
Line 1640 xhci_open(struct usbd_pipe *pipe) |
|
Line 1645 xhci_open(struct usbd_pipe *pipe) |
|
break; |
break; |
} |
} |
|
|
|
KASSERT(xs != NULL); |
|
KASSERT(xs->xs_xr[dci] == NULL); |
|
|
|
/* allocate transfer ring */ |
|
err = xhci_ring_init(sc, &xs->xs_xr[dci], XHCI_TRANSFER_RING_TRBS, |
|
XHCI_TRB_ALIGN); |
|
if (err) { |
|
DPRINTFN(1, "ring alloc failed %jd", err, 0, 0, 0); |
|
return err; |
|
} |
|
|
if (ed->bEndpointAddress != USB_CONTROL_ENDPOINT) |
if (ed->bEndpointAddress != USB_CONTROL_ENDPOINT) |
return xhci_configure_endpoint(pipe); |
return xhci_configure_endpoint(pipe); |
|
|
Line 1681 xhci_close_pipe(struct usbd_pipe *pipe) |
|
Line 1697 xhci_close_pipe(struct usbd_pipe *pipe) |
|
|
|
if (dci == XHCI_DCI_EP_CONTROL) { |
if (dci == XHCI_DCI_EP_CONTROL) { |
DPRINTFN(4, "closing ep0", 0, 0, 0, 0); |
DPRINTFN(4, "closing ep0", 0, 0, 0, 0); |
|
/* This frees all rings */ |
xhci_disable_slot(sc, xs->xs_idx); |
xhci_disable_slot(sc, xs->xs_idx); |
return; |
return; |
} |
} |
Line 1702 xhci_close_pipe(struct usbd_pipe *pipe) |
|
Line 1719 xhci_close_pipe(struct usbd_pipe *pipe) |
|
cp[0] = htole32(XHCI_SCTX_0_CTX_NUM_SET(dci)); |
cp[0] = htole32(XHCI_SCTX_0_CTX_NUM_SET(dci)); |
|
|
/* configure ep context performs an implicit dequeue */ |
/* configure ep context performs an implicit dequeue */ |
xhci_host_dequeue(&xs->xs_ep[dci].xe_tr); |
xhci_host_dequeue(xs->xs_xr[dci]); |
|
|
/* sync input contexts before they are read from memory */ |
/* sync input contexts before they are read from memory */ |
usb_syncmem(&xs->xs_ic_dma, 0, sc->sc_pgsz, BUS_DMASYNC_PREWRITE); |
usb_syncmem(&xs->xs_ic_dma, 0, sc->sc_pgsz, BUS_DMASYNC_PREWRITE); |
Line 1714 xhci_close_pipe(struct usbd_pipe *pipe) |
|
Line 1731 xhci_close_pipe(struct usbd_pipe *pipe) |
|
|
|
(void)xhci_do_command_locked(sc, &trb, USBD_DEFAULT_TIMEOUT); |
(void)xhci_do_command_locked(sc, &trb, USBD_DEFAULT_TIMEOUT); |
usb_syncmem(&xs->xs_dc_dma, 0, sc->sc_pgsz, BUS_DMASYNC_POSTREAD); |
usb_syncmem(&xs->xs_dc_dma, 0, sc->sc_pgsz, BUS_DMASYNC_POSTREAD); |
|
|
|
xhci_ring_free(sc, &xs->xs_xr[dci]); |
} |
} |
|
|
/* |
/* |
Line 1809 xhci_clear_endpoint_stall_async_task(voi |
|
Line 1828 xhci_clear_endpoint_stall_async_task(voi |
|
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
struct xhci_ring * const tr = &xs->xs_ep[dci].xe_tr; |
struct xhci_ring * const tr = xs->xs_xr[dci]; |
|
|
XHCIHIST_FUNC(); |
XHCIHIST_FUNC(); |
XHCIHIST_CALLARGS("xfer %#jx slot %ju dci %ju", (uintptr_t)xfer, xs->xs_idx, |
XHCIHIST_CALLARGS("xfer %#jx slot %ju dci %ju", (uintptr_t)xfer, xs->xs_idx, |
Line 1828 xhci_clear_endpoint_stall_async_task(voi |
|
Line 1847 xhci_clear_endpoint_stall_async_task(voi |
|
return; |
return; |
} |
} |
|
|
|
KASSERT(tr != NULL); |
|
|
xhci_reset_endpoint(xfer->ux_pipe); |
xhci_reset_endpoint(xfer->ux_pipe); |
xhci_set_dequeue(xfer->ux_pipe); |
xhci_set_dequeue(xfer->ux_pipe); |
|
|
Line 1913 xhci_event_transfer(struct xhci_softc * |
|
Line 1934 xhci_event_transfer(struct xhci_softc * |
|
slot = XHCI_TRB_3_SLOT_GET(trb_3); |
slot = XHCI_TRB_3_SLOT_GET(trb_3); |
dci = XHCI_TRB_3_EP_GET(trb_3); |
dci = XHCI_TRB_3_EP_GET(trb_3); |
xs = &sc->sc_slots[slot]; |
xs = &sc->sc_slots[slot]; |
xr = &xs->xs_ep[dci].xe_tr; |
xr = xs->xs_xr[dci]; |
|
|
/* sanity check */ |
/* sanity check */ |
|
KASSERT(xr != NULL); |
KASSERTMSG(xs->xs_idx != 0 && xs->xs_idx <= sc->sc_maxslots, |
KASSERTMSG(xs->xs_idx != 0 && xs->xs_idx <= sc->sc_maxslots, |
"invalid xs_idx %u slot %u", xs->xs_idx, slot); |
"invalid xs_idx %u slot %u", xs->xs_idx, slot); |
|
|
Line 2154 xhci_softintr(void *v) |
|
Line 2176 xhci_softintr(void *v) |
|
{ |
{ |
struct usbd_bus * const bus = v; |
struct usbd_bus * const bus = v; |
struct xhci_softc * const sc = XHCI_BUS2SC(bus); |
struct xhci_softc * const sc = XHCI_BUS2SC(bus); |
struct xhci_ring * const er = &sc->sc_er; |
struct xhci_ring * const er = sc->sc_er; |
struct xhci_trb *trb; |
struct xhci_trb *trb; |
int i, j, k; |
int i, j, k; |
|
|
Line 2341 xhci_new_device(device_t parent, struct |
|
Line 2363 xhci_new_device(device_t parent, struct |
|
|
|
up->up_dev = dev; |
up->up_dev = dev; |
|
|
/* Establish the default pipe. */ |
|
err = usbd_setup_pipe(dev, 0, &dev->ud_ep0, USBD_DEFAULT_INTERVAL, |
|
&dev->ud_pipe0); |
|
if (err) { |
|
goto bad; |
|
} |
|
|
|
dd = &dev->ud_ddesc; |
dd = &dev->ud_ddesc; |
|
|
if (depth == 0 && port == 0) { |
if (depth == 0 && port == 0) { |
KASSERT(bus->ub_devices[USB_ROOTHUB_INDEX] == NULL); |
KASSERT(bus->ub_devices[USB_ROOTHUB_INDEX] == NULL); |
bus->ub_devices[USB_ROOTHUB_INDEX] = dev; |
bus->ub_devices[USB_ROOTHUB_INDEX] = dev; |
err = usbd_get_initial_ddesc(dev, dd); |
|
|
/* Establish the default pipe. */ |
|
err = usbd_setup_pipe(dev, 0, &dev->ud_ep0, |
|
USBD_DEFAULT_INTERVAL, &dev->ud_pipe0); |
if (err) { |
if (err) { |
DPRINTFN(1, "get_initial_ddesc %ju", err, 0, 0, 0); |
DPRINTFN(1, "setup default pipe failed %jd", err,0,0,0); |
goto bad; |
goto bad; |
} |
} |
|
err = usbd_get_initial_ddesc(dev, dd); |
err = usbd_reload_device_desc(dev); |
|
if (err) { |
if (err) { |
DPRINTFN(1, "reload desc %ju", err, 0, 0, 0); |
DPRINTFN(1, "get_initial_ddesc %ju", err, 0, 0, 0); |
goto bad; |
goto bad; |
} |
} |
} else { |
} else { |
Line 2393 xhci_new_device(device_t parent, struct |
|
Line 2410 xhci_new_device(device_t parent, struct |
|
goto bad; |
goto bad; |
} |
} |
|
|
|
/* |
|
* We have to establish the default pipe _after_ slot |
|
* structure has been prepared. |
|
*/ |
|
err = usbd_setup_pipe(dev, 0, &dev->ud_ep0, |
|
USBD_DEFAULT_INTERVAL, &dev->ud_pipe0); |
|
if (err) { |
|
DPRINTFN(1, "setup default pipe failed %jd", err, 0, 0, |
|
0); |
|
goto bad; |
|
} |
|
|
/* 4.3.4 Address Assignment */ |
/* 4.3.4 Address Assignment */ |
err = xhci_set_address(dev, slot, false); |
err = xhci_set_address(dev, slot, false); |
if (err) { |
if (err) { |
Line 2449 xhci_new_device(device_t parent, struct |
|
Line 2478 xhci_new_device(device_t parent, struct |
|
DPRINTFN(1, "update mps of ep0 %ju", err, 0, 0, 0); |
DPRINTFN(1, "update mps of ep0 %ju", err, 0, 0, 0); |
goto bad; |
goto bad; |
} |
} |
|
} |
|
|
err = usbd_reload_device_desc(dev); |
err = usbd_reload_device_desc(dev); |
if (err) { |
if (err) { |
DPRINTFN(1, "reload desc %ju", err, 0, 0, 0); |
DPRINTFN(1, "reload desc %ju", err, 0, 0, 0); |
goto bad; |
goto bad; |
} |
|
} |
} |
|
|
DPRINTFN(1, "adding unit addr=%jd, rev=%02jx,", |
DPRINTFN(1, "adding unit addr=%jd, rev=%02jx,", |
Line 2486 xhci_new_device(device_t parent, struct |
|
Line 2515 xhci_new_device(device_t parent, struct |
|
} |
} |
|
|
static usbd_status |
static usbd_status |
xhci_ring_init(struct xhci_softc * const sc, struct xhci_ring * const xr, |
xhci_ring_init(struct xhci_softc * const sc, struct xhci_ring **xrp, |
size_t ntrb, size_t align) |
size_t ntrb, size_t align) |
{ |
{ |
usbd_status err; |
usbd_status err; |
size_t size = ntrb * XHCI_TRB_SIZE; |
size_t size = ntrb * XHCI_TRB_SIZE; |
|
struct xhci_ring *xr; |
|
|
XHCIHIST_FUNC(); |
XHCIHIST_FUNC(); |
XHCIHIST_CALLARGS("xr %#jx ntrb %#jx align %#jx", |
XHCIHIST_CALLARGS("xr %#jx ntrb %#jx align %#jx", |
(uintptr_t)xr, ntrb, align, 0); |
(uintptr_t)*xrp, ntrb, align, 0); |
|
|
|
xr = kmem_zalloc(sizeof(struct xhci_ring), KM_SLEEP); |
|
DPRINTFN(1, "ring %#jx", (uintptr_t)xr, 0, 0, 0); |
|
|
err = usb_allocmem(&sc->sc_bus, size, align, &xr->xr_dma); |
err = usb_allocmem(&sc->sc_bus, size, align, &xr->xr_dma); |
if (err) |
if (err) { |
|
kmem_free(xr, sizeof(struct xhci_ring)); |
|
DPRINTFN(1, "alloc xr_dma failed %jd", err, 0, 0, 0); |
return err; |
return err; |
|
} |
mutex_init(&xr->xr_lock, MUTEX_DEFAULT, IPL_SOFTUSB); |
mutex_init(&xr->xr_lock, MUTEX_DEFAULT, IPL_SOFTUSB); |
xr->xr_cookies = kmem_zalloc(sizeof(*xr->xr_cookies) * ntrb, KM_SLEEP); |
xr->xr_cookies = kmem_zalloc(sizeof(*xr->xr_cookies) * ntrb, KM_SLEEP); |
xr->xr_trb = xhci_ring_trbv(xr, 0); |
xr->xr_trb = xhci_ring_trbv(xr, 0); |
xr->xr_ntrb = ntrb; |
xr->xr_ntrb = ntrb; |
xr->is_halted = false; |
xr->is_halted = false; |
xhci_host_dequeue(xr); |
xhci_host_dequeue(xr); |
|
*xrp = xr; |
|
|
return USBD_NORMAL_COMPLETION; |
return USBD_NORMAL_COMPLETION; |
} |
} |
|
|
static void |
static void |
xhci_ring_free(struct xhci_softc * const sc, struct xhci_ring * const xr) |
xhci_ring_free(struct xhci_softc * const sc, struct xhci_ring ** const xr) |
{ |
{ |
usb_freemem(&sc->sc_bus, &xr->xr_dma); |
if (*xr == NULL) |
mutex_destroy(&xr->xr_lock); |
return; |
kmem_free(xr->xr_cookies, sizeof(*xr->xr_cookies) * xr->xr_ntrb); |
|
|
usb_freemem(&sc->sc_bus, &(*xr)->xr_dma); |
|
mutex_destroy(&(*xr)->xr_lock); |
|
kmem_free((*xr)->xr_cookies, |
|
sizeof(*(*xr)->xr_cookies) * (*xr)->xr_ntrb); |
|
kmem_free(*xr, sizeof(struct xhci_ring)); |
|
*xr = NULL; |
} |
} |
|
|
static void |
static void |
Line 2631 xhci_ring_put(struct xhci_softc * const |
|
Line 2674 xhci_ring_put(struct xhci_softc * const |
|
static void |
static void |
xhci_abort_command(struct xhci_softc *sc) |
xhci_abort_command(struct xhci_softc *sc) |
{ |
{ |
struct xhci_ring * const cr = &sc->sc_cr; |
struct xhci_ring * const cr = sc->sc_cr; |
uint64_t crcr; |
uint64_t crcr; |
int i; |
int i; |
|
|
Line 2675 static usbd_status |
|
Line 2718 static usbd_status |
|
xhci_do_command_locked(struct xhci_softc * const sc, |
xhci_do_command_locked(struct xhci_softc * const sc, |
struct xhci_soft_trb * const trb, int timeout) |
struct xhci_soft_trb * const trb, int timeout) |
{ |
{ |
struct xhci_ring * const cr = &sc->sc_cr; |
struct xhci_ring * const cr = sc->sc_cr; |
usbd_status err; |
usbd_status err; |
|
|
XHCIHIST_FUNC(); |
XHCIHIST_FUNC(); |
Line 2806 xhci_disable_slot(struct xhci_softc * co |
|
Line 2849 xhci_disable_slot(struct xhci_softc * co |
|
if (!err) { |
if (!err) { |
xs = &sc->sc_slots[slot]; |
xs = &sc->sc_slots[slot]; |
if (xs->xs_idx != 0) { |
if (xs->xs_idx != 0) { |
xhci_free_slot(sc, xs, XHCI_DCI_SLOT + 1, 32); |
xhci_free_slot(sc, xs); |
xhci_set_dcba(sc, 0, slot); |
xhci_set_dcba(sc, 0, slot); |
memset(xs, 0, sizeof(*xs)); |
memset(xs, 0, sizeof(*xs)); |
} |
} |
Line 2908 xhci_init_slot(struct usbd_device *dev, |
|
Line 2951 xhci_init_slot(struct usbd_device *dev, |
|
struct xhci_softc * const sc = XHCI_BUS2SC(dev->ud_bus); |
struct xhci_softc * const sc = XHCI_BUS2SC(dev->ud_bus); |
struct xhci_slot *xs; |
struct xhci_slot *xs; |
usbd_status err; |
usbd_status err; |
u_int dci; |
|
|
|
XHCIHIST_FUNC(); |
XHCIHIST_FUNC(); |
XHCIHIST_CALLARGS("slot %ju", slot, 0, 0, 0); |
XHCIHIST_CALLARGS("slot %ju", slot, 0, 0, 0); |
Line 2918 xhci_init_slot(struct usbd_device *dev, |
|
Line 2960 xhci_init_slot(struct usbd_device *dev, |
|
/* allocate contexts */ |
/* allocate contexts */ |
err = usb_allocmem(&sc->sc_bus, sc->sc_pgsz, sc->sc_pgsz, |
err = usb_allocmem(&sc->sc_bus, sc->sc_pgsz, sc->sc_pgsz, |
&xs->xs_dc_dma); |
&xs->xs_dc_dma); |
if (err) |
if (err) { |
|
DPRINTFN(1, "failed to allocmem output device context %jd", |
|
err, 0, 0, 0); |
return err; |
return err; |
|
} |
memset(KERNADDR(&xs->xs_dc_dma, 0), 0, sc->sc_pgsz); |
memset(KERNADDR(&xs->xs_dc_dma, 0), 0, sc->sc_pgsz); |
|
|
err = usb_allocmem(&sc->sc_bus, sc->sc_pgsz, sc->sc_pgsz, |
err = usb_allocmem(&sc->sc_bus, sc->sc_pgsz, sc->sc_pgsz, |
&xs->xs_ic_dma); |
&xs->xs_ic_dma); |
if (err) |
if (err) { |
|
DPRINTFN(1, "failed to allocmem input device context %jd", |
|
err, 0, 0, 0); |
goto bad1; |
goto bad1; |
memset(KERNADDR(&xs->xs_ic_dma, 0), 0, sc->sc_pgsz); |
|
|
|
for (dci = 0; dci < 32; dci++) { |
|
//CTASSERT(sizeof(xs->xs_ep[dci]) == sizeof(struct xhci_endpoint)); |
|
memset(&xs->xs_ep[dci], 0, sizeof(xs->xs_ep[dci])); |
|
if (dci == XHCI_DCI_SLOT) |
|
continue; |
|
err = xhci_ring_init(sc, &xs->xs_ep[dci].xe_tr, |
|
XHCI_TRANSFER_RING_TRBS, XHCI_TRB_ALIGN); |
|
if (err) { |
|
DPRINTFN(0, "ring init failure", 0, 0, 0, 0); |
|
goto bad2; |
|
} |
|
} |
} |
|
memset(KERNADDR(&xs->xs_ic_dma, 0), 0, sc->sc_pgsz); |
|
|
bad2: |
memset(&xs->xs_xr[0], 0, sizeof(xs->xs_xr)); |
if (err == USBD_NORMAL_COMPLETION) { |
xs->xs_idx = slot; |
xs->xs_idx = slot; |
|
} else { |
|
xhci_free_slot(sc, xs, XHCI_DCI_SLOT + 1, dci); |
|
} |
|
|
|
return err; |
return USBD_NORMAL_COMPLETION; |
|
|
bad1: |
bad1: |
usb_freemem(&sc->sc_bus, &xs->xs_dc_dma); |
usb_freemem(&sc->sc_bus, &xs->xs_dc_dma); |
Line 2957 xhci_init_slot(struct usbd_device *dev, |
|
Line 2988 xhci_init_slot(struct usbd_device *dev, |
|
} |
} |
|
|
static void |
static void |
xhci_free_slot(struct xhci_softc *sc, struct xhci_slot *xs, int start_dci, |
xhci_free_slot(struct xhci_softc *sc, struct xhci_slot *xs) |
int end_dci) |
|
{ |
{ |
u_int dci; |
u_int dci; |
|
|
XHCIHIST_FUNC(); |
XHCIHIST_FUNC(); |
XHCIHIST_CALLARGS("slot %ju start %ju end %ju", |
XHCIHIST_CALLARGS("slot %ju", xs->xs_idx, 0, 0, 0); |
xs->xs_idx, start_dci, end_dci, 0); |
|
|
|
for (dci = start_dci; dci < end_dci; dci++) { |
/* deallocate all allocated rings in the slot */ |
xhci_ring_free(sc, &xs->xs_ep[dci].xe_tr); |
for (dci = XHCI_DCI_SLOT; dci <= XHCI_MAX_DCI; dci++) { |
memset(&xs->xs_ep[dci], 0, sizeof(xs->xs_ep[dci])); |
if (xs->xs_xr[dci] != NULL) |
|
xhci_ring_free(sc, &xs->xs_xr[dci]); |
} |
} |
usb_freemem(&sc->sc_bus, &xs->xs_ic_dma); |
usb_freemem(&sc->sc_bus, &xs->xs_ic_dma); |
usb_freemem(&sc->sc_bus, &xs->xs_dc_dma); |
usb_freemem(&sc->sc_bus, &xs->xs_dc_dma); |
Line 3109 xhci_setup_ctx(struct usbd_pipe *pipe) |
|
Line 3139 xhci_setup_ctx(struct usbd_pipe *pipe) |
|
/* rewind TR dequeue pointer in xHC */ |
/* rewind TR dequeue pointer in xHC */ |
/* can't use xhci_ep_get_dci() yet? */ |
/* can't use xhci_ep_get_dci() yet? */ |
*(uint64_t *)(&cp[2]) = htole64( |
*(uint64_t *)(&cp[2]) = htole64( |
xhci_ring_trbp(&xs->xs_ep[dci].xe_tr, 0) | |
xhci_ring_trbp(xs->xs_xr[dci], 0) | |
XHCI_EPCTX_2_DCS_SET(1)); |
XHCI_EPCTX_2_DCS_SET(1)); |
|
|
cp[0] = htole32(cp[0]); |
cp[0] = htole32(cp[0]); |
Line 3117 xhci_setup_ctx(struct usbd_pipe *pipe) |
|
Line 3147 xhci_setup_ctx(struct usbd_pipe *pipe) |
|
cp[4] = htole32(cp[4]); |
cp[4] = htole32(cp[4]); |
|
|
/* rewind TR dequeue pointer in driver */ |
/* rewind TR dequeue pointer in driver */ |
struct xhci_ring *xr = &xs->xs_ep[dci].xe_tr; |
struct xhci_ring *xr = xs->xs_xr[dci]; |
mutex_enter(&xr->xr_lock); |
mutex_enter(&xr->xr_lock); |
xhci_host_dequeue(xr); |
xhci_host_dequeue(xr); |
mutex_exit(&xr->xr_lock); |
mutex_exit(&xr->xr_lock); |
Line 3811 xhci_device_ctrl_start(struct usbd_xfer |
|
Line 3841 xhci_device_ctrl_start(struct usbd_xfer |
|
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
struct xhci_ring * const tr = &xs->xs_ep[dci].xe_tr; |
struct xhci_ring * const tr = xs->xs_xr[dci]; |
struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); |
struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); |
usb_device_request_t * const req = &xfer->ux_request; |
usb_device_request_t * const req = &xfer->ux_request; |
const int isread = usbd_xfer_isread(xfer); |
const int isread = usbd_xfer_isread(xfer); |
Line 3948 xhci_device_bulk_start(struct usbd_xfer |
|
Line 3978 xhci_device_bulk_start(struct usbd_xfer |
|
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
struct xhci_ring * const tr = &xs->xs_ep[dci].xe_tr; |
struct xhci_ring * const tr = xs->xs_xr[dci]; |
struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); |
struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); |
const uint32_t len = xfer->ux_length; |
const uint32_t len = xfer->ux_length; |
usb_dma_t * const dma = &xfer->ux_dmabuf; |
usb_dma_t * const dma = &xfer->ux_dmabuf; |
Line 4069 xhci_device_intr_start(struct usbd_xfer |
|
Line 4099 xhci_device_intr_start(struct usbd_xfer |
|
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_softc * const sc = XHCI_XFER2SC(xfer); |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); |
struct xhci_ring * const tr = &xs->xs_ep[dci].xe_tr; |
struct xhci_ring * const tr = xs->xs_xr[dci]; |
struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); |
struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); |
const uint32_t len = xfer->ux_length; |
const uint32_t len = xfer->ux_length; |
const bool polling = xhci_polling_p(sc); |
const bool polling = xhci_polling_p(sc); |