Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Aug 2010 18:25:58 GMT
From:      Hans Petter Selasky <hselasky@skunkworks.freebsd.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 182149 for review
Message-ID:  <201008111825.o7BIPwvV084044@skunkworks.freebsd.org>

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

Change 182149 by hselasky@hselasky_laptop001 on 2010/08/09 19:48:33

	USB controller (XHCI):
		- fix problem about short USB transfers (compute correct remainder).
		- correctly initialise USB HUB fields in slot context
		- correct interrupt endpoint intervals (we round down the intervals).
		- add support for USB 2.0 device suspend and resume
		- add new callback function to correctly update the current XHCI device state.
		- at this point the XHCI driver works with any kind of USB device (HS/LS/FS and SS)
		- have tested ISOC, BULK, CONTROL and INTERRUPT transfer types.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#23 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#20 edit

Differences ...

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

@@ -122,10 +122,9 @@
 static struct xhci_endpoint_ext *xhci_get_endpoint_ext(struct usb_device *, struct usb_endpoint_descriptor *);
 static usb_proc_callback_t xhci_configure_msg;
 static usb_error_t xhci_configure_device(struct usb_device *);
-static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_t, uint8_t, uint8_t, uint16_t, uint16_t);
+static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
 static usb_error_t xhci_configure_mask(struct usb_device *, uint32_t, uint8_t);
 static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *, uint64_t, uint8_t);
-static usb_error_t xhci_cmd_reset_dev(struct xhci_softc *, uint8_t);
 
 extern struct usb_bus_methods xhci_bus_methods;
 
@@ -637,6 +636,7 @@
 static void
 xhci_check_transfer(struct xhci_softc *sc, struct xhci_trb *trb)
 {
+	int64_t offset;
 	uint64_t td_event;
 	uint32_t temp;
 	uint32_t remainder;
@@ -688,18 +688,37 @@
 
 		td = xfer->td_transfer_cache;
 
-		DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx +/- 16)\n",
+		DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx)\n",
 			(long long)td_event,
 			(long long)td->td_self,
-			(long long)td->td_event_last);
+			(long long)td->td_self + sizeof(td->td_trb));
+
+		/*
+		 * NOTE: Some XHCI implementations might not trigger
+		 * an event on the last LINK TRB so we need to
+		 * consider both the last and second last event
+		 * address as conditions for a successful transfer.
+		 *
+		 * NOTE: We assume that the XHCI will only trigger one
+		 * event per chain of TRBs.
+		 */
+
+		offset = td_event - td->td_self;
 
