PERFORCE change 181655 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sat Jul 31 18:39:07 UTC 2010


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

Change 181655 by hselasky at hselasky_laptop001 on 2010/07/31 18:38:39

	USB controller (XHCI):
		- implement event ring decoding
		- compile fixes

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#7 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci_pci.c#3 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#8 edit
.. //depot/projects/usb/src/sys/dev/usb/usb.h#52 edit

Differences ...

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

@@ -109,6 +109,12 @@
 	uint8_t direction;
 };
 
+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 *);
+
+extern struct usb_bus_methods xhci_bus_methods;
+
 void
 xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
 {
@@ -117,16 +123,16 @@
         cb(bus, &sc->sc_hw.root_pc, &sc->sc_hw.root_pg,
 	   sizeof(struct xhci_hw_root), XHCI_PAGE_SIZE);
 
-        cb(bus, &sc->sc_ctx.root_pc, &sc->sc_ctx.root_pg,
-	   sizeof(struct xhci_ctx_root), XHCI_PAGE_SIZE);
+        cb(bus, &sc->sc_hw.ctx_pc, &sc->sc_hw.ctx_pg,
+	   sizeof(struct xhci_dev_ctx_addr), XHCI_PAGE_SIZE);
 }
 
-static usb_error_t
+usb_error_t
 xhci_start_controller(struct xhci_softc *sc)
 {
 	struct usb_page_search buf_res;
 	struct xhci_hw_root *phwr;
-	struct xhci_ctx_root *pctxr;
+	struct xhci_dev_ctx_addr *pctxa;
 	uint64_t addr;
 	uint32_t temp;
 	uint16_t i;
@@ -138,6 +144,9 @@
 	sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0xF;
 	sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
 
+	sc->sc_event_ccs = 1;
+	sc->sc_event_idx = 0;
+
 	DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
 
 	/* Reset controller */
@@ -145,7 +154,7 @@
 
 	for (i = 0; i != 100; i++) {
 		usb_pause_mtx(NULL, hz / 1000);
-		temp = XREAD4(sc, XHCI_USBCMD) & XHCI_CMD_HCRST;
+		temp = XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST;
 		if (!temp)
 			break;
 	}
@@ -160,10 +169,26 @@
 		return (USB_ERR_IOERROR);
 	}
 
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS1);
+
+	i = XHCI_HCS1_N_PORTS(temp);
+
+	if ((i < 1) || (i > 15)) {
+		device_printf(sc->sc_bus.bdev, "Invalid number "
+		    "of ports: %u\n", i);
+		if (i < 1)
+			return (USB_ERR_IOERROR);
+		else
+			i = 15;
+	}
+
+	sc->sc_noport = i;
+	sc->sc_nodev = XHCI_HCS1_DEVSLOT_MAX(temp);
+
 	temp = XREAD4(sc, oper, XHCI_USBSTS);
 
 	/* clear interrupts */
-	XWRITE4(sc, oper, XHCI_USBSTS, status);
+	XWRITE4(sc, oper, XHCI_USBSTS, temp);
 
 	/* disable all device notifications */
 	XWRITE4(sc, oper, XHCI_DNCTRL, 0);
@@ -173,9 +198,9 @@
 	usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res);
 
 	addr = buf_res.physaddr;
-	pctxr = buf_res.ptr;
+	pctxa = buf_res.buffer;
 
-	memset(pctxr, 0, sizeof(*pctxr));
+	memset(pctxa, 0, sizeof(*pctxa));
 
 	XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr);
 	XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32));
@@ -187,16 +212,16 @@
 	/* Setup interrupter registers */
 
 	temp = XREAD4(sc, runt, XHCI_IMAN(0));
-	temp |= XHCI_IMAN_IE_BIT | XHCI_IMAN_IP_BIT;
-	XWRITE4(sc, runt, XHCI_IMAN(0));
+	temp |= XHCI_IMAN_INTR_ENA | XHCI_IMAN_INTR_PEND;
+	XWRITE4(sc, runt, XHCI_IMAN(0), temp);
 
 	/* Setup interrupt rate */
 
