PERFORCE change 182097 for review
Hans Petter Selasky
hselasky at skunkworks.freebsd.org
Wed Aug 11 18:25:49 UTC 2010
http://p4web.freebsd.org/@@182097?ac=10
Change 182097 by hselasky at hselasky_laptop001 on 2010/08/08 18:42:59
USB core + USB controller (XHCI):
- patches related to USB re-enumeration using XHCI chip.
- be smarter when reading the USB device descriptor
by exploiting information about the device speed.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#19 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_device.c#77 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_request.c#42 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_request.h#14 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#19 (text+ko) ====
@@ -125,6 +125,7 @@
static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_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;
@@ -624,7 +625,6 @@
if (xfer->flags_int.control_xfr &&
!xfer->flags_int.control_act)
err = xhci_generic_done_sub(xfer);
-
done:
/* transfer is complete */
xhci_device_done(xfer, err);
@@ -1072,14 +1072,21 @@
switch (hdev->state) {
case XHCI_ST_ADDRESSED:
case XHCI_ST_CONFIGURED:
- err = 0;
- break;
+ if (udev->address == 0) {
+ err = xhci_cmd_reset_dev(sc, index);
- case XHCI_ST_DEFAULT:
- if (address == 0) {
+ if (err != 0) {
+ DPRINTF("Device reset failed\n");
+ }
+ } else {
err = 0;
break;
}
+
+ case XHCI_ST_DEFAULT:
+
+ hdev->state = XHCI_ST_ENABLED;
+
/* FALLTHROUGH */
case XHCI_ST_ENABLED:
@@ -1129,7 +1136,8 @@
if (err != 0) {
DPRINTF("Could not set address\n");
- break;
+ if (address != 0)
+ break;
}
/* update device address to new value */
@@ -1155,7 +1163,6 @@
}
err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
-
if (err != 0) {
DPRINTF("Could not evaluate device context\n");
break;
@@ -1286,7 +1293,6 @@
return (xhci_do_command(sc, &trb, 50 /* ms */));
}
-#if 0
static usb_error_t
xhci_cmd_reset_dev(struct xhci_softc *sc, uint8_t slot_id)
{
@@ -1304,7 +1310,6 @@
return (xhci_do_command(sc, &trb, 50 /* ms */));
}
-#endif
/*------------------------------------------------------------------------*
* xhci_interrupt - XHCI interrupt handler
@@ -3166,6 +3171,10 @@
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
==== //depot/projects/usb/src/sys/dev/usb/usb_device.c#77 (text+ko) ====
@@ -1681,45 +1681,16 @@
}
usb_set_device_state(udev, USB_STATE_ADDRESSED);
- /*
- * Get the first 8 bytes of the device descriptor !
- *
- * NOTE: "usbd_do_request" will check the device descriptor
- * next time we do a request to see if the maximum packet size
- * changed! The 8 first bytes of the device descriptor
- * contains the maximum packet size to use on control endpoint
- * 0. If this value is different from "USB_MAX_IPACKET" a new
- * USB control request will be setup!
- */
- err = usbd_req_get_desc(udev, NULL, NULL, &udev->ddesc,
- USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
- if (err) {
- DPRINTFN(0, "getting device descriptor "
- "at addr %d failed, %s\n", udev->address,
- usbd_errstr(err));
+ /* setup the device descriptor and the initial "wMaxPacketSize" */
+ err = usbd_setup_device_desc(udev, NULL);
+
+ if (err != 0) {
/* XXX try to re-enumerate the device */
err = usbd_req_re_enumerate(udev, NULL);
- if (err) {
+ if (err)
goto done;
- }
}
- DPRINTF("adding unit addr=%d, rev=%02x, class=%d, "
- "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
- udev->address, UGETW(udev->ddesc.bcdUSB),
- udev->ddesc.bDeviceClass,
- udev->ddesc.bDeviceSubClass,
- udev->ddesc.bDeviceProtocol,
- udev->ddesc.bMaxPacketSize,
- udev->ddesc.bLength,
- udev->speed);
- /* get the full device descriptor */
- err = usbd_req_get_device_desc(udev, NULL, &udev->ddesc);
- if (err) {
- DPRINTF("addr=%d, getting full desc failed\n",
- udev->address);
- goto done;
- }
/*
* Setup temporary USB attach args so that we can figure out some
* basic quirks for this device.
==== //depot/projects/usb/src/sys/dev/usb/usb_request.c#42 (text+ko) ====
@@ -1763,6 +1763,68 @@
}
/*------------------------------------------------------------------------*
+ * usbd_setup_device_desc
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_setup_device_desc(struct usb_device *udev, struct mtx *mtx)
+{
+ usb_error_t err;
+
+ /*
+ * Get the first 8 bytes of the device descriptor !
+ *
+ * NOTE: "usbd_do_request()" will check the device descriptor
+ * next time we do a request to see if the maximum packet size
+ * changed! The 8 first bytes of the device descriptor
+ * contains the maximum packet size to use on control endpoint
+ * 0. If this value is different from "USB_MAX_IPACKET" a new
+ * USB control request will be setup!
+ */
+ switch (udev->speed) {
+ case USB_SPEED_FULL:
+ case USB_SPEED_LOW:
+ err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
+ USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
+ if (err != 0) {
+ DPRINTFN(0, "getting device descriptor "
+ "at addr %d failed, %s\n", udev->address,
+ usbd_errstr(err));
+ return (err);
+ }
+ break;
+ default:
+ DPRINTF("Minimum MaxPacketSize is large enough "
+ "to hold the complete device descriptor\n");
+ break;
+ }
+
+ /* get the full device descriptor */
+ err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+
+ /* try one more time, if error */
+ if (err)
+ err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+
+ if (err) {
+ DPRINTF("addr=%d, getting full desc failed\n",
+ udev->address);
+ return (err);
+ }
+
+ DPRINTF("adding unit addr=%d, rev=%02x, class=%d, "
+ "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
+ udev->address, UGETW(udev->ddesc.bcdUSB),
+ udev->ddesc.bDeviceClass,
+ udev->ddesc.bDeviceSubClass,
+ udev->ddesc.bDeviceProtocol,
+ udev->ddesc.bMaxPacketSize,
+ udev->ddesc.bLength,
+ udev->speed);
+
+ return (err);
+}
+
+/*------------------------------------------------------------------------*
* usbd_req_re_enumerate
*
* NOTE: After this function returns the hardware is in the
@@ -1821,23 +1883,9 @@
if (udev->address == USB_START_ADDR)
udev->address = old_addr;
- /* get the device descriptor */
- err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
- USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
- if (err) {
- DPRINTFN(0, "getting device descriptor "
- "at addr %d failed, %s\n", udev->address,
- usbd_errstr(err));
- goto done;
- }
- /* get the full device descriptor */
- err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
- if (err) {
- DPRINTFN(0, "addr=%d, getting device "
- "descriptor failed, %s\n", old_addr,
- usbd_errstr(err));
- goto done;
- }
+ /* setup the device descriptor and the initial "wMaxPacketSize" */
+ err = usbd_setup_device_desc(udev, mtx);
+
done:
if (err && do_retry) {
/* give the USB firmware some time to load */
==== //depot/projects/usb/src/sys/dev/usb/usb_request.h#14 (text+ko) ====
@@ -71,6 +71,7 @@
uint16_t sel);
usb_error_t usbd_req_set_port_feature(struct usb_device *udev,
struct mtx *mtx, uint8_t port, uint16_t sel);
+usb_error_t usbd_setup_device_desc(struct usb_device *udev, struct mtx *mtx);
usb_error_t usbd_req_re_enumerate(struct usb_device *udev, struct mtx *mtx);
usb_error_t usbd_req_clear_device_feature(struct usb_device *udev,
struct mtx *mtx, uint16_t sel);
More information about the p4-projects
mailing list