Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Aug 2010 15:51:47 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 181776 for review
Message-ID:  <201008031551.o73FplPM003633@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181776?ac=10

Change 181776 by hselasky@hselasky_laptop001 on 2010/08/03 15:51:26

	USB controller (XHCI):
		- add more XHCI command function wrappers
		- rename some variables/functions

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#10 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#12 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci_pci.c#4 edit

Differences ...

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

@@ -117,7 +117,7 @@
 
 extern struct usb_bus_methods xhci_bus_methods;
 
-void
+static void
 xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
 {
         struct xhci_softc *sc = XHCI_BUS2SC(bus);
@@ -184,7 +184,10 @@
 	}
 
 	sc->sc_noport = i;
-	sc->sc_nodev = XHCI_HCS1_DEVSLOT_MAX(temp);
+	sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp);
+
+	if (sc->sc_noslot > XHCI_MAX_DEVICES)
+		sc->sc_noslot = XHCI_MAX_DEVICES;
 
 	temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
 
@@ -223,7 +226,7 @@
 
 	/* setup number of device slots */
 
-	XWRITE4(sc, oper, XHCI_CONFIG, XHCI_MAX_DEVICES);
+	XWRITE4(sc, oper, XHCI_CONFIG, sc->sc_noslot);
 
 	/* Setup interrupter registers */
 
@@ -277,12 +280,6 @@
 	XWRITE4(sc, oper, XHCI_CRCR_LO, ((uint32_t)addr) | XHCI_CRCR_LO_RCS);
 	XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32));
 
-	/*
-	 * We only need the 32-lower bits of the command dequeue
-	 * pointer to keep track of the TRBs:
-	 */
-	sc->sc_cmd_dp = (uint32_t)addr;
-
 	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(
@@ -350,7 +347,9 @@
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = XHCI_MAX_DEVICES;
 
-	TAILQ_INIT(&sc->sc_cmd_head);
+	/* setup command queue mutex and condition varible */
+	cv_init(&sc->sc_cmd_cv, "CMDQ");
+	sx_init(&sc->sc_cmd_sx, "CMDQ lock");
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -362,6 +361,15 @@
 }
 
 void
+xhci_uninit(struct xhci_softc *sc)
+{
+	usb_bus_mem_free_all(&sc->sc_bus, &xhci_iterate_hw_softc);
+
+	cv_destroy(&sc->sc_cmd_cv);
+	sx_destroy(&sc->sc_cmd_sx);
+}
+
+void
 xhci_suspend(struct xhci_softc *sc)
 {
 	/* XXX TODO */
@@ -582,11 +590,20 @@
 }
 
 static void
