diff options
Diffstat (limited to 'sys/dev/sound/pcm/dsp.c')
-rw-r--r-- | sys/dev/sound/pcm/dsp.c | 112 |
1 files changed, 70 insertions, 42 deletions
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 94b1274..d1ae32f 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -22,8 +22,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <sys/param.h> @@ -31,6 +29,8 @@ #include <dev/sound/pcm/sound.h> +SND_DECLARE_FILE("$FreeBSD$"); + #define OLDPCM_IOCTL static d_open_t dsp_open; @@ -75,6 +75,34 @@ dsp_get_info(dev_t dev) return d; } +static u_int32_t +dsp_get_flags(dev_t dev) +{ + device_t bdev; + int unit; + + unit = PCMUNIT(dev); + if (unit >= devclass_get_maxunit(pcm_devclass)) + return 0xffffffff; + bdev = devclass_get_device(pcm_devclass, unit); + + return pcm_getflags(bdev); +} + +static void +dsp_set_flags(dev_t dev, u_int32_t flags) +{ + device_t bdev; + int unit; + + unit = PCMUNIT(dev); + if (unit >= devclass_get_maxunit(pcm_devclass)) + return; + bdev = devclass_get_device(pcm_devclass, unit); + + pcm_setflags(bdev, flags); +} + /* * return the channels channels associated with an open device instance. * set the priority if the device is simplex and one direction (only) is @@ -85,37 +113,41 @@ static int getchns(dev_t dev, struct pcm_channel **rdch, struct pcm_channel **wrch, u_int32_t prio) { struct snddev_info *d; + u_int32_t flags; + flags = dsp_get_flags(dev); d = dsp_get_info(dev); - snd_mtxlock(d->lock); - d->inprog++; - KASSERT((d->flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \ + pcm_lock(d); + pcm_inprog(d, 1); + KASSERT((flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \ ("getchns: read and write both prioritised")); - if ((d->flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR))) - d->flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR); + if ((flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR))) { + flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR); + dsp_set_flags(dev, flags); + } *rdch = dev->si_drv1; *wrch = dev->si_drv2; - if ((d->flags & SD_F_SIMPLEX) && (d->flags & SD_F_PRIO_SET)) { + if ((flags & SD_F_SIMPLEX) && (flags & SD_F_PRIO_SET)) { if (prio) { - if (*rdch && d->flags & SD_F_PRIO_WR) { + if (*rdch && flags & SD_F_PRIO_WR) { dev->si_drv1 = NULL; - *rdch = d->fakechan; - } else if (*wrch && d->flags & SD_F_PRIO_RD) { + *rdch = pcm_getfakechan(d); + } else if (*wrch && flags & SD_F_PRIO_RD) { dev->si_drv2 = NULL; - *wrch = d->fakechan; + *wrch = pcm_getfakechan(d); } } - d->fakechan->flags |= CHN_F_BUSY; + pcm_getfakechan(d)->flags |= CHN_F_BUSY; } + pcm_unlock(d); - if (*rdch && *rdch != d->fakechan && (prio & SD_F_PRIO_RD)) + if (*rdch && *rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD)) CHN_LOCK(*rdch); - if (*wrch && *wrch != d->fakechan && (prio & SD_F_PRIO_WR)) + if (*wrch && *wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR)) CHN_LOCK(*wrch); - snd_mtxunlock(d->lock); return 0; } @@ -127,13 +159,13 @@ relchns(dev_t dev, struct pcm_channel *rdch, struct pcm_channel *wrch, u_int32_t struct snddev_info *d; d = dsp_get_info(dev); - if (wrch && wrch != d->fakechan && (prio & SD_F_PRIO_WR)) + if (wrch && wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR)) CHN_UNLOCK(wrch); - if (rdch && rdch != d->fakechan && (prio & SD_F_PRIO_RD)) + if (rdch && rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD)) CHN_UNLOCK(rdch); - snd_mtxlock(d->lock); - d->inprog--; - snd_mtxunlock(d->lock); + pcm_lock(d); + pcm_inprog(d, -1); + pcm_unlock(d); } static int @@ -172,10 +204,10 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p) } /* lock snddev so nobody else can monkey with it */ - snd_mtxlock(d->lock); - if ((d->flags & SD_F_SIMPLEX) && (i_dev->si_drv1 || i_dev->si_drv2)) { + pcm_lock(d); + if ((dsp_get_flags(i_dev) & SD_F_SIMPLEX) && (i_dev->si_drv1 || i_dev->si_drv2)) { /* simplex device, already open, exit */ - snd_mtxunlock(d->lock); + pcm_unlock(d); splx(s); return EBUSY; } @@ -191,14 +223,14 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p) rdch = pcm_chnalloc(d, PCMDIR_REC, p->p_pid); if (!rdch) { /* no channel available, exit */ - snd_mtxunlock(d->lock); + pcm_unlock(d); splx(s); return EBUSY; } /* got a channel, already locked for us */ } else { /* already open for read, exit */ - snd_mtxunlock(d->lock); + pcm_unlock(d); splx(s); return EBUSY; } @@ -216,7 +248,7 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p) pcm_chnrelease(rdch); } /* exit */ - snd_mtxunlock(d->lock); + pcm_unlock(d); splx(s); return EBUSY; } @@ -228,7 +260,7 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p) pcm_chnrelease(rdch); } /* exit */ - snd_mtxunlock(d->lock); + pcm_unlock(d); splx(s); return EBUSY; } @@ -236,7 +268,7 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p) i_dev->si_drv1 = rdch; i_dev->si_drv2 = wrch; - snd_mtxunlock(d->lock); + pcm_unlock(d); /* finished with snddev, new channels still locked */ /* bump refcounts, reset and unlock any channels that we just opened */ @@ -276,7 +308,7 @@ dsp_close(dev_t i_dev, int flags, int mode, struct proc *p) s = spltty(); d = dsp_get_info(i_dev); - snd_mtxlock(d->lock); + pcm_lock(d); rdch = i_dev->si_drv1; wrch = i_dev->si_drv2; @@ -298,21 +330,21 @@ dsp_close(dev_t i_dev, int flags, int mode, struct proc *p) } } if (exit) { - snd_mtxunlock(d->lock); + pcm_unlock(d); splx(s); return 0; } /* both refcounts are zero, abort and release */ - if (d->fakechan) - d->fakechan->flags = 0; + if (pcm_getfakechan(d)) + pcm_getfakechan(d)->flags = 0; i_dev->si_drv1 = NULL; i_dev->si_drv2 = NULL; - d->flags &= ~SD_F_TRANSIENT; - snd_mtxunlock(d->lock); + dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT); + pcm_unlock(d); if (rdch) { chn_abort(rdch); /* won't sleep */ @@ -425,10 +457,6 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p) if (kill & 2) rdch = NULL; - /* - * all routines are called with int. blocked. Make sure that - * ints are re-enabled when calling slow or blocking functions! - */ switch(cmd) { #ifdef OLDPCM_IOCTL /* @@ -527,8 +555,8 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p) p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & (wrch? chn_getformats(wrch) : 0xffffffff); if (rdch && wrch) - p->formats |= (d->flags & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX; - pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(device_get_unit(d->dev), SND_DEV_CTL, 0)); + p->formats |= (dsp_get_flags(i_dev) & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX; + pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(PCMUNIT(i_dev), SND_DEV_CTL, 0)); p->mixers = 1; /* default: one mixer */ p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; p->left = p->right = 100; @@ -842,7 +870,7 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p) case SNDCTL_DSP_GETCAPS: *arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER; - if (rdch && wrch && !(d->flags & SD_F_SIMPLEX)) + if (rdch && wrch && !(dsp_get_flags(i_dev) & SD_F_SIMPLEX)) *arg_i |= DSP_CAP_DUPLEX; break; |