svn commit: r198501 - head/sys/dev/usb/controller

Andrew Thompson thompsa at FreeBSD.org
Mon Oct 26 21:47:17 UTC 2009


Author: thompsa
Date: Mon Oct 26 21:47:16 2009
New Revision: 198501
URL: http://svn.freebsd.org/changeset/base/198501

Log:
  Revert r198500 for now, this will break situations when
  hw.pci.usb_early_takeover is set to zero and the SMM release
  is never done.
  
  Pointed out by:	marcel

Modified:
  head/sys/dev/usb/controller/ehci_pci.c
  head/sys/dev/usb/controller/ohci.c
  head/sys/dev/usb/controller/uhci_pci.c

Modified: head/sys/dev/usb/controller/ehci_pci.c
==============================================================================
--- head/sys/dev/usb/controller/ehci_pci.c	Mon Oct 26 20:23:15 2009	(r198500)
+++ head/sys/dev/usb/controller/ehci_pci.c	Mon Oct 26 21:47:16 2009	(r198501)
@@ -102,6 +102,8 @@ __FBSDID("$FreeBSD$");
 
 #define	PCI_EHCI_BASE_REG	0x10
 
+static void ehci_pci_takecontroller(device_t self);
+
 static device_probe_t ehci_pci_probe;
 static device_attach_t ehci_pci_attach;
 static device_detach_t ehci_pci_detach;
@@ -127,6 +129,7 @@ ehci_pci_resume(device_t self)
 {
 	ehci_softc_t *sc = device_get_softc(self);
 
+	ehci_pci_takecontroller(self);
 	ehci_resume(sc);
 
 	bus_generic_resume(self);
@@ -411,6 +414,7 @@ ehci_pci_attach(device_t self)
 		sc->sc_intr_hdl = NULL;
 		goto error;
 	}
+	ehci_pci_takecontroller(self);
 
 	/* Undocumented quirks taken from Linux */
 
@@ -502,6 +506,51 @@ ehci_pci_detach(device_t self)
 	return (0);
 }
 
+static void
+ehci_pci_takecontroller(device_t self)
+{
+	ehci_softc_t *sc = device_get_softc(self);
+	uint32_t cparams;
+	uint32_t eec;
+	uint16_t to;
+	uint8_t eecp;
+	uint8_t bios_sem;
+
+	cparams = EREAD4(sc, EHCI_HCCPARAMS);
+
+	/* Synchronise with the BIOS if it owns the controller. */
+	for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
+	    eecp = EHCI_EECP_NEXT(eec)) {
+		eec = pci_read_config(self, eecp, 4);
+		if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) {
+			continue;
+		}
+		bios_sem = pci_read_config(self, eecp +
+		    EHCI_LEGSUP_BIOS_SEM, 1);
+		if (bios_sem == 0) {
+			continue;
+		}
+		device_printf(sc->sc_bus.bdev, "waiting for BIOS "
+		    "to give up control\n");
+		pci_write_config(self, eecp +
+		    EHCI_LEGSUP_OS_SEM, 1, 1);
+		to = 500;
+		while (1) {
+			bios_sem = pci_read_config(self, eecp +
+			    EHCI_LEGSUP_BIOS_SEM, 1);
+			if (bios_sem == 0)
+				break;
+
+			if (--to == 0) {
+				device_printf(sc->sc_bus.bdev,
+				    "timed out waiting for BIOS\n");
+				break;
+			}
+			usb_pause_mtx(NULL, hz / 100);	/* wait 10ms */
+		}
+	}
+}
+
 static driver_t ehci_driver =
 {
 	.name = "ehci",

Modified: head/sys/dev/usb/controller/ohci.c
==============================================================================
--- head/sys/dev/usb/controller/ohci.c	Mon Oct 26 20:23:15 2009	(r198500)
+++ head/sys/dev/usb/controller/ohci.c	Mon Oct 26 21:47:16 2009	(r198501)
@@ -175,6 +175,30 @@ ohci_controller_init(ohci_softc_t *sc)
 	uint32_t per;
 	uint32_t desca;
 
+	/* Determine in what context we are running. */
+	ctl = OREAD4(sc, OHCI_CONTROL);
+	if (ctl & OHCI_IR) {
+		/* SMM active, request change */
+		DPRINTF("SMM active, request owner change\n");
+		OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_OCR);
+		for (i = 0; (i < 100) && (ctl & OHCI_IR); i++) {
+			usb_pause_mtx(NULL, hz / 1000);
+			ctl = OREAD4(sc, OHCI_CONTROL);
+		}
+		if (ctl & OHCI_IR) {
+			device_printf(sc->sc_bus.bdev,
+			    "SMM does not respond, resetting\n");
+			OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+			goto reset;
+		}
+	} else {
+		DPRINTF("cold started\n");
+reset:
+		/* controller was cold started */
+		usb_pause_mtx(NULL,
+		    USB_MS_TO_TICKS(USB_BUS_RESET_DELAY));
+	}
+
 	/*
 	 * This reset should not be necessary according to the OHCI spec, but
 	 * without it some controllers do not start.

Modified: head/sys/dev/usb/controller/uhci_pci.c
==============================================================================
--- head/sys/dev/usb/controller/uhci_pci.c	Mon Oct 26 20:23:15 2009	(r198500)
+++ head/sys/dev/usb/controller/uhci_pci.c	Mon Oct 26 21:47:16 2009	(r198501)
@@ -115,6 +115,8 @@ uhci_pci_resume(device_t self)
 {
 	uhci_softc_t *sc = device_get_softc(self);
 
+	pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
+
 	uhci_resume(sc);
 
 	bus_generic_resume(self);
@@ -361,6 +363,19 @@ uhci_pci_attach(device_t self)
 		sc->sc_intr_hdl = NULL;
 		goto error;
 	}
+	/*
+	 * Set the PIRQD enable bit and switch off all the others. We don't
+	 * want legacy support to interfere with us XXX Does this also mean
+	 * that the BIOS won't touch the keyboard anymore if it is connected
+	 * to the ports of the root hub?
+	 */
+#ifdef USB_DEBUG
+	if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN) {
+		device_printf(self, "LegSup = 0x%04x\n",
+		    pci_read_config(self, PCI_LEGSUP, 2));
+	}
+#endif
+	pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
 
 	err = uhci_init(sc);
 	if (!err) {


More information about the svn-src-all mailing list