+xhci_check_command(struct xhci_softc *sc, struct xhci_trb *trb)
+{
+	if (sc->sc_cmd_addr == trb->qwTrb0) {
+		sc->sc_cmd_result[0] = trb->dwTrb2;
+		sc->sc_cmd_result[1] = trb->dwTrb2;
+		cv_signal(&sc->sc_cmd_cv);
+	}
+}
+
+static void
 xhci_interrupt_poll(struct xhci_softc *sc)
 {
 	struct usb_page_search buf_res;
 	struct xhci_hw_root *phwr;
-	struct xhci_command *pcmd;
 	uint32_t temp;
 	uint16_t i;
 	uint8_t event;
@@ -598,7 +615,7 @@
 
 	phwr = buf_res.buffer;
 
-	/* 1) Receive any events */
+	/* Receive any events */
 
 	usb_pc_cpu_invalidate(&sc->sc_hw.root_pc);
 
@@ -622,6 +639,9 @@
 		case XHCI_TRB_EVENT_TRANSFER:
 			xhci_check_transfer(sc, &phwr->hwr_events[i]);
 			break;
+		case XHCI_TRB_EVENT_CMD_COMPLETE:
+			xhci_check_command(sc, &phwr->hwr_events[i]);
+			break;
 		default:
 			DPRINTF("Received event = 0x%x\n", event);
 			break;
@@ -647,94 +667,161 @@
 
 	sc->sc_event_idx = i;
 	sc->sc_event_ccs = j;
+}
+
+static usb_error_t
+xhci_do_command(struct xhci_softc *sc, struct xhci_trb *trb, 
+    uint16_t timeout_ms)
+{
+	struct usb_page_search buf_res;
+	struct xhci_hw_root *phwr;
+	uint64_t addr;
+	uint32_t temp;
+	uint8_t i;
+	uint8_t j;
+	int err;
+
+	XHCI_CMD_ASSERT_LOCKED(sc);
+
+	/* get hardware root structure */
+
+	usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
+
+	phwr = buf_res.buffer;
 
-	/* 2) Queue any commands */
+	/* Queue command */
+
+	USB_BUS_LOCK(&sc->sc_bus);
 
 	i = sc->sc_command_idx;
 	j = sc->sc_command_ccs;
 
-	/* check if there are any commands on the queue */
-	while ((pcmd = TAILQ_FIRST(&sc->sc_cmd_head)) != NULL) {
+	phwr->hwr_commands[i].qwTrb0 = trb->qwTrb0;
+	phwr->hwr_commands[i].dwTrb2 = trb->dwTrb2;
+
+	usb_pc_cpu_flush(&sc->sc_hw.root_pc);
+
+	temp = trb->dwTrb3;
+
+	if (j)
+		temp |= htole32(XHCI_TRB_3_CYCLE_BIT);
+	else
+		temp &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
+
+	phwr->hwr_commands[i].dwTrb3 = temp;
 
-		k = (phwr->hwr_events[i].dwTrb3 & htole32(XHCI_TRB_3_CYCLE_BIT)) ? 1 : 0;
+	usb_pc_cpu_flush(&sc->sc_hw.root_pc);
 
-		temp = (uint32_t)buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[i];
+	DPRINTFN(10, "command[%u] = %u\n", i,
+	    XHCI_TRB_3_TYPE_GET(le32toh(temp)));
 
-		/* check if we need to wait for XHCI to process commands */
-		if ((sc->sc_cmd_dp == temp) && (j == k))
-			break;
+	addr = (uint64_t)buf_res.physaddr + 
+	  (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[i];
+	sc->sc_cmd_addr = htole64(addr);
 
-		TAILQ_REMOVE(&sc->sc_cmd_head, pcmd, entry);
-		pcmd->entry.tqe_prev = NULL;
+	i++;
 
-		phwr->hwr_events[i].qwTrb0 = pcmd->trb.qwTrb0;
-		phwr->hwr_events[i].dwTrb2 = pcmd->trb.dwTrb2;
+	if (i == (XHCI_MAX_COMMANDS - 1)) {
 
-		usb_pc_cpu_flush(&sc->sc_hw.root_pc);
+		/* update cycle bit of LINK TRB */
 
-		temp = pcmd->trb.dwTrb3;
+		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_events[i].dwTrb3 = temp;
+		phwr->hwr_commands[i].dwTrb3 = temp;
 
 		usb_pc_cpu_flush(&sc->sc_hw.root_pc);
 
-		XWRITE4(sc, door, XHCI_DOORBELL(0), 0);
+		i = 0;
+		j ^= 1;
+	}
+
+	sc->sc_command_idx = i;
+	sc->sc_command_ccs = j;
+
+	XWRITE4(sc, door, XHCI_DOORBELL(0), 0);
 
-		DPRINTFN(10, "command[%u] = %u\n", i,
-		    XHCI_TRB_3_TYPE_GET(le32toh(temp)));
+	err = cv_timedwait(&sc->sc_cmd_cv, &sc->sc_bus.bus_mtx,
+	    USB_MS_TO_TICKS(timeout_ms));
 
-		i++;
+	if (err) {
+		DPRINTFN(0, "Command timeout!\n");
+		err = USB_ERR_TIMEOUT;
+		trb->dwTrb2 = 0;
+		trb->dwTrb3 = 0;
+	} else {
+		temp = le32toh(sc->sc_cmd_result[0]);
+		if (XHCI_TRB_2_ERROR_GET(temp) != XHCI_TRB_ERROR_SUCCESS)
+			err = USB_ERR_INVAL;
 
-		if (i == (XHCI_MAX_COMMANDS - 1)) {
+		trb->dwTrb2 = sc->sc_cmd_result[0];
+		trb->dwTrb3 = sc->sc_cmd_result[1];
+	}
 
-			/* update cycle bit of LINK TRB */
+	USB_BUS_UNLOCK(&sc->sc_bus);
 
-			temp = phwr->hwr_events[i].dwTrb3;
+	return (err);
+}
 
-			if (j)
-				temp |= htole32(XHCI_TRB_3_CYCLE_BIT);
-			else
-				temp &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
+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;
 
-			phwr->hwr_events[i].dwTrb3 = temp;
+	trb.qwTrb0 = 0;
+	trb.dwTrb2 = 0;
+	trb.dwTrb3 = htole32(XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ENABLE_SLOT));
 
-			usb_pc_cpu_flush(&sc->sc_hw.root_pc);
+	err = xhci_do_command(sc, &trb, 50 /* ms */);
+	if (err)
+		goto done;
 
-			XWRITE4(sc, door, XHCI_DOORBELL(0), 0);
+	temp = le32toh(trb.dwTrb3);
 
-			i = 0;
-			j ^= 1;
-		}
-	}
+	*pslot = XHCI_TRB_3_SLOT_GET(temp); 
 
