summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorHakan Olsson <ho@cvs.openbsd.org>2000-05-24 13:44:19 +0000
committerHakan Olsson <ho@cvs.openbsd.org>2000-05-24 13:44:19 +0000
commitc5ab1f153fd2480c2c69739c17ffd657875cc645 (patch)
treeab0f4c0b66531ce5e9622177ebe00f7f4e4c20d1 /sys/dev
parentfa1f4284b2b2285267bac742e98ded00f28822f3 (diff)
Permit detach of audio devices, such as uaudio. Selected code
from NetBSD/Lennart Augustsson. (niklas@ ok)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/audio.c278
-rw-r--r--sys/dev/audio_if.h7
-rw-r--r--sys/dev/audiovar.h5
-rw-r--r--sys/dev/midi.c8
-rw-r--r--sys/dev/midi_if.h13
-rw-r--r--sys/dev/usb/uaudio.c7
6 files changed, 245 insertions, 73 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index 18db7eb464c..b8c47d0fe95 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: audio.c,v 1.21 2000/04/10 19:49:14 mickey Exp $ */
+/* $OpenBSD: audio.c,v 1.22 2000/05/24 13:44:17 ho Exp $ */
/* $NetBSD: audio.c,v 1.105 1998/09/27 16:43:56 christos Exp $ */
/*
@@ -106,7 +106,7 @@ int audio_blk_ms = AUDIO_BLK_MS;
int audiosetinfo __P((struct audio_softc *, struct audio_info *));
int audiogetinfo __P((struct audio_softc *, struct audio_info *));
-int audio_open __P((dev_t, int, int, struct proc *));
+int audio_open __P((dev_t, struct audio_softc *, int, int, struct proc *));
int audio_close __P((dev_t, int, int, struct proc *));
int audio_read __P((dev_t, struct uio *, int));
int audio_write __P((dev_t, struct uio *, int));
@@ -114,7 +114,7 @@ int audio_ioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
int audio_select __P((dev_t, int, struct proc *));
int audio_mmap __P((dev_t, int, int));
-int mixer_open __P((dev_t, int, int, struct proc *));
+int mixer_open __P((dev_t, struct audio_softc *, int, int, struct proc *));
int mixer_close __P((dev_t, int, int, struct proc *));
int mixer_ioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
static void mixer_remove __P((struct audio_softc *, struct proc *p));
@@ -154,6 +154,8 @@ int audioprobe __P((struct device *, void *, void *));
int audioprobe __P((struct device *, struct cfdata *, void *));
#endif
void audioattach __P((struct device *, struct device *, void *));
+int audiodetach __P((struct device *, int));
+int audioactivate __P((struct device *, enum devact));
struct portname {
char *name;
@@ -193,7 +195,8 @@ struct audio_params audio_default =
{ 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1 };
struct cfattach audio_ca = {
- sizeof(struct audio_softc), audioprobe, audioattach
+ sizeof(struct audio_softc), audioprobe, audioattach,
+ audiodetach, audioactivate
};
struct cfdriver audio_cd = {
@@ -321,6 +324,67 @@ audioattach(parent, self, aux)
}
int
+audioactivate(self, act)
+ struct device *self;
+ enum devact act;
+{
+ struct audio_softc *sc = (struct audio_softc *)self;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ break;
+ }
+ return (0);
+}
+
+int
+audiodetach(self, flags)
+ struct device *self;
+ int flags;
+{
+ struct audio_softc *sc = (struct audio_softc *)self;
+ int maj, mn;
+ int s;
+
+ DPRINTF(("audio_detach: sc=%p flags=%d\n", sc, flags));
+
+ sc->sc_dying = 1;
+
+ wakeup(&sc->sc_wchan);
+ wakeup(&sc->sc_rchan);
+ s = splaudio();
+ if (--sc->sc_refcnt >= 0) {
+ if (tsleep(&sc->sc_refcnt, PZERO, "auddet", hz * 120))
+ printf("audiodetach: %s didn't detach\n",
+ sc->dev.dv_xname);
+ }
+ splx(s);
+
+ /* free resources */
+ audio_free_ring(sc, &sc->sc_pr);
+ audio_free_ring(sc, &sc->sc_rr);
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == audioopen)
+ break;
+
+ /* Nuke the vnodes for any open instances (calls close). */
+ mn = self->dv_unit;
+ vdevgone(maj, mn | SOUND_DEVICE, mn | SOUND_DEVICE, VCHR);
+ vdevgone(maj, mn | AUDIO_DEVICE, mn | AUDIO_DEVICE, VCHR);
+ vdevgone(maj, mn | AUDIOCTL_DEVICE, mn | AUDIOCTL_DEVICE, VCHR);
+ vdevgone(maj, mn | MIXER_DEVICE, mn | MIXER_DEVICE, VCHR);
+
+ return (0);
+}
+
+int
au_portof(sc, name)
struct audio_softc *sc;
char *name;
@@ -391,7 +455,7 @@ au_check_ports(sc, ports, mi, cls, name, mname, tbl)
* Called from hardware driver. This is where the MI audio driver gets
* probed/attached to the hardware driver.
*/
-void
+struct device *
audio_attach_mi(ahwp, hdlp, dev)
struct audio_hw_if *ahwp;
void *hdlp;
@@ -399,12 +463,17 @@ audio_attach_mi(ahwp, hdlp, dev)
{
struct audio_attach_args arg;
- if (ahwp != NULL) {
- arg.type = AUDIODEV_TYPE_AUDIO;
- arg.hwif = ahwp;
- arg.hdl = hdlp;
- (void)config_found(dev, &arg, audioprint);
+#ifdef DIAGNOSTIC
+ if (ahwp == NULL) {
+ printf ("audio_attach_mi: NULL\n");
+ return 0;
}
+#endif
+
+ arg.type = AUDIODEV_TYPE_AUDIO;
+ arg.hwif = ahwp;
+ arg.hdl = hdlp;
+ return config_found(dev, &arg, audioprint);
}
#if NAUDIO > 0
@@ -508,17 +577,39 @@ audioopen(dev, flags, ifmt, p)
int flags, ifmt;
struct proc *p;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc;
+ int error;
+
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
+ if (sc->sc_dying)
+ return (EIO);
+
+ if (!sc->hw_if)
+ return (ENXIO);
+
+ sc->sc_refcnt ++;
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
case AUDIOCTL_DEVICE:
- return (audio_open(dev, flags, ifmt, p));
+ error = audio_open(dev, sc, flags, ifmt, p);
+ break;
case MIXER_DEVICE:
- return (mixer_open(dev, flags, ifmt, p));
+ error = mixer_open(dev, sc, flags, ifmt, p);
+ break;
default:
- return (ENXIO);
+ error = ENXIO;
+ break;
}
+
+ if (--sc->sc_refcnt < 0)
+ wakeup(&sc->sc_refcnt);
+
+ return (error);
}
int
@@ -547,17 +638,35 @@ audioread(dev, uio, ioflag)
struct uio *uio;
int ioflag;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc;
+ int error;
+
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt ++;
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
- return (audio_read(dev, uio, ioflag));
+ error = audio_read(dev, uio, ioflag);
+ break;
case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
- return (ENODEV);
+ error = ENODEV;
+ break;
default:
- return (ENXIO);
+ error = ENXIO;
+ break;
}
+
+ if (--sc->sc_refcnt < 0)
+ wakeup(&sc->sc_refcnt);
+ return (error);
}
int
@@ -566,17 +675,35 @@ audiowrite(dev, uio, ioflag)
struct uio *uio;
int ioflag;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc;
+ int error;
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt ++;
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
- return (audio_write(dev, uio, ioflag));
+ error = audio_write(dev, uio, ioflag);
+ break;
case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
- return (ENODEV);
+ error = ENODEV;
+ break;
default:
- return (ENXIO);
+ error = ENXIO;
+ break;
}
+
+ if (--sc->sc_refcnt < 0)
+ wakeup(&sc->sc_refcnt);
+ return (error);
}
int
@@ -587,17 +714,35 @@ audioioctl(dev, cmd, addr, flag, p)
int flag;
struct proc *p;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc;
+ int error;
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt ++;
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
case AUDIOCTL_DEVICE:
- return (audio_ioctl(dev, cmd, addr, flag, p));
+ error = audio_ioctl(dev, cmd, addr, flag, p);
+ break;
case MIXER_DEVICE:
- return (mixer_ioctl(dev, cmd, addr, flag, p));
+ error = mixer_ioctl(dev, cmd, addr, flag, p);
+ break;
default:
- return (ENXIO);
+ error = ENXIO;
+ break;
}
+
+ if (--sc->sc_refcnt < 0)
+ wakeup(&sc->sc_refcnt);
+ return (error);
}
int
@@ -606,17 +751,35 @@ audioselect(dev, events, p)
int events;
struct proc *p;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc;
+ int error;
+
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
+
+ if (sc->sc_dying)
+ return (EIO);
+ sc->sc_refcnt ++;
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
- return (audio_select(dev, events, p));
+ error = audio_select(dev, events, p);
+ break;
case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
- return (0);
+ error = 0;
+ break;
default:
- return (0);
+ error = 0;
+ break;
}
+
+ if (--sc->sc_refcnt < 0)
+ wakeup(&sc->sc_refcnt);
+ return (error);
}
int
@@ -624,17 +787,35 @@ audiommap(dev, off, prot)
dev_t dev;
int off, prot;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc;
+ int error;
+
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt ++;
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
- return (audio_mmap(dev, off, prot));
+ error = audio_mmap(dev, off, prot);
+ break;
case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
- return -1;
+ error = -1;
+ break;
default:
- return -1;
+ error = -1;
+ break;
}
+
+ if (--sc->sc_refcnt < 0)
+ wakeup(&sc->sc_refcnt);
+ return (error);
}
/*
@@ -774,26 +955,16 @@ audio_wakeup(chan)
}
int
-audio_open(dev, flags, ifmt, p)
+audio_open(dev, sc, flags, ifmt, p)
dev_t dev;
+ struct audio_softc *sc;
int flags, ifmt;
struct proc *p;
{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc;
int error;
int mode;
- struct audio_hw_if *hw;
struct audio_info ai;
- if (unit >= audio_cd.cd_ndevs ||
- (sc = audio_cd.cd_devs[unit]) == NULL)
- return ENXIO;
-
- hw = sc->hw_if;
- if (!hw)
- return ENXIO;
-
DPRINTF(("audio_open: dev=0x%x flags=0x%x sc=%p hdl=%p\n", dev, flags, sc, sc->hw_hdl));
if (ISDEVAUDIOCTL(dev))
@@ -802,7 +973,7 @@ audio_open(dev, flags, ifmt, p)
if ((sc->sc_open & (AUOPEN_READ|AUOPEN_WRITE)) != 0)
return (EBUSY);
- error = hw->open(sc->hw_hdl, flags);
+ error = sc->hw_if->open(sc->hw_hdl, flags);
if (error)
return (error);
@@ -819,7 +990,7 @@ audio_open(dev, flags, ifmt, p)
sc->sc_full_duplex = 0;
/* doesn't always work right on SB.
(flags & (FWRITE|FREAD)) == (FWRITE|FREAD) &&
- (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX);
+ (sc->hw_if->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX);
*/
mode = 0;
@@ -874,7 +1045,7 @@ audio_open(dev, flags, ifmt, p)
return 0;
bad:
- hw->close(sc->hw_hdl);
+ sc->hw_if->close(sc->hw_hdl);
sc->sc_open = 0;
sc->sc_mode = 0;
sc->sc_full_duplex = 0;
@@ -965,6 +1136,8 @@ audio_drain(sc)
* we can't interrupt this sleep, so we set a timeout just in case.
*/
error = audio_sleep_timo(&sc->sc_wchan, "aud_dr", 30*hz);
+ if (sc->sc_dying)
+ error = EIO;
}
splx(s);
return error;
@@ -1071,6 +1244,8 @@ audio_read(dev, uio, ioflag)
return EWOULDBLOCK;
}
error = audio_sleep(&sc->sc_rchan, "aud_hr");
+ if (sc->sc_dying)
+ error = EIO;
if (error) {
splx(s);
return error;
@@ -1102,6 +1277,8 @@ audio_read(dev, uio, ioflag)
}
DPRINTFN(2, ("audio_read: sleep used=%d\n", cb->used));
error = audio_sleep(&sc->sc_rchan, "aud_rd");
+ if (sc->sc_dying)
+ error = EIO;
if (error) {
splx(s);
return error;
@@ -1327,6 +1504,8 @@ audio_write(dev, uio, ioflag)
return (EWOULDBLOCK);
}
error = audio_sleep(&sc->sc_wchan, "aud_wr");
+ if (sc->sc_dying)
+ error = EIO;
if (error) {
splx(s);
return error;
@@ -2710,21 +2889,12 @@ audiogetinfo(sc, ai)
* Mixer driver
*/
int
-mixer_open(dev, flags, ifmt, p)
+mixer_open(dev, sc, flags, ifmt, p)
dev_t dev;
+ struct audio_softc *sc;
int flags, ifmt;
struct proc *p;
{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc;
-
- if (unit >= audio_cd.cd_ndevs ||
- (sc = audio_cd.cd_devs[unit]) == NULL)
- return ENXIO;
-
- if (!sc->hw_if)
- return (ENXIO);
-
DPRINTF(("mixer_open: dev=0x%x flags=0x%x sc=%p\n", dev, flags, sc));
return (0);
diff --git a/sys/dev/audio_if.h b/sys/dev/audio_if.h
index 7d82a7cc252..ba2d5cef311 100644
--- a/sys/dev/audio_if.h
+++ b/sys/dev/audio_if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: audio_if.h,v 1.9 1999/07/23 13:18:04 niklas Exp $ */
+/* $OpenBSD: audio_if.h,v 1.10 2000/05/24 13:44:17 ho Exp $ */
/* $NetBSD: audio_if.h,v 1.24 1998/01/10 14:07:25 tv Exp $ */
/*
@@ -136,8 +136,9 @@ struct audio_attach_args {
#define AUDIODEV_TYPE_MPU 3
/* Attach the MI driver(s) to the MD driver. */
-void audio_attach_mi __P((struct audio_hw_if *, void *, struct device *));
-int audioprint __P((void *, const char *));
+struct device *audio_attach_mi __P((struct audio_hw_if *, void *,
+ struct device *));
+int audioprint __P((void *, const char *));
/* Device identity flags */
#define SOUND_DEVICE 0
diff --git a/sys/dev/audiovar.h b/sys/dev/audiovar.h
index d185a65c4f8..d5a44d2987d 100644
--- a/sys/dev/audiovar.h
+++ b/sys/dev/audiovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: audiovar.h,v 1.7 2000/04/13 00:00:08 csapuntz Exp $ */
+/* $OpenBSD: audiovar.h,v 1.8 2000/05/24 13:44:18 ho Exp $ */
/* $NetBSD: audiovar.h,v 1.18 1998/03/03 09:16:16 augustss Exp $ */
/*
@@ -133,6 +133,9 @@ struct audio_softc {
struct au_mixer_ports sc_inports, sc_outports;
int sc_monitor_port;
+ int sc_refcnt;
+ int sc_dying;
+
#ifdef AUDIO_INTR_TIME
u_long sc_pfirstintr; /* first time we saw a play interrupt */
int sc_pnintr; /* number of interrupts */
diff --git a/sys/dev/midi.c b/sys/dev/midi.c
index c1fdc511dc6..24e690ea4d9 100644
--- a/sys/dev/midi.c
+++ b/sys/dev/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.3 2000/01/03 19:38:13 fgsch Exp $ */
+/* $OpenBSD: midi.c,v 1.4 2000/05/24 13:44:18 ho Exp $ */
/* $NetBSD: midi.c,v 1.10 1998/12/20 14:26:44 drochner Exp $ */
/*
@@ -746,7 +746,7 @@ midi_getinfo(dev, mi)
int midiprint __P((void *, const char *));
-void
+struct device *
midi_attach_mi(mhwp, hdlp, dev)
struct midi_hw_if *mhwp;
void *hdlp;
@@ -757,13 +757,13 @@ midi_attach_mi(mhwp, hdlp, dev)
#ifdef DIAGNOSTIC
if (mhwp == NULL) {
printf("midi_attach_mi: NULL\n");
- return;
+ return 0;
}
#endif
arg.type = AUDIODEV_TYPE_MIDI;
arg.hwif = mhwp;
arg.hdl = hdlp;
- (void)config_found(dev, &arg, midiprint);
+ return config_found(dev, &arg, midiprint);
}
int
diff --git a/sys/dev/midi_if.h b/sys/dev/midi_if.h
index d46aaa217d6..4254df26293 100644
--- a/sys/dev/midi_if.h
+++ b/sys/dev/midi_if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi_if.h,v 1.1 1999/01/02 00:02:37 niklas Exp $ */
+/* $OpenBSD: midi_if.h,v 1.2 2000/05/24 13:44:18 ho Exp $ */
/* $NetBSD: midi_if.h,v 1.3 1998/11/25 22:17:07 augustss Exp $ */
/*
@@ -60,11 +60,12 @@ struct midi_hw_if {
int (*ioctl)__P((void *, u_long, caddr_t, int, struct proc *));
};
-void midi_attach __P((struct midi_softc *, struct device *));
-void midi_attach_mi __P((struct midi_hw_if *, void *, struct device *));
+void midi_attach __P((struct midi_softc *, struct device *));
+struct device *midi_attach_mi __P((struct midi_hw_if *, void *,
+ struct device *));
-int midi_unit_count __P((void));
-void midi_getinfo __P((dev_t, struct midi_info *));
-int midi_writebytes __P((int, u_char *, int));
+int midi_unit_count __P((void));
+void midi_getinfo __P((dev_t, struct midi_info *));
+int midi_writebytes __P((int, u_char *, int));
#endif /* _SYS_DEV_MIDI_IF_H_ */
diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c
index d579aebc15d..c802b22f301 100644
--- a/sys/dev/usb/uaudio.c
+++ b/sys/dev/usb/uaudio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uaudio.c,v 1.4 2000/03/30 16:19:33 aaron Exp $ */
+/* $OpenBSD: uaudio.c,v 1.5 2000/05/24 13:44:18 ho Exp $ */
/* $NetBSD: uaudio.c,v 1.23 2000/03/29 18:24:53 augustss Exp $ */
/*
@@ -388,11 +388,8 @@ USB_ATTACH(uaudio)
sc->sc_chan.sc = sc;
DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
-#if defined(__OpenBSD__)
- audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
-#else
+
sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
-#endif
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
USBDEV(sc->sc_dev));