diff options
author | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2007-03-22 05:53:37 +0000 |
---|---|---|
committer | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2007-03-22 05:53:37 +0000 |
commit | 11e40ec323edd0c00a1fb92e5027889d05c29bde (patch) | |
tree | 3e3e4e0a3151a2e5b771c20eb649fe4174eaab1a /sys/dev/pci/ohci_pci.c | |
parent | 55c7994211c29cfec508c44539391d806e41e8ee (diff) |
Perform legacy emulation handover for USB1 companion controllers immediately
but defer the remainder of their initialisation until after the other devices
on their PCI bus have attached. This ensures that any USB2 controller has also
completed its initialisation before we start to initialise the USB1 parts.
This minimises the chance that a nasty SMM implementation will trash the USB1
controller's config when it performs legacy emulation handover of the USB2 part.
This time without accidentally leaving the OHCI controller shutdown, and with
some cosmetic fixes.
ok dlg@, OHCI tests mglocker@
Diffstat (limited to 'sys/dev/pci/ohci_pci.c')
-rw-r--r-- | sys/dev/pci/ohci_pci.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/sys/dev/pci/ohci_pci.c b/sys/dev/pci/ohci_pci.c index 9b435a1b80f..0e0e716cf35 100644 --- a/sys/dev/pci/ohci_pci.c +++ b/sys/dev/pci/ohci_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ohci_pci.c,v 1.31 2007/03/18 20:14:51 mglocker Exp $ */ +/* $OpenBSD: ohci_pci.c,v 1.32 2007/03/22 05:53:36 pascoe Exp $ */ /* $NetBSD: ohci_pci.c,v 1.23 2002/10/02 16:51:47 thorpej Exp $ */ /* @@ -66,6 +66,7 @@ int ohci_pci_match(struct device *, void *, void *); void ohci_pci_attach(struct device *, struct device *, void *); +void ohci_pci_attach_deferred(struct device *); int ohci_pci_detach(struct device *, int); struct ohci_pci_softc { @@ -100,7 +101,6 @@ ohci_pci_attach(struct device *parent, struct device *self, void *aux) pci_chipset_tag_t pc = pa->pa_pc; char const *intrstr; pci_intr_handle_t ih; - usbd_status r; int s; const char *vendor; char *devname = sc->sc.sc_bus.bdev.dv_xname; @@ -158,6 +158,35 @@ ohci_pci_attach(struct device *parent, struct device *self, void *aux) else snprintf(sc->sc.sc_vendor, sizeof (sc->sc.sc_vendor), "vendor 0x%04x", PCI_VENDOR(pa->pa_id)); + + /* Display revision and perform legacy emulation handover. */ + if (ohci_checkrev(&sc->sc) != USBD_NORMAL_COMPLETION || + ohci_handover(&sc->sc) != USBD_NORMAL_COMPLETION) { + bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); + splx(s); + return; + } + + /* Ignore interrupts for now */ + sc->sc.sc_dying = 1; + + config_defer(self, ohci_pci_attach_deferred); + + splx(s); + + return; +} + +void +ohci_pci_attach_deferred(struct device *self) +{ + struct ohci_pci_softc *sc = (struct ohci_pci_softc *)self; + usbd_status r; + int s; + + s = splusb(); + + sc->sc.sc_dying = 0; r = ohci_init(&sc->sc); if (r != USBD_NORMAL_COMPLETION) { |