-	XWRITE4(sc, runt, XHCI_IMOD, XHCI_IMOD_DEFAULT);
+	XWRITE4(sc, runt, XHCI_IMOD(0), XHCI_IMOD_DEFAULT);
 
 	usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
 
-	phwr = buf_res.ptr;
+	phwr = buf_res.buffer;
 	addr = (uint64_t)buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[0];
 
 	/* reset hardware root structure */
@@ -219,10 +244,10 @@
 
 	sc->sc_erst_max = temp;
 
-	XWRITE4(sc, runt, XHCI_ERSTSZ(0), temp);
+	XWRITE4(sc, runt, XHCI_ERSTS_SET(0), temp);
 
-	XWRITE4(sc, oper, XHCI_ERDP_LO(0), (uint32_t)addr);
-	XWRITE4(sc, oper, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32));
+	XWRITE4(sc, oper, XHCI_ERSTDP_LO(0), (uint32_t)addr);
+	XWRITE4(sc, oper, XHCI_ERSTDP_HI(0), (uint32_t)(addr >> 32));
 
 	addr = (uint64_t)buf_res.physaddr;
 
@@ -236,7 +261,7 @@
 	XWRITE4(sc, oper, XHCI_CRCR_LO, (uint32_t)addr);
 	XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32));
 
-	usb_bus_mem_flush_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+	usb_bus_mem_flush_all(&sc->sc_bus, &xhci_iterate_hw_softc);
 
 	/* Go! */
 	XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_RS | XHCI_CMD_INTE | XHCI_CMD_HSEE);
@@ -248,6 +273,7 @@
 			break;
 	}
 	if (temp) {
+		XWRITE4(sc, oper, XHCI_USBCMD, 0);
 		device_printf(sc->sc_bus.bdev, "Run timeout.\n");
 		return (USB_ERR_IOERROR);
 	}
@@ -258,7 +284,7 @@
 	return (0);
 }
 
-static usb_error_t
+usb_error_t
 xhci_halt_controller(struct xhci_softc *sc)
 {
 	uint32_t temp;
@@ -284,43 +310,45 @@
 }
 
 usb_error_t
-xhci_init(struct xhci_softc *sc)
+xhci_init(struct xhci_softc *sc, device_t self)
 {
 	/* set the bus revision */
 	sc->sc_bus.usbrev = USB_REV_3_0;
 
-        /* set up the bus struct */
-        sc->sc_bus.methods = &ehci_bus_methods;
+	/* set up the bus struct */
+	sc->sc_bus.methods = &xhci_bus_methods;
 
-	return (0);
-}
+	/* setup devices array */
+	sc->sc_bus.devices = sc->sc_devices;
+	sc->sc_bus.devices_max = XHCI_MAX_DEVICES;
 
-void
-xhci_detach(struct xhci_softc *sc)
-{
+	/* get all DMA memory */
+	if (usb_bus_mem_alloc_all(&sc->sc_bus,
+	    USB_GET_DMA_TAG(self), &xhci_iterate_hw_softc)) {
+		return (ENOMEM);
+	}
 
-
+	return (0);
 }
 
 void
 xhci_suspend(struct xhci_softc *sc)
 {
-
-
+	/* XXX TODO */
 }
 
 void
 xhci_resume(struct xhci_softc *sc)
 {
-
-
+	/* XXX TODO */
 }
 
 void
 xhci_shutdown(struct xhci_softc *sc)
 {
+	DPRINTF("Stopping the XHCI\n");
 
-
+	xhci_halt_controller(sc);
 }
 
 static usb_error_t
