diff options
-rw-r--r-- | sys/dev/usb/ehci.c | 112 | ||||
-rw-r--r-- | sys/dev/usb/ehcivar.h | 3 |
2 files changed, 75 insertions, 40 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 709791f7ecb..cef634ba88d 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ehci.c,v 1.22 2004/09/30 11:33:56 dlg Exp $ */ +/* $OpenBSD: ehci.c,v 1.23 2004/10/19 08:10:27 dlg Exp $ */ /* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */ /* @@ -100,6 +100,10 @@ struct cfdriver ehci_cd = { }; #endif +#ifdef USB_DEBUG +#define EHCI_DEBUG +#endif /* USB_DEBUG */ + #ifdef EHCI_DEBUG #define DPRINTF(x) do { if (ehcidebug) printf x; } while(0) #define DPRINTFN(n,x) do { if (ehcidebug>(n)) printf x; } while (0) @@ -904,12 +908,13 @@ void ehci_power(int why, void *v) { ehci_softc_t *sc = v; - //u_int32_t ctl; - int s; + u_int32_t cmd, hcr; + int s, i; #ifdef EHCI_DEBUG DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why)); - ehci_dump_regs(sc); + if (ehcidebug > 0) + ehci_dump_regs(sc); #endif s = splhardusb(); @@ -917,46 +922,69 @@ ehci_power(int why, void *v) case PWR_SUSPEND: case PWR_STANDBY: sc->sc_bus.use_polling++; -#if 0 -OOO - ctl = OREAD4(sc, EHCI_CONTROL) & ~EHCI_HCFS_MASK; - if (sc->sc_control == 0) { - /* - * Preserve register values, in case that APM BIOS - * does not recover them. - */ - sc->sc_control = ctl; - sc->sc_intre = OREAD4(sc, EHCI_INTERRUPT_ENABLE); + + sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD); + + cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE); + EOWRITE4(sc, EHCI_USBCMD, cmd); + + for (i = 0; i < 100; i++) { + hcr = EOREAD4(sc, EHCI_USBSTS) & + (EHCI_STS_ASS | EHCI_STS_PSS); + if (hcr == 0) + break; + + usb_delay_ms(&sc->sc_bus, 1); } - ctl |= EHCI_HCFS_SUSPEND; - OWRITE4(sc, EHCI_CONTROL, ctl); -#endif - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); + if (hcr != 0) { + printf("%s: reset timeout\n", + USBDEVNAME(sc->sc_bus.bdev)); + } + + cmd &= ~EHCI_CMD_RS; + EOWRITE4(sc, EHCI_USBCMD, cmd); + + for (i = 0; i < 100; i++) { + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (hcr == EHCI_STS_HCH) + break; + + usb_delay_ms(&sc->sc_bus, 1); + } + if (hcr != EHCI_STS_HCH) { + printf("%s: config timeout\n", + USBDEVNAME(sc->sc_bus.bdev)); + } + sc->sc_bus.use_polling--; break; + case PWR_RESUME: sc->sc_bus.use_polling++; -#if 0 -OOO - /* Some broken BIOSes do not recover these values */ - OWRITE4(sc, EHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); - OWRITE4(sc, EHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); - OWRITE4(sc, EHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); - if (sc->sc_intre) - OWRITE4(sc, EHCI_INTERRUPT_ENABLE, - sc->sc_intre & (EHCI_ALL_INTRS | EHCI_MIE)); - if (sc->sc_control) - ctl = sc->sc_control; - else - ctl = OREAD4(sc, EHCI_CONTROL); - ctl |= EHCI_HCFS_RESUME; - OWRITE4(sc, EHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - ctl = (ctl & ~EHCI_HCFS_MASK) | EHCI_HCFS_OPERATIONAL; - OWRITE4(sc, EHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_control = sc->sc_intre = 0; -#endif + + /* restore things in case the bios sucks */ + EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); + EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); + EOWRITE4(sc, EHCI_ASYNCLISTADDR, + sc->sc_async_head->physaddr | EHCI_LINK_QH); + EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); + + EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); + + for (i = 0; i < 100; i++) { + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (hcr != EHCI_STS_HCH) + break; + + usb_delay_ms(&sc->sc_bus, 1); + } + if (hcr == EHCI_STS_HCH) { + printf("%s: config timeout\n", + USBDEVNAME(sc->sc_bus.bdev)); + } + + usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); + sc->sc_bus.use_polling--; break; #if defined(__NetBSD__) @@ -967,6 +995,12 @@ OOO #endif } splx(s); + +#ifdef EHCI_DEBUG + DPRINTF(("ehci_power: sc=%p\n", sc)); + if (ehcidebug > 0) + ehci_dump_regs(sc); +#endif } /* diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h index 90849232c6f..447729f1b19 100644 --- a/sys/dev/usb/ehcivar.h +++ b/sys/dev/usb/ehcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ehcivar.h,v 1.4 2004/05/30 01:25:17 tedu Exp $ */ +/* $OpenBSD: ehcivar.h,v 1.5 2004/10/19 08:10:27 dlg Exp $ */ /* $NetBSD: ehcivar.h,v 1.12 2001/12/31 12:16:57 augustss Exp $ */ /* @@ -83,6 +83,7 @@ typedef struct ehci_softc { char sc_vendor[16]; /* vendor string for root hub */ int sc_id_vendor; /* vendor ID for root hub */ + u_int32_t sc_cmd; /* shadow of cmd reg during suspend */ void *sc_powerhook; /* cookie from power hook */ void *sc_shutdownhook; /* cookie from shutdown hook */ |