Index: src/sys/dev/audio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/audio.c,v
retrieving revision 1.288
diff -u -r1.288 audio.c
--- src/sys/dev/audio.c 28 Dec 2016 02:44:59 -0000      1.288
+++ src/sys/dev/audio.c 28 Dec 2016 02:50:48 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.288 2016/12/28 02:44:59 nat Exp $  */
+/*     $NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $  */

/*-
 * Copyright (c) 2016 Nathanial Sloss <[email protected]>
@@ -148,7 +148,7 @@
 */

#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.288 2016/12/28 02:44:59 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $");

#include "audio.h"
#if NAUDIO > 0
@@ -157,6 +157,8 @@
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
#include <sys/vnode.h>
#include <sys/select.h>
#include <sys/poll.h>
@@ -206,19 +208,20 @@
int    audiosetinfo(struct audio_softc *, struct audio_info *, bool, int);
int    audiogetinfo(struct audio_softc *, struct audio_info *, int, int);

-int    audio_open(dev_t, struct audio_softc *, int, int, struct lwp *);
-int    audio_close(struct audio_softc *, int, int, struct lwp *, int);
-int    audio_read(struct audio_softc *, struct uio *, int);
-int    audio_write(struct audio_softc *, struct uio *, int);
-int    audio_ioctl(dev_t, struct audio_softc *, u_long, void *, int,
-                   struct lwp *);
-int    audio_poll(struct audio_softc *, int, struct lwp *);
+int    audio_open(dev_t, struct audio_softc *, int, int, struct lwp *,
+                  struct file **);
+int    audio_close(struct audio_softc *, int, int);
+int    audio_read(struct audio_softc *, struct uio *, int, int);
+int    audio_write(struct audio_softc *, struct uio *, int, int);
+int    audio_ioctl(dev_t, struct audio_softc *, u_long, void *, int, int);
+int    audio_poll(struct audio_softc *, int, int);
int    audio_kqfilter(struct audio_softc *, struct knote *);
paddr_t        audio_mmap(struct audio_softc *, off_t, int);

-int    mixer_open(dev_t, struct audio_softc *, int, int, struct lwp *);
-int    mixer_close(struct audio_softc *, int, int, struct lwp *);
-int    mixer_ioctl(struct audio_softc *, u_long, void *, int, struct lwp *);
+int    mixer_open(dev_t, struct audio_softc *, int, int, struct lwp *,
+                  struct file **);
+int    mixer_close(struct audio_softc *, int, int);
+int    mixer_ioctl(struct audio_softc *, u_long, void *, int);
static void mixer_remove(struct audio_softc *);
static void mixer_signal(struct audio_softc *);

@@ -321,6 +324,15 @@
static void    audio_exit(struct audio_softc *);
static int     audio_waitio(struct audio_softc *, kcondvar_t *);

+int audioclose(struct file *);
+int audioread(struct file *, off_t *, struct uio *, kauth_cred_t, int);
+int audiowrite(struct file *, off_t *, struct uio *, kauth_cred_t, int);
+int audioioctl(struct file *, u_long, void *);
+int audiopoll(struct file *, int);
+int audiokqfilter(struct file *, struct knote *);
+
+int audiobellopen(dev_t, int, int, struct lwp *, struct file **);
+
#define AUDIO_OUTPUT_CLASS 0
#define AUDIO_INPUT_CLASS 1

@@ -380,29 +392,34 @@
                                     audio_stream_t *, int);

dev_type_open(audioopen);
-dev_type_close(audioclose);
-dev_type_read(audioread);
-dev_type_write(audiowrite);
-dev_type_ioctl(audioioctl);
-dev_type_poll(audiopoll);
dev_type_mmap(audiommap);
-dev_type_kqfilter(audiokqfilter);

const struct cdevsw audio_cdevsw = {
       .d_open = audioopen,
-       .d_close = audioclose,
-       .d_read = audioread,
-       .d_write = audiowrite,
-       .d_ioctl = audioioctl,
+       .d_close = noclose,
+       .d_read = noread,
+       .d_write = nowrite,
+       .d_ioctl = noioctl,
       .d_stop = nostop,
       .d_tty = notty,
-       .d_poll = audiopoll,
+       .d_poll = nopoll,
       .d_mmap = audiommap,
-       .d_kqfilter = audiokqfilter,
+       .d_kqfilter = nokqfilter,
       .d_discard = nodiscard,
       .d_flag = D_MCLOSE | D_MPSAFE
};