-		if ((td_event == td->td_event_last) ||
-		    (td_event == (td->td_event_last - 16)) ||
-		    (halted && (td_event >= td->td_self) &&
-		    (td_event <= td->td_event_last))) {
+		if ((offset >= 0) &&
+		    (offset < sizeof(td->td_trb))) {
 
 			usb_pc_cpu_invalidate(td->page_cache);
 
+			/* compute rest of remainder, if any */
+			for (i = (offset / 16) + 1; i < td->ntrb; i++) {
+				temp = le32toh(td->td_trb[i].dwTrb2);
+				remainder += XHCI_TRB_2_BYTES_GET(temp);
+			}
+
+			DPRINTFN(5, "New remainder: %u\n", remainder);
+
+			/* clear isochronous transfer errors */
 			if (xfer->flags_int.isochronous_xfr) {
 				if (halted) {
 					halted = 0;
@@ -1073,27 +1092,11 @@
 	XHCI_CMD_LOCK(sc);
 
 	switch (hdev->state) {
-	case XHCI_ST_ADDRESSED:
-	case XHCI_ST_CONFIGURED:
-		if (udev->address == 0) {
-			err = xhci_cmd_reset_dev(sc, index);
-
-			if (err != 0) {
-				DPRINTF("Device reset failed\n");
-			}
-		} else {
-			err = 0;
-			break;
-		}
-
 	case XHCI_ST_DEFAULT:
+	case XHCI_ST_ENABLED:
 
 		hdev->state = XHCI_ST_ENABLED;
 
-		/* FALLTHROUGH */
-
-	case XHCI_ST_ENABLED:
-
 		/* set configure mask to slot and EP0 */
 		xhci_configure_mask(udev, 3, 0);
 
@@ -1124,7 +1127,7 @@
 		    &udev->ctrl_ep_desc);
 		err = xhci_configure_endpoint(udev,
 		    &udev->ctrl_ep_desc, pepext->physaddr,
-		    0, 1, 1, mps, mps);
+		    0, 1, 1, 0, mps, mps);
 
 		if (err != 0) {
 			DPRINTF("Could not configure default endpoint\n");
@@ -1138,7 +1141,8 @@
 		    (address == 0), index);
 
 		if (err != 0) {
-			DPRINTF("Could not set address\n");
+			DPRINTF("Could not set address "
+			    "for slot %u.\n", index);
 			if (address != 0)
 				break;
 		}
@@ -1152,27 +1156,10 @@
 
 		/* update device state to new value */
 
-		if (address != 0) {
-
-			/* we skip the addressed state */
-			hdev->state = XHCI_ST_CONFIGURED;
-
-			xhci_configure_mask(udev, 1, 0);
-
-			err = xhci_configure_device(udev);
-			if (err != 0) {
-				DPRINTF("Could not configure device\n");
-				break;
-			}
-
-			err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
-			if (err != 0) {
-				DPRINTF("Could not evaluate device context\n");
-				break;
-			}
-		} else {
+		if (address != 0)
+			hdev->state = XHCI_ST_ADDRESSED;
+		else
 			hdev->state = XHCI_ST_DEFAULT;
-		}
 		break;
 
 	default:
@@ -1399,7 +1386,6 @@
 	struct xhci_td *td;
 	struct xhci_td *td_next;
 	struct xhci_td *td_alt_next;
-	uint64_t addr;
 	uint32_t buf_offset;
 	uint32_t average;
 	uint32_t len_old;
@@ -1553,11 +1539,20 @@
 			  XHCI_TRB_3_TYPE_SET(temp->trb_type) | 
 			  XHCI_TRB_3_FRID_SET(temp->isoc_frame);
 
-			if (temp->direction == UE_DIR_IN)
+			if (temp->direction == UE_DIR_IN) {
 				dword |= XHCI_TRB_3_DIR_IN;
 
-			if (average == 0)
-				dword |= XHCI_TRB_3_IDT_BIT;
+				/*
+				 * NOTE: Only the SETUP stage should
+				 * use the IDT bit. Else transactions
+				 * can be sent using the wrong data
+				 * toggle value.
+				 */
+
+				if ((temp->trb_type != XHCI_TRB_TYPE_SETUP_STAGE) &&
+				    (temp->trb_type != XHCI_TRB_TYPE_STATUS_STAGE))
+					dword |= XHCI_TRB_3_ISP_BIT;
+			}
 
 			td->td_trb[x].dwTrb3 = htole32(dword);
 
@@ -1578,12 +1573,6 @@
 
 		DPRINTF("NTRB=%u\n", x);
 
-		/* compute event pointer */
-
-		addr = td->td_self;
-		addr += x * sizeof(struct xhci_trb);
-		td->td_event_last = addr;
-
 		/* fill out link TRB */
 
 		if (td_next != NULL) {
@@ -1629,7 +1618,7 @@
 		goto restart;
 	}
 
-	if (temp->multishort == 0) {
+	if (temp->multishort != 0) {
 		/* remove chain bit and clear TD SIZE - end of frame */
 		td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15));
  		td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
@@ -1656,6 +1645,7 @@
 	temp.last_frame = 0;
 	temp.offset = 0;
 	temp.multishort = xfer->flags_int.isochronous_xfr ||
+	    xfer->flags_int.control_xfr ||
 	    xfer->flags_int.short_frames_ok;
 
 	/* toggle the DMA set we are using */
@@ -1867,23 +1857,6 @@
 	usb_pc_cpu_flush(&sc->sc_hw.ctx_pc);
 }
 
-static uint8_t
-xhci_log2(uint32_t x)
-{
-	uint8_t retval;
-
-	retval = 0;
-	while (1) {
-		if (x == 1)
-			break;
-		x >>= 2;
-		if (x == 0)
-			break;
-		retval++;
-	}
-	return (retval);
-}
-
 static usb_error_t
 xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop)
 {
@@ -1913,7 +1886,7 @@
 xhci_configure_endpoint(struct usb_device *udev,
     struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
     uint16_t interval, uint8_t max_packet_count, uint8_t mult,
-    uint16_t max_packet_size, uint16_t max_frame_size)
+    uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size)
 {
 	struct usb_page_search buf_inp;
 	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
@@ -1921,7 +1894,7 @@
 	uint32_t temp;
 	uint8_t index;
 	uint8_t epno;
-	uint8_t k;
+	uint8_t type;
 
 	index = udev->controller_slot_id;
 
@@ -1930,8 +1903,9 @@
 	pinp = buf_inp.buffer;
 
 	epno = edesc->bEndpointAddress;
+	type = edesc->bmAttributes & UE_XFERTYPE;
 
-	if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL)
+	if (type == UE_CONTROL)
 		epno |= UE_DIR_IN;
 
 	epno = XHCI_EPNO2EPID(epno);
@@ -1947,21 +1921,38 @@
 	if (mult == 0)
 		return (USB_ERR_BAD_BUFSIZE);
 
-	mult--;
-
 	temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
 	    XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
 	    XHCI_EPCTX_0_LSA_SET(0);
 
-	switch (edesc->bmAttributes & UE_XFERTYPE) {
+	switch (udev->speed) {
+	case USB_SPEED_FULL:
+	case USB_SPEED_LOW:
+		/* 1ms -> 125us */
+		fps_shift += 3;
+		break;
+	default:
+		break;
+	}
+
+	switch (type) {
 	case UE_INTERRUPT:
-		k = xhci_log2(interval) + 3;
-		temp |= XHCI_EPCTX_0_IVAL_SET(k);
+		if (fps_shift > 3)
+			fps_shift--;
+		temp |= XHCI_EPCTX_0_IVAL_SET(fps_shift);
 		break;
 	case UE_ISOCHRONOUS:
-		if (udev->speed == USB_SPEED_SUPER) {
-			temp |= XHCI_EPCTX_0_MULT_SET(mult);
+		temp |= XHCI_EPCTX_0_IVAL_SET(fps_shift);
+
+		switch (udev->speed) {
+		case USB_SPEED_SUPER:
+			if (mult > 3)
+				mult = 3;
+			temp |= XHCI_EPCTX_0_MULT_SET(mult - 1);
 			max_packet_count /= mult;
+			break;
+		default:
+			break;
 		}
 		break;
 	default:
@@ -1976,11 +1967,11 @@
 	    XHCI_EPCTX_1_MAXP_SIZE_SET(max_packet_size);
 
 	if ((udev->parent_hs_hub != NULL) || (udev->address != 0)) {
-		if ((edesc->bmAttributes & UE_XFERTYPE) != UE_ISOCHRONOUS)
+		if (type != UE_ISOCHRONOUS)
 			temp |= XHCI_EPCTX_1_CERR_SET(3);
 	}
 
-	switch (edesc->bmAttributes & UE_XFERTYPE) {
+	switch (type) {
 	case UE_CONTROL:
 		temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
 		break;
@@ -1995,7 +1986,8 @@
 		break;
 	}
 
-	if (edesc->bEndpointAddress & UE_DIR_IN)
+	/* check for IN direction */
+	if (epno & 1)
 		temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
 
 	pinp->ctx_ep[epno - 1].dwEpCtx1 = htole32(temp);
@@ -2004,19 +1996,17 @@
 
 	pinp->ctx_ep[epno - 1].qwEpCtx2 = htole64(ring_addr);
 
-	temp = 0;
-
 	switch (edesc->bmAttributes & UE_XFERTYPE) {
 	case UE_INTERRUPT:
 	case UE_ISOCHRONOUS:
-		temp |= XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET(max_frame_size);
-		temp |= XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_TD_PAYLOAD_MAX);
+		temp = XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET(max_frame_size);
+		temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_TD_PAYLOAD_MAX);
 		break;
 	case UE_CONTROL:
-		temp |= XHCI_EPCTX_4_AVG_TRB_LEN_SET(8);
+		temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(8);
 		break;
 	default:
-		temp |= XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_TD_PAYLOAD_MAX);
+		temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_TD_PAYLOAD_MAX);
 		break;
 	}
 
@@ -2048,7 +2038,8 @@
 	    xfer->endpoint->edesc, pepext->physaddr,
 	    xfer->interval, xfer->max_packet_count,
 	    (ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1,
-	    xfer->max_packet_size, xfer->max_frame_size));
+	    usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
+	    xfer->max_frame_size));
 }
 
 static usb_error_t
