diff options
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
-rw-r--r-- | sys/dev/usb/usb_subr.c | 111 |
1 files changed, 83 insertions, 28 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 981663dd903..3d38b7d3bbb 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usb_subr.c,v 1.4 1999/08/27 09:00:30 fgsch Exp $ */ -/* $NetBSD: usb_subr.c,v 1.38 1999/08/17 20:59:04 augustss Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */ +/* $NetBSD: usb_subr.c,v 1.48 1999/09/16 19:20:34 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -51,6 +51,8 @@ #include <sys/proc.h> #include <sys/select.h> +#include <machine/bus.h> + #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -78,14 +80,14 @@ char *usbd_get_string __P((usbd_device_handle, int, char *)); int usbd_getnewaddr __P((usbd_bus_handle bus)); int usbd_print __P((void *aux, const char *pnp)); #if defined(__NetBSD__) -int usbd_submatch __P((bdevice *, struct cfdata *cf, void *)); +int usbd_submatch __P((device_ptr_t, struct cfdata *cf, void *)); #elif defined(__OpenBSD__) -int usbd_submatch __P((bdevice *, void *, void *)); +int usbd_submatch __P((device_ptr_t, void *, void *)); #endif void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno)); void usbd_kill_pipe __P((usbd_pipe_handle)); usbd_status usbd_probe_and_attach - __P((bdevice *parent, usbd_device_handle dev, int port, int addr)); + __P((device_ptr_t parent, usbd_device_handle dev, int port, int addr)); #ifdef USBVERBOSE @@ -106,8 +108,7 @@ struct usb_knowndev { #include <dev/usb/usbdevs_data.h> #endif /* USBVERBOSE */ -#ifdef USB_DEBUG -char *usbd_error_strs[] = { +const char *usbd_error_strs[] = { "NORMAL_COMPLETION", "IN_PROGRESS", "PENDING_REQUESTS", @@ -129,33 +130,23 @@ char *usbd_error_strs[] = { "INTERRUPTED", "XXX", }; -#endif -char * +const char * usbd_errstr(err) usbd_status err; { static char buffer[5]; -#ifdef USB_DEBUG - if ( err < USBD_ERROR_MAX ) { + if (err < USBD_ERROR_MAX) { return usbd_error_strs[err]; } else { #if !defined(__OpenBSD__) snprintf(buffer, sizeof buffer, "%d", err); #else sprintf(buffer, "%d", err); -#endif /* !defined(__OpenBSD__) */ +#endif return buffer; } -#else -#if !defined(__OpenBSD__) - snprintf(buffer, sizeof buffer, "%d", err); -#else - sprintf(buffer, "%d", err); -#endif /* !defined(__OpenBSD__) */ - return buffer; -#endif } usbd_status @@ -612,7 +603,7 @@ usbd_set_config_index(dev, index, msg) selfpowered, cdp->bMaxPower * 2)); #ifdef USB_DEBUG if (!dev->powersrc) { - printf("usbd_set_config_index: No power source?\n"); + DPRINTF(("usbd_set_config_index: No power source?\n")); return (USBD_IOERROR); } #endif @@ -694,7 +685,7 @@ usbd_setup_pipe(dev, iface, ep, pipe) p->running = 0; p->repeat = 0; SIMPLEQ_INIT(&p->queue); - r = dev->bus->open_pipe(p); + r = dev->bus->methods->open_pipe(p); if (r != USBD_NORMAL_COMPLETION) { DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" "%s\n", @@ -734,7 +725,7 @@ usbd_getnewaddr(bus) usbd_status usbd_probe_and_attach(parent, dev, port, addr) - bdevice *parent; + device_ptr_t parent; usbd_device_handle dev; int port; int addr; @@ -742,7 +733,7 @@ usbd_probe_and_attach(parent, dev, port, addr) struct usb_attach_arg uaa; usb_device_descriptor_t *dd = &dev->ddesc; int r, found, i, confi, nifaces; - struct device *dv; + device_ptr_t dv; usbd_interface_handle ifaces[256]; /* 256 is the absolute max */ #if defined(__FreeBSD__) @@ -750,7 +741,7 @@ usbd_probe_and_attach(parent, dev, port, addr) * XXX uaa is a static var. Not a problem as it _should_ be used only * during probe and attach. Should be changed however. */ - bdevice bdev; + device_t bdev; bdev = device_add_child(*parent, NULL, -1, &uaa); if (!bdev) { printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev)); @@ -791,11 +782,11 @@ usbd_probe_and_attach(parent, dev, port, addr) if (r != USBD_NORMAL_COMPLETION) { #ifdef USB_DEBUG DPRINTF(("%s: port %d, set config at addr %d failed, " - "error=%s\n", USBDEVNAME(*parent), port, + "error=%s\n", USBDEVPTRNAME(parent), port, addr, usbd_errstr(r))); #else printf("%s: port %d, set config at addr %d failed\n", - USBDEVNAME(*parent), port, addr); + USBDEVPTRNAME(parent), port, addr); #endif #if defined(__FreeBSD__) device_delete_child(*parent, bdev); @@ -880,7 +871,7 @@ usbd_probe_and_attach(parent, dev, port, addr) */ usbd_status usbd_new_device(parent, bus, depth, lowspeed, port, up) - bdevice *parent; + device_ptr_t parent; usbd_bus_handle bus; int depth; int lowspeed; @@ -1183,3 +1174,67 @@ usb_free_device(dev) free(dev->subdevs, M_USB); free(dev, M_USB); } + +/* + * The general mechanism for detaching drivers works as follows: Each + * driver is responsible for maintaining a reference count on the + * number of outstanding references to its softc (e.g. from + * processing hanging in a read or write). The detach method of the + * driver decrements this counter and flags in the softc that the + * driver is dying and then wakes any sleepers. It then sleeps on the + * softc. Each place that can sleep must maintain the reference + * count. When the reference count drops to -1 (0 is the normal value + * of the reference count) the a wakeup on the softc is performed + * signaling to the detach waiter that all references are gone. + */ + +/* + * Called from process context when we discover that a port has + * been disconnected. + */ +void +usb_disconnect_port(up) + struct usbd_port *up; +{ + usbd_device_handle dev = up->device; + char *hubname; + int i; + + DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n", + up, dev, up->portno)); + +#ifdef DIAGNOSTIC + if (!dev) { + printf("usb_disconnect_port: no device\n"); + return; + } +#endif + + if (!dev->cdesc) { + /* Partially attached device, just drop it. */ + dev->bus->devices[dev->address] = 0; + up->device = 0; + return; + } + + if (dev->subdevs) { + hubname = USBDEVPTRNAME(up->parent->subdevs[0]); + for (i = 0; dev->subdevs[i]; i++) { + printf("%s: at %s port %d (addr %d) disconnected\n", + USBDEVPTRNAME(dev->subdevs[i]), hubname, + up->portno, dev->address); + config_detach(dev->subdevs[i], DETACH_FORCE); + } + } + + dev->bus->devices[dev->address] = 0; + up->device = 0; + usb_free_device(dev); + +#if defined(__FreeBSD__) + device_delete_child( + device_get_parent(((struct softc *)dev->softc)->sc_dev), + ((struct softc *)dev->softc)->sc_dev); +#endif +} + |