From owner-p4-projects@FreeBSD.ORG Thu Aug 5 16:29:23 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 8F6911065677; Thu, 5 Aug 2010 16:29:23 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 533621065675 for ; Thu, 5 Aug 2010 16:29:23 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 3E5848FC14 for ; Thu, 5 Aug 2010 16:29:23 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.4/8.14.4) with ESMTP id o75GTNSo010420 for ; Thu, 5 Aug 2010 16:29:23 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.4/8.14.4/Submit) id o75GTNvB010418 for perforce@freebsd.org; Thu, 5 Aug 2010 16:29:23 GMT (envelope-from hselasky@FreeBSD.org) Date: Thu, 5 Aug 2010 16:29:23 GMT Message-Id: <201008051629.o75GTNvB010418@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 181872 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Aug 2010 16:29:23 -0000 http://p4web.freebsd.org/@@181872?ac=10 Change 181872 by hselasky@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 {