diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/cardbus/ohci_cardbus.c | 12 | ||||
-rw-r--r-- | sys/dev/pci/ohci_pci.c | 33 | ||||
-rw-r--r-- | sys/dev/pci/uhci_pci.c | 29 | ||||
-rw-r--r-- | sys/dev/usb/ohci.c | 72 | ||||
-rw-r--r-- | sys/dev/usb/ohcivar.h | 4 |
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); |