svn commit: r187730 - in head/sys/dev/usb2: controller core

Andrew Thompson thompsa at FreeBSD.org
Mon Jan 26 09:50:01 PST 2009


Author: thompsa
Date: Mon Jan 26 17:49:58 2009
New Revision: 187730
URL: http://svn.freebsd.org/changeset/base/187730

Log:
  MFp4 //depot/projects/usb/ @156522,156530
  
   UHCI SOF Quirk. Makes some broken USB devices work again.  Reported by several
   people. Patch made by me.
  
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb2/controller/uhci2.c
  head/sys/dev/usb2/controller/usb2_controller.h
  head/sys/dev/usb2/core/usb2_hub.c

Modified: head/sys/dev/usb2/controller/uhci2.c
==============================================================================
--- head/sys/dev/usb2/controller/uhci2.c	Mon Jan 26 17:49:48 2009	(r187729)
+++ head/sys/dev/usb2/controller/uhci2.c	Mon Jan 26 17:49:58 2009	(r187730)
@@ -2396,6 +2396,24 @@ uhci_portreset(uhci_softc_t *sc, uint16_
 	else
 		return (USB_ERR_IOERROR);
 
+	/*
+	 * Before we do anything, turn on SOF messages on the USB
+	 * BUS. Some USB devices do not cope without them!
+	 */
+  	if (!(UREAD2(sc, UHCI_CMD) & UHCI_CMD_RS)) {
+
+		DPRINTF("Activating SOFs!\n");
+
+		UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS));
+
+		/* wait a little bit */
+		if (use_polling) {
+			DELAY(10000);
+		} else {
+			usb2_pause_mtx(&sc->sc_bus.bus_mtx, 10);
+		}
+	}
+
 	x = URWMASK(UREAD2(sc, port));
 	UWRITE2(sc, port, x | UHCI_PORTSC_PR);
 
@@ -3320,7 +3338,13 @@ uhci_set_hw_power(struct usb2_bus *bus)
 
 	flags = bus->hw_power_state;
 
+	/*
+	 * WARNING: Some FULL speed USB devices require periodic SOF
+	 * messages! If any USB devices are connected through the
+	 * UHCI, power save will be disabled!
+	 */
 	if (flags & (USB_HW_POWER_CONTROL |
+	    USB_HW_POWER_NON_ROOT_HUB |
 	    USB_HW_POWER_BULK |
 	    USB_HW_POWER_INTERRUPT |
 	    USB_HW_POWER_ISOC)) {

Modified: head/sys/dev/usb2/controller/usb2_controller.h
==============================================================================
--- head/sys/dev/usb2/controller/usb2_controller.h	Mon Jan 26 17:49:48 2009	(r187729)
+++ head/sys/dev/usb2/controller/usb2_controller.h	Mon Jan 26 17:49:58 2009	(r187730)
@@ -84,6 +84,11 @@ struct usb2_bus_methods {
 	 * are active:
 	 */
 #define	USB_HW_POWER_ISOC	0x08
+	/*
+	 * The following flag is set if one or more non-root-HUB devices 
+	 * are present on the given USB bus:
+	 */
+#define	USB_HW_POWER_NON_ROOT_HUB 0x10
 
 	/* USB Device mode only - Mandatory */
 

Modified: head/sys/dev/usb2/core/usb2_hub.c
==============================================================================
--- head/sys/dev/usb2/core/usb2_hub.c	Mon Jan 26 17:49:48 2009	(r187729)
+++ head/sys/dev/usb2/core/usb2_hub.c	Mon Jan 26 17:49:58 2009	(r187730)
@@ -1503,7 +1503,7 @@ usb2_bus_powerd(struct usb2_bus *bus)
 	unsigned int temp;
 	unsigned int limit;
 	unsigned int mintime;
-	uint32_t type_refs[4];
+	uint32_t type_refs[5];
 	uint8_t x;
 	uint8_t rem_wakeup;
 
@@ -1564,6 +1564,7 @@ usb2_bus_powerd(struct usb2_bus *bus)
 	type_refs[1] = 0;
 	type_refs[2] = 0;
 	type_refs[3] = 0;
+	type_refs[4] = 0;
 
 	/* Re-loop all the devices to get the actual state */
 
@@ -1574,6 +1575,9 @@ usb2_bus_powerd(struct usb2_bus *bus)
 		if (udev == NULL)
 			continue;
 
+		/* we found a non-Root-Hub USB device */
+		type_refs[4] += 1;
+
 		/* "last_xfer_time" can be updated by a resume */
 		temp = ticks - udev->pwr_save.last_xfer_time;
 
@@ -1604,6 +1608,8 @@ usb2_bus_powerd(struct usb2_bus *bus)
 			bus->hw_power_state |= USB_HW_POWER_INTERRUPT;
 		if (type_refs[UE_ISOCHRONOUS] != 0)
 			bus->hw_power_state |= USB_HW_POWER_ISOC;
+		if (type_refs[4] != 0)
+			bus->hw_power_state |= USB_HW_POWER_NON_ROOT_HUB;
 	}
 	USB_BUS_UNLOCK(bus);
 


More information about the svn-src-head mailing list