diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-06-16 01:36:23 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-06-16 01:36:23 +0000 |
commit | 5055b6edf91f37a1af59e70bd25bb5dc4ce1f935 (patch) | |
tree | 4f77fb6347230e352dff6b7c52088086abd968eb /sys/dev/audio.c | |
parent | c5483cc5a8c7783c1799b22fa05aec841b0e7a90 (diff) |
implement kqueue for audio; tested on wiggy and niels@ ok
Diffstat (limited to 'sys/dev/audio.c')
-rw-r--r-- | sys/dev/audio.c | 145 |
1 files changed, 113 insertions, 32 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c index 349b4afc18e..7260653e923 100644 --- a/sys/dev/audio.c +++ b/sys/dev/audio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: audio.c,v 1.38 2002/03/14 01:26:51 millert Exp $ */ +/* $OpenBSD: audio.c,v 1.39 2002/06/16 01:36:22 mickey Exp $ */ /* $NetBSD: audio.c,v 1.105 1998/09/27 16:43:56 christos Exp $ */ /* @@ -137,6 +137,7 @@ void audio_calcwater(struct audio_softc *); static __inline int audio_sleep_timo(int *, char *, int); static __inline int audio_sleep(int *, char *); static __inline void audio_wakeup(int *); +void audio_selwakeup(struct audio_softc *sc, int play); int audio_drain(struct audio_softc *); void audio_clear(struct audio_softc *); static __inline void audio_pint_silence(struct audio_softc *, struct audio_ringbuffer *, u_char *, int); @@ -202,6 +203,18 @@ struct cfdriver audio_cd = { NULL, "audio", DV_DULL }; +void filt_audiowdetach(struct knote *kn); +int filt_audiowrite(struct knote *kn, long hint); + +struct filterops audiowrite_filtops = + { 1, NULL, filt_audiowdetach, filt_audiowrite}; + +void filt_audiordetach(struct knote *kn); +int filt_audioread(struct knote *kn, long hint); + +struct filterops audioread_filtops = + { 1, NULL, filt_audiordetach, filt_audioread}; + int audioprobe(parent, match, aux) struct device *parent; @@ -1780,6 +1793,25 @@ audio_ioctl(dev, cmd, addr, flag, p) return (error); } +void +audio_selwakeup(struct audio_softc *sc, int play) +{ + struct selinfo *si; + + si = play? &sc->sc_wsel : &sc->sc_rsel; + + audio_wakeup(play? &sc->sc_wchan : &sc->sc_rchan); + selwakeup(si); + if (sc->sc_async_audio) + psignal(sc->sc_async_audio, SIGIO); + KNOTE(&si->si_note, 0); +} + +#define AUDIO_FILTREAD(sc) ((sc->sc_mode & AUMODE_PLAY) ? \ + sc->sc_pr.stamp > sc->sc_wstamp : sc->sc_rr.used > sc->sc_rr.usedlow) +#define AUDIO_FILTWRITE(sc) \ + (sc->sc_mode & AUMODE_RECORD || sc->sc_pr.used <= sc->sc_pr.usedlow) + int audio_select(dev, rw, p) dev_t dev; @@ -1788,28 +1820,25 @@ audio_select(dev, rw, p) { int unit = AUDIOUNIT(dev); struct audio_softc *sc = audio_cd.cd_devs[unit]; - int s = splaudio(); + int rv, s = splaudio(); DPRINTF(("audio_select: rw=0x%x mode=%d\n", rw, sc->sc_mode)); switch (rw) { case FREAD: - if ((sc->sc_mode & AUMODE_PLAY) ? - sc->sc_pr.stamp > sc->sc_wstamp : - sc->sc_rr.used > sc->sc_rr.usedlow) { - splx(s); + rv = AUDIO_FILTREAD(sc); + splx(s); + if (rv) return (1); - } selrecord(p, &sc->sc_rsel); break; case FWRITE: - if (sc->sc_mode & AUMODE_RECORD || - sc->sc_pr.used <= sc->sc_pr.usedlow) { - splx(s); + rv = AUDIO_FILTWRITE(sc); + splx(s); + if (rv) return (1); - } selrecord(p, &sc->sc_wsel); break; } @@ -2089,25 +2118,13 @@ audio_pint(v) DPRINTFN(2, ("audio_pint: mode=%d pause=%d used=%d lowat=%d\n", sc->sc_mode, cb->pause, cb->used, cb->usedlow)); - if ((sc->sc_mode & AUMODE_PLAY) && !cb->pause) { - if (cb->used <= cb->usedlow) { - audio_wakeup(&sc->sc_wchan); - selwakeup(&sc->sc_wsel); - if (sc->sc_async_audio) { - DPRINTFN(3, ("audio_pint: sending SIGIO %p\n", - sc->sc_async_audio)); - psignal(sc->sc_async_audio, SIGIO); - } - } - } + if ((sc->sc_mode & AUMODE_PLAY) && !cb->pause && + cb->used <= cb->usedlow) + audio_selwakeup(sc, 1); /* Possible to return one or more "phantom blocks" now. */ - if (!sc->sc_full_duplex && sc->sc_rchan) { - audio_wakeup(&sc->sc_rchan); - selwakeup(&sc->sc_rsel); - if (sc->sc_async_audio) - psignal(sc->sc_async_audio, SIGIO); - } + if (!sc->sc_full_duplex && sc->sc_rchan) + audio_selwakeup(sc, 0); } /* @@ -2197,10 +2214,7 @@ audio_rint(v) } } - audio_wakeup(&sc->sc_rchan); - selwakeup(&sc->sc_rsel); - if (sc->sc_async_audio) - psignal(sc->sc_async_audio, SIGIO); + audio_selwakeup(sc, 0); } int @@ -3029,3 +3043,70 @@ mixer_ioctl(dev, cmd, addr, flag, p) return (error); } #endif + +int +audiokqfilter(dev, kn) + dev_t dev; + struct knote *kn; +{ + int unit = AUDIOUNIT(dev); + struct audio_softc *sc = audio_cd.cd_devs[unit]; + struct klist *klist; + int s; + + switch (kn->kn_filter) { + case EVFILT_READ: + klist = &sc->sc_rsel.si_note; + kn->kn_fop = &audioread_filtops; + break; + case EVFILT_WRITE: + klist = &sc->sc_wsel.si_note; + kn->kn_fop = &audiowrite_filtops; + break; + default: + return (1); + } + kn->kn_hook = (void *)sc; + + s = splaudio(); + SLIST_INSERT_HEAD(klist, kn, kn_selnext); + splx(s); + + return (0); +} + +void +filt_audiordetach(struct knote *kn) +{ + struct audio_softc *sc = (struct audio_softc *)kn->kn_hook; + int s = splaudio(); + + SLIST_REMOVE(&sc->sc_rsel.si_note, kn, knote, kn_selnext); + splx(s); +} + +int +filt_audioread(struct knote *kn, long hint) +{ + struct audio_softc *sc = (struct audio_softc *)kn->kn_hook; + + return AUDIO_FILTREAD(sc); +} + +void +filt_audiowdetach(struct knote *kn) +{ + struct audio_softc *sc = (struct audio_softc *)kn->kn_hook; + int s = splaudio(); + + SLIST_REMOVE(&sc->sc_wsel.si_note, kn, knote, kn_selnext); + splx(s); +} + +int +filt_audiowrite(struct knote *kn, long hint) +{ + struct audio_softc *sc = (struct audio_softc *)kn->kn_hook; + + return AUDIO_FILTWRITE(sc); +} |