summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/usb.c101
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;