@@ -526,18 +554,62 @@
 static void
 xhci_interrupt_poll(struct xhci_softc *sc)
 {
-	struct usb_xfer *xfer;
+	struct usb_page_search buf_res;
+	struct xhci_hw_root *phwr;
+	uint32_t temp;
+	uint16_t i;
+	uint8_t j;
+	uint8_t k;
+	uint8_t t;
+
+	usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
+
+	phwr = buf_res.buffer;
+
+	usb_pc_cpu_invalidate(&sc->sc_hw.root_pc);
+
+	i = sc->sc_event_idx;
+	j = sc->sc_event_ccs;
+	t = 2;
+
+	while (1) {
+
+		temp = le32toh(phwr->hwr_events[i].dwTrb3);
+		k = (temp & XHCI_TRB_3_CYCLE_BIT) ? 1 : 0;
+
+		if (j != k)
+			break;
+
+		switch (XHCI_TRB_3_TYPE_GET(temp)) {
+		case XHCI_TRB_EVENT_TRANSFER:
+			xhci_check_transfer(sc, &phwr->hwr_events[i]);
+			break;
+		default:
+			DPRINTF("Received event = 0x%x\n", 
+			    XHCI_TRB_3_TYPE_GET(temp));
+			break;
+		}
+
+		i++;
+
+		if (i == XHCI_MAX_EVENTS) {
+			i = 0;
+			j ^= 1;
 
-repeat:
-	TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-		/*
-		 * check if transfer is transferred
-		 */
-		if (xhci_check_transfer(xfer)) {
-			/* queue has been modified */
-			goto repeat;
+			/* check for timeout */
+			if (!--t)
+				break;
 		}
 	}
+
+	temp = buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[i];
+
+	/* we are within a PAGE - no need to update the high bits */
+
+	XWRITE4(sc, oper, XHCI_ERSTDP_LO(0), temp);
+
+	sc->sc_event_idx = i;
+	sc->sc_event_ccs = j;
 }
 
 /*------------------------------------------------------------------------*
@@ -1037,10 +1109,6 @@
 	/* must have at least one frame! */
 
 	xfer->td_transfer_last = td;
-
-	if (xfer->xroot->udev->flags.self_suspended == 0) {
-		EHCI_APPEND_QH(qh, *qh_last); XXX;
-	}
 }
 
 static void
@@ -1227,8 +1295,7 @@
 };
 
 static const
-struct usb_hub_ss_descriptor xhci_hubd =
-{
+struct usb_hub_ss_descriptor xhci_hubd = {
 	.bLength = sizeof(xhci_hubd),
 	.bDescriptorType = UDESC_SS_HUB,
 };
@@ -1473,7 +1540,7 @@
 				    DeviceRemovable[j / 8] |= 1U << (j % 8);
 			}
 		}
-		len = sc->sc_hub_desc.hubd.bDescLength;
+		len = sc->sc_hub_desc.hubd.bLength;
 		break;
 
 	case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
@@ -1842,103 +1909,31 @@
 static void
 xhci_device_resume(struct usb_device *udev)
 {
-	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
-	struct usb_xfer *xfer;
-	struct usb_pipe_methods *methods;
-
 	DPRINTF("\n");
 
 	USB_BUS_LOCK(udev->bus);
 
-	TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
-		if (xfer->xroot->udev == udev) {
-
-			methods = xfer->endpoint->methods;
-
-			if ((methods == &xhci_device_bulk_methods) ||
-			    (methods == &xhci_device_ctrl_methods)) {
-				XHCI_APPEND_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
-				    sc->sc_async_p_last);
-			}
-			if (methods == &xhci_device_intr_methods) {
-				XHCI_APPEND_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
-				    sc->sc_intr_p_last[xfer->qh_pos]);
-			}
-		}
-	}
+	/* start endpoint */
 
 	USB_BUS_UNLOCK(udev->bus);