-	sc->sc_command_idx = i;
-	sc->sc_command_ccs = j;
+done:
+	return (err);
 }
 
 static usb_error_t
-xhci_do_command(struct xhci_softc *sc, struct xhci_trb *trb, 
-    uint16_t timeout_ms)
+xhci_cmd_disable_slot(struct xhci_softc *sc, uint8_t slot_id)
 {
-	XXX implement;
+	struct xhci_trb trb;
+	uint32_t temp;
+
+	trb.qwTrb0 = 0;
+	trb.dwTrb2 = 0;
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DISABLE_SLOT) |
+	    XHCI_TRB_3_SLOT_SET(slot_id);
+
+	trb.dwTrb3 = htole32(temp);
+
+	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
 
 static usb_error_t
-xhci_cmd_disable_slot(struct xhci_softc *sc, uint8_t slot_id)
+xhci_cmd_set_address(struct xhci_softc *sc, uint64_t input_ctx,
+    uint8_t bsr, uint8_t slot_id)
 {
 	struct xhci_trb trb;
-	uint32_t dword;
+	uint32_t temp;
 
-	trb.qwTrb0 = 0;
+	trb.qwTrb0 = htole64(input_ctx);
 	trb.dwTrb2 = 0;
-	dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DISABLE_SLOT) |
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ADDRESS_DEVICE) |
 	    XHCI_TRB_3_SLOT_SET(slot_id);
 
-	trb.dwTrb3 = htole32(dword);
+	if (bsr)
+		temp |= XHCI_TRB_3_BSR_BIT;
+
+	trb.dwTrb3 = htole32(temp);
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
@@ -744,17 +831,17 @@
     uint8_t deconfigure, uint8_t slot_id)
 {
 	struct xhci_trb trb;
-	uint32_t dword;
+	uint32_t temp;
 
 	trb.qwTrb0 = htole64(input_ctx);
 	trb.dwTrb2 = 0;
-	dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_CONFIGURE_EP) |
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_CONFIGURE_EP) |
 	    XHCI_TRB_3_SLOT_SET(slot_id);
 
 	if (deconfigure)
-		dword |= XHCI_TRB_3_DCEP_BIT;
+		temp |= XHCI_TRB_3_DCEP_BIT;
 
-	trb.dwTrb3 = htole32(dword);
+	trb.dwTrb3 = htole32(temp);
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
@@ -764,13 +851,13 @@
     uint8_t slot_id)
 {
 	struct xhci_trb trb;
-	uint32_t dword;
+	uint32_t temp;
 
 	trb.qwTrb0 = htole64(input_ctx);
 	trb.dwTrb2 = 0;
-	dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_EVALUATE_CTX) |
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_EVALUATE_CTX) |
 	    XHCI_TRB_3_SLOT_SET(slot_id);
-	trb.dwTrb3 = htole32(dword);
+	trb.dwTrb3 = htole32(temp);
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
@@ -780,18 +867,18 @@
     uint8_t ep_id, uint8_t slot_id)
 {
 	struct xhci_trb trb;
-	uint32_t dword;
+	uint32_t temp;
 
 	trb.qwTrb0 = 0;
 	trb.dwTrb2 = 0;
-	dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_EP) |
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_EP) |
 	    XHCI_TRB_3_SLOT_SET(slot_id) |
 	    XHCI_TRB_3_SLOT_SET(ep_id);
 
 	if (preserve)
