Lock channels only as necessary in dsp_ioctl(), and only lock one
channel at a time unless it is actually necessary to lock both. This avoids problems with lock order reversal and malloc() calls with a mutex held when lower level code unlocks a channel, calls malloc(), and relocks the channel. This also avoids the cost of some unnecessary locking and unlocking. Tested by: matk
This commit is contained in:
parent
1843690ef3
commit
11e768d9c0
@ -444,7 +444,7 @@ dsp_write(dev_t i_dev, struct uio *buf, int flag)
|
||||
static int
|
||||
dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
{
|
||||
struct pcm_channel *wrch, *rdch;
|
||||
struct pcm_channel *chn, *rdch, *wrch;
|
||||
struct snddev_info *d;
|
||||
intrmask_t s;
|
||||
int kill;
|
||||
@ -477,22 +477,19 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
if (kill & 2)
|
||||
rdch = NULL;
|
||||
|
||||
if (rdch != NULL)
|
||||
CHN_LOCK(rdch);
|
||||
if (wrch != NULL)
|
||||
CHN_LOCK(wrch);
|
||||
|
||||
switch(cmd) {
|
||||
#ifdef OLDPCM_IOCTL
|
||||
/*
|
||||
* we start with the new ioctl interface.
|
||||
*/
|
||||
case AIONWRITE: /* how many bytes can write ? */
|
||||
CHN_LOCK(wrch);
|
||||
/*
|
||||
if (wrch && wrch->bufhard.dl)
|
||||
while (chn_wrfeed(wrch) == 0);
|
||||
*/
|
||||
*arg_i = wrch? sndbuf_getfree(wrch->bufsoft) : 0;
|
||||
CHN_UNLOCK(wrch);
|
||||
break;
|
||||
|
||||
case AIOSSIZE: /* set the current blocksize */
|
||||
@ -502,12 +499,16 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
p->play_size = 0;
|
||||
p->rec_size = 0;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
chn_setblocksize(wrch, 2, p->play_size);
|
||||
p->play_size = sndbuf_getblksz(wrch->bufsoft);
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
chn_setblocksize(rdch, 2, p->rec_size);
|
||||
p->rec_size = sndbuf_getblksz(rdch->bufsoft);
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -515,36 +516,50 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
{
|
||||
struct snd_size *p = (struct snd_size *)arg;
|
||||
|
||||
if (wrch)
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
p->play_size = sndbuf_getblksz(wrch->bufsoft);
|
||||
if (rdch)
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
p->rec_size = sndbuf_getblksz(rdch->bufsoft);
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AIOSFMT:
|
||||
{
|
||||
snd_chan_param *p = (snd_chan_param *)arg;
|
||||
|
||||
if (wrch) {
|
||||
chn_setformat(wrch, p->play_format);
|
||||
chn_setspeed(wrch, p->play_rate);
|
||||
}
|
||||
if (rdch) {
|
||||
chn_setformat(rdch, p->rec_format);
|
||||
chn_setspeed(rdch, p->rec_rate);
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case AIOGFMT:
|
||||
{
|
||||
snd_chan_param *p = (snd_chan_param *)arg;
|
||||
|
||||
p->play_rate = wrch? wrch->speed : 0;
|
||||
p->rec_rate = rdch? rdch->speed : 0;
|
||||
p->play_format = wrch? wrch->format : 0;
|
||||
p->rec_format = rdch? rdch->format : 0;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
if (cmd == AIOSFMT) {
|
||||
chn_setformat(wrch, p->play_format);
|
||||
chn_setspeed(wrch, p->play_rate);
|
||||
}
|
||||
p->play_rate = wrch->speed;
|
||||
p->play_format = wrch->format;
|
||||
CHN_UNLOCK(wrch);
|
||||
} else {
|
||||
p->play_rate = 0;
|
||||
p->play_format = 0;
|
||||
}
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
if (cmd == AIOSFMT) {
|
||||
chn_setformat(rdch, p->rec_format);
|
||||
chn_setspeed(rdch, p->rec_rate);
|
||||
}
|
||||
p->rec_rate = rdch->speed;
|
||||
p->rec_format = rdch->format;
|
||||
CHN_UNLOCK(rdch);
|
||||
} else {
|
||||
p->rec_rate = 0;
|
||||
p->rec_format = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -554,10 +569,14 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
struct pcmchan_caps *pcaps = NULL, *rcaps = NULL;
|
||||
dev_t pdev;
|
||||
|
||||
if (rdch)
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
rcaps = chn_getcaps(rdch);
|
||||
if (wrch)
|
||||
}
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
pcaps = chn_getcaps(wrch);
|
||||
}
|
||||
p->rate_min = max(rcaps? rcaps->minspeed : 0,
|
||||
pcaps? pcaps->minspeed : 0);
|
||||
p->rate_max = min(rcaps? rcaps->maxspeed : 1000000,
|
||||
@ -573,15 +592,23 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
p->mixers = 1; /* default: one mixer */
|
||||
p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0;
|
||||
p->left = p->right = 100;
|
||||
if (rdch)
|
||||
CHN_UNLOCK(rdch);
|
||||
if (wrch)
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
break;
|
||||
|
||||
case AIOSTOP:
|
||||
if (*arg_i == AIOSYNC_PLAY && wrch)
|
||||
if (*arg_i == AIOSYNC_PLAY && wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
*arg_i = chn_abort(wrch);
|
||||
else if (*arg_i == AIOSYNC_CAPTURE && rdch)
|
||||
CHN_UNLOCK(wrch);
|
||||
} else if (*arg_i == AIOSYNC_CAPTURE && rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
*arg_i = chn_abort(rdch);
|
||||
else {
|
||||
CHN_UNLOCK(rdch);
|
||||
} else {
|
||||
printf("AIOSTOP: bad channel 0x%x\n", *arg_i);
|
||||
*arg_i = 0;
|
||||
}
|
||||
@ -596,9 +623,15 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
* here follow the standard ioctls (filio.h etc.)
|
||||
*/
|
||||
case FIONREAD: /* get # bytes to read */
|
||||
/* if (rdch && rdch->bufhard.dl)
|
||||
while (chn_rdfeed(rdch) == 0);
|
||||
*/ *arg_i = rdch? sndbuf_getready(rdch->bufsoft) : 0;
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
/* if (rdch && rdch->bufhard.dl)
|
||||
while (chn_rdfeed(rdch) == 0);
|
||||
*/
|
||||
*arg_i = sndbuf_getready(rdch->bufsoft);
|
||||
CHN_UNLOCK(rdch);
|
||||
} else
|
||||
*arg_i = 0;
|
||||
break;
|
||||
|
||||
case FIOASYNC: /*set/clear async i/o */
|
||||
@ -607,15 +640,21 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
|
||||
case SNDCTL_DSP_NONBLOCK:
|
||||
case FIONBIO: /* set/clear non-blocking i/o */
|
||||
if (rdch)
|
||||
rdch->flags &= ~CHN_F_NBIO;
|
||||
if (wrch)
|
||||
wrch->flags &= ~CHN_F_NBIO;
|
||||
if (*arg_i) {
|
||||
if (rdch)
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
if (*arg_i)
|
||||
rdch->flags |= CHN_F_NBIO;
|
||||
if (wrch)
|
||||
else
|
||||
rdch->flags &= ~CHN_F_NBIO;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
if (*arg_i)
|
||||
wrch->flags |= CHN_F_NBIO;
|
||||
else
|
||||
wrch->flags &= ~CHN_F_NBIO;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -625,71 +664,93 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
#define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int)
|
||||
case THE_REAL_SNDCTL_DSP_GETBLKSIZE:
|
||||
case SNDCTL_DSP_GETBLKSIZE:
|
||||
if (wrch)
|
||||
*arg_i = sndbuf_getblksz(wrch->bufsoft);
|
||||
else if (rdch)
|
||||
*arg_i = sndbuf_getblksz(rdch->bufsoft);
|
||||
else
|
||||
*arg_i = 0;
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = sndbuf_getblksz(chn->bufsoft);
|
||||
CHN_UNLOCK(chn);
|
||||
break ;
|
||||
|
||||
case SNDCTL_DSP_SETBLKSIZE:
|
||||
RANGE(*arg_i, 16, 65536);
|
||||
if (wrch)
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
chn_setblocksize(wrch, 2, *arg_i);
|
||||
if (rdch)
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
chn_setblocksize(rdch, 2, *arg_i);
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_RESET:
|
||||
DEB(printf("dsp reset\n"));
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
chn_abort(wrch);
|
||||
chn_resetbuf(wrch);
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
chn_abort(rdch);
|
||||
chn_resetbuf(rdch);
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SYNC:
|
||||
DEB(printf("dsp sync\n"));
|
||||
/* chn_sync may sleep */
|
||||
if (wrch)
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
chn_sync(wrch, sndbuf_getsize(wrch->bufsoft) - 4);
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SPEED:
|
||||
/* chn_setspeed may sleep */
|
||||
tmp = 0;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
ret = chn_setspeed(wrch, *arg_i);
|
||||
tmp = wrch->speed;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch && ret == 0) {
|
||||
CHN_LOCK(rdch);
|
||||
ret = chn_setspeed(rdch, *arg_i);
|
||||
if (tmp == 0)
|
||||
tmp = rdch->speed;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
*arg_i = tmp;
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_RATE:
|
||||
*arg_i = wrch? wrch->speed : rdch->speed;
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = chn->speed;
|
||||
CHN_UNLOCK(chn);
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_STEREO:
|
||||
tmp = -1;
|
||||
*arg_i = (*arg_i)? AFMT_STEREO : 0;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
|
||||
tmp = (wrch->format & AFMT_STEREO)? 1 : 0;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch && ret == 0) {
|
||||
CHN_LOCK(rdch);
|
||||
ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
|
||||
if (tmp == -1)
|
||||
tmp = (rdch->format & AFMT_STEREO)? 1 : 0;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
*arg_i = tmp;
|
||||
break;
|
||||
@ -700,47 +761,67 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
tmp = 0;
|
||||
*arg_i = (*arg_i != 1)? AFMT_STEREO : 0;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
|
||||
tmp = (wrch->format & AFMT_STEREO)? 2 : 1;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch && ret == 0) {
|
||||
CHN_LOCK(rdch);
|
||||
ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
|
||||
if (tmp == 0)
|
||||
tmp = (rdch->format & AFMT_STEREO)? 2 : 1;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
*arg_i = tmp;
|
||||
} else
|
||||
*arg_i = ((wrch? wrch->format : rdch->format) & AFMT_STEREO)? 2 : 1;
|
||||
} else {
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
|
||||
CHN_UNLOCK(chn);
|
||||
}
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_CHANNELS:
|
||||
*arg_i = ((wrch? wrch->format : rdch->format) & AFMT_STEREO)? 2 : 1;
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
|
||||
CHN_UNLOCK(chn);
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */
|
||||
*arg_i = wrch? chn_getformats(wrch) : chn_getformats(rdch);
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = chn_getformats(chn);
|
||||
CHN_UNLOCK(chn);
|
||||
break ;
|
||||
|
||||
case SNDCTL_DSP_SETFMT: /* sets _one_ format */
|
||||
/* XXX locking */
|
||||
if ((*arg_i != AFMT_QUERY)) {
|
||||
tmp = 0;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
ret = chn_setformat(wrch, (*arg_i) | (wrch->format & AFMT_STEREO));
|
||||
tmp = wrch->format & ~AFMT_STEREO;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch && ret == 0) {
|
||||
CHN_LOCK(rdch);
|
||||
ret = chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO));
|
||||
if (tmp == 0)
|
||||
tmp = rdch->format & ~AFMT_STEREO;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
*arg_i = tmp;
|
||||
} else
|
||||
*arg_i = (wrch? wrch->format : rdch->format) & ~AFMT_STEREO;
|
||||
} else {
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = chn->format & ~AFMT_STEREO;
|
||||
CHN_UNLOCK(chn);
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETFRAGMENT:
|
||||
/* XXX locking */
|
||||
DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg));
|
||||
{
|
||||
u_int32_t fragln = (*arg_i) & 0x0000ffff;
|
||||
@ -759,14 +840,18 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
|
||||
DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz));
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
ret = chn_setblocksize(rdch, maxfrags, fragsz);
|
||||
maxfrags = sndbuf_getblkcnt(rdch->bufsoft);
|
||||
fragsz = sndbuf_getblksz(rdch->bufsoft);
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
if (wrch && ret == 0) {
|
||||
CHN_LOCK(wrch);
|
||||
ret = chn_setblocksize(wrch, maxfrags, fragsz);
|
||||
maxfrags = sndbuf_getblkcnt(wrch->bufsoft);
|
||||
fragsz = sndbuf_getblksz(wrch->bufsoft);
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
|
||||
fragln = 0;
|
||||
@ -785,10 +870,12 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
if (rdch) {
|
||||
struct snd_dbuf *bs = rdch->bufsoft;
|
||||
|
||||
CHN_LOCK(rdch);
|
||||
a->bytes = sndbuf_getready(bs);
|
||||
a->fragments = a->bytes / sndbuf_getblksz(bs);
|
||||
a->fragstotal = sndbuf_getblkcnt(bs);
|
||||
a->fragsize = sndbuf_getblksz(bs);
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -800,11 +887,13 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
if (wrch) {
|
||||
struct snd_dbuf *bs = wrch->bufsoft;
|
||||
|
||||
CHN_LOCK(wrch);
|
||||
chn_wrupdate(wrch);
|
||||
a->bytes = sndbuf_getfree(bs);
|
||||
a->fragments = a->bytes / sndbuf_getblksz(bs);
|
||||
a->fragstotal = sndbuf_getblkcnt(bs);
|
||||
a->fragsize = sndbuf_getblksz(bs);
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -815,11 +904,13 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
if (rdch) {
|
||||
struct snd_dbuf *bs = rdch->bufsoft;
|
||||
|
||||
CHN_LOCK(rdch);
|
||||
chn_rdupdate(rdch);
|
||||
a->bytes = sndbuf_gettotal(bs);
|
||||
a->blocks = sndbuf_getblocks(bs) - rdch->blocks;
|
||||
a->ptr = sndbuf_getreadyptr(bs);
|
||||
rdch->blocks = sndbuf_getblocks(bs);
|
||||
CHN_UNLOCK(rdch);
|
||||
} else
|
||||
ret = EINVAL;
|
||||
}
|
||||
@ -831,11 +922,13 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
if (wrch) {
|
||||
struct snd_dbuf *bs = wrch->bufsoft;
|
||||
|
||||
CHN_LOCK(wrch);
|
||||
chn_wrupdate(wrch);
|
||||
a->bytes = sndbuf_gettotal(bs);
|
||||
a->blocks = sndbuf_getblocks(bs) - wrch->blocks;
|
||||
a->ptr = sndbuf_getreadyptr(bs);
|
||||
wrch->blocks = sndbuf_getblocks(bs);
|
||||
CHN_UNLOCK(wrch);
|
||||
} else
|
||||
ret = EINVAL;
|
||||
}
|
||||
@ -848,32 +941,47 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_BITS:
|
||||
*arg_i = ((wrch? wrch->format : rdch->format) & AFMT_16BIT)? 16 : 8;
|
||||
chn = wrch ? wrch : rdch;
|
||||
CHN_LOCK(chn);
|
||||
*arg_i = (chn->format & AFMT_16BIT) ? 16 : 8;
|
||||
CHN_UNLOCK(chn);
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETTRIGGER:
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
rdch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
|
||||
if (*arg_i & PCM_ENABLE_INPUT)
|
||||
chn_start(rdch, 1);
|
||||
else
|
||||
rdch->flags |= CHN_F_NOTRIGGER;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
wrch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
|
||||
if (*arg_i & PCM_ENABLE_OUTPUT)
|
||||
chn_start(wrch, 1);
|
||||
else
|
||||
wrch->flags |= CHN_F_NOTRIGGER;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_GETTRIGGER:
|
||||
*arg_i = 0;
|
||||
if (wrch && wrch->flags & CHN_F_TRIGGERED)
|
||||
*arg_i |= PCM_ENABLE_OUTPUT;
|
||||
if (rdch && rdch->flags & CHN_F_TRIGGERED)
|
||||
*arg_i |= PCM_ENABLE_INPUT;
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
if (wrch->flags & CHN_F_TRIGGERED)
|
||||
*arg_i |= PCM_ENABLE_OUTPUT;
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
if (rdch) {
|
||||
CHN_LOCK(rdch);
|
||||
if (rdch->flags & CHN_F_TRIGGERED)
|
||||
*arg_i |= PCM_ENABLE_INPUT;
|
||||
CHN_UNLOCK(rdch);
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_GETODELAY:
|
||||
@ -881,16 +989,20 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
struct snd_dbuf *b = wrch->bufhard;
|
||||
struct snd_dbuf *bs = wrch->bufsoft;
|
||||
|
||||
CHN_LOCK(wrch);
|
||||
chn_wrupdate(wrch);
|
||||
*arg_i = sndbuf_getready(b) + sndbuf_getready(bs);
|
||||
CHN_UNLOCK(wrch);
|
||||
} else
|
||||
ret = EINVAL;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_POST:
|
||||
if (wrch) {
|
||||
CHN_LOCK(wrch);
|
||||
wrch->flags &= ~CHN_F_NOTRIGGER;
|
||||
chn_start(wrch, 1);
|
||||
CHN_UNLOCK(wrch);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -908,10 +1020,6 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (rdch != NULL)
|
||||
CHN_UNLOCK(rdch);
|
||||
if (wrch != NULL)
|
||||
CHN_UNLOCK(wrch);
|
||||
relchns(i_dev, rdch, wrch, 0);
|
||||
splx(s);
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user