PERFORCE change 181695 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sun Aug 1 21:21:32 UTC 2010


http://p4web.freebsd.org/@@181695?ac=10

Change 181695 by hselasky at hselasky_laptop001 on 2010/08/01 21:20:47

	USB controller (XHCI):
		- add code to allocate, initialise and free XHCI device contexts.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#8 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#10 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#11 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#8 (text+ko) ====

@@ -112,6 +112,7 @@
 static void xhci_do_poll(struct usb_bus *);
 static void xhci_device_done(struct usb_xfer *, usb_error_t);
 static void xhci_root_intr(struct xhci_softc *);
+static void xhci_free_device_ext(struct usb_device *udev);
 
 extern struct usb_bus_methods xhci_bus_methods;
 
@@ -175,18 +176,30 @@
 
 	i = XHCI_HCS1_N_PORTS(temp);
 
-	if ((i < 1) || (i > 15)) {
+	if (i == 0) {
 		device_printf(sc->sc_bus.bdev, "Invalid number "
 		    "of ports: %u\n", i);
-		if (i < 1)
-			return (USB_ERR_IOERROR);
-		else
-			i = 15;
+		return (USB_ERR_IOERROR);
 	}
 
 	sc->sc_noport = i;
 	sc->sc_nodev = XHCI_HCS1_DEVSLOT_MAX(temp);
 
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
+
+	sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp);
+
+	if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) {
+		device_printf(sc->sc_bus.bdev, "XHCI request "
+		    "too many scratchpads\n");
+		return (USB_ERR_NOMEM);
+	}
+
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS3);
+
+	sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) +
+	    XHCI_HCS3_U2_DEL(temp) + 250 /* us */;
+
 	temp = XREAD4(sc, oper, XHCI_USBSTS);
 
 	/* clear interrupts */
@@ -1316,6 +1329,186 @@
 }
 
 static usb_error_t