-		dword |= XHCI_TRB_3_PRSV_BIT;
+		temp |= XHCI_TRB_3_PRSV_BIT;
 
-	trb.dwTrb3 = htole32(dword);
+	trb.dwTrb3 = htole32(temp);
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
@@ -801,18 +888,18 @@
     uint8_t ep_id, uint8_t slot_id)
 {
 	struct xhci_trb trb;
-	uint32_t dword;
+	uint32_t temp;
 
 	trb.qwTrb0 = 0;
 	trb.dwTrb2 = 0;
-	dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STOP_EP) |
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STOP_EP) |
 	    XHCI_TRB_3_SLOT_SET(slot_id) |
 	    XHCI_TRB_3_SLOT_SET(ep_id);
 
 	if (suspend)
-		dword |= XHCI_TRB_3_SUSP_EP_BIT;
+		temp |= XHCI_TRB_3_SUSP_EP_BIT;
 
-	trb.dwTrb3 = htole32(dword);
+	trb.dwTrb3 = htole32(temp);
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
@@ -821,14 +908,14 @@
 xhci_cmd_reset_dev(struct xhci_softc *sc, uint8_t slot_id)
 {
 	struct xhci_trb trb;
-	uint32_t dword;
+	uint32_t temp;
 
 	trb.qwTrb0 = 0;
 	trb.dwTrb2 = 0;
-	dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_DEVICE) |
+	temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_DEVICE) |
 	    XHCI_TRB_3_SLOT_SET(slot_id);
 
-	trb.dwTrb3 = htole32(dword);
+	trb.dwTrb3 = htole32(temp);
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
@@ -1339,7 +1426,7 @@
 }
 
 static usb_error_t
-xhci_set_slot_scratch(struct xhci_softc *sc, uint8_t index,
+xhci_set_slot_pointers(struct xhci_softc *sc, uint8_t index,
     uint64_t dev_addr, uint64_t scratch_addr)
 {
 	struct usb_page_search buf_res;
@@ -1372,7 +1459,7 @@
 }
 
 static usb_error_t
-xhci_configure_endpoint(struct usb_xfer *xfer)
+xhci_configure_endpoint(struct usb_xfer *xfer, uint8_t drop)
 {
 	struct usb_page_search buf_inp;
 	struct usb_page_search buf_ep;
@@ -1383,6 +1470,7 @@
 	struct usb_device *udev;
 	uint64_t addr;
 	uint32_t temp;
+	uint32_t mask;
 	uint8_t index;
 	uint8_t epno;
 	uint8_t k;
@@ -1394,7 +1482,7 @@
 
 	udev = xfer->xroot->udev;
 
-	index = udev->device_index;
+	index = udev->controller_slot_id;
 
 	edesc = xfer->endpoint->edesc;
 
@@ -1410,9 +1498,18 @@
 
 	pinp = buf_inp.buffer;
 
-	XXX;
-	pinp->ctx_input.dwInCtx0 |= htole32(0xFFFFFFFC);
-	pinp->ctx_input.dwInCtx1 &= htole32(0x1);
+	mask = 1U << epno;
+
+	if (drop) {
+		mask &= 0xFFFFFFFC;
+		pinp->ctx_input.dwInCtx0 = htole32(mask);
+		pinp->ctx_input.dwInCtx1 = 0;
+	} else {
+		if (mask & 2)
+			mask |= 1;
+		pinp->ctx_input.dwInCtx0 = 0;
+		pinp->ctx_input.dwInCtx1 = htole32(mask);
+	}
 
 	temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
 	    XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
@@ -1461,22 +1558,25 @@
 
 	pinp->ctx_ep[epno - 1].dwEpCtx1 = htole32(temp);
 
-	pepext->trb_ccs = 1;
-	pepext->trb_index = 0;
-	pepext->trb_halted = 0;
+	if (drop == 0) {
+
+		pepext->trb_ccs = 1;
+		pepext->trb_index = 0;
+		pepext->trb_halted = 0;
 
-	for (k = 0; k != XHCI_MAX_TRANSFERS; k++)
-		pepext->trb[k].dwTrb3 = 0;
+		for (k = 0; k != XHCI_MAX_TRANSFERS; k++)
+			pepext->trb[k].dwTrb3 = 0;
 
-	usb_pc_cpu_flush(pepext->page_cache);
+		usb_pc_cpu_flush(pepext->page_cache);
+	}
 
 	addr = XHCI_EPCTX_2_DCS_SET(1) |
 	    (buf_ep.physaddr + (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[epno][0]);
 
 	pinp->ctx_ep[epno - 1].qwEpCtx2 = htole64(addr);
 
-	temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET() |
-	    XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET();
+	temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(xfer->max_frame_size) |
+	    XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET(xfer->max_frame_size);
 
 	pinp->ctx_ep[epno - 1].dwEpCtx4 = htole32(temp);
 
@@ -1563,7 +1663,7 @@
 	hubdev = udev->parent_hs_hub;
 
 	if (hubdev != NULL) {
-		temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->device_index);
+		temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->controller_slot_id);
 		temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(hubdev->port_no);
 	}
 
@@ -1585,10 +1685,8 @@
 
 	usb_pc_cpu_flush(pcinp);
 
-	xhci_set_slot_scratch(sc, udev->device_index, buf_dev.physaddr,
+	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]);
-
-	XXX_cmd_config();
 }
 
 static usb_error_t