+const struct fileops audio_fileops = {
+       .fo_read = audioread,
+       .fo_write = audiowrite,
+       .fo_ioctl = audioioctl,
+       .fo_fcntl = fnullop_fcntl,
+       .fo_poll = audiopoll,
+       .fo_close = audioclose,
+       .fo_kqfilter = audiokqfilter,
+       .fo_restart = fnullop_restart
+};
+
/* The default audio mode: 8 kHz mono mu-law */
const struct audio_params audio_default = {
       .sample_rate = 8000,
@@ -923,7 +940,8 @@

       /* free resources */
       for (n = 0; n < VAUDIOCHANS; n++) {
-               if (n != 0 && sc->sc_audiopid[n].pid == -1)
+               if (n != 0 && (sc->sc_audiopid[n].pid == -1 ||
+                   sc->sc_audiopid[n].pid == -2))
                       continue;
               audio_free_ring(sc, &sc->sc_vchan[n]->sc_mpr);
               audio_free_ring(sc, &sc->sc_vchan[n]->sc_mrr);
@@ -931,7 +949,8 @@
       audio_free_ring(sc, &sc->sc_pr);
       audio_free_ring(sc, &sc->sc_rr);
       for (n = 0; n < VAUDIOCHANS; n++) {
-               if (n != 0 && sc->sc_audiopid[n].pid == -1)
+               if (n != 0 && (sc->sc_audiopid[n].pid == -1 ||
+                   sc->sc_audiopid[n].pid == -2))
                       continue;
               for (i = 0; i < sc->sc_vchan[n]->sc_npfilters; i++) {
                       sc->sc_vchan[n]->sc_pfilters[i]->dtor
@@ -1089,15 +1108,7 @@
void
audio_printsc(struct audio_softc *sc)
{
-       int n;
-
-       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
-
-       if (n == VAUDIOCHANS)
-               return;
+       int n = 0;

       printf("hwhandle %p hw_if %p ", sc->hw_hdl, sc->hw_if);
       printf("open 0x%x mode 0x%x\n", sc->sc_vchan[n]->sc_open,
@@ -1474,9 +1485,37 @@
}

int
+audiobellopen(dev_t dev, int flags, int ifmt, struct lwp *l, struct file **fp)
+{
+       struct audio_softc *sc;
+       int error;
+
+       if ((error = audio_enter(dev, RW_WRITER, &sc)) != 0)
+               return error;
+       device_active(sc->dev, DVA_SYSTEM);
+       switch (AUDIODEV(dev)) {
+       case SOUND_DEVICE:
+       case AUDIO_DEVICE:
+       case AUDIOCTL_DEVICE:
+               error = audio_open(dev, sc, flags, ifmt, l, fp);
+               break;
+       case MIXER_DEVICE:
+               error = mixer_open(dev, sc, flags, ifmt, l, fp);
+               break;
+       default:
+               error = ENXIO;
+               break;
+       }
+       audio_exit(sc);
+
+       return error;
+}
+
+int
audioopen(dev_t dev, int flags, int ifmt, struct lwp *l)
{
       struct audio_softc *sc;
+       struct file *fp;
       int error;

       if ((error = audio_enter(dev, RW_WRITER, &sc)) != 0)
@@ -1486,10 +1525,10 @@
       case SOUND_DEVICE:
       case AUDIO_DEVICE:
       case AUDIOCTL_DEVICE:
-               error = audio_open(dev, sc, flags, ifmt, l);
+               error = audio_open(dev, sc, flags, ifmt, l, &fp);
               break;
       case MIXER_DEVICE:
-               error = mixer_open(dev, sc, flags, ifmt, l);
+               error = mixer_open(dev, sc, flags, ifmt, l, &fp);
               break;
       default:
               error = ENXIO;
@@ -1501,30 +1540,29 @@
}

int
-audioclose(dev_t dev, int flags, int ifmt, struct lwp *l)
+audioclose(struct file *fp)
{
       struct audio_softc *sc;
       int error, n;
+       dev_t dev;
+
+       dev = fp->f_audioctx->dev;

       if ((error = audio_enter(dev, RW_WRITER, &sc)) != 0)
               return error;
+       for (n = 1; n < VAUDIOCHANS; n++) {
+               if (fp->f_audioctx == &sc->sc_audiopid[n])
+                       break;
+       }
       device_active(sc->dev, DVA_SYSTEM);
       switch (AUDIODEV(dev)) {
       case SOUND_DEVICE:
       case AUDIO_DEVICE:
       case AUDIOCTL_DEVICE:
-               for (n = 1; n < VAUDIOCHANS; n++) {
-                       if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                               break;
-               }
-               if (n == VAUDIOCHANS) {
-                       error = EIO;
-                       break;
-               }
-               error = audio_close(sc, flags, ifmt, l, n);
+               error = audio_close(sc, fp->f_flag, n);
               break;
       case MIXER_DEVICE:
-               error = mixer_close(sc, flags, ifmt, l);
+               error = mixer_close(sc, fp->f_flag, n);
               break;
       default:
               error = ENXIO;
@@ -1536,17 +1574,25 @@
}

int
-audioread(dev_t dev, struct uio *uio, int ioflag)
+audioread(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
+         int ioflag)
{
       struct audio_softc *sc;
-       int error;
+       int error, n;
+       dev_t dev;
+
+       dev = fp->f_audioctx->dev;

       if ((error = audio_enter(dev, RW_READER, &sc)) != 0)
               return error;
+       for (n = 1; n < VAUDIOCHANS; n++) {
+               if (fp->f_audioctx == &sc->sc_audiopid[n])
+                       break;
+       }
       switch (AUDIODEV(dev)) {
       case SOUND_DEVICE:
       case AUDIO_DEVICE:
-               error = audio_read(sc, uio, ioflag);
+               error = audio_read(sc, uio, ioflag, n);
               break;
       case AUDIOCTL_DEVICE:
       case MIXER_DEVICE:
@@ -1562,17 +1608,26 @@
}

int
-audiowrite(dev_t dev, struct uio *uio, int ioflag)
+audiowrite(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
+          int ioflag)
{
       struct audio_softc *sc;
-       int error;
+       int error, n;
+       dev_t dev;
+
+       dev = fp->f_audioctx->dev;

       if ((error = audio_enter(dev, RW_READER, &sc)) != 0)
               return error;
+
+       for (n = 1; n < VAUDIOCHANS; n++) {
+               if (fp->f_audioctx == &sc->sc_audiopid[n])
+                       break;
+       }
       switch (AUDIODEV(dev)) {
       case SOUND_DEVICE:
       case AUDIO_DEVICE:
-               error = audio_write(sc, uio, ioflag);
+               error = audio_write(sc, uio, ioflag, n);
               break;
       case AUDIOCTL_DEVICE:
       case MIXER_DEVICE:
@@ -1588,11 +1643,14 @@
}

int
-audioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
+audioioctl(struct file *fp, u_long cmd, void *addr)
{
       struct audio_softc *sc;
-       int error;
+       int error, n;
       krw_t rw;
+       dev_t dev;
+
+       dev = fp->f_audioctx->dev;

       /* Figure out which lock type we need. */
       switch (cmd) {
@@ -1609,18 +1667,23 @@

       if ((error = audio_enter(dev, rw, &sc)) != 0)
               return error;
+
+       for (n = 1; n < VAUDIOCHANS; n++) {
+               if (fp->f_audioctx == &sc->sc_audiopid[n])
+                       break;
+       }
       switch (AUDIODEV(dev)) {
       case SOUND_DEVICE:
       case AUDIO_DEVICE:
       case AUDIOCTL_DEVICE:
               device_active(sc->dev, DVA_SYSTEM);
               if (IOCGROUP(cmd) == IOCGROUP(AUDIO_MIXER_READ))
-                       error = mixer_ioctl(sc, cmd, addr, flag, l);
+                       error = mixer_ioctl(sc, cmd, addr, fp->f_flag);
               else
-                       error = audio_ioctl(dev, sc, cmd, addr, flag, l);
+                       error = audio_ioctl(dev, sc, cmd, addr, fp->f_flag, n);
               break;
       case MIXER_DEVICE:
-               error = mixer_ioctl(sc, cmd, addr, flag, l);
+               error = mixer_ioctl(sc, cmd, addr, fp->f_flag);
               break;
       default:
               error = ENXIO;
@@ -1632,10 +1695,13 @@
}

int
-audiopoll(dev_t dev, int events, struct lwp *l)
+audiopoll(struct file *fp, int events)
{
       struct audio_softc *sc;
-       int revents;
+       int n, revents;
+       dev_t dev;
+
+       dev = fp->f_audioctx->dev;

       /* Don't bother with device level lock here. */
       sc = device_lookup_private(&audio_cd, AUDIOUNIT(dev));
@@ -1646,10 +1712,14 @@
               mutex_exit(sc->sc_lock);
               return EIO;
       }
+       for (n = 1; n < VAUDIOCHANS; n++) {
+               if (fp->f_audioctx == &sc->sc_audiopid[n])
+                       break;
+       }
       switch (AUDIODEV(dev)) {
       case SOUND_DEVICE:
       case AUDIO_DEVICE:
-               revents = audio_poll(sc, events, l);
+               revents = audio_poll(sc, events, n);
               break;
       case AUDIOCTL_DEVICE:
       case MIXER_DEVICE:
@@ -1665,10 +1735,13 @@
}

int
-audiokqfilter(dev_t dev, struct knote *kn)
+audiokqfilter(struct file *fp, struct knote *kn)
{
       struct audio_softc *sc;
       int rv;
+       dev_t dev;
+
+       dev = fp->f_audioctx->dev;

       /* Don't bother with device level lock here. */
       sc = device_lookup_private(&audio_cd, AUDIOUNIT(dev));
@@ -1702,6 +1775,8 @@
       struct audio_softc *sc;
       paddr_t error;

+       return -1;
+
       /*
        * Acquire a reader lock.  audio_mmap() will drop sc_lock
        * in order to allow the device's mmap routine to sleep.
@@ -1861,8 +1936,10 @@

int
audio_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
-    struct lwp *l)
+    struct lwp *l, struct file **nfp)
{
+       struct file *fp;
+       int fd;
       int error, i, n;
       u_int mode;
       const struct audio_hw_if *hw;
@@ -1874,13 +1951,6 @@
               return ENXIO;

       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
-       if (n < VAUDIOCHANS)
-               return ENXIO;
-
-       for (n = 1; n < VAUDIOCHANS; n++) {
               if (sc->sc_audiopid[n].pid == -1)
                       break;
       }
@@ -1891,6 +1961,10 @@
       if (hw == NULL)
               return ENXIO;

+       error = fd_allocfile(&fp, &fd);
+       if (error)
+               return error;
+
       sc->sc_vchan[n] = kmem_zalloc(sizeof(struct virtual_channel), KM_SLEEP);
       vc = sc->sc_vchan[n];

@@ -2014,7 +2088,12 @@
       sc->sc_nmixer_states += 2;
       mutex_exit(sc->sc_intr_lock);

-       return 0;
+       sc->sc_audiopid[n].dev = dev;
+       error = fd_clone(fp, fd, flags, &audio_fileops, &sc->sc_audiopid[n]);
+       KASSERT(error == EMOVEFD);
+
+       *nfp = fp;
+       return error;

bad:
       for (i = 0; i < vc->sc_npfilters; i++) {
@@ -2168,8 +2247,7 @@
 */
/* ARGSUSED */
int
-audio_close(struct audio_softc *sc, int flags, int ifmt,
-    struct lwp *l, int n)
+audio_close(struct audio_softc *sc, int flags, int n)
{
       struct virtual_channel *vc;
       const struct audio_hw_if *hw;
@@ -2260,20 +2338,16 @@
}

int
-audio_read(struct audio_softc *sc, struct uio *uio, int ioflag)
+audio_read(struct audio_softc *sc, struct uio *uio, int ioflag, int m)
{
       struct audio_ringbuffer *cb;
       struct virtual_channel *vc;
       const uint8_t *outp;
       uint8_t *inp;
-       int error, used, cc, n, m;
+       int error, used, cc, n;

       KASSERT(mutex_owned(sc->sc_lock));

-       for (m = 1; m < VAUDIOCHANS; m++) {
-               if (sc->sc_audiopid[m].pid == curproc->p_pid)
-                       break;
-       }
       if (m == VAUDIOCHANS)
               return EINVAL;

@@ -2590,7 +2664,7 @@
}

int
-audio_write(struct audio_softc *sc, struct uio *uio, int ioflag)
+audio_write(struct audio_softc *sc, struct uio *uio, int ioflag, int n)
{
       uio_fetcher_t ufetcher;
       audio_stream_t stream;
@@ -2599,14 +2673,10 @@
       stream_fetcher_t *fetcher;
       stream_filter_t *filter;
       uint8_t *inp, *einp;
-       int saveerror, error, n, m, cc, used;
+       int saveerror, error, m, cc, used;

       KASSERT(mutex_owned(sc->sc_lock));

-       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
       if (n == VAUDIOCHANS)
               return EINVAL;

@@ -2757,20 +2827,16 @@

int
audio_ioctl(dev_t dev, struct audio_softc *sc, u_long cmd, void *addr, int flag,
-           struct lwp *l)
+           int n)
{
       const struct audio_hw_if *hw;
       struct virtual_channel *vc;
       struct audio_offset *ao;
       u_long stamp;
-       int error, offs, fd, m, n;
+       int error, offs, fd, m;
       bool rbus, pbus;

       KASSERT(mutex_owned(sc->sc_lock));
-       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
       m = n;
       for (n = 1; n < VAUDIOCHANS; n++) {
               if (sc->sc_despid[m].pid >= 0 && sc->sc_audiopid[n].pid ==
@@ -2960,7 +3026,8 @@

       default:
               if (hw->dev_ioctl) {
-                       error = hw->dev_ioctl(sc->hw_hdl, cmd, addr, flag, l);
+                       error = hw->dev_ioctl(sc->hw_hdl, cmd, addr, flag,
+                           curlwp);
               } else {
                       DPRINTF(("audio_ioctl: unknown ioctl\n"));
                       error = EINVAL;
@@ -2973,17 +3040,13 @@
}

int
-audio_poll(struct audio_softc *sc, int events, struct lwp *l)
+audio_poll(struct audio_softc *sc, int events, int n)
{
       struct virtual_channel *vc;
       int revents;
-       int used, n;
+       int used;

       KASSERT(mutex_owned(sc->sc_lock));
-       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
       if (n == VAUDIOCHANS)
               return ENXIO;
       vc = sc->sc_vchan[n];
@@ -3022,10 +3085,10 @@

       if (revents == 0) {
               if (events & (POLLIN | POLLRDNORM))
-                       selrecord(l, &sc->sc_rsel);
+                       selrecord(curlwp, &sc->sc_rsel);

               if (events & (POLLOUT | POLLWRNORM))
-                       selrecord(l, &sc->sc_wsel);
+                       selrecord(curlwp, &sc->sc_wsel);
       }

       return revents;
@@ -3047,17 +3110,10 @@
{
       struct audio_softc *sc;
       struct virtual_channel *vc;
-       int n;

       sc = kn->kn_hook;
-       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
-       if (n == VAUDIOCHANS)
-               return ENXIO;

-       vc = sc->sc_vchan[n];
+       vc = sc->sc_vchan[0];
       mutex_enter(sc->sc_intr_lock);
       if (!vc->sc_full_duplex && (vc->sc_mode & AUMODE_PLAY))
               kn->kn_data = vc->sc_mpr.stamp - vc->sc_wstamp;
@@ -3088,18 +3144,11 @@
{
       struct audio_softc *sc;
       audio_stream_t *stream;
-       int n;

       sc = kn->kn_hook;
       mutex_enter(sc->sc_intr_lock);
-       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == curproc->p_pid)
-                       break;
-       }
-       if (n == VAUDIOCHANS)
-               return ENXIO;

-       stream = sc->sc_vchan[n]->sc_pustream;
+       stream = sc->sc_vchan[0]->sc_pustream;
       kn->kn_data = (stream->end - stream->start)
               - audio_stream_get_used(stream);
       mutex_exit(sc->sc_intr_lock);
@@ -3431,6 +3480,8 @@
               if (sc->sc_audiopid[n].pid == -1)
                       continue;
               i--;
+               if (sc->sc_audiopid[n].pid == -2)
+                       continue;
               vc = sc->sc_vchan[n];
               if (!vc->sc_open)
                       continue;
@@ -3623,6 +3674,9 @@
               if (sc->sc_audiopid[n].pid == -1)
                       continue;
               i--;
+               if (sc->sc_audiopid[n].pid == -2)
+                       continue;
+
               vc = sc->sc_vchan[n];
               if (!(vc->sc_open & AUOPEN_READ))
                       continue;
@@ -4685,8 +4739,10 @@
 */
int
mixer_open(dev_t dev, struct audio_softc *sc, int flags,
-    int ifmt, struct lwp *l)
+    int ifmt, struct lwp *l, struct file **nfp)
{
+       struct file *fp;
+       int error, fd, n;

       KASSERT(mutex_owned(sc->sc_lock));

@@ -4695,7 +4751,25 @@

       DPRINTF(("mixer_open: flags=0x%x sc=%p\n", flags, sc));

-       return 0;
+       for (n = 1; n < VAUDIOCHANS; n++) {
+               if (sc->sc_audiopid[n].pid == -1)
+                       break;
+       }
+       if (n == VAUDIOCHANS)
+               return ENOMEM;
+
+       error = fd_allocfile(&fp, &fd);
+       if (error)
+               return error;
+
+       sc->sc_audiopid[n].pid = -2;
+
+       sc->sc_audiopid[n].dev = dev;
+       error = fd_clone(fp, fd, flags, &audio_fileops, &sc->sc_audiopid[n]);
+       KASSERT(error == EMOVEFD);
+
+       *nfp = fp;
+       return error;
}

/*
@@ -4742,21 +4816,22 @@
 */
/* ARGSUSED */
int
-mixer_close(struct audio_softc *sc, int flags, int ifmt, struct lwp *l)
+mixer_close(struct audio_softc *sc, int flags, int n)
{

       KASSERT(mutex_owned(sc->sc_lock));
       if (sc->hw_if == NULL)
               return ENXIO;

+       sc->sc_audiopid[n].pid = -1;
+
       DPRINTF(("mixer_close: sc %p\n", sc));
       mixer_remove(sc);
       return 0;
}

int
-mixer_ioctl(struct audio_softc *sc, u_long cmd, void *addr, int flag,
-           struct lwp *l)
+mixer_ioctl(struct audio_softc *sc, u_long cmd, void *addr, int flag)
{
       const struct audio_hw_if *hw;
       struct mixer_asyncs *ma;
@@ -4829,9 +4904,10 @@
               break;

       default:
-               if (hw->dev_ioctl)
-                       error = hw->dev_ioctl(sc->hw_hdl, cmd, addr, flag, l);
-               else
+               if (hw->dev_ioctl) {
+                       error = hw->dev_ioctl(sc->hw_hdl, cmd, addr, flag,
+                           curlwp);
+               } else
                       error = EINVAL;
               break;
       }
@@ -4993,7 +5069,7 @@
       mutex_enter(sc->sc_lock);
       audio_mixer_capture(sc);
       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == -1)
+               if (sc->sc_audiopid[n].pid == -1 || sc->sc_audiopid[n].pid == -2)
                       continue;

               vc = sc->sc_vchan[n];
@@ -5032,7 +5108,7 @@

       audio_mixer_restore(sc);
       for (n = 1; n < VAUDIOCHANS; n++) {
-               if (sc->sc_audiopid[n].pid == -1)
+               if (sc->sc_audiopid[n].pid == -1 || sc->sc_audiopid[n].pid == -2)
                       continue;
               vc = sc->sc_vchan[n];

Index: src/sys/dev/audiobell.c
===================================================================
RCS file: /cvsroot/src/sys/dev/audiobell.c,v
retrieving revision 1.12
diff -u -r1.12 audiobell.c
--- src/sys/dev/audiobell.c     13 Dec 2016 20:18:32 -0000      1.12
+++ src/sys/dev/audiobell.c     28 Dec 2016 02:50:48 -0000
@@ -38,19 +38,22 @@
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/null.h>
#include <sys/systm.h>
#include <sys/uio.h>
+#include <sys/unistd.h>

#include <dev/audio_if.h>
#include <dev/audiobellvar.h>

-extern dev_type_open(audioopen);
-extern dev_type_ioctl(audioioctl);
-extern dev_type_write(audiowrite);
-extern dev_type_close(audioclose);
+extern int audiobellopen(dev_t, int, int, struct lwp *, struct file **);
+extern int audioclose(struct file *);
+extern int audiowrite(struct file *, off_t *, struct uio *, kauth_cred_t, int);
+extern int audioioctl(struct file *, u_long, void *);

/* Convert a %age volume to an amount to add to u-law values */
/* XXX Probably highly inaccurate -- should be regenerated */
@@ -143,18 +146,23 @@
       struct audio_info ai;
       struct uio auio;
       struct iovec aiov;
+       struct file *fp;
       int size, len, offset;
+
+       fp = NULL;
       dev_t audio = AUDIO_DEVICE | device_unit((device_t)v);

       /* The audio system isn't built for polling. */
       if (poll) return;

       /* If not configured, we can't beep. */
-       if (audioopen(audio, FWRITE, 0, NULL) != 0)
+       if (audiobellopen(audio, FWRITE, 0, NULL, &fp) != EMOVEFD || fp == NULL)
               return;

-       if (audioioctl(audio, AUDIO_GETINFO, &ai, 0, NULL) != 0)
+       if (audioioctl(fp, AUDIO_GETINFO, &ai) != 0) {
+               audioclose(fp);
               return;
+       }

       buf = NULL;

@@ -179,11 +187,11 @@
               auio.uio_rw = UIO_WRITE;
               UIO_SETUP_SYSSPACE(&auio);

-               audiowrite(audio, &auio, 0);
+               audiowrite(fp, NULL, &auio, NULL, 0);
               len -= size;
               offset += size;
       }
out:
       if (buf != NULL) free(buf, M_TEMP);
-       audioclose(audio, FWRITE, 0, NULL);
+       audioclose(fp);
}
Index: src/sys/sys/audioio.h
===================================================================
RCS file: /cvsroot/src/sys/sys/audioio.h,v
retrieving revision 1.35
diff -u -r1.35 audioio.h
--- src/sys/sys/audioio.h       8 Dec 2016 10:28:44 -0000       1.35
+++ src/sys/sys/audioio.h       28 Dec 2016 02:50:48 -0000
@@ -144,6 +144,7 @@
} audio_encoding_t;

struct audio_pid {
+       dev_t   dev;
       pid_t   pid;                    /* for audio device belonging to pid */
       lwpid_t lwpid;                  /* unused */
};
Index: src/sys/sys/file.h
===================================================================
RCS file: /cvsroot/src/sys/sys/file.h,v
retrieving revision 1.79
diff -u -r1.79 file.h
--- src/sys/sys/file.h  30 May 2015 20:09:47 -0000      1.79
+++ src/sys/sys/file.h  28 Dec 2016 02:50:48 -0000
@@ -103,6 +103,7 @@
       struct kqueue *fd_kq;           // DTYPE_KQUEUE
       void *fd_data;                  // DTYPE_MISC
       struct rnd_ctx *fd_rndctx;      // DTYPE_MISC (rnd)
+       struct audio_pid *fd_audioctx;  // DTYPE_MISC (audio)
       int fd_devunit;                 // DTYPE_MISC (tap)
       struct bpf_d *fd_bpf;           // DTYPE_MISC (bpf)
       struct fcrypt *fd_fcrypt;       // DTYPE_CRYPTO is not used
@@ -144,6 +145,7 @@
#define f_ksem         f_undata.fd_ks

#define f_rndctx       f_undata.fd_rndctx
+#define f_audioctx     f_undata.fd_audioctx
#define f_devunit      f_undata.fd_devunit
#define f_bpf          f_undata.fd_bpf
#define f_fcrypt       f_undata.fd_fcrypt