diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2000-05-24 13:44:19 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2000-05-24 13:44:19 +0000 |
commit | c5ab1f153fd2480c2c69739c17ffd657875cc645 (patch) | |
tree | ab0f4c0b66531ce5e9622177ebe00f7f4e4c20d1 /sys/dev | |
parent | fa1f4284b2b2285267bac742e98ded00f28822f3 (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.c | 278 | ||||
-rw-r--r-- | sys/dev/audio_if.h | 7 | ||||
-rw-r--r-- | sys/dev/audiovar.h | 5 | ||||
-rw-r--r-- | sys/dev/midi.c | 8 | ||||
-rw-r--r-- | sys/dev/midi_if.h | 13 | ||||
-rw-r--r-- | sys/dev/usb/uaudio.c | 7 |
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)); |