- Add support for 64-byte contexts to XHCI driver.
- Remove some dead code. - Fixed one instance of missing endian conversion. Approved by: thompsa (mentor)
This commit is contained in:
parent
ad10f5790b
commit
c1338c65d6
@ -133,6 +133,12 @@ static usb_error_t xhci_configure_mask(struct usb_device *,
|
||||
static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
|
||||
uint64_t, uint8_t);
|
||||
static void xhci_endpoint_doorbell(struct usb_xfer *);
|
||||
static void xhci_ctx_set_le32(struct xhci_softc *sc, volatile uint32_t *ptr, uint32_t val);
|
||||
static uint32_t xhci_ctx_get_le32(struct xhci_softc *sc, volatile uint32_t *ptr);
|
||||
static void xhci_ctx_set_le64(struct xhci_softc *sc, volatile uint64_t *ptr, uint64_t val);
|
||||
#ifdef USB_DEBUG
|
||||
static uint64_t xhci_ctx_get_le64(struct xhci_softc *sc, volatile uint64_t *ptr);
|
||||
#endif
|
||||
|
||||
extern struct usb_bus_methods xhci_bus_methods;
|
||||
|
||||
@ -147,26 +153,26 @@ xhci_dump_trb(struct xhci_trb *trb)
|
||||
}
|
||||
|
||||
static void
|
||||
xhci_dump_endpoint(struct xhci_endp_ctx *pep)
|
||||
xhci_dump_endpoint(struct xhci_softc *sc, struct xhci_endp_ctx *pep)
|
||||
{
|
||||
DPRINTFN(5, "pep = %p\n", pep);
|
||||
DPRINTFN(5, "dwEpCtx0=0x%08x\n", pep->dwEpCtx0);
|
||||
DPRINTFN(5, "dwEpCtx1=0x%08x\n", pep->dwEpCtx1);
|
||||
DPRINTFN(5, "qwEpCtx2=0x%016llx\n", (long long)pep->qwEpCtx2);
|
||||
DPRINTFN(5, "dwEpCtx4=0x%08x\n", pep->dwEpCtx4);
|
||||
DPRINTFN(5, "dwEpCtx5=0x%08x\n", pep->dwEpCtx5);
|
||||
DPRINTFN(5, "dwEpCtx6=0x%08x\n", pep->dwEpCtx6);
|
||||
DPRINTFN(5, "dwEpCtx7=0x%08x\n", pep->dwEpCtx7);
|
||||
DPRINTFN(5, "dwEpCtx0=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx0));
|
||||
DPRINTFN(5, "dwEpCtx1=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx1));
|
||||
DPRINTFN(5, "qwEpCtx2=0x%016llx\n", (long long)xhci_ctx_get_le64(sc, &pep->qwEpCtx2));
|
||||
DPRINTFN(5, "dwEpCtx4=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx4));
|
||||
DPRINTFN(5, "dwEpCtx5=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx5));
|
||||
DPRINTFN(5, "dwEpCtx6=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx6));
|
||||
DPRINTFN(5, "dwEpCtx7=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx7));
|
||||
}
|
||||
|
||||
static void
|
||||
xhci_dump_device(struct xhci_slot_ctx *psl)
|
||||
xhci_dump_device(struct xhci_softc *sc, struct xhci_slot_ctx *psl)
|
||||
{
|
||||
DPRINTFN(5, "psl = %p\n", psl);
|
||||
DPRINTFN(5, "dwSctx0=0x%08x\n", psl->dwSctx0);
|
||||
DPRINTFN(5, "dwSctx1=0x%08x\n", psl->dwSctx1);
|
||||
DPRINTFN(5, "dwSctx2=0x%08x\n", psl->dwSctx2);
|
||||
DPRINTFN(5, "dwSctx3=0x%08x\n", psl->dwSctx3);
|
||||
DPRINTFN(5, "dwSctx0=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx0));
|
||||
DPRINTFN(5, "dwSctx1=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx1));
|
||||
DPRINTFN(5, "dwSctx2=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx2));
|
||||
DPRINTFN(5, "dwSctx3=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx3));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -188,6 +194,60 @@ xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xhci_ctx_set_le32(struct xhci_softc *sc, volatile uint32_t *ptr, uint32_t val)
|
||||
{
|
||||
if (sc->sc_ctx_is_64_byte) {
|
||||
uint32_t offset;
|
||||
/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
|
||||
/* all contexts are initially 32-bytes */
|
||||
offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
|
||||
ptr = (volatile uint32_t *)(((volatile uint8_t *)ptr) + offset);
|
||||
}
|
||||
*ptr = htole32(val);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
xhci_ctx_get_le32(struct xhci_softc *sc, volatile uint32_t *ptr)
|
||||
{
|
||||
if (sc->sc_ctx_is_64_byte) {
|
||||
uint32_t offset;
|
||||
/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
|
||||
/* all contexts are initially 32-bytes */
|
||||
offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
|
||||
ptr = (volatile uint32_t *)(((volatile uint8_t *)ptr) + offset);
|
||||
}
|
||||
return (le32toh(*ptr));
|
||||
}
|
||||
|
||||
static void
|
||||
xhci_ctx_set_le64(struct xhci_softc *sc, volatile uint64_t *ptr, uint64_t val)
|
||||
{
|
||||
if (sc->sc_ctx_is_64_byte) {
|
||||
uint32_t offset;
|
||||
/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
|
||||
/* all contexts are initially 32-bytes */
|
||||
offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
|
||||
ptr = (volatile uint64_t *)(((volatile uint8_t *)ptr) + offset);
|
||||
}
|
||||
*ptr = htole64(val);
|
||||
}
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
static uint64_t
|
||||
xhci_ctx_get_le64(struct xhci_softc *sc, volatile uint64_t *ptr)
|
||||
{
|
||||
if (sc->sc_ctx_is_64_byte) {
|
||||
uint32_t offset;
|
||||
/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
|
||||
/* all contexts are initially 32-bytes */
|
||||
offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
|
||||
ptr = (volatile uint64_t *)(((volatile uint8_t *)ptr) + offset);
|
||||
}
|
||||
return (le64toh(*ptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_error_t
|
||||
xhci_start_controller(struct xhci_softc *sc)
|
||||
{
|
||||
@ -221,9 +281,11 @@ xhci_start_controller(struct xhci_softc *sc)
|
||||
DPRINTF("HCS0 = 0x%08x\n", temp);
|
||||
|
||||
if (XHCI_HCS0_CSZ(temp)) {
|
||||
device_printf(sc->sc_bus.parent, "Driver does not "
|
||||
"support 64-byte contexts.");
|
||||
return (USB_ERR_IOERROR);
|
||||
sc->sc_ctx_is_64_byte = 1;
|
||||
device_printf(sc->sc_bus.parent, "64 byte context size.\n");
|
||||
} else {
|
||||
sc->sc_ctx_is_64_byte = 0;
|
||||
device_printf(sc->sc_bus.parent, "32 byte context size.\n");
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
@ -1126,6 +1188,7 @@ xhci_set_address(struct usb_device *udev, struct mtx *mtx, uint16_t address)
|
||||
struct xhci_hw_dev *hdev;
|
||||
struct xhci_dev_ctx *pdev;
|
||||
struct xhci_endpoint_ext *pepext;
|
||||
uint32_t temp;
|
||||
uint16_t mps;
|
||||
usb_error_t err;
|
||||
uint8_t index;
|
||||
@ -1203,7 +1266,9 @@ xhci_set_address(struct usb_device *udev, struct mtx *mtx, uint16_t address)
|
||||
usbd_get_page(&hdev->device_pc, 0, &buf_dev);
|
||||
pdev = buf_dev.buffer;
|
||||
usb_pc_cpu_invalidate(&hdev->device_pc);
|
||||
udev->address = XHCI_SCTX_3_DEV_ADDR_GET(pdev->ctx_slot.dwSctx3);
|
||||
|
||||
temp = xhci_ctx_get_le32(sc, &pdev->ctx_slot.dwSctx3);
|
||||
udev->address = XHCI_SCTX_3_DEV_ADDR_GET(temp);
|
||||
|
||||
/* update device state to new value */
|
||||
|
||||
@ -1963,11 +2028,11 @@ xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop)
|
||||
|
||||
if (drop) {
|
||||
mask &= XHCI_INCTX_NON_CTRL_MASK;
|
||||
pinp->ctx_input.dwInCtx0 = htole32(mask);
|
||||
pinp->ctx_input.dwInCtx1 = 0;
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, mask);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, 0);
|
||||
} else {
|
||||
pinp->ctx_input.dwInCtx0 = 0;
|
||||
pinp->ctx_input.dwInCtx1 = htole32(mask);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -2049,7 +2114,7 @@ xhci_configure_endpoint(struct usb_device *udev,
|
||||
break;
|
||||
}
|
||||
|
||||
pinp->ctx_ep[epno - 1].dwEpCtx0 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx0, temp);
|
||||
|
||||
temp =
|
||||
XHCI_EPCTX_1_HID_SET(0) |
|
||||
@ -2080,11 +2145,11 @@ xhci_configure_endpoint(struct usb_device *udev,
|
||||
if (epno & 1)
|
||||
temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
|
||||
|
||||
pinp->ctx_ep[epno - 1].dwEpCtx1 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx1, temp);
|
||||
|
||||
ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
|
||||
|
||||
pinp->ctx_ep[epno - 1].qwEpCtx2 = htole64(ring_addr);
|
||||
xhci_ctx_set_le64(sc, &pinp->ctx_ep[epno - 1].qwEpCtx2, ring_addr);
|
||||
|
||||
switch (edesc->bmAttributes & UE_XFERTYPE) {
|
||||
case UE_INTERRUPT:
|
||||
@ -2101,10 +2166,10 @@ xhci_configure_endpoint(struct usb_device *udev,
|
||||
break;
|
||||
}
|
||||
|
||||
pinp->ctx_ep[epno - 1].dwEpCtx4 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx4, temp);
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
xhci_dump_endpoint(&pinp->ctx_ep[epno - 1]);
|
||||
xhci_dump_endpoint(sc, &pinp->ctx_ep[epno - 1]);
|
||||
#endif
|
||||
usb_pc_cpu_flush(&sc->sc_hw.devs[index].input_pc);
|
||||
|
||||
@ -2137,12 +2202,9 @@ static usb_error_t
|
||||
xhci_configure_device(struct usb_device *udev)
|
||||
{
|
||||
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
|
||||
struct usb_page_search buf_dev;
|
||||
struct usb_page_search buf_inp;
|
||||
struct usb_page_cache *pcdev;
|
||||
struct usb_page_cache *pcinp;
|
||||
struct xhci_input_dev_ctx *pinp;
|
||||
struct xhci_dev_ctx *pdev;
|
||||
struct usb_device *hubdev;
|
||||
uint32_t temp;
|
||||
uint32_t route;
|
||||
@ -2154,13 +2216,10 @@ xhci_configure_device(struct usb_device *udev)
|
||||
|
||||
DPRINTF("index=%u\n", index);
|
||||
|
||||
pcdev = &sc->sc_hw.devs[index].device_pc;
|
||||
pcinp = &sc->sc_hw.devs[index].input_pc;
|
||||
|
||||
usbd_get_page(pcdev, 0, &buf_dev);
|
||||
usbd_get_page(pcinp, 0, &buf_inp);
|
||||
|
||||
pdev = buf_dev.buffer;
|
||||
pinp = buf_inp.buffer;
|
||||
|
||||
rh_port = 0;
|
||||
@ -2231,7 +2290,7 @@ xhci_configure_device(struct usb_device *udev)
|
||||
#endif
|
||||
}
|
||||
|
||||
pinp->ctx_slot.dwSctx0 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
|
||||
|
||||
temp = XHCI_SCTX_1_RH_PORT_SET(rh_port);
|
||||
|
||||
@ -2257,7 +2316,7 @@ xhci_configure_device(struct usb_device *udev)
|
||||
break;
|
||||
}
|
||||
|
||||
pinp->ctx_slot.dwSctx1 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx1, temp);
|
||||
|
||||
temp = XHCI_SCTX_2_IRQ_TARGET_SET(0);
|
||||
|
||||
@ -2281,15 +2340,15 @@ xhci_configure_device(struct usb_device *udev)
|
||||
break;
|
||||
}
|
||||
|
||||
pinp->ctx_slot.dwSctx2 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx2, temp);
|
||||
|
||||
temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) |
|
||||
XHCI_SCTX_3_SLOT_STATE_SET(0);
|
||||
|
||||
pinp->ctx_slot.dwSctx3 = htole32(temp);
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx3, temp);
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
xhci_dump_device(&pinp->ctx_slot);
|
||||
xhci_dump_device(sc, &pinp->ctx_slot);
|
||||
#endif
|
||||
usb_pc_cpu_flush(pcinp);
|
||||
|
||||
@ -2317,7 +2376,9 @@ 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_ctx), XHCI_PAGE_SIZE))
|
||||
if (usb_pc_alloc_mem(pc, pg, sc->sc_ctx_is_64_byte ?
|
||||
(2 * sizeof(struct xhci_dev_ctx)) :
|
||||
sizeof(struct xhci_dev_ctx), XHCI_PAGE_SIZE))
|
||||
goto error;
|
||||
|
||||
usbd_get_page(pc, 0, &buf_dev);
|
||||
@ -2328,7 +2389,9 @@ 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_input_dev_ctx), XHCI_PAGE_SIZE))
|
||||
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))
|
||||
goto error;
|
||||
|
||||
pc = &sc->sc_hw.devs[index].endpoint_pc;
|
||||
@ -3347,13 +3410,10 @@ static usb_error_t
|
||||
xhci_configure_reset_endpoint(struct usb_xfer *xfer)
|
||||
{
|
||||
struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
|
||||
struct usb_page_search buf_dev;
|
||||
struct usb_page_search buf_inp;
|
||||
struct usb_device *udev;
|
||||
struct xhci_endpoint_ext *pepext;
|
||||
struct usb_endpoint_descriptor *edesc;
|
||||
struct xhci_dev_ctx *pdctx;
|
||||
struct usb_page_cache *pcdev;
|
||||
struct usb_page_cache *pcinp;
|
||||
usb_error_t err;
|
||||
uint8_t index;
|
||||
@ -3365,14 +3425,10 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
|
||||
udev = xfer->xroot->udev;
|
||||
index = udev->controller_slot_id;
|
||||
|
||||
pcdev = &sc->sc_hw.devs[index].device_pc;
|
||||
pcinp = &sc->sc_hw.devs[index].input_pc;
|
||||
|
||||
usbd_get_page(pcdev, 0, &buf_dev);
|
||||
usbd_get_page(pcinp, 0, &buf_inp);
|
||||
|
||||
pdctx = buf_dev.buffer;
|
||||
|
||||
edesc = xfer->endpoint->edesc;
|
||||
|
||||
epno = edesc->bEndpointAddress;
|
||||
|
@ -477,6 +477,9 @@ struct xhci_softc {
|
||||
uint8_t sc_conf;
|
||||
uint8_t sc_hub_idata[2];
|
||||
|
||||
/* size of context */
|
||||
uint8_t sc_ctx_is_64_byte;
|
||||
|
||||
/* vendor string for root HUB */
|
||||
char sc_vendor[16];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user