PERFORCE change 182148 for review
Hans Petter Selasky
hselasky at skunkworks.freebsd.org
Wed Aug 11 18:26:03 UTC 2010
http://p4web.freebsd.org/@@182148?ac=10
Change 182148 by hselasky at hselasky_laptop001 on 2010/08/09 19:43:23
USB core:
- changes needed for XHCI support (Super Speed USB)
- compute fps_shift also for interrupt endpoints
- add helper function to USB HUB driver to give
information about number of HUB ports before
the HUB driver gets attached.
- add new USB method that allows the USB controller
driver to track the state of the USB devices.
- correct some Super Speed burst computations.
- add missing state changes in the re-enumerate
function
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_controller.h#27 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_device.c#78 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_device.h#41 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.c#56 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.h#18 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_request.c#43 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#185 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_controller.h#27 (text+ko) ====
@@ -126,6 +126,8 @@
void (*start_dma_delay) (struct usb_xfer *);
+ void (*device_state_change) (struct usb_device *);
+
/* Optional for host mode */
usb_error_t (*set_address) (struct usb_device *, struct mtx *, uint16_t);
==== //depot/projects/usb/src/sys/dev/usb/usb_device.c#78 (text+ko) ====
@@ -1560,7 +1560,6 @@
udev->bus = bus;
udev->address = USB_START_ADDR; /* default value */
udev->plugtime = (usb_ticks_t)ticks;
- usb_set_device_state(udev, USB_STATE_POWERED);
/*
* We need to force the power mode to "on" because there are plenty
* of USB devices out there that do not work very well with
@@ -1637,6 +1636,8 @@
goto done;
}
}
+ /* set powered device state after device init is complete */
+ usb_set_device_state(udev, USB_STATE_POWERED);
if (udev->flags.usb_mode == USB_MODE_HOST) {
@@ -2616,6 +2617,17 @@
DPRINTF("udev %p state %s -> %s\n", udev,
usb_statestr(udev->state), usb_statestr(state));
udev->state = state;
+
+ if (udev->bus->methods->device_state_change != NULL)
+ (udev->bus->methods->device_state_change) (udev);
+}
+
+enum usb_dev_state
+usb_get_device_state(struct usb_device *udev)
+{
+ if (udev == NULL)
+ return (USB_STATE_DETACHED);
+ return (udev->state);
}
uint8_t
==== //depot/projects/usb/src/sys/dev/usb/usb_device.h#41 (text+ko) ====
@@ -215,8 +215,9 @@
void usb_linux_free_device(struct usb_device *dev);
uint8_t usb_peer_can_wakeup(struct usb_device *udev);
struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep);
-void usb_set_device_state(struct usb_device *udev,
- enum usb_dev_state state);
+void usb_set_device_state(struct usb_device *, enum usb_dev_state);
+enum usb_dev_state usb_get_device_state(struct usb_device *);
+
void usbd_enum_lock(struct usb_device *);
void usbd_enum_unlock(struct usb_device *);
void usbd_sr_lock(struct usb_device *);
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.c#56 (text+ko) ====
@@ -805,6 +805,67 @@
return (ENXIO);
}
+/* NOTE: The information returned by this function can be wrong. */
+usb_error_t
+uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt)
+{
+ struct usb_hub_descriptor hubdesc20;
+ struct usb_hub_ss_descriptor hubdesc30;
+ usb_error_t err;
+ uint8_t nports;
+ uint8_t tt;
+
+ if (udev->ddesc.bDeviceClass != UDCLASS_HUB)
+ return (USB_ERR_INVAL);
+
+ nports = 0;
+ tt = 0;
+
+ switch (udev->speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ case USB_SPEED_HIGH:
+ /* assuming that there is one port */
+ err = usbd_req_get_hub_descriptor(udev, NULL, &hubdesc20, 1);
+ if (err) {
+ DPRINTFN(0, "getting USB 2.0 HUB descriptor failed,"
+ "error=%s\n", usbd_errstr(err));
+ break;
+ }
+ nports = hubdesc20.bNbrPorts;
+ if (nports > 127)
+ nports = 127;
+
+ if (udev->speed == USB_SPEED_HIGH)
+ tt = (UGETW(hubdesc20.wHubCharacteristics) >> 5) & 3;
+ break;
+
+ case USB_SPEED_SUPER:
+ err = usbd_req_get_ss_hub_descriptor(udev, NULL, &hubdesc30, 1);
+ if (err) {
+ DPRINTFN(0, "Getting USB 3.0 HUB descriptor failed,"
+ "error=%s\n", usbd_errstr(err));
+ break;
+ }
+ nports = hubdesc30.bNbrPorts;
+ if (nports > 16)
+ nports = 16;
+ break;
+
+ default:
+ err = USB_ERR_INVAL;
+ break;
+ }
+
+ if (pnports != NULL)
+ *pnports = nports;
+
+ if (ptt != NULL)
+ *ptt = tt;
+
+ return (err);
+}
+
static int
uhub_attach(device_t dev)
{
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.h#18 (text+ko) ====
@@ -78,5 +78,6 @@
void usb_bus_power_update(struct usb_bus *bus);
void usb_bus_powerd(struct usb_bus *bus);
void uhub_root_intr(struct usb_bus *, const uint8_t *, uint8_t);
+usb_error_t uhub_query_info(struct usb_device *, uint8_t *, uint8_t *);
#endif /* _USB_HUB_H_ */
==== //depot/projects/usb/src/sys/dev/usb/usb_request.c#43 (text+ko) ====
@@ -1858,6 +1858,7 @@
old_addr, usbd_errstr(err));
goto done;
}
+
/*
* After that the port has been reset our device should be at
* address zero:
@@ -1867,6 +1868,9 @@
/* reset "bMaxPacketSize" */
udev->ddesc.bMaxPacketSize = USB_MAX_IPACKET;
+ /* reset USB state */
+ usb_set_device_state(udev, USB_STATE_POWERED);
+
/*
* Restore device address:
*/
@@ -1898,6 +1902,9 @@
/* restore address */
if (udev->address == USB_START_ADDR)
udev->address = old_addr;
+ /* update state, if successful */
+ if (err == 0)
+ usb_set_device_state(udev, USB_STATE_ADDRESSED);
return (err);
}
==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#185 (text+ko) ====
@@ -315,6 +315,7 @@
};
struct usb_xfer *xfer = parm->curr_xfer;
const struct usb_config *setup = parm->curr_setup;
+ struct usb_endpoint_ss_comp_descriptor *ecomp;
struct usb_endpoint_descriptor *edesc;
struct usb_std_packet_size std_size;
usb_frcount_t n_frlengths;
@@ -322,7 +323,6 @@
usb_frcount_t x;
uint8_t type;
uint8_t zmps;
- uint8_t mult;
/*
* Sanity check. The following parameters must be initialized before
@@ -335,6 +335,7 @@
goto done;
}
edesc = xfer->endpoint->edesc;
+ ecomp = xfer->endpoint->ecomp;
type = (edesc->bmAttributes & UE_XFERTYPE);
@@ -353,41 +354,48 @@
switch (parm->speed) {
case USB_SPEED_HIGH:
- xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
- /* check for invalid max packet count */
- if (xfer->max_packet_count > 3)
- xfer->max_packet_count = 3;
+ switch (type) {
+ case UE_ISOCHRONOUS:
+ case UE_INTERRUPT:
+ xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
+
+ /* check for invalid max packet count */
+ if (xfer->max_packet_count > 3)
+ xfer->max_packet_count = 3;
+ break;
+ default:
+ break;
+ }
xfer->max_packet_size &= 0x7FF;
break;
-
case USB_SPEED_SUPER:
xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
- mult = 1;
+
+ if (ecomp != NULL)
+ xfer->max_packet_count += ecomp->bMaxBurst;
- /* compute additional bMaxBurst */
- if (xfer->endpoint->ecomp != NULL) {
- xfer->max_packet_count +=
- xfer->endpoint->ecomp->bMaxBurst;
+ if ((xfer->max_packet_count == 0) ||
+ (xfer->max_packet_count > 16))
+ xfer->max_packet_count = 16;
- if (type == UE_ISOCHRONOUS) {
- mult +=
- (xfer->endpoint->ecomp->bmAttributes & 3);
- }
- }
+ switch (type) {
+ case UE_CONTROL:
+ xfer->max_packet_count = 1;
+ break;
+ case UE_ISOCHRONOUS:
+ if (ecomp != NULL) {
+ uint8_t mult;
- xfer->max_packet_count *= mult;
+ mult = (ecomp->bmAttributes & 3) + 1;
+ if (mult > 3)
+ mult = 3;
- /* check for invalid max packet count */
- if (type == UE_ISOCHRONOUS) {
- if ((xfer->max_packet_count == 0) ||
- (xfer->max_packet_count > (16 * 3)))
- xfer->max_packet_count = (16 * 3);
- } else {
- if ((xfer->max_packet_count == 0) ||
- (xfer->max_packet_count > (16 * 1)))
- xfer->max_packet_count = (16 * 1);
+ xfer->max_packet_count *= mult;
+ }
+ break;
+ default:
+ break;
}
-
xfer->max_packet_size &= 0x7FF;
break;
default:
@@ -484,41 +492,57 @@
} else {
/*
- * if a value is specified use that else check the endpoint
- * descriptor
+ * If a value is specified use that else check the
+ * endpoint descriptor!
*/
- if (xfer->interval == 0) {
+ if (type == UE_INTERRUPT) {
+
+ uint32_t temp;
- if (type == UE_INTERRUPT) {
+ if (xfer->interval == 0) {
xfer->interval = edesc->bInterval;
switch (parm->speed) {
- case USB_SPEED_SUPER:
- case USB_SPEED_VARIABLE:
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ break;
+ default:
/* 125us -> 1ms */
if (xfer->interval < 4)
xfer->interval = 1;
else if (xfer->interval > 16)
- xfer->interval = (1<<(16-4));
+ xfer->interval = (1 << (16 - 4));
else
xfer->interval =
- (1 << (xfer->interval-4));
+ (1 << (xfer->interval - 4));
break;
- case USB_SPEED_HIGH:
- /* 125us -> 1ms */
- xfer->interval /= 8;
- break;
- default:
- break;
}
- if (xfer->interval == 0) {
- /*
- * One millisecond is the smallest
- * interval we support:
- */
- xfer->interval = 1;
- }
+ }
+
+ if (xfer->interval == 0) {
+ /*
+ * One millisecond is the smallest
+ * interval we support:
+ */
+ xfer->interval = 1;
+ }
+
+ xfer->fps_shift = 0;
+ temp = 1;
+
+ while ((temp != 0) && (temp < xfer->interval)) {
+ xfer->fps_shift++;
+ temp *= 2;
+ }
+
+ switch (parm->speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ break;
+ default:
+ xfer->fps_shift += 3;
+ break;
}
}
}
More information about the p4-projects
mailing list