@@ -1600,7 +1698,7 @@
 	uint8_t i;
 	uint8_t index;
 
-	index = udev->device_index;
+	index = udev->controller_slot_id;
 
 	pc = &sc->sc_hw.devs[index].device_pc;
 	pg = &sc->sc_hw.devs[index].device_pg;
@@ -1656,9 +1754,9 @@
 	uint8_t index;
 	uint8_t i;
 
-	index = udev->device_index;
+	index = udev->controller_slot_id;
 
-	xhci_set_slot_scratch(sc, index, 0, 0);
+	xhci_set_slot_pointers(sc, index, 0, 0);
 
 	pc = &sc->sc_hw.devs[index].device_pc;
 
@@ -1694,7 +1792,7 @@
 		epno |= UE_DIR_IN;
 
 	epno = XHCI_EPNO2EPID(epno);
-	index = xfer->xroot->udev->device_index;
+	index = xfer->xroot->udev->controller_slot_id;
 
 	pc = &sc->sc_hw.devs[index].endpoint_pc;
 
@@ -1720,7 +1818,7 @@
 		epno |= UE_DIR_IN;
 
 	epno = XHCI_EPNO2EPID(epno);
-	index = xfer->xroot->udev->device_index;
+	index = xfer->xroot->udev->controller_slot_id;
 
 	XWRITE4(sc, door, XHCI_DOORBELL(index), epno | XHCI_DB_SID_SET(0));
 }
@@ -1987,7 +2085,7 @@
 		.bLength = sizeof(xhci_bosd.usbdcd),
 		.bDescriptorType = UDESC_DEVICE_CAPABILITY,
 		.bDevCapabilityType = 3,
-		.bmAttributes = XXX,
+		.bmAttributes = 0, /* XXX */
 		HSETW(.wSpeedsSupported, 0x000C),
 		.bFunctionalitySupport = 8,
 		.bU1DevExitLat = 255,	/* dummy - not used */
@@ -1998,7 +2096,7 @@
 		.bDescriptorType = 1,
 		.bDevCapabilityType = 4,
 		.bReserved = 0,
-		.bContainerID = XXX,
+		.bContainerID = 0, /* XXX */
 	},
 };
 
@@ -2555,6 +2653,73 @@
 		xfer->flags_int.curr_dma_set = 1;
 		goto alloc_dma_set;
 	}