+xhci_set_slot_scratch(struct xhci_softc *sc, uint8_t index,
+    uint64_t dev_addr, uint64_t scratch_addr)
+{
+	struct usb_page_search buf_res;
+	volatile uint64_t *ptr;
+
+	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);
+
+	usb_pc_cpu_flush(&sc->sc_hw.ctx_pc);
+}
+
+static usb_error_t
+xhci_alloc_device_ext(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_cache *pcd;
+	struct usb_page *pgd;
+	struct usb_page_cache *pcs;
+	struct usb_page *pgs;
+	struct xhci_dev_ctx *pdctx;
+	struct usb_device *hubdev;
+	uint64_t addr;
+	uint32_t temp;
+	uint8_t index;
+	uint8_t failure;
+	uint8_t i;
+	uint8_t rh_port;
+
+	index = udev->device_index;
+	failure = 0;
+
+	pcd = &sc->sc_hw.devs[index].device_pc;
+	pgd = &sc->sc_hw.devs[index].device_pg;
+
+	/* need to initialize the page cache */
+	pcd->tag_parent = sc->sc_bus.dma_parent_tag;
+
+	if (usb_pc_alloc_mem(pcd, pgd, sizeof(*pdctx), XHCI_PAGE_SIZE))
+		failure = 1;
+
+	if (failure == 0) {
+
+		usbd_get_page(pcd, 0, &buf_dev);
+
+		pdctx = buf_dev.buffer;
+		addr = buf_dev.physaddr;
+
+		hubdev = udev;
+		temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1);
+
+		while (hubdev->parent_hub != NULL) {
+			temp |= (hubdev->port_no & 0xF) << ((hubdev->depth - 1) * 4);
+			hubdev = hubdev->parent_hub;
+		}
+
+		rh_port = hubdev->port_no;
+
+		switch (udev->speed) {
+		case USB_SPEED_LOW:
+			temp |= XHCI_SCTX_0_SPEED_SET(2);
+			break;
+		case USB_SPEED_HIGH:
+			temp |= XHCI_SCTX_0_SPEED_SET(3);
+			break;
+		case USB_SPEED_FULL:
+			temp |= XHCI_SCTX_0_SPEED_SET(1);
+			break;
+		default:
+			temp |= XHCI_SCTX_0_SPEED_SET(4);
+			break;
+		}
+
+		if (udev->hub != NULL)
+			temp |= XHCI_SCTX_0_HUB_SET(1);
+
+		pdctx->ctx_slot.dwSctx0 = htole32(temp);
+
+		temp = XHCI_SCTX_1_RH_PORT_SET(rh_port);
+
+		if (udev->hub != NULL)
+			temp |= XHCI_SCTX_1_NUM_PORTS_SET(udev->hub->nports);
+
+		switch (udev->speed) {
+		case USB_SPEED_LOW:
+		case USB_SPEED_HIGH:
+		case USB_SPEED_FULL:
+		default:
+			temp |= XHCI_SCTX_1_MAX_EL_SET(sc->sc_exit_lat_max);
+			break;
+		}
+
+		pdctx->ctx_slot.dwSctx1 = htole32(temp);
+
+		temp = XHCI_SCTX_2_IRQ_TARGET_SET(0);
+
+		if ((udev->hub != NULL) &&
+		    (udev->speed == USB_SPEED_HIGH))
+			temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(3);
+
+		hubdev = udev->parent_hs_hub;
+
+		if (hubdev != NULL) {
+			temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->device_index);
+			temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(hubdev->port_no);
+		}
+
+		pdctx->ctx_slot.dwSctx2 = htole32(temp);
+
+		temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) |
+		    XHCI_SCTX_3_SLOT_STATE_SET(3);
+
+		pdctx->ctx_slot.dwSctx3 = htole32(temp);
+
+	} else {
+		pdctx = NULL;
+	}
+
+	for (i = 0; i != sc->sc_noscratch; i++) {
+
+		pcs = &sc->sc_hw.devs[index].scratch_pc[i];
+		pgs = &sc->sc_hw.devs[index].scratch_pg[i];
+
+		/* need to initialize the page cache */
+		pcs->tag_parent = sc->sc_bus.dma_parent_tag;
+
+		if (usb_pc_alloc_mem(pcs, pgs, XHCI_PAGE_SIZE, XHCI_PAGE_SIZE))
+			failure = 1;
+
+		if (failure == 0) {
+			usbd_get_page(pcs, 0, &buf_scp);
+			pdctx->ctx_sp_buf_ptr[i] = htole64((uint64_t)buf_scp.physaddr);
+		}
+	}
+	if (failure)
+		goto error;
+
+	usb_pc_cpu_flush(pcd);
+
+	xhci_set_slot_scratch(sc, udev->device_index, addr,
+	    addr + (uintptr_t)&((struct xhci_dev_ctx *)0)->ctx_sp_buf_ptr[0]);
+
+	return (0);
+
+error:
+	xhci_free_device_ext(udev);
+
+	return (USB_ERR_NOMEM);
+}
+
+static void
+xhci_free_device_ext(struct usb_device *udev)
+{
+	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+	struct usb_page_cache *pcd;
+	struct usb_page_cache *pcs;
+	uint8_t index;
+	uint8_t i;
+
+	index = udev->device_index;
+
+	pcd = &sc->sc_hw.devs[index].device_pc;
+
+	usb_pc_free_mem(pcd);
+
+	for (i = 0; i != sc->sc_noscratch; i++) {
+		pcs = &sc->sc_hw.devs[index].scratch_pc[i];
+
+		usb_pc_free_mem(pcs);
+	}
+
+	xhci_set_slot_scratch(sc, udev->device_index, 0, 0);
+}
+
+static usb_error_t
 xhci_alloc_endpoint_ext(struct xhci_softc *sc, uint8_t index, 
     struct usb_endpoint_descriptor *edesc)
 {
@@ -1931,13 +2124,6 @@
 		}
 		break;
 
-	case C(UR_SET_HUB_DEPTH, UT_WRITE_CLASS_DEVICE):
-		if ((index != 0) || (value != 0)) {
-			err = USB_ERR_IOERROR;
-			goto done;
-		}
-		break;
-
 	case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
 		if ((value & 0xff) != 0) {
 			err = USB_ERR_IOERROR;

==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#10 (text+ko) ====

@@ -148,7 +148,6 @@
 };
 
 struct xhci_dev_ctx {
-	struct xhci_slot_ctx	ctx_input;
 	struct xhci_slot_ctx	ctx_slot;
 	struct xhci_endp_ctx	ctx_ep0;
 	struct xhci_endp_ctx	ctx_epN[XHCI_MAX_ENDPOINTS - 2];
@@ -408,6 +407,7 @@
 
 	uint32_t sc_cmd;		/* copy of cmd register */
 	uint32_t sc_cmd_dp;		/* copy of command dequeue pointer */
+	uint32_t sc_exit_lat_max;	/* worst case exit latency */
 
 	uint32_t sc_oper_off;		/* offset to operational registers */
 	uint32_t sc_capa_off;		/* offset to capability registers */
@@ -423,6 +423,7 @@
 	uint8_t sc_command_ccs;
 	uint8_t	sc_nodev;		/* number of devices on root HUB */
 	uint8_t	sc_noport;		/* number of ports on root HUB */
+	uint8_t sc_noscratch;		/* number of scratch pages */
 	uint8_t	sc_addr;		/* root HUB device address */
 	uint8_t	sc_conf;		/* root HUB device configuration */
 	uint8_t	sc_hub_idata[2];

==== //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#11 (text+ko) ====



More information about the p4-projects mailing list