Add preliminary (untested) code for detaching the USB host controller
(needed for CardBus based controllers).
This commit is contained in:
parent
f7c22e9eaa
commit
7049e8eb1b
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ohci_pci.c,v 1.12 1999/09/14 01:07:13 augustss Exp $ */
|
||||
/* $NetBSD: ohci_pci.c,v 1.13 1999/09/15 10:25:30 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -67,7 +67,8 @@ int ohci_pci_match __P((struct device *, struct cfdata *, void *));
|
|||
void ohci_pci_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach ohci_pci_ca = {
|
||||
sizeof(struct ohci_softc), ohci_pci_match, ohci_pci_attach
|
||||
sizeof(struct ohci_softc), ohci_pci_match, ohci_pci_attach,
|
||||
ohci_detach, ohci_activate
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -157,5 +158,5 @@ ohci_pci_attach(parent, self, aux)
|
|||
}
|
||||
|
||||
/* Attach usb device. */
|
||||
config_found((void *)sc, &sc->sc_bus, usbctlprint);
|
||||
sc->sc_child = config_found((void *)sc, &sc->sc_bus, usbctlprint);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uhci_pci.c,v 1.10 1999/09/14 09:29:05 augustss Exp $ */
|
||||
/* $NetBSD: uhci_pci.c,v 1.11 1999/09/15 10:25:30 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -60,7 +60,8 @@ int uhci_pci_match __P((struct device *, struct cfdata *, void *));
|
|||
void uhci_pci_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach uhci_pci_ca = {
|
||||
sizeof(uhci_softc_t), uhci_pci_match, uhci_pci_attach
|
||||
sizeof(uhci_softc_t), uhci_pci_match, uhci_pci_attach,
|
||||
uhci_detach, uhci_activate
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -163,5 +164,5 @@ uhci_pci_attach(parent, self, aux)
|
|||
}
|
||||
|
||||
/* Attach usb device. */
|
||||
config_found((void *)sc, &sc->sc_bus, usbctlprint);
|
||||
sc->sc_child = config_found((void *)sc, &sc->sc_bus, usbctlprint);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ohci.c,v 1.46 1999/09/13 21:33:25 augustss Exp $ */
|
||||
/* $NetBSD: ohci.c,v 1.47 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -283,6 +283,45 @@ struct usbd_pipe_methods ohci_device_isoc_methods = {
|
|||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
ohci_activate(self, act)
|
||||
device_ptr_t self;
|
||||
enum devact act;
|
||||
{
|
||||
/*struct ohci_softc *sc = (struct ohci_softc *)self;*/
|
||||
int rv = 0;
|
||||
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
return (EOPNOTSUPP);
|
||||
break;
|
||||
|
||||
case DVACT_DEACTIVATE:
|
||||
break;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int
|
||||
ohci_detach(self, flags)
|
||||
device_ptr_t self;
|
||||
int flags;
|
||||
{
|
||||
struct ohci_softc *sc = (struct ohci_softc *)self;
|
||||
int rv = 0;
|
||||
|
||||
if (sc->sc_child != NULL)
|
||||
rv = config_detach(sc->sc_child, flags);
|
||||
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
powerhook_disestablish(sc->sc_powerhook);
|
||||
/* free data structures XXX */
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
ohci_soft_ed_t *
|
||||
ohci_alloc_sed(sc)
|
||||
ohci_softc_t *sc;
|
||||
|
@ -539,7 +578,7 @@ ohci_init(sc)
|
|||
sc->sc_bus.methods = &ohci_bus_methods;
|
||||
sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
|
||||
|
||||
powerhook_establish(ohci_power, sc);
|
||||
sc->sc_powerhook = powerhook_establish(ohci_power, sc);
|
||||
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ohcivar.h,v 1.9 1999/09/13 19:18:17 augustss Exp $ */
|
||||
/* $NetBSD: ohcivar.h,v 1.10 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -96,10 +96,15 @@ typedef struct ohci_softc {
|
|||
|
||||
char sc_vendor[16];
|
||||
int sc_id_vendor;
|
||||
|
||||
void *sc_powerhook;
|
||||
device_ptr_t sc_child;
|
||||
} ohci_softc_t;
|
||||
|
||||
usbd_status ohci_init __P((ohci_softc_t *));
|
||||
int ohci_intr __P((void *));
|
||||
int ohci_detach __P((device_ptr_t, int));
|
||||
int ohci_activate __P((device_ptr_t, enum devact));
|
||||
|
||||
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uhci.c,v 1.52 1999/09/13 21:33:25 augustss Exp $ */
|
||||
/* $NetBSD: uhci.c,v 1.53 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -407,7 +407,7 @@ uhci_init(sc)
|
|||
sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
|
||||
|
||||
sc->sc_suspend = PWR_RESUME;
|
||||
powerhook_establish(uhci_power, sc);
|
||||
sc->sc_powerhook = powerhook_establish(uhci_power, sc);
|
||||
|
||||
DPRINTFN(1,("uhci_init: enabling\n"));
|
||||
UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
|
||||
|
@ -416,6 +416,45 @@ uhci_init(sc)
|
|||
return (uhci_run(sc, 1)); /* and here we go... */
|
||||
}
|
||||
|
||||
int
|
||||
uhci_activate(self, act)
|
||||
device_ptr_t self;
|
||||
enum devact act;
|
||||
{
|
||||
/*struct uhci_softc *sc = (struct uhci_softc *)self;*/
|
||||
int rv = 0;
|
||||
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
return (EOPNOTSUPP);
|
||||
break;
|
||||
|
||||
case DVACT_DEACTIVATE:
|
||||
break;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int
|
||||
uhci_detach(self, flags)
|
||||
device_ptr_t self;
|
||||
int flags;
|
||||
{
|
||||
struct uhci_softc *sc = (struct uhci_softc *)self;
|
||||
int rv = 0;
|
||||
|
||||
if (sc->sc_child != NULL)
|
||||
rv = config_detach(sc->sc_child, flags);
|
||||
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
powerhook_disestablish(sc->sc_powerhook);
|
||||
/* free data structures XXX */
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
usbd_status
|
||||
uhci_allocm(bus, dma, size)
|
||||
struct usbd_bus *bus;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uhcivar.h,v 1.13 1999/09/13 19:18:17 augustss Exp $ */
|
||||
/* $NetBSD: uhcivar.h,v 1.14 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -166,13 +166,15 @@ typedef struct uhci_softc {
|
|||
|
||||
char sc_vendor[16];
|
||||
int sc_id_vendor;
|
||||
|
||||
void *sc_powerhook;
|
||||
device_ptr_t sc_child;
|
||||
} uhci_softc_t;
|
||||
|
||||
usbd_status uhci_init __P((uhci_softc_t *));
|
||||
int uhci_intr __P((void *));
|
||||
#if 0
|
||||
void uhci_reset __P((void *));
|
||||
#endif
|
||||
int uhci_detach __P((device_ptr_t, int));
|
||||
int uhci_activate __P((device_ptr_t, enum devact));
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
#define DPRINTF(x) if (uhcidebug) printf x
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uhub.c,v 1.28 1999/09/13 19:18:17 augustss Exp $ */
|
||||
/* $NetBSD: uhub.c,v 1.29 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -78,7 +78,6 @@ struct uhub_softc {
|
|||
};
|
||||
|
||||
usbd_status uhub_init_port __P((struct usbd_port *));
|
||||
void uhub_disconnect_port __P((struct usbd_port *up));
|
||||
usbd_status uhub_explore __P((usbd_device_handle hub));
|
||||
void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
|
||||
|
||||
|
@ -377,7 +376,7 @@ uhub_explore(dev)
|
|||
DPRINTF(("uhub_explore: device %d disappeared "
|
||||
"on port %d\n",
|
||||
up->device->address, port));
|
||||
uhub_disconnect_port(up);
|
||||
usb_disconnect_port(up);
|
||||
usbd_clear_port_feature(dev, port,
|
||||
UHF_C_PORT_CONNECTION);
|
||||
}
|
||||
|
@ -432,62 +431,6 @@ uhub_explore(dev)
|
|||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
uhub_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));
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
int
|
||||
uhub_activate(self, act)
|
||||
device_ptr_t self;
|
||||
|
@ -544,7 +487,7 @@ uhub_detach(self, flags)
|
|||
for(p = 0; p < nports; p++) {
|
||||
rup = &dev->hub->ports[p];
|
||||
if (rup->device)
|
||||
uhub_disconnect_port(rup);
|
||||
usb_disconnect_port(rup);
|
||||
}
|
||||
|
||||
free(dev->hub, M_USBDEV);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: usb.c,v 1.21 1999/09/13 21:33:25 augustss Exp $ */
|
||||
/* $NetBSD: usb.c,v 1.22 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -57,6 +57,7 @@
|
|||
#include <sys/uio.h>
|
||||
#include <sys/conf.h>
|
||||
#endif
|
||||
#include <sys/conf.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/select.h>
|
||||
|
@ -90,25 +91,22 @@ int usb_noexplore = 0;
|
|||
#define DPRINTFN(n,x)
|
||||
#endif
|
||||
|
||||
int usb_nbus = 0;
|
||||
|
||||
#define USBUNIT(dev) (minor(dev))
|
||||
|
||||
struct usb_softc {
|
||||
USBBASEDEVICE sc_dev; /* base device */
|
||||
usbd_bus_handle sc_bus; /* USB controller */
|
||||
struct usbd_port sc_port; /* dummy port for root hub */
|
||||
char sc_running;
|
||||
char sc_exploring;
|
||||
char sc_dying;
|
||||
struct selinfo sc_consel; /* waiting for connect change */
|
||||
int shutdown;
|
||||
struct proc *event_thread;
|
||||
struct proc *sc_event_thread;
|
||||
};
|
||||
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
int usbopen __P((dev_t, int, int, struct proc *));
|
||||
int usbclose __P((dev_t, int, int, struct proc *));
|
||||
int usbioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
|
||||
int usbpoll __P((dev_t, int, struct proc *));
|
||||
|
||||
cdev_decl(usb);
|
||||
#elif defined(__FreeBSD__)
|
||||
d_open_t usbopen;
|
||||
d_close_t usbclose;
|
||||
|
@ -156,15 +154,15 @@ USB_ATTACH(usb)
|
|||
usbd_init();
|
||||
sc->sc_bus = aux;
|
||||
sc->sc_bus->usbctl = sc;
|
||||
sc->sc_running = 1;
|
||||
sc->sc_bus->use_polling = 1;
|
||||
sc->sc_port.power = USB_MAX_POWER;
|
||||
r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0,0,0, &sc->sc_port);
|
||||
r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0,0,0,
|
||||
&sc->sc_port);
|
||||
|
||||
if (r == USBD_NORMAL_COMPLETION) {
|
||||
dev = sc->sc_port.device;
|
||||
if (!dev->hub) {
|
||||
sc->sc_running = 0;
|
||||
sc->sc_dying = 1;
|
||||
printf("%s: root device is not a hub\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
|
@ -174,12 +172,13 @@ USB_ATTACH(usb)
|
|||
} else {
|
||||
printf("%s: root hub problem, error=%d\n",
|
||||
USBDEVNAME(sc->sc_dev), r);
|
||||
sc->sc_running = 0;
|
||||
sc->sc_dying = 1;
|
||||
}
|
||||
sc->sc_bus->use_polling = 0;
|
||||
|
||||
kthread_create(usb_create_event_thread, sc);
|
||||
|
||||
usb_nbus++;
|
||||
USB_ATTACH_SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
|
@ -189,7 +188,7 @@ usb_create_event_thread(arg)
|
|||
{
|
||||
struct usb_softc *sc = arg;
|
||||
|
||||
if (kthread_create1(usb_event_thread, sc, &sc->event_thread,
|
||||
if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
|
||||
"%s", sc->sc_dev.dv_xname)) {
|
||||
printf("%s: unable to create event thread for\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
|
@ -203,17 +202,16 @@ usb_event_thread(arg)
|
|||
{
|
||||
struct usb_softc *sc = arg;
|
||||
|
||||
while (!sc->shutdown) {
|
||||
(void)tsleep(&sc->sc_bus->needs_explore,
|
||||
PWAIT, "usbevt", hz*30);
|
||||
while (!sc->sc_dying) {
|
||||
#ifdef USB_DEBUG
|
||||
if (usb_noexplore)
|
||||
continue;
|
||||
if (!usb_noexplore)
|
||||
#endif
|
||||
DPRINTFN(2,("usb_event_thread: woke up\n"));
|
||||
usb_discover(sc);
|
||||
(void)tsleep(&sc->sc_bus->needs_explore,
|
||||
PWAIT, "usbevt", hz*60);
|
||||
DPRINTFN(2,("usb_event_thread: woke up\n"));
|
||||
}
|
||||
sc->event_thread = 0;
|
||||
sc->sc_event_thread = 0;
|
||||
|
||||
/* In case parent is waiting for us to exit. */
|
||||
wakeup(sc);
|
||||
|
@ -243,8 +241,10 @@ usbopen(dev, flag, mode, p)
|
|||
{
|
||||
USB_GET_SC_OPEN(usb, USBUNIT(dev), sc);
|
||||
|
||||
if (sc == 0 || !sc->sc_running)
|
||||
if (sc == 0)
|
||||
return (ENXIO);
|
||||
if (sc->sc_dying)
|
||||
return (EIO);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -268,8 +268,9 @@ usbioctl(dev, cmd, data, flag, p)
|
|||
{
|
||||
USB_GET_SC(usb, USBUNIT(dev), sc);
|
||||
|
||||
if (sc == 0 || !sc->sc_running)
|
||||
return (ENXIO);
|
||||
if (sc->sc_dying)
|
||||
return (EIO);
|
||||
|
||||
switch (cmd) {
|
||||
#ifdef USB_DEBUG
|
||||
case USB_SETDEBUG:
|
||||
|
@ -371,6 +372,9 @@ usbpoll(dev, events, p)
|
|||
int revents, s;
|
||||
USB_GET_SC(usb, USBUNIT(dev), sc);
|
||||
|
||||
if (sc->sc_dying)
|
||||
return (EIO);
|
||||
|
||||
DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events));
|
||||
s = splusb();
|
||||
revents = 0;
|
||||
|
@ -388,36 +392,6 @@ usbpoll(dev, events, p)
|
|||
return (revents);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
usb_bus_count()
|
||||
{
|
||||
int i, n;
|
||||
|
||||
for (i = n = 0; i < usb_cd.cd_ndevs; i++)
|
||||
if (usb_cd.cd_devs[i])
|
||||
n++;
|
||||
return (n);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
usbd_status
|
||||
usb_get_bus_handle(n, h)
|
||||
int n;
|
||||
usbd_bus_handle *h;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < usb_cd.cd_ndevs; i++)
|
||||
if (usb_cd.cd_devs[i] && n-- == 0) {
|
||||
*h = usb_cd.cd_devs[i];
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
return (USBD_INVAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
usbd_status
|
||||
usb_discover(sc)
|
||||
struct usb_softc *sc;
|
||||
|
@ -440,7 +414,7 @@ usb_discover(sc)
|
|||
sc->sc_exploring = 0;
|
||||
wakeup(&sc->sc_exploring);
|
||||
splx(s);
|
||||
} while (sc->sc_bus->needs_explore);
|
||||
} while (sc->sc_bus->needs_explore && !sc->sc_dying);
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
|
||||
|
@ -458,8 +432,19 @@ usb_activate(self, act)
|
|||
device_ptr_t self;
|
||||
enum devact act;
|
||||
{
|
||||
panic("usb_activate\n");
|
||||
return (0);
|
||||
struct usb_softc *sc = (struct usb_softc *)self;
|
||||
int rv = 0;
|
||||
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
return (EOPNOTSUPP);
|
||||
break;
|
||||
|
||||
case DVACT_DEACTIVATE:
|
||||
sc->sc_dying = 1;
|
||||
break;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -467,7 +452,32 @@ usb_detach(self, flags)
|
|||
device_ptr_t self;
|
||||
int flags;
|
||||
{
|
||||
panic("usb_detach\n");
|
||||
struct usb_softc *sc = (struct usb_softc *)self;
|
||||
|
||||
sc->sc_dying = 1;
|
||||
|
||||
/* Make all devices disconnect. */
|
||||
usb_disconnect_port(&sc->sc_port);
|
||||
|
||||
/* Kill off event thread. */
|
||||
if (sc->sc_event_thread) {
|
||||
wakeup(&sc->sc_bus->needs_explore);
|
||||
if (tsleep(sc, PWAIT, "usbdet", hz * 60))
|
||||
printf("%s: event thread didn't die\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
}
|
||||
|
||||
usb_nbus--;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
usbread(dev, uio, flag)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
int flag;
|
||||
{
|
||||
/* XXX */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: usb_subr.c,v 1.46 1999/09/13 19:18:17 augustss Exp $ */
|
||||
/* $NetBSD: usb_subr.c,v 1.47 1999/09/15 10:25:31 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -1169,3 +1169,60 @@ 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));
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: usbdi.c,v 1.40 1999/09/13 21:33:25 augustss Exp $ */
|
||||
/* $NetBSD: usbdi.c,v 1.41 1999/09/15 10:25:32 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -698,11 +698,10 @@ usbd_ar_pipe(pipe)
|
|||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
|
||||
static int usbd_global_init_done = 0;
|
||||
|
||||
void
|
||||
usbd_init()
|
||||
{
|
||||
static int usbd_global_init_done = 0;
|
||||
#if defined(__FreeBSD__)
|
||||
dev_t dev;
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: usbdivar.h,v 1.33 1999/09/13 21:33:25 augustss Exp $ */
|
||||
/* $NetBSD: usbdivar.h,v 1.34 1999/09/15 10:25:32 augustss Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -216,6 +216,7 @@ void usb_free_device __P((usbd_device_handle));
|
|||
|
||||
usbd_status usb_insert_transfer __P((usbd_request_handle reqh));
|
||||
void usb_transfer_complete __P((usbd_request_handle reqh));
|
||||
void usb_disconnect_port __P((struct usbd_port *up));
|
||||
|
||||
/* Routines from usb.c */
|
||||
int usb_bus_count __P((void));
|
||||
|
|
Loading…
Reference in New Issue