+
+	if ((parm->buf != NULL) && (parm->err == 0)) {
+		struct usb_page_search buf_dev;
+		struct usb_page_search buf_inp;
+		struct usb_device *udev;
+		struct xhci_endpoint_ext *pepext;
+		struct xhci_dev_ctx *pdctx;
+		struct usb_page_cache *pcdev;
+		struct usb_page_cache *pcinp;
+		usb_error_t err;
+		uint32_t temp;
+		uint8_t index;
+
+		pepext = xhci_get_endpoint_ext(xfer);
+		udev = xfer->xroot->udev;
+		index = udev->controller_slot_id;
+
+		pcdev = &sc->sc_hw.devs[index].device_pc;
+		pcinp = &sc->sc_hw.devs[index].input_pc;
+
+		usbd_get_page(pcdev, 0, &buf_dev);
+		usbd_get_page(pcinp, 0, &buf_inp);
+
+		pdctx = buf_dev.buffer;
+
+		XHCI_CMD_LOCK(sc);
+
+		err = xhci_configure_endpoint(xfer, 1);
+		if (err == 0)
+			err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
+		if (err == 0)
+			err = xhci_configure_endpoint(xfer, 0);
+		if (err == 0)
+			err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
+
+		if (err != 0)
+			DPRINTFN(0, "Could not configure endpoint\n");
+
+		if (xfer->flags_int.control_xfr) {
+
+			if (udev->address != 0) {
+				err = xhci_cmd_set_address(sc, buf_inp.physaddr, 0, index);
+				if (err == 0) {
+					usb_pc_cpu_invalidate(pcdev);
+
+					temp = le32toh(pdctx->ctx_slot.dwSctx3);
+
+					/* update address */
+					udev->address = XHCI_SCTX_3_DEV_ADDR_GET(temp);
+
+					if (udev->address == 0)
+						DPRINTFN(0, "XHCI returned address zero!\n");
+				}
+			} else {
+				err = xhci_cmd_set_address(sc, buf_inp.physaddr, 1, index);
+
+				if (err != 0)
+					err = xhci_cmd_reset_dev(sc, index);
+			}
+
+			if (err != 0)
+				DPRINTFN(0, "Could not set address\n");
+		}
+		XHCI_CMD_UNLOCK(sc);
+
+		parm->err = err;
+	}
 }
 
 static void
@@ -2578,28 +2743,75 @@
 		/* not supported */
 		return;
 	}
-	if (udev->device_index != sc->sc_addr) {
+	if (udev->parent_hub != NULL)
+		ep->methods = &xhci_device_generic_methods;
+}
+
+static void
+xhci_ep_uninit(struct usb_device *udev, struct usb_endpoint *ep)
+{
+
+}
+
+static usb_error_t
+xhci_device_init(struct usb_device *udev)
+{
+	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+	usb_error_t err;
+	uint8_t temp;
+
+	/* no init for root HUB */
+	if (udev->parent_hub == NULL)
+		return (0);
+
+	XHCI_CMD_LOCK(sc);
+
+	/* set invalid default */
+
+	udev->controller_slot_id = sc->sc_noslot;
+
+	/* try to get a new slot ID from the XHCI */
+
+	err = xhci_cmd_enable_slot(sc, &temp);
 
-		ep->methods = &xhci_device_generic_methods;
+	if (err) {
+		XHCI_CMD_UNLOCK(sc);
+		return (err);
+	}
 
-		if ((udev->speed != USB_SPEED_HIGH) &&
-		    ((udev->hs_hub_addr == 0) ||
-		    (udev->hs_port_no == 0) ||
-		    (udev->parent_hs_hub == NULL) ||
-		    (udev->parent_hs_hub->hub == NULL))) {
-			/* We need a transaction translator */
-			goto done;
-		}
+	if (temp >= sc->sc_noslot) {
+		XHCI_CMD_UNLOCK(sc);
+		return (USB_ERR_INVAL);
 	}
-done:
-	return;
+
+	/* store slot ID for later reference */
+
+	udev->controller_slot_id = temp;
+
+	err = xhci_alloc_device_ext(udev);
+
+	XHCI_CMD_UNLOCK(sc);
+
+	return (err);
 }
 
 static void
-xhci_ep_uninit(struct usb_device *udev, struct usb_endpoint *ep)
+xhci_device_uninit(struct usb_device *udev)
 {
+	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
 
+	/* no init for root HUB */
+	if (udev->parent_hub == NULL)
+		return;
 
+	XHCI_CMD_LOCK(sc);
+
+	if (udev->controller_slot_id < sc->sc_noslot)
+		xhci_cmd_disable_slot(sc, udev->controller_slot_id);
+
+	xhci_free_device_ext(udev);
+
+	XHCI_CMD_UNLOCK(sc);
 }
 
 static void
@@ -2607,9 +2819,9 @@
 {
 	/*
 	 * Wait until the hardware has finished any possible use of
-	 * the transfer descriptor(s) and QH
+	 * the transfer descriptor(s)
 	 */
-	*pus = (188);			/* microseconds */
+	*pus = 2048;			/* microseconds */
 }
 
 static void
