Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Aug 2010 16:29:23 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 181872 for review
Message-ID:  <201008051629.o75GTNvB010418@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008051629.o75GTNvB010418>