diff options
author | shiba <shiba@FreeBSD.org> | 2003-12-22 15:40:10 +0000 |
---|---|---|
committer | shiba <shiba@FreeBSD.org> | 2003-12-22 15:40:10 +0000 |
commit | 11d4c5569bc85b8e50ead99512307e28af5d893d (patch) | |
tree | c4b1bb6425dc7bef4e1369e1abdd79ade12f8503 /sys | |
parent | 7fcf777b3211125d10357f00f4f9fa2f728a64c3 (diff) | |
download | FreeBSD-src-11d4c5569bc85b8e50ead99512307e28af5d893d.zip FreeBSD-src-11d4c5569bc85b8e50ead99512307e28af5d893d.tar.gz |
Fixed incomplete initialization in some ohci controllers with
broken BIOS. Separate ohci_controller_init() from ohci_init(),
and call ohci_controller_init() at resume process once more.
Discussed on [bsd-nomads:16737] - [bsd-nomads:16746].
Submitted by Hiroyuki Aizu <eyes@navi.org> [bsd-nomads:16741]
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/ohci.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 00a92c6..609473e 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -229,6 +229,8 @@ Static void ohci_abort_xfer(usbd_xfer_handle, usbd_status); Static void ohci_device_clear_toggle(usbd_pipe_handle pipe); Static void ohci_noop(usbd_pipe_handle pipe); +Static usbd_status ohci_controller_init(ohci_softc_t *sc); + #ifdef USB_DEBUG Static void ohci_dumpregs(ohci_softc_t *); Static void ohci_dump_tds(ohci_soft_td_t *); @@ -697,7 +699,7 @@ ohci_init(ohci_softc_t *sc) ohci_soft_ed_t *sed, *psed; usbd_status err; int i; - u_int32_t s, ctl, ival, hcr, fm, per, rev, desca; + u_int32_t rev; DPRINTF(("ohci_init: start\n")); #if defined(__OpenBSD__) @@ -797,6 +799,44 @@ ohci_init(ohci_softc_t *sc) } #endif + err = ohci_controller_init(sc); + if (err != USBD_NORMAL_COMPLETION) + goto bad5; + + /* Set up the bus struct. */ + sc->sc_bus.methods = &ohci_bus_methods; + sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); + +#if defined(__NetBSD__) || defined(__OpenBSD__) + sc->sc_control = sc->sc_intre = 0; + sc->sc_powerhook = powerhook_establish(ohci_power, sc); + sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc); +#endif + + usb_callout_init(sc->sc_tmo_rhsc); + + return (USBD_NORMAL_COMPLETION); + + bad5: + for (i = 0; i < OHCI_NO_EDS; i++) + ohci_free_sed(sc, sc->sc_eds[i]); + bad4: + ohci_free_sed(sc, sc->sc_isoc_head); + bad3: + ohci_free_sed(sc, sc->sc_ctrl_head); + bad2: + ohci_free_sed(sc, sc->sc_bulk_head); + bad1: + usb_freemem(&sc->sc_bus, &sc->sc_hccadma); + return (err); +} + +Static usbd_status +ohci_controller_init(ohci_softc_t *sc) +{ + int i; + u_int32_t s, ctl, ival, hcr, fm, per, desca; + /* Determine in what context we are running. */ ctl = OREAD4(sc, OHCI_CONTROL); if (ctl & OHCI_IR) { @@ -852,8 +892,7 @@ ohci_init(ohci_softc_t *sc) } if (hcr) { printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - err = USBD_IOERROR; - goto bad5; + return (USBD_IOERROR); } #ifdef USB_DEBUG if (ohcidebug > 15) @@ -906,33 +945,7 @@ ohci_init(ohci_softc_t *sc) if (ohcidebug > 5) ohci_dumpregs(sc); #endif - - /* Set up the bus struct. */ - sc->sc_bus.methods = &ohci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); - -#if defined(__NetBSD__) || defined(__OpenBSD__) - sc->sc_control = sc->sc_intre = 0; - sc->sc_powerhook = powerhook_establish(ohci_power, sc); - sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc); -#endif - - usb_callout_init(sc->sc_tmo_rhsc); - return (USBD_NORMAL_COMPLETION); - - bad5: - for (i = 0; i < OHCI_NO_EDS; i++) - ohci_free_sed(sc, sc->sc_eds[i]); - bad4: - ohci_free_sed(sc, sc->sc_isoc_head); - bad3: - ohci_free_sed(sc, sc->sc_ctrl_head); - bad2: - ohci_free_sed(sc, sc->sc_bulk_head); - bad1: - usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - return (err); } usbd_status @@ -1047,10 +1060,10 @@ ohci_power(int why, void *v) sc->sc_bus.use_polling--; } else { sc->sc_bus.use_polling++; - /* Some broken BIOSes do not recover these values */ - OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); - OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); - OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); + + /* Some broken BIOSes never initialize Controller chip */ + ohci_controller_init(sc); + if (sc->sc_intre) OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); |