-
-	return;
 }
 
 static void
 xhci_device_suspend(struct usb_device *udev)
 {
-	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
-	struct usb_xfer *xfer;
-	struct usb_pipe_methods *methods;
-
 	DPRINTF("\n");
 
 	USB_BUS_LOCK(udev->bus);
 
-	TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
-		if (xfer->xroot->udev == udev) {
+	/* stop endpoint */
 
-			methods = xfer->endpoint->methods;
-
-			if ((methods == &xhci_device_bulk_methods) ||
-			    (methods == &xhci_device_ctrl_methods)) {
-				XHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
-				    sc->sc_async_p_last);
-			}
-			if (methods == &xhci_device_intr_methods) {
-				XHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
-				    sc->sc_intr_p_last[xfer->qh_pos]);
-			}
-		}
-	}
-
 	USB_BUS_UNLOCK(udev->bus);
-
-	return;
 }
 
 static void
 xhci_set_hw_power(struct usb_bus *bus)
 {
-	struct xhci_softc *sc = XHCI_BUS2SC(bus);
-	uint32_t temp;
-	uint32_t flags;
-
 	DPRINTF("\n");
-
-	USB_BUS_LOCK(bus);
-
-	flags = bus->hw_power_state;
-
-	temp = EOREAD4(sc, XHCI_USBCMD);
-
-	temp &= ~(XHCI_CMD_ASE | XHCI_CMD_PSE);
-
-	if (flags & (USB_HW_POWER_CONTROL |
-	    USB_HW_POWER_BULK)) {
-		DPRINTF("Async is active\n");
-		temp |= XHCI_CMD_ASE;
-	}
-	if (flags & (USB_HW_POWER_INTERRUPT |
-	    USB_HW_POWER_ISOC)) {
-		DPRINTF("Periodic is active\n");
-		temp |= XHCI_CMD_PSE;
-	}
-	EOWRITE4(sc, XHCI_USBCMD, temp);
-
-	USB_BUS_UNLOCK(bus);
-
-	return;
 }
 
 struct usb_bus_methods xhci_bus_methods =

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

@@ -326,10 +326,6 @@
 	struct xhci_trb			hwr_commands[XHCI_MAX_COMMANDS];
 };
 
