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 182148 for review
Message-ID:  <201008111825.o7BIPwa4084037@skunkworks.freebsd.org>

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

Change 182148 by hselasky@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;
 			}
 		}
 	}



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