summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/cardbus/ohci_cardbus.c12
-rw-r--r--sys/dev/pci/ohci_pci.c33
-rw-r--r--sys/dev/pci/uhci_pci.c29
-rw-r--r--sys/dev/usb/ohci.c72
-rw-r--r--sys/dev/usb/ohcivar.h4
5 files changed, 118 insertions, 32 deletions
diff --git a/sys/dev/cardbus/ohci_cardbus.c b/sys/dev/cardbus/ohci_cardbus.c
index 5df15b2f135..857fea72a90 100644
--- a/sys/dev/cardbus/ohci_cardbus.c
+++ b/sys/dev/cardbus/ohci_cardbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci_cardbus.c,v 1.8 2006/10/12 16:35:52 grange Exp $ */
+/* $OpenBSD: ohci_cardbus.c,v 1.9 2007/03/22 05:53:36 pascoe Exp $ */
/* $NetBSD: ohci_cardbus.c,v 1.19 2004/08/02 19:14:28 mycroft Exp $ */
/*
@@ -159,7 +159,15 @@ ohci_cardbus_attach(struct device *parent, struct device *self, void *aux)
else
snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
"vendor 0x%04x", CARDBUS_VENDOR(ca->ca_id));
-
+
+ /* Display revision and perform legacy emulation handover. */
+ if (ohci_checkrev(&sc->sc) != USBD_NORMAL_COMPLETION ||
+ ohci_handover(&sc->sc) != USBD_NORMAL_COMPLETION) {
+ cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih);
+ sc->sc_ih = 0;
+ return;
+ }
+
r = ohci_init(&sc->sc);
if (r != USBD_NORMAL_COMPLETION) {
printf("%s: init failed, error=%d\n", devname, r);
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) {
diff --git a/sys/dev/pci/uhci_pci.c b/sys/dev/pci/uhci_pci.c
index 7cdbc61add9..859be8ef5c8 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.24 2007/03/18 20:14:51 mglocker Exp $ */
+/* $OpenBSD: uhci_pci.c,v 1.25 2007/03/22 05:53:36 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);
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 122a67ee846..20daeffb8d5 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.75 2007/03/18 20:14:51 mglocker Exp $ */
+/* $OpenBSD: ohci.c,v 1.76 2007/03/22 05:53:36 pascoe Exp $ */
/* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */
@@ -611,14 +611,10 @@ ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
}
usbd_status
-ohci_init(ohci_softc_t *sc)
+ohci_checkrev(ohci_softc_t *sc)
{
- ohci_soft_ed_t *sed, *psed;
- usbd_status err;
- int i;
- u_int32_t s, ctl, rwc, ival, hcr, fm, per, rev, desca, descb;
+ u_int32_t rev;
- DPRINTF(("ohci_init: start\n"));
printf(",");
rev = OREAD4(sc, OHCI_REVISION);
printf(" version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
@@ -632,6 +628,48 @@ ohci_init(ohci_softc_t *sc)
}
sc->sc_bus.usbrev = USBREV_1_0;
+ return (USBD_NORMAL_COMPLETION);
+}
+
+usbd_status
+ohci_handover(ohci_softc_t *sc)
+{
+ u_int32_t s, ctl;
+ int i;
+
+ ctl = OREAD4(sc, OHCI_CONTROL);
+ if (ctl & OHCI_IR) {
+ /* SMM active, request change */
+ DPRINTF(("ohci_handover: SMM active, request owner change\n"));
+ if ((sc->sc_intre & (OHCI_OC | OHCI_MIE)) ==
+ (OHCI_OC | OHCI_MIE))
+ OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_MIE);
+ s = OREAD4(sc, OHCI_COMMAND_STATUS);
+ OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR);
+ for (i = 0; i < 100 && (ctl & OHCI_IR); i++) {
+ usb_delay_ms(&sc->sc_bus, 1);
+ ctl = OREAD4(sc, OHCI_CONTROL);
+ }
+ OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_MIE);
+ if (ctl & OHCI_IR) {
+ printf("%s: SMM does not respond, will reset\n",
+ USBDEVNAME(sc->sc_bus.bdev));
+ }
+ }
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
+usbd_status
+ohci_init(ohci_softc_t *sc)
+{
+ ohci_soft_ed_t *sed, *psed;
+ usbd_status err;
+ int i;
+ u_int32_t ctl, rwc, ival, hcr, fm, per, desca, descb;
+
+ DPRINTF(("ohci_init: start\n"));
+
for (i = 0; i < OHCI_HASH_SIZE; i++)
LIST_INIT(&sc->sc_hash_tds[i]);
for (i = 0; i < OHCI_HASH_SIZE; i++)
@@ -720,24 +758,8 @@ ohci_init(ohci_softc_t *sc)
/* Determine in what context we are running. */
if (ctl & OHCI_IR) {
- /* SMM active, request change */
- DPRINTF(("ohci_init: SMM active, request owner change\n"));
- if ((sc->sc_intre & (OHCI_OC | OHCI_MIE)) ==
- (OHCI_OC | OHCI_MIE))
- OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_MIE);
- s = OREAD4(sc, OHCI_COMMAND_STATUS);
- OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR);
- for (i = 0; i < 100 && (ctl & OHCI_IR); i++) {
- usb_delay_ms(&sc->sc_bus, 1);
- ctl = OREAD4(sc, OHCI_CONTROL);
- }
- OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_MIE);
- if (ctl & OHCI_IR) {
- printf("%s: SMM does not respond, resetting\n",
- USBDEVNAME(sc->sc_bus.bdev));
- OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc);
- goto reset;
- }
+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc);
+ goto reset;
#if 0
/* Don't bother trying to reuse the BIOS init, we'll reset it anyway. */
} else if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_RESET) {
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index 8750962a44e..fa9ce3e21c7 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohcivar.h,v 1.21 2006/05/22 15:52:48 krw Exp $ */
+/* $OpenBSD: ohcivar.h,v 1.22 2007/03/22 05:53:36 pascoe Exp $ */
/* $NetBSD: ohcivar.h,v 1.32 2003/02/22 05:24:17 tsutsui Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.13 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -147,6 +147,8 @@ struct ohci_xfer {
struct usb_task abort_task;
};
+usbd_status ohci_checkrev(ohci_softc_t *);
+usbd_status ohci_handover(ohci_softc_t *);
usbd_status ohci_init(ohci_softc_t *);
int ohci_intr(void *);
int ohci_detach(ohci_softc_t *, int);