version 1.33, 2008/01/27 20:09:14 |
version 1.34, 2008/01/28 00:44:17 |
Line 67 extern int ehcidebug; |
|
Line 67 extern int ehcidebug; |
|
#define DPRINTF(x) |
#define DPRINTF(x) |
#endif |
#endif |
|
|
|
static void ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, |
|
pcitag_t tag); |
static void ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, |
static void ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, |
pcitag_t tag); |
pcitag_t tag); |
|
static bool ehci_pci_suspend(device_t); |
static bool ehci_pci_resume(device_t); |
static bool ehci_pci_resume(device_t); |
|
|
struct ehci_pci_softc { |
struct ehci_pci_softc { |
Line 213 ehci_pci_attach(struct device *parent, s |
|
Line 216 ehci_pci_attach(struct device *parent, s |
|
return; |
return; |
} |
} |
|
|
if (!pmf_device_register(self, ehci_suspend, ehci_pci_resume)) |
if (!pmf_device_register(self, ehci_pci_suspend, ehci_pci_resume)) |
aprint_error_dev(self, "couldn't establish power handler\n"); |
aprint_error_dev(self, "couldn't establish power handler\n"); |
|
|
/* Attach usb device. */ |
/* Attach usb device. */ |
Line 236 ehci_pci_detach(device_ptr_t self, int f |
|
Line 239 ehci_pci_detach(device_ptr_t self, int f |
|
sc->sc_ih = NULL; |
sc->sc_ih = NULL; |
} |
} |
if (sc->sc.sc_size) { |
if (sc->sc.sc_size) { |
|
ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); |
bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); |
bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); |
sc->sc.sc_size = 0; |
sc->sc.sc_size = 0; |
} |
} |
|
|
return (0); |
return (0); |
} |
} |
|
|
Line 276 ehci_dump_caps(ehci_softc_t *sc, pci_chi |
|
Line 281 ehci_dump_caps(ehci_softc_t *sc, pci_chi |
|
#endif |
#endif |
|
|
static void |
static void |
|
ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) |
|
{ |
|
const char *devname = sc->sc_bus.bdev.dv_xname; |
|
u_int32_t cparams, addr, cap; |
|
pcireg_t legsup; |
|
int maxcap = 10; |
|
|
|
cparams = EREAD4(sc, EHCI_HCCPARAMS); |
|
addr = EHCI_HCC_EECP(cparams); |
|
while (addr != 0) { |
|
cap = pci_conf_read(pc, tag, addr); |
|
if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY) |
|
goto next; |
|
legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); |
|
pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, |
|
legsup & ~EHCI_LEG_HC_OS_OWNED); |
|
|
|
next: |
|
if (--maxcap < 0) { |
|
aprint_normal("%s: broken extended capabilities " |
|
"ignored\n", devname); |
|
return; |
|
} |
|
addr = EHCI_CAP_GET_NEXT(cap); |
|
} |
|
} |
|
|
|
static void |
ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) |
ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) |
{ |
{ |
const char *devname = sc->sc_bus.bdev.dv_xname; |
const char *devname = sc->sc_bus.bdev.dv_xname; |
Line 292 ehci_get_ownership(ehci_softc_t *sc, pci |
|
Line 325 ehci_get_ownership(ehci_softc_t *sc, pci |
|
addr = EHCI_HCC_EECP(cparams); |
addr = EHCI_HCC_EECP(cparams); |
while (addr != 0) { |
while (addr != 0) { |
cap = pci_conf_read(pc, tag, addr); |
cap = pci_conf_read(pc, tag, addr); |
if (EHCI_CAP_GET_ID(cap) == EHCI_CAP_ID_LEGACY) |
if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY) |
break; |
goto next; |
|
legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); |
|
/* Ask BIOS to give up ownership */ |
|
pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, |
|
legsup | EHCI_LEG_HC_OS_OWNED); |
|
if (legsup & EHCI_LEG_HC_BIOS_OWNED) { |
|
for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) { |
|
legsup = pci_conf_read(pc, tag, |
|
addr + PCI_EHCI_USBLEGSUP); |
|
if (!(legsup & EHCI_LEG_HC_BIOS_OWNED)) |
|
break; |
|
delay(1000); |
|
} |
|
if (ms == EHCI_MAX_BIOS_WAIT) { |
|
aprint_normal("%s: BIOS refuses to give up " |
|
"ownership, using force\n", devname); |
|
pci_conf_write(pc, tag, |
|
addr + PCI_EHCI_USBLEGSUP, 0); |
|
} else |
|
aprint_verbose("%s: BIOS has given up " |
|
"ownership\n", devname); |
|
} |
|
|
|
/* Disable SMIs */ |
|
pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS, |
|
EHCI_LEG_EXT_SMI_BAR | EHCI_LEG_EXT_SMI_PCICMD | |
|
EHCI_LEG_EXT_SMI_OS_CHANGE); |
|
|
|
next: |
if (--maxcap < 0) { |
if (--maxcap < 0) { |
aprint_normal("%s: broken extended capabilities " |
aprint_normal("%s: broken extended capabilities " |
"ignored\n", devname); |
"ignored\n", devname); |
Line 302 ehci_get_ownership(ehci_softc_t *sc, pci |
|
Line 363 ehci_get_ownership(ehci_softc_t *sc, pci |
|
addr = EHCI_CAP_GET_NEXT(cap); |
addr = EHCI_CAP_GET_NEXT(cap); |
} |
} |
|
|
/* If the USB legacy capability is not specified, we are done */ |
} |
if (addr == 0) |
|
return; |
|
|
|
legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); |
static bool |
if (legsup & EHCI_LEG_HC_BIOS_OWNED) { |
ehci_pci_suspend(device_t dv) |
/* Ask BIOS to give up ownership */ |
{ |
legsup |= EHCI_LEG_HC_OS_OWNED; |
struct ehci_pci_softc *sc = device_private(dv); |
pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, legsup); |
|
for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) { |
ehci_suspend(dv); |
legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); |
ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); |
if (!(legsup & EHCI_LEG_HC_BIOS_OWNED)) |
|
break; |
|
delay(1000); |
|
} |
|
if (ms == EHCI_MAX_BIOS_WAIT) { |
|
aprint_normal("%s: BIOS refuses to give up ownership, " |
|
"using force\n", devname); |
|
pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, 0); |
|
} else { |
|
aprint_verbose("%s: BIOS has given up ownership\n", devname); |
|
} |
|
} |
|
|
|
/* Disable SMIs */ |
return true; |
pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS, |
|
EHCI_LEG_EXT_SMI_BAR | EHCI_LEG_EXT_SMI_PCICMD | |
|
EHCI_LEG_EXT_SMI_OS_CHANGE); |
|
} |
} |
|
|
static bool |
static bool |