@@ -2135,7 +2126,7 @@
 		break;
 	}
 
-	is_hub = (udev->hub != NULL) && 
+	is_hub = (sc->sc_hw.devs[index].nports != 0) &&
 	    ((udev->speed == USB_SPEED_SUPER) ||
 	    (udev->speed = USB_SPEED_HIGH));
 
@@ -2147,7 +2138,7 @@
 	temp = XHCI_SCTX_1_RH_PORT_SET(rh_port);
 
 	if (is_hub)
-		temp |= XHCI_SCTX_1_NUM_PORTS_SET(udev->hub->nports);
+		temp |= XHCI_SCTX_1_NUM_PORTS_SET(sc->sc_hw.devs[index].nports);
 
 	switch (udev->speed) {
 	case USB_SPEED_SUPER:
@@ -2170,16 +2161,24 @@
 
 	temp = XHCI_SCTX_2_IRQ_TARGET_SET(0);
 
-	if (is_hub) {
-		if (udev->speed == USB_SPEED_HIGH)
-			temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(3);
-	}
+	if (is_hub)
+		temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(sc->sc_hw.devs[index].tt);
 
 	hubdev = udev->parent_hs_hub;
 
-	if (hubdev != NULL) {
-		temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->controller_slot_id);
-		temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(hubdev->port_no);
+	/* check if we should activate the transaction translator */
+	switch (udev->speed) {
+	case USB_SPEED_FULL:
+	case USB_SPEED_LOW:
+		if (hubdev != NULL) {
+			temp |= XHCI_SCTX_2_TT_HUB_SID_SET(
+			    hubdev->controller_slot_id);
+			temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(
+			    udev->hs_port_no);
+		}
+		break;
+	default:
+		break;
 	}
 
 	pinp->ctx_slot.dwSctx2 = htole32(temp);
@@ -2342,7 +2341,8 @@
 	epno = XHCI_EPNO2EPID(epno);
 	index = xfer->xroot->udev->controller_slot_id;
 
-	XWRITE4(sc, door, XHCI_DOORBELL(index), epno | XHCI_DB_SID_SET(0));
+	if (xfer->xroot->udev->flags.self_suspended == 0)
+		XWRITE4(sc, door, XHCI_DOORBELL(index), epno | XHCI_DB_SID_SET(0));
 }
 
 static void
