diff options
| author | Don Lewis <truckman@FreeBSD.org> | 2007-08-12 18:45:24 +0000 |
|---|---|---|
| committer | Don Lewis <truckman@FreeBSD.org> | 2007-08-12 18:45:24 +0000 |
| commit | 4d54b88811d95961d759a77daad84d5bb4990e53 (patch) | |
| tree | 28615061eab47cfdd635b8a3c1f0aafa636ff4da | |
| parent | 9136384dc29f227386e3fcb1524e2db62146d27a (diff) | |
Notes
| -rw-r--r-- | sys/dev/usb/ehci.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 2ce95e68375d..6b99d54b42e3 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -311,6 +311,39 @@ static struct usbd_pipe_methods ehci_device_isoc_methods = { ehci_device_isoc_done, }; +static usbd_status +ehci_hcreset(ehci_softc_t *sc) +{ + u_int32_t hcr; + u_int i; + + EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ + for (i = 0; i < 100; i++) { + usb_delay_ms(&sc->sc_bus, 1); + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (hcr) + break; + } + if (!hcr) + /* + * Fall through and try reset anyway even though + * Table 2-9 in the EHCI spec says this will result + * in undefined behavior. + */ + printf("%s: stop timeout\n", + device_get_nameunit(sc->sc_bus.bdev)); + + EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); + for (i = 0; i < 100; i++) { + usb_delay_ms(&sc->sc_bus, 1); + hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; + if (!hcr) + return (USBD_NORMAL_COMPLETION); + } + printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev)); + return (USBD_IOERROR); +} + usbd_status ehci_init(ehci_softc_t *sc) { @@ -365,20 +398,9 @@ ehci_init(ehci_softc_t *sc) /* Reset the controller */ DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev))); - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - usb_delay_ms(&sc->sc_bus, 1); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); - for (i = 0; i < 100; i++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; - if (!hcr) - break; - } - if (hcr) { - printf("%s: reset timeout\n", - device_get_nameunit(sc->sc_bus.bdev)); - return (USBD_IOERROR); - } + err = ehci_hcreset(sc); + if (err != USBD_NORMAL_COMPLETION) + return (err); /* frame list size at default, read back what we got and use that */ switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))) { @@ -927,8 +949,7 @@ ehci_detach(struct ehci_softc *sc, int flags) sc->sc_dying = 1; EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - EOWRITE4(sc, EHCI_USBCMD, 0); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); + (void) ehci_hcreset(sc); callout_stop(&sc->sc_tmo_intrlist); callout_stop(&sc->sc_tmo_pcd); @@ -1090,8 +1111,7 @@ ehci_shutdown(void *v) ehci_softc_t *sc = v; DPRINTF(("ehci_shutdown: stopping the HC\n")); - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); + (void) ehci_hcreset(sc); } usbd_status |