@@ -2649,6 +2861,8 @@
 	.xfer_setup = xhci_xfer_setup,
 	.xfer_unsetup = xhci_xfer_unsetup,
 	.get_dma_delay = xhci_get_dma_delay,
+	.device_init = xhci_device_init,
+	.device_uninit = xhci_device_uninit,
 	.device_resume = xhci_device_resume,
 	.device_suspend = xhci_device_suspend,
 	.set_hw_power = xhci_set_hw_power,

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

@@ -159,10 +159,6 @@
 	struct xhci_endp_ctx	ctx_epN[XHCI_MAX_ENDPOINTS - 1];
 } __aligned(XHCI_DEV_CTX_ALIGN);
 
-struct xhci_dev_endpoint_trbs {
-	struct xhci_trb	trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
-};
-
 struct xhci_stream_ctx {
 	volatile uint64_t	qwSctx0;
 #define	XHCI_SCTX_0_DCS_GET(x)		((x) & 0x1)
@@ -210,6 +206,7 @@
 #define	XHCI_TRB_3_BEI_BIT		(1U << 9)
 #define	XHCI_TRB_3_DCEP_BIT		(1U << 9)
 #define	XHCI_TRB_3_PRSV_BIT		(1U << 9)
+#define	XHCI_TRB_3_BSR_BIT		(1U << 9)
 #define	XHCI_TRB_3_TRT_MASK		(3U << 16)
 #define	XHCI_TRB_3_TRT_NONE		(0U << 16)
 #define	XHCI_TRB_3_TRT_OUT		(2U << 16)
@@ -300,6 +297,10 @@
 #define	XHCI_TRB_ERROR_SPLIT_XACT	0x24
 };
 
+struct xhci_dev_endpoint_trbs {
+	struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
+};
+
 #define	XHCI_TD_PAGE_NBUF	5	/* units */
 #define	XHCI_TD_PAGE_SIZE	4096	/* bytes */
 #define	XHCI_TD_PAYLOAD_MAX	(XHCI_TD_PAGE_SIZE * (XHCI_TD_PAGE_NBUF - 1))
@@ -342,8 +343,6 @@
 };
 
 struct xhci_endpoint_ext {
-	struct xhci_command ep_stop_cmd;
-	struct xhci_command ep_config_cmd;
 	struct xhci_trb *trb;
 	struct usb_page_cache *page_cache;
 	uint64_t physaddr;
@@ -404,7 +403,8 @@
 
 	union xhci_hub_desc sc_hub_desc;
 
-	TAILQ_HEAD(, xhci_command) sc_cmd_head;
+	struct cv sc_cmd_cv;
+	struct sx sc_cmd_sx;
 
 	struct usb_device *sc_devices[XHCI_MAX_DEVICES];
 	struct resource *sc_io_res;
@@ -415,8 +415,10 @@
 	bus_space_tag_t sc_io_tag;
 	bus_space_handle_t sc_io_hdl;
 
+	uint64_t sc_cmd_addr;		/* current pending command */
+	uint32_t sc_cmd_result[2];	/* result of command */
+
 	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 */
@@ -431,7 +433,7 @@
 
 	uint8_t sc_event_ccs;
 	uint8_t sc_command_ccs;
-	uint8_t	sc_nodev;		/* number of devices on root HUB */
+	uint8_t	sc_noslot;		/* number of XHCI device slots */
 	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 */
@@ -442,14 +444,18 @@
 
 };
 
+#define	XHCI_CMD_LOCK(sc)	sx_xlock(&sc->sc_cmd_sx)
+#define	XHCI_CMD_UNLOCK(sc)	sx_xunlock(&sc->sc_cmd_sx)
+#define	XHCI_CMD_ASSERT_LOCKED(sc) sx_assert(&sc->sc_cmd_sx, SA_LOCKED)
+
 /* prototypes */
 
 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 *, device_t);
+void xhci_uninit(struct xhci_softc *);
 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 *);
 void xhci_interrupt(struct xhci_softc *);
 

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

@@ -268,7 +268,8 @@
 		    sc->sc_io_res);
 		sc->sc_io_res = NULL;
 	}
-	usb_bus_mem_free_all(&sc->sc_bus, &xhci_iterate_hw_softc);
+
+	xhci_uninit(sc);
 
 	return (0);
 }



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