diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/usb.c | 101 |
1 files changed, 61 insertions, 40 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index d15ecf68f2d..15a43b62bcd 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb.c,v 1.94 2014/03/08 11:49:19 mpi Exp $ */ +/* $OpenBSD: usb.c,v 1.95 2014/03/31 16:18:06 mpi Exp $ */ /* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */ /* @@ -92,6 +92,7 @@ struct usb_softc { struct device sc_dev; /* base device */ struct usbd_bus *sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ + int sc_speed; struct usb_task sc_explore_task; @@ -125,6 +126,9 @@ void usb_attach(struct device *, struct device *, void *); int usb_detach(struct device *, int); int usb_activate(struct device *, int); +int usb_attach_roothub(struct usb_softc *); +void usb_detach_roothub(struct usb_softc *); + struct cfdriver usb_cd = { NULL, "usb", DV_DULL }; @@ -147,10 +151,7 @@ void usb_attach(struct device *parent, struct device *self, void *aux) { struct usb_softc *sc = (struct usb_softc *)self; - struct usbd_device *dev; - usbd_status err; int usbrev; - int speed; if (usb_nbuses == 0) { rw_init(&usbpalock, "usbpalock"); @@ -171,13 +172,13 @@ usb_attach(struct device *parent, struct device *self, void *aux) switch (usbrev) { case USBREV_1_0: case USBREV_1_1: - speed = USB_SPEED_FULL; + sc->sc_speed = USB_SPEED_FULL; break; case USBREV_2_0: - speed = USB_SPEED_HIGH; + sc->sc_speed = USB_SPEED_HIGH; break; case USBREV_3_0: - speed = USB_SPEED_SUPER; + sc->sc_speed = USB_SPEED_SUPER; break; default: printf(", not supported\n"); @@ -206,17 +207,10 @@ usb_attach(struct device *parent, struct device *self, void *aux) return; } - err = usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, speed, 0, - &sc->sc_port); - if (!err) { - dev = sc->sc_port.device; - if (dev->hub == NULL) { - sc->sc_bus->dying = 1; - printf("%s: root device is not a hub\n", - sc->sc_dev.dv_xname); - return; - } - sc->sc_bus->root_hub = dev; + + + if (!usb_attach_roothub(sc)) { + struct usbd_device *dev = sc->sc_bus->root_hub; #if 1 /* * Turning this code off will delay attachment of USB devices @@ -226,11 +220,8 @@ usb_attach(struct device *parent, struct device *self, void *aux) if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1)) dev->hub->explore(sc->sc_bus->root_hub); #endif - } else { - printf("%s: root hub problem, error=%d\n", - sc->sc_dev.dv_xname, err); - sc->sc_bus->dying = 1; } + if (cold) sc->sc_bus->use_polling--; @@ -243,6 +234,41 @@ usb_attach(struct device *parent, struct device *self, void *aux) } } +int +usb_attach_roothub(struct usb_softc *sc) +{ + struct usbd_device *dev; + + if (usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, sc->sc_speed, 0, + &sc->sc_port)) { + printf("%s: root hub problem\n", sc->sc_dev.dv_xname); + sc->sc_bus->dying = 1; + return (1); + } + + dev = sc->sc_port.device; + if (dev->hub == NULL) { + printf("%s: root device is not a hub\n", sc->sc_dev.dv_xname); + sc->sc_bus->dying = 1; + return (1); + } + sc->sc_bus->root_hub = dev; + + return (0); +} + +void +usb_detach_roothub(struct usb_softc *sc) +{ + /* Make all devices disconnect. */ + if (sc->sc_port.device != NULL) + usb_disconnect_port(&sc->sc_port, (struct device *)sc); + + usb_rem_wait_task(sc->sc_bus->root_hub, &sc->sc_explore_task); + + sc->sc_bus->root_hub = NULL; +} + void usb_create_task_threads(void *arg) { @@ -866,23 +892,22 @@ int usb_activate(struct device *self, int act) { struct usb_softc *sc = (struct usb_softc *)self; - struct usbd_device *dev = sc->sc_port.device; - int i, rv = 0, r; + int rv = 0; switch (act) { - case DVACT_DEACTIVATE: + case DVACT_QUIESCE: sc->sc_bus->dying = 1; - if (dev != NULL && dev->cdesc != NULL && - dev->subdevs != NULL) { - for (i = 0; dev->subdevs[i]; i++) { - r = config_deactivate(dev->subdevs[i]); - if (r) - rv = r; - } - } + if (sc->sc_bus->root_hub != NULL) + usb_detach_roothub(sc); break; - case DVACT_RESUME: - usb_needs_explore(sc->sc_bus->root_hub, 0); + case DVACT_WAKEUP: + sc->sc_bus->dying = 0; + if (!usb_attach_roothub(sc)) + usb_needs_explore(sc->sc_bus->root_hub, 0); + break; + case DVACT_DEACTIVATE: + rv = config_activate_children(self, act); + sc->sc_bus->dying = 1; break; default: rv = config_activate_children(self, act); @@ -901,11 +926,7 @@ usb_detach(struct device *self, int flags) sc->sc_bus->dying = 1; if (sc->sc_bus->root_hub != NULL) { - /* Make all devices disconnect. */ - if (sc->sc_port.device != NULL) - usb_disconnect_port(&sc->sc_port, self); - - usb_rem_wait_task(sc->sc_bus->root_hub, &sc->sc_explore_task); + usb_detach_roothub(sc); if (--usb_nbuses == 0) { usb_run_tasks = usb_run_abort_tasks = 0; |