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"