diff options
author | thompsa <thompsa@FreeBSD.org> | 2009-10-26 21:47:16 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2009-10-26 21:47:16 +0000 |
commit | e7629ee2bb8183368e57023949d649f501ab1e3a (patch) | |
tree | 26d1a93a0f4d08ef8f9a568d58099f7c70932e45 /sys/dev/usb/controller/ehci_pci.c | |
parent | 8f17b6fdd9def8c843751b1b5f7eb581d17a8a56 (diff) | |
download | FreeBSD-src-e7629ee2bb8183368e57023949d649f501ab1e3a.zip FreeBSD-src-e7629ee2bb8183368e57023949d649f501ab1e3a.tar.gz |
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
Diffstat (limited to 'sys/dev/usb/controller/ehci_pci.c')
-rw-r--r-- | sys/dev/usb/controller/ehci_pci.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c index 5931c51..fc2035b 100644 --- a/sys/dev/usb/controller/ehci_pci.c +++ b/sys/dev/usb/controller/ehci_pci.c @@ -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", |