PERFORCE change 181872 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Thu Aug 5 16:29:23 UTC 2010
http://p4web.freebsd.org/@@181872?ac=10
Change 181872 by hselasky at hselasky_laptop001 on 2010/08/05 16:28:58
USB controller (XHCI):
- correct programming errors
- scratchpads are only needed per HC and not per USB device
- add more debug prints
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#14 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#16 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#14 (text+ko) ====
@@ -119,16 +119,51 @@
extern struct usb_bus_methods xhci_bus_methods;
+#ifdef USB_DEBUG
+#if 0
static void
+xhci_dump_device(struct usb_device *udev)
+{
+ struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+ struct usb_page_search buf_dev;
+ struct usb_page_cache *pcdev;
+ struct xhci_dev_ctx *pdev;
+ uint8_t index;
+
+ index = udev->controller_slot_id;
+
+ pcdev = &sc->sc_hw.devs[index].device_pc;
+
+ usbd_get_page(pcdev, 0, &buf_dev);
+
+ usb_pc_cpu_invalidate(pcdev);
+
+ pdev = buf_dev.buffer;
+
+ DPRINTF("SCTX0=0x%08x\n", pdev->ctx_slot.dwSctx0);
+ DPRINTF("SCTX1=0x%08x\n", pdev->ctx_slot.dwSctx1);
+ DPRINTF("SCTX2=0x%08x\n", pdev->ctx_slot.dwSctx2);
+ DPRINTF("SCTX3=0x%08x\n", pdev->ctx_slot.dwSctx3);
+}
+#endif
+#endif
+
+static void
xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
{
- struct xhci_softc *sc = XHCI_BUS2SC(bus);
+ struct xhci_softc *sc = XHCI_BUS2SC(bus);
+ uint8_t i;
- cb(bus, &sc->sc_hw.root_pc, &sc->sc_hw.root_pg,
+ cb(bus, &sc->sc_hw.root_pc, &sc->sc_hw.root_pg,
sizeof(struct xhci_hw_root), XHCI_PAGE_SIZE);
- cb(bus, &sc->sc_hw.ctx_pc, &sc->sc_hw.ctx_pg,
+ cb(bus, &sc->sc_hw.ctx_pc, &sc->sc_hw.ctx_pg,
sizeof(struct xhci_dev_ctx_addr), XHCI_PAGE_SIZE);
+
+ for (i = 0; i != XHCI_MAX_SCRATCHPADS; i++) {
+ cb(bus, &sc->sc_hw.scratch_pc[i], &sc->sc_hw.scratch_pg[i],
+ XHCI_PAGE_SIZE, XHCI_PAGE_SIZE);
+ }
}
usb_error_t
@@ -136,7 +171,7 @@
{
struct usb_page_search buf_res;
struct xhci_hw_root *phwr;
- struct xhci_dev_ctx_addr *pctxa;
+ struct xhci_dev_ctx_addr *pdctxa;
uint64_t addr;
uint32_t temp;
uint16_t i;
@@ -145,10 +180,12 @@
sc->sc_capa_off = 0;
sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
- sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0xF;
+ sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
+ DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
+ DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
sc->sc_event_ccs = 1;
sc->sc_event_idx = 0;
@@ -157,6 +194,15 @@
DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
+ temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+
+ 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);
+ }
+
/* Reset controller */
XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
@@ -168,12 +214,13 @@
}
if (temp) {
- device_printf(sc->sc_bus.bdev, "Controller reset timeout.\n");
+ device_printf(sc->sc_bus.parent, "Controller reset timeout.\n");
return (USB_ERR_IOERROR);
}
if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) {
- device_printf(sc->sc_bus.bdev, "Controller does not support 4K page size.\n");
+ device_printf(sc->sc_bus.parent, "Controller does "
+ "not support 4K page size.\n");
return (USB_ERR_IOERROR);
}
@@ -182,7 +229,7 @@
i = XHCI_HCS1_N_PORTS(temp);
if (i == 0) {
- device_printf(sc->sc_bus.bdev, "Invalid number "
+ device_printf(sc->sc_bus.parent, "Invalid number "
"of ports: %u\n", i);
return (USB_ERR_IOERROR);
}
@@ -204,7 +251,7 @@
sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp);
if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) {
- device_printf(sc->sc_bus.bdev, "XHCI request "
+ device_printf(sc->sc_bus.parent, "XHCI request "
"too many scratchpads\n");
return (USB_ERR_NOMEM);
}
@@ -228,10 +275,25 @@
usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res);
+ pdctxa = buf_res.buffer;
+
+ memset(pdctxa, 0, sizeof(*pdctxa));
+
+ addr = buf_res.physaddr + (uintptr_t)&((struct xhci_dev_ctx_addr *)0)->qwSpBufPtr[0];
+
+ /* slot 0 points to the table of scratchpad pointers */
+ pdctxa->qwBaaDevCtxAddr[0] = htole64(buf_res.physaddr);
+
+ for (i = 0; i != sc->sc_noscratch; i++) {
+
+ struct usb_page_search buf_scp;
+
+ usbd_get_page(&sc->sc_hw.scratch_pc[i], 0, &buf_scp);
+
+ pdctxa->qwSpBufPtr[i] = htole64((uint64_t)buf_scp.physaddr);
+ }
+
addr = buf_res.physaddr;
- pctxa = buf_res.buffer;
-
- memset(pctxa, 0, sizeof(*pctxa));
XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr);
XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32));
@@ -239,7 +301,7 @@
/* Setup interrupter registers */
temp = XREAD4(sc, runt, XHCI_IMAN(0));
- temp |= XHCI_IMAN_INTR_ENA | XHCI_IMAN_INTR_PEND;
+ temp |= XHCI_IMAN_INTR_ENA;
XWRITE4(sc, runt, XHCI_IMAN(0), temp);
/* Setup interrupt rate */
@@ -271,7 +333,7 @@
sc->sc_erst_max = temp;
- XWRITE4(sc, runt, XHCI_ERSTS_SET(0), temp);
+ XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(temp));
DPRINTF("ERDP(0)=0x%016llx\n", (unsigned long long)addr);
@@ -295,10 +357,6 @@
XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32));
phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].qwTrb0 = htole64(addr);
- phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].dwTrb2 = htole32(0);
- phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].dwTrb3 = htole32(
- XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
- XHCI_TRB_3_IOC_BIT | XHCI_TRB_3_TC_BIT);
usb_bus_mem_flush_all(&sc->sc_bus, &xhci_iterate_hw_softc);
@@ -314,7 +372,7 @@
}
if (temp) {
XWRITE4(sc, oper, XHCI_USBCMD, 0);
- device_printf(sc->sc_bus.bdev, "Run timeout.\n");
+ device_printf(sc->sc_bus.parent, "Run timeout.\n");
return (USB_ERR_IOERROR);
}
@@ -348,7 +406,7 @@
}
if (!temp) {
- device_printf(sc->sc_bus.bdev, "Controller halt timeout.\n");
+ device_printf(sc->sc_bus.parent, "Controller halt timeout.\n");
return (USB_ERR_IOERROR);
}
return (0);
@@ -651,7 +709,7 @@
if (sc->sc_cmd_addr == trb->qwTrb0) {
DPRINTF("Received command event\n");
sc->sc_cmd_result[0] = trb->dwTrb2;
- sc->sc_cmd_result[1] = trb->dwTrb2;
+ sc->sc_cmd_result[1] = trb->dwTrb3;
cv_signal(&sc->sc_cmd_cv);
}
}
@@ -690,7 +748,10 @@
event = XHCI_TRB_3_TYPE_GET(temp);
- DPRINTFN(10, "event[%u] = %u\n", i, event);
+ DPRINTFN(10, "event[%u] = %u (0x%016llx 0x%08lx 0x%08lx)\n",
+ i, event, (long long)le64toh(phwr->hwr_events[i].qwTrb0),
+ (long)le32toh(phwr->hwr_events[i].dwTrb2),
+ (long)le32toh(phwr->hwr_events[i].dwTrb3));
switch (event) {
case XHCI_TRB_EVENT_TRANSFER:
@@ -720,6 +781,8 @@
/* we are within a PAGE - no need to update the high bits */
+ temp |= XHCI_ERDP_LO_SINDEX(i) | XHCI_ERDP_LO_BUSY;
+
XWRITE4(sc, runt, XHCI_ERDP_LO(0), temp);
sc->sc_event_idx = i;
@@ -753,6 +816,12 @@
i = sc->sc_command_idx;
j = sc->sc_command_ccs;
+ DPRINTFN(10, "command[%u] = %u (0x%016llx, 0x%08lx, 0x%08lx)\n",
+ i, XHCI_TRB_3_TYPE_GET(le32toh(trb->qwTrb0)),
+ (long long)le64toh(trb->qwTrb0),
+ (long)le32toh(trb->dwTrb2),
+ (long)le32toh(trb->dwTrb3));
+
phwr->hwr_commands[i].qwTrb0 = trb->qwTrb0;
phwr->hwr_commands[i].dwTrb2 = trb->dwTrb2;
@@ -765,30 +834,30 @@
else
temp &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
+ temp &= ~htole32(XHCI_TRB_3_TC_BIT);
+
phwr->hwr_commands[i].dwTrb3 = temp;
usb_pc_cpu_flush(&sc->sc_hw.root_pc);
- DPRINTFN(10, "command[%u] = %u\n", i,
- XHCI_TRB_3_TYPE_GET(le32toh(temp)));
-
addr = (uint64_t)buf_res.physaddr +
(uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[i];
+
sc->sc_cmd_addr = htole64(addr);
i++;
if (i == (XHCI_MAX_COMMANDS - 1)) {
- /* update cycle bit of LINK TRB */
+ if (j) {
+ temp |= htole32(XHCI_TRB_3_CYCLE_BIT |
+ XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
+ XHCI_TRB_3_TC_BIT);
+ } else {
+ temp &= htole32(XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
+ XHCI_TRB_3_TC_BIT);
+ }
- temp = phwr->hwr_commands[i].dwTrb3;
-
- if (j)
- temp |= htole32(XHCI_TRB_3_CYCLE_BIT);
- else
- temp &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
-
phwr->hwr_commands[i].dwTrb3 = temp;
usb_pc_cpu_flush(&sc->sc_hw.root_pc);
@@ -824,13 +893,34 @@
return (err);
}
+#if 0
static usb_error_t
+xhci_cmd_nop(struct xhci_softc *sc)
+{
+ struct xhci_trb trb;
+ uint32_t temp;
+
+ DPRINTF("\n");
+
+ trb.qwTrb0 = 0;
+ trb.dwTrb2 = 0;
+ temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NOOP);
+
+ trb.dwTrb3 = htole32(temp);
+
+ return (xhci_do_command(sc, &trb, 50 /* ms */));
+}
+#endif
+
+static usb_error_t
xhci_cmd_enable_slot(struct xhci_softc *sc, uint8_t *pslot)
{
struct xhci_trb trb;
uint32_t temp;
usb_error_t err;
+ DPRINTF("\n");
+
trb.qwTrb0 = 0;
trb.dwTrb2 = 0;
trb.dwTrb3 = htole32(XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ENABLE_SLOT));
@@ -853,6 +943,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = 0;
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DISABLE_SLOT) |
@@ -870,6 +962,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = htole64(input_ctx);
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ADDRESS_DEVICE) |
@@ -890,6 +984,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = htole64(input_ctx);
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_CONFIGURE_EP) |
@@ -911,6 +1007,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = htole64(input_ctx);
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_EVALUATE_CTX) |
@@ -928,6 +1026,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = 0;
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_EP) |
@@ -950,6 +1050,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = 0;
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STOP_EP) |
@@ -971,6 +1073,8 @@
struct xhci_trb trb;
uint32_t temp;
+ DPRINTF("\n");
+
trb.qwTrb0 = 0;
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_DEVICE) |
@@ -988,35 +1092,43 @@
xhci_interrupt(struct xhci_softc *sc)
{
uint32_t status;
+ uint32_t temp;
USB_BUS_LOCK(&sc->sc_bus);
- DPRINTFN(16, "real interrupt\n");
+ status = XREAD4(sc, oper, XHCI_USBSTS);
+
+ /* acknowledge interrupts */
+
+ XWRITE4(sc, oper, XHCI_USBSTS, status);
- status = XREAD4(sc, oper, XHCI_USBSTS);
+ temp = XREAD4(sc, runt, XHCI_IMAN(0));
- if (status & XHCI_STS_PCD) {
- xhci_root_intr(sc);
- }
+ /* acknowledge pending event */
+ XWRITE4(sc, runt, XHCI_IMAN(0), temp);
- if (status & XHCI_STS_HCH) {
- printf("%s: host controller halted\n",
- __FUNCTION__);
- }
+ DPRINTFN(16, "real interrupt (sts=0x%08x, iman=0x%08x)\n", status, temp);
- if (status & XHCI_STS_HSE) {
- printf("%s: host system error\n",
- __FUNCTION__);
- }
+ if (status != 0) {
+ if (status & XHCI_STS_PCD) {
+ xhci_root_intr(sc);
+ }
- if (status & XHCI_STS_HCE) {
- printf("%s: host controller error\n",
- __FUNCTION__);
- }
+ if (status & XHCI_STS_HCH) {
+ printf("%s: host controller halted\n",
+ __FUNCTION__);
+ }
- /* acknowledge interrupts */
+ if (status & XHCI_STS_HSE) {
+ printf("%s: host system error\n",
+ __FUNCTION__);
+ }
- XWRITE4(sc, oper, XHCI_USBSTS, status);
+ if (status & XHCI_STS_HCE) {
+ printf("%s: host controller error\n",
+ __FUNCTION__);
+ }
+ }
xhci_interrupt_poll(sc);
@@ -1038,9 +1150,11 @@
pepext = xhci_get_endpoint_ext(xfer);
+#if 0
/* check if endpoint is halted */
if (pepext->trb_halted != 0)
return;
+#endif
/* transfer is transferred */
xhci_device_done(xfer, USB_ERR_TIMEOUT);
@@ -1494,17 +1608,16 @@
}
static void
-xhci_set_slot_pointers(struct xhci_softc *sc, uint8_t index,
- uint64_t dev_addr, uint64_t scratch_addr)
+xhci_set_slot_pointer(struct xhci_softc *sc, uint8_t index, uint64_t dev_addr)
{
struct usb_page_search buf_res;
- volatile uint64_t *ptr;
+ struct xhci_dev_ctx_addr *pdctxa;
usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res);
- ptr = buf_res.buffer;
- ptr[(2*index) + 0] = htole64(dev_addr);
- ptr[(2*index) + 1] = htole64(scratch_addr);
+ pdctxa = buf_res.buffer;
+
+ pdctxa->qwBaaDevCtxAddr[index] = htole64(dev_addr);
usb_pc_cpu_flush(&sc->sc_hw.ctx_pc);
}
@@ -1550,7 +1663,6 @@
index = udev->controller_slot_id;
usbd_get_page(&sc->sc_hw.devs[index].input_pc, 0, &buf_inp);
- usbd_get_page(&sc->sc_hw.devs[index].endpoint_pc, 0, &buf_ep);
edesc = xfer->endpoint->edesc;
@@ -1564,6 +1676,8 @@
if (epno == 0)
return (USB_ERR_INVAL); /* invalid */
+ usbd_get_page(&sc->sc_hw.devs[index].endpoint_pc, (XHCI_MAX_TRANSFERS * sizeof(struct xhci_trb)) * epno, &buf_ep);
+
pinp = buf_inp.buffer;
mask = 1U << epno;
@@ -1589,7 +1703,7 @@
break;
case UE_ISOCHRONOUS:
if (udev->speed == USB_SPEED_SUPER)
- temp |= XHCI_EPCTX_0_MULT_SET(xfer->max_packet_count);
+ temp |= XHCI_EPCTX_0_MULT_SET(xfer->max_packet_count - 1);
break;
default:
break;
@@ -1599,7 +1713,7 @@
temp =
XHCI_EPCTX_1_HID_SET(0) |
- XHCI_EPCTX_1_MAXB_SET(xfer->max_packet_count) |
+ XHCI_EPCTX_1_MAXB_SET(xfer->max_packet_count - 1) |
XHCI_EPCTX_1_MAXP_SIZE_SET(xfer->max_packet_size);
if ((udev->parent_hs_hub != NULL) || (udev->address != 0))
@@ -1659,18 +1773,15 @@
xhci_configure_device(struct usb_device *udev)
{
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
- struct usb_page_search buf_scp;
struct usb_page_search buf_dev;
struct usb_page_search buf_inp;
struct usb_page_cache *pcdev;
struct usb_page_cache *pcinp;
- struct usb_page_cache *pc;
struct xhci_input_dev_ctx *pinp;
struct usb_device *hubdev;
uint32_t temp;
uint8_t index;
uint8_t rh_port;
- uint8_t i;
index = udev->controller_slot_id;
@@ -1686,7 +1797,16 @@
temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1);
while (hubdev->parent_hub != NULL) {
- temp |= ((uint32_t)(hubdev->port_no & 0xF)) << ((hubdev->depth - 1) * 4);
+
+ uint32_t pn;
+
+ /* HS/FS/LS devices can have more than 15 ports */
+ pn = hubdev->port_no;
+ if (pn > 15)
+ pn = 15;
+
+ temp |= pn << ((hubdev->depth - 1) * 4);
+
hubdev = hubdev->parent_hub;
}
@@ -1721,6 +1841,7 @@
case USB_SPEED_LOW:
case USB_SPEED_HIGH:
case USB_SPEED_FULL:
+ break;
default:
temp |= XHCI_SCTX_1_MAX_EL_SET(sc->sc_exit_lat_max);
break;
@@ -1744,24 +1865,10 @@
pinp->ctx_slot.dwSctx2 = htole32(temp);
temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) |
- XHCI_SCTX_3_SLOT_STATE_SET(3);
+ XHCI_SCTX_3_SLOT_STATE_SET(0);
pinp->ctx_slot.dwSctx3 = htole32(temp);
- for (i = 0; i != sc->sc_noscratch; i++) {
-
- pc = &sc->sc_hw.devs[index].scratch_pc[i];
-
- usbd_get_page(pc, 0, &buf_scp);
-
- pinp->ctx_sp_buf_ptr[i] = htole64((uint64_t)buf_scp.physaddr);
- }
-
- usb_pc_cpu_flush(pcinp);
-
- xhci_set_slot_pointers(sc, udev->controller_slot_id, buf_dev.physaddr,
- buf_inp.physaddr + (uintptr_t)&((struct xhci_input_dev_ctx *)0)->ctx_sp_buf_ptr[0]);
-
return (0); /* success */
}
@@ -1769,9 +1876,9 @@
xhci_alloc_device_ext(struct usb_device *udev)
{
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+ struct usb_page_search buf_dev;
struct usb_page_cache *pc;
struct usb_page *pg;
- uint8_t i;
uint8_t index;
index = udev->controller_slot_id;
@@ -1785,6 +1892,8 @@
if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_dev_ctx), XHCI_PAGE_SIZE))
goto error;
+ usbd_get_page(pc, 0, &buf_dev);
+
pc = &sc->sc_hw.devs[index].input_pc;
pg = &sc->sc_hw.devs[index].input_pg;
@@ -1803,17 +1912,8 @@
if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_dev_endpoint_trbs), XHCI_PAGE_SIZE))
goto error;
- for (i = 0; i != sc->sc_noscratch; i++) {
-
- pc = &sc->sc_hw.devs[index].scratch_pc[i];
- pg = &sc->sc_hw.devs[index].scratch_pg[i];
-
- /* need to initialize the page cache */
- pc->tag_parent = sc->sc_bus.dma_parent_tag;
+ xhci_set_slot_pointer(sc, index, buf_dev.physaddr);
- if (usb_pc_alloc_mem(pc, pg, XHCI_PAGE_SIZE, XHCI_PAGE_SIZE))
- goto error;
- }
return (0);
error:
@@ -1828,11 +1928,10 @@
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
struct usb_page_cache *pc;
uint8_t index;
- uint8_t i;
index = udev->controller_slot_id;
- xhci_set_slot_pointers(sc, index, 0, 0);
+ xhci_set_slot_pointer(sc, index, 0);
pc = &sc->sc_hw.devs[index].device_pc;
@@ -1845,12 +1944,6 @@
pc = &sc->sc_hw.devs[index].endpoint_pc;
usb_pc_free_mem(pc);
-
- for (i = 0; i != sc->sc_noscratch; i++) {
- pc = &sc->sc_hw.devs[index].scratch_pc[i];
-
- usb_pc_free_mem(pc);
- }
}
static struct xhci_endpoint_ext *
@@ -1960,7 +2053,7 @@
else
temp &= ~htole32(XHCI_TRB_3_TC_BIT);
- addr += (uintptr_t)&((struct xhci_endpoint_ext *)0)->trb[i + 1];
+ addr += sizeof(struct xhci_trb) * (i + 1);
td_last->td_trb[td_last->ntrb].dwTrb3 = temp;
td_last->td_trb[td_last->ntrb].qwTrb0 = htole64(addr);
@@ -2078,6 +2171,8 @@
static void
xhci_device_generic_close(struct usb_xfer *xfer)
{
+ DPRINTF("\n");
+
xhci_device_done(xfer, USB_ERR_CANCELLED);
if (xfer->flags_int.isochronous_xfr)
@@ -2087,25 +2182,34 @@
static void
xhci_device_generic_enter(struct usb_xfer *xfer)
{
+ DPRINTF("\n");
+
/* setup TD's and QH */
xhci_setup_generic_chain(xfer);
+#ifdef NOTYET
/* put transfer on interrupt queue */
usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
/* try to insert xfer on HW queue */
xhci_transfer_insert(xfer);
+#endif
}
static void
xhci_device_generic_start(struct usb_xfer *xfer)
{
+ DPRINTF("\n");
+
/* try to insert xfer on HW queue */
if (xhci_transfer_insert(xfer) != 0) {
DPRINTFN(0, "Failed to insert "
"transfer %p into HW queue.\n", xfer);
}
+ /* put transfer on interrupt queue */
+ usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
+
/* start timeout, if any */
if (xfer->timeout != 0)
usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
@@ -2949,7 +3053,7 @@
/* set invalid default */
- udev->controller_slot_id = sc->sc_noslot;
+ udev->controller_slot_id = sc->sc_noslot + 1;
/* try to get a new slot ID from the XHCI */
@@ -2960,7 +3064,13 @@
return (err);
}
- if (temp >= sc->sc_noslot) {
+ if (temp > sc->sc_noslot) {
+ XHCI_CMD_UNLOCK(sc);
+ return (USB_ERR_INVAL);
+ }
+
+ if (sc->sc_hw.devs[temp].allocated) {
+ DPRINTF("slot %u already allocated.\n", temp);
XHCI_CMD_UNLOCK(sc);
return (USB_ERR_INVAL);
}
@@ -2969,6 +3079,10 @@
udev->controller_slot_id = temp;
+ /* set allocated bit */
+
+ sc->sc_hw.devs[temp].allocated = 1;
+
err = xhci_alloc_device_ext(udev);
XHCI_CMD_UNLOCK(sc);
@@ -2980,6 +3094,7 @@
xhci_device_uninit(struct usb_device *udev)
{
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+ uint8_t index;
/* no init for root HUB */
if (udev->parent_hub == NULL)
@@ -2987,8 +3102,12 @@
XHCI_CMD_LOCK(sc);
- if (udev->controller_slot_id < sc->sc_noslot)
- xhci_cmd_disable_slot(sc, udev->controller_slot_id);
+ index = udev->controller_slot_id;
+
+ if (index <= sc->sc_noslot) {
+ xhci_cmd_disable_slot(sc, index);
+ sc->sc_hw.devs[index].allocated = 0;
+ }
xhci_free_device_ext(udev);
==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#16 (text+ko) ====
@@ -366,6 +366,8 @@
struct usb_page endpoint_pg;
struct xhci_endpoint_ext endp[XHCI_MAX_ENDPOINTS];
+
+ uint8_t allocated;
};
struct xhci_hw_softc {
@@ -377,7 +379,7 @@
struct usb_page ctx_pg;
struct usb_page scratch_pg[XHCI_MAX_SCRATCHPADS];
- struct xhci_hw_dev devs[XHCI_MAX_DEVICES];
+ struct xhci_hw_dev devs[XHCI_MAX_DEVICES + 1];
};
struct xhci_config_desc {
More information about the p4-projects
mailing list