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) {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to