summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorshiba <shiba@FreeBSD.org>2003-12-22 15:40:10 +0000
committershiba <shiba@FreeBSD.org>2003-12-22 15:40:10 +0000
commit11d4c5569bc85b8e50ead99512307e28af5d893d (patch)
treec4b1bb6425dc7bef4e1369e1abdd79ade12f8503 /sys
parent7fcf777b3211125d10357f00f4f9fa2f728a64c3 (diff)
downloadFreeBSD-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.c79
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));
OpenPOWER on IntegriCloud