-struct xhci_ctx_root {
-	volatile uint64_t		ctxr_ptr[XHCI_MAX_DEVICES];
-};
-
 struct xhci_endpoint_ext {
 	TAILQ_HEAD(, xhci_qh) head;
 
@@ -407,7 +403,10 @@
 
 	uint16_t sc_flags;		/* chip specific flags */
 	uint16_t sc_erst_max;
+	uint16_t sc_event_idx;
 
+	uint8_t sc_event_ccs;
+	uint8_t	sc_nodev;		/* number of devices on root HUB */
 	uint8_t	sc_noport;		/* number of ports on root HUB */
 	uint8_t	sc_addr;		/* root HUB device address */
 	uint8_t	sc_conf;		/* root HUB device configuration */
@@ -422,7 +421,7 @@
 void xhci_suspend(struct xhci_softc *);
 void xhci_resume(struct xhci_softc *);
 void xhci_shutdown(struct xhci_softc *);
-usb_error_t xhci_init(struct xhci_softc *);
+usb_error_t xhci_init(struct xhci_softc *, device_t);
 usb_error_t xhci_start_controller(struct xhci_softc *);
 void xhci_iterate_hw_softc(struct usb_bus *, usb_bus_mem_sub_cb_t *);
 usb_error_t xhci_halt_controller(struct xhci_softc *);

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

@@ -169,7 +169,7 @@
 
 	/* XXX check for 64-bit capability */
 
-	if (xhci_init(sc)) {
+	if (xhci_init(sc, self)) {
 		device_printf(self, "Could not initialize softc\n");
 		goto error;
 	}

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

@@ -156,24 +156,24 @@
 /* XHCI runtime registers.  Offset given by XHCI_CAPLENGTH + XHCI_RTSOFF registers */
 #define	XHCI_MFINDEX		0x0000		/* RO - microframe index */
 #define	XHCI_MFINDEX_GET(x)	((x) & 0x1FFF)
-#define	XHCI_IMAN(n)		(0x0020 + (0x20 * (n))	/* XHCI interrupt management */
+#define	XHCI_IMAN(n)		(0x0020 + (0x20 * (n)))	/* XHCI interrupt management */
 #define	XHCI_IMAN_INTR_PEND	0x00000001	/* RW - interrupt pending */
 #define	XHCI_IMAN_INTR_ENA	0x00000002	/* RW - interrupt enable */
-#define	XHCI_IMOD(n)		(0x0024 + (0x20 * (n))	/* XHCI interrupt moderation */
+#define	XHCI_IMOD(n)		(0x0024 + (0x20 * (n)))	/* XHCI interrupt moderation */
 #define	XHCI_IMOD_IVAL_GET(x)	(((x) >> 0) & 0xFFFF)	/* 250ns unit */
 #define	XHCI_IMOD_IVAL_SET(x)	(((x) & 0xFFFF) << 0)	/* 250ns unit */
 #define	XHCI_IMOD_ICNT_GET(x)	(((x) >> 16) & 0xFFFF)	/* 250ns unit */
 #define	XHCI_IMOD_ICNT_SET(x)	(((x) & 0xFFFF) << 16)	/* 250ns unit */
 #define	XHCI_IMOD_DEFAULT	0x000001F4U	/* 8000 IRQ/second */
-#define	XHCI_ERSTSZ(n)		(0x0028 + (0x20 * (n))	/* XHCI event ring segment table size */
+#define	XHCI_ERSTSZ(n)		(0x0028 + (0x20 * (n)))	/* XHCI event ring segment table size */
 #define	XHCI_ERSTS_GET(x)	((x) & 0xFFFF)
 #define	XHCI_ERSTS_SET(x)	((x) & 0xFFFF)
-#define	XHCI_ERSTBA_LO(n)	(0x0030 + (0x20 * (n))	/* XHCI event ring segment table BA */
-#define	XHCI_ERSTBA_HI(n)	(0x0034 + (0x20 * (n))	/* XHCI event ring segment table BA */
-#define	XHCI_ERSTDP_LO(n)	(0x0038 + (0x20 * (n))	/* XHCI event ring dequeue pointer */
+#define	XHCI_ERSTBA_LO(n)	(0x0030 + (0x20 * (n)))	/* XHCI event ring segment table BA */
+#define	XHCI_ERSTBA_HI(n)	(0x0034 + (0x20 * (n)))	/* XHCI event ring segment table BA */
+#define	XHCI_ERSTDP_LO(n)	(0x0038 + (0x20 * (n)))	/* XHCI event ring dequeue pointer */
 #define	XHCI_ERSTDP_LO_SIGET(x)	((x) & 0x7)	/* RO - dequeue segment index */
 #define	XHCI_ERSTDP_LO_BUSY	0x00000008	/* RW - event handler busy */
-#define	XHCI_ERSTDP_HI(n)	(0x003C + (0x20 * (n))	/* XHCI event ring dequeue pointer */
+#define	XHCI_ERSTDP_HI(n)	(0x003C + (0x20 * (n)))	/* XHCI event ring dequeue pointer */
 
 /* XHCI doorbell registers. Offset given by XHCI_CAPLENGTH + XHCI_DBOFF registers */
 #define	XHCI_DOORBELL		0x0000

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

@@ -593,7 +593,7 @@
 typedef struct usb_hub_descriptor usb_hub_descriptor_t;
 
 struct usb_hub_ss_descriptor {
-	uByte	bDescLength;
+	uByte	bLength;
 	uByte	bDescriptorType;
 	uByte	bNbrPorts;		/* max 15 */
 	uWord	wHubCharacteristics;


More information about the p4-projects mailing list