@@ -2536,8 +2536,15 @@
 static void
 xhci_device_generic_open(struct usb_xfer *xfer)
 {
-	if (xfer->flags_int.isochronous_xfr)
-		usb_hs_bandwidth_alloc(xfer);
+	if (xfer->flags_int.isochronous_xfr) {
+		switch (xfer->xroot->udev->speed) {
+		case USB_SPEED_FULL:
+			break;
+		default:
+			usb_hs_bandwidth_alloc(xfer);
+			break;
+		}
+	}
 }
 
 static void
@@ -2547,8 +2554,15 @@
 
 	xhci_device_done(xfer, USB_ERR_CANCELLED);
 
-	if (xfer->flags_int.isochronous_xfr)
-		usb_hs_bandwidth_free(xfer);
+	if (xfer->flags_int.isochronous_xfr) {
+		switch (xfer->xroot->udev->speed) {
+		case USB_SPEED_FULL:
+			break;
+		default:
+			usb_hs_bandwidth_free(xfer);
+			break;
+		}
+	}
 }
 
 static void
@@ -3237,10 +3251,6 @@
 		xfer->flags_int.curr_dma_set = 1;
 		goto alloc_dma_set;
 	}
-
-	/* make sure we catch any set address updates */
-	if (parm->buf != NULL)
-		xhci_set_address(xfer->xroot->udev, NULL, 0);
 }
 
 static usb_error_t
@@ -3249,7 +3259,6 @@
 	struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
 	struct usb_page_search buf_dev;
 	struct usb_page_search buf_inp;
-	struct usb_device *hub;
 	struct usb_device *udev;
 	struct xhci_endpoint_ext *pepext;
 	struct usb_endpoint_descriptor *edesc;
@@ -3288,46 +3297,6 @@
 
 	XHCI_CMD_LOCK(sc);
 
-	/* figure out if a parent HUB should be configured */
-
-	hub = udev->parent_hs_hub;
-	if (hub == NULL) {
-		hub = udev->parent_hub;
-		if (hub == NULL)
-			hub = NULL;
-		else if (hub->parent_hub == NULL)
-			hub = NULL;
-		else if (hub->speed != USB_SPEED_SUPER)
-			hub = NULL;
-	} else {
-		/* check for root HUB */
-		if (hub->parent_hub == NULL)
-			hub = NULL;
-	}
-
-	if (hub != NULL) {
-
-		struct usb_page_search buf_hub;
-
-		DPRINTF("Configure HUB\n");
-
-		usbd_get_page(&sc->sc_hw.devs[
-		    hub->controller_slot_id].input_pc, 0, &buf_hub);
-
-		/* set configure mask to slot only */
-		xhci_configure_mask(hub, 1, 0);
-
-		/* configure input slot context structure */
-		err = xhci_configure_device(hub);
-
-		/* update context */
-		if (err == 0)
-			err = xhci_cmd_evaluate_ctx(sc, buf_hub.physaddr, index);
-
-		if (err)
-			DPRINTF("Could not update parent HS HUB context.\n");
-	}
-
 	/* configure endpoint */
 
 	err = xhci_configure_endpoint_by_xfer(xfer);
@@ -3625,25 +3594,61 @@
 static void
 xhci_device_resume(struct usb_device *udev)
 {
+	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+	uint8_t index;
+	uint8_t n;
+
 	DPRINTF("\n");
 
+	/* check for root HUB */
+	if (udev->parent_hub == NULL)
+		return;
+
+	index = udev->controller_slot_id;
+
+	XHCI_CMD_LOCK(sc);
+
+	/* blindly resume all endpoints */
+
 	USB_BUS_LOCK(udev->bus);
 
-	/* start endpoint */
+	for (n = 1; n != XHCI_MAX_ENDPOINTS; n++)
+		XWRITE4(sc, door, XHCI_DOORBELL(index), n | XHCI_DB_SID_SET(0));
 
 	USB_BUS_UNLOCK(udev->bus);
+
+	XHCI_CMD_UNLOCK(sc);
 }
 
 static void
 xhci_device_suspend(struct usb_device *udev)
 {
+	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+	uint8_t index;
+	uint8_t n;
+	usb_error_t err;
+
 	DPRINTF("\n");
 
-	USB_BUS_LOCK(udev->bus);
+	/* check for root HUB */
+	if (udev->parent_hub == NULL)
+		return;
+
+	index = udev->controller_slot_id;
+
+	XHCI_CMD_LOCK(sc);
+
+	/* blindly suspend all endpoints */
 
-	/* stop endpoint */
+	for (n = 1; n != XHCI_MAX_ENDPOINTS; n++) {
+		err = xhci_cmd_stop_ep(sc, 1, n, index);
+		if (err != 0) {
+			DPRINTF("Failed to suspend endpoint "
+			    "%u on slot %u (ignored).\n", n, index);
+		}
+	}
 
-	USB_BUS_UNLOCK(udev->bus);
+	XHCI_CMD_UNLOCK(sc);
 }
 
 static void
@@ -3652,6 +3657,89 @@
 	DPRINTF("\n");
 }
 
+static void
+xhci_device_state_change(struct usb_device *udev)
+{
+	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
+	struct usb_page_search buf_inp;
+	usb_error_t err;
+	uint8_t index;
+
+	/* check for root HUB */
+	if (udev->parent_hub == NULL)
+		return;
+
+	index = udev->controller_slot_id;
+
+	DPRINTF("\n");
+
+	if (usb_get_device_state(udev) == USB_STATE_CONFIGURED) {
+		err = uhub_query_info(udev, &sc->sc_hw.devs[index].nports, 
+		    &sc->sc_hw.devs[index].tt);
+		if (err != 0)
+			sc->sc_hw.devs[index].nports = 0;
+	}
+
+	XHCI_CMD_LOCK(sc);
+
+	switch (usb_get_device_state(udev)) {
+	case USB_STATE_POWERED:
+		if (sc->sc_hw.devs[index].state == XHCI_ST_DEFAULT)
+			break;
+
+		sc->sc_hw.devs[index].state = XHCI_ST_DEFAULT;
+
+		err = xhci_cmd_reset_dev(sc, index);
+
+		if (err != 0) {
+			DPRINTF("Device reset failed "
+			    "for slot %u.\n", index);
+		}
+		break;
+
+	case USB_STATE_ADDRESSED:
+		if (sc->sc_hw.devs[index].state == XHCI_ST_ADDRESSED)
+			break;
+
+		sc->sc_hw.devs[index].state = XHCI_ST_ADDRESSED;
+
+		err = xhci_cmd_configure_ep(sc, 0, 1, index);
+
+		if (err) {
+			DPRINTF("Failed to deconfigure "
+			    "slot %u.\n", index);
+		}
+		break;
+
+	case USB_STATE_CONFIGURED:
+		if (sc->sc_hw.devs[index].state == XHCI_ST_CONFIGURED)
+			break;
+
+		sc->sc_hw.devs[index].state = XHCI_ST_CONFIGURED;
+
+		usbd_get_page(&sc->sc_hw.devs[index].input_pc, 0, &buf_inp);
+
+		xhci_configure_mask(udev, 1, 0);
+
+		err = xhci_configure_device(udev);
+		if (err != 0) {
+			DPRINTF("Could not configure device "
+			    "at slot %u.\n", index);
+		}
+
+		err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+		if (err != 0) {
+			DPRINTF("Could not evaluate device "
+			    "context at slot %u.\n", index);
+		}
+		break;
+
+	default:
+		break;
+	}
+	XHCI_CMD_UNLOCK(sc);
+}
+
 struct usb_bus_methods xhci_bus_methods = {
 	.endpoint_init = xhci_ep_init,
 	.endpoint_uninit = xhci_ep_uninit,
@@ -3668,4 +3756,5 @@
 	.start_dma_delay = xhci_start_dma_delay,
 	.set_address = xhci_set_address,
 	.clear_stall = xhci_ep_clear_stall,
+	.device_state_change = xhci_device_state_change,
 };

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

@@ -314,7 +314,6 @@
  * Extra information needed:
  */
 	uint64_t td_self;
-	uint64_t td_event_last;
 	struct xhci_td *next;
 	struct xhci_td *alt_next;
 	struct xhci_td *obj_next;
@@ -378,6 +377,9 @@
 	struct xhci_endpoint_ext endp[XHCI_MAX_ENDPOINTS];
 
 	uint8_t state;
+	uint8_t nports;
+	uint8_t tt;
+	uint8_t reserved;
 };
 
 struct xhci_hw_softc {



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