summaryrefslogtreecommitdiff
path: root/sys/dev/pci/uhci_pci.c
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2007-03-18 06:08:25 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2007-03-18 06:08:25 +0000
commit112100be1d15b3241b1e8acf05932b12c18880e6 (patch)
tree4ed2b7de8afa2f4ef56b68241325f6763653e45a /sys/dev/pci/uhci_pci.c
parenta4aa20bbe39a4ed79d63cfde14fc8c13f34abe59 (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.
Diffstat (limited to 'sys/dev/pci/uhci_pci.c')
-rw-r--r--sys/dev/pci/uhci_pci.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/sys/dev/pci/uhci_pci.c b/sys/dev/pci/uhci_pci.c
index 2d03e1ab30a..f609b453af9 100644
--- a/sys/dev/pci/uhci_pci.c
+++ b/sys/dev/pci/uhci_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhci_pci.c,v 1.22 2006/08/25 04:17:00 pascoe Exp $ */
+/* $OpenBSD: uhci_pci.c,v 1.23 2007/03/18 06:08:24 pascoe Exp $ */
/* $NetBSD: uhci_pci.c,v 1.24 2002/10/02 16:51:58 thorpej Exp $ */
/*
@@ -59,6 +59,7 @@
int uhci_pci_match(struct device *, void *, void *);
void uhci_pci_attach(struct device *, struct device *, void *);
+void uhci_pci_attach_deferred(struct device *);
int uhci_pci_detach(struct device *, int);
struct uhci_pci_softc {
@@ -97,7 +98,6 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
pci_intr_handle_t ih;
const char *vendor;
char *devname = sc->sc.sc_bus.bdev.dv_xname;
- usbd_status r;
int s;
#if defined(__NetBSD__)
@@ -172,7 +172,32 @@ uhci_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));
+
+ config_defer(self, uhci_pci_attach_deferred);
+
+ /* Ignore interrupts for now */
+ sc->sc.sc_dying = 1;
+
+ splx(s);
+
+ return;
+
+unmap_ret:
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ splx(s);
+}
+
+void
+uhci_pci_attach_deferred(struct device *self)
+{
+ struct uhci_pci_softc *sc = (struct uhci_pci_softc *)self;
+ char *devname = sc->sc.sc_bus.bdev.dv_xname;
+ usbd_status r;
+ int s;
+
+ s = splhardusb();
+ sc->sc.sc_dying = 0;
r = uhci_init(&sc->sc);
if (r != USBD_NORMAL_COMPLETION) {
printf("%s: init failed, error=%d\n", devname, r);