diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 1ecc31e..4874e67 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -472,7 +472,7 @@ chn_wrintr(struct pcm_channel *c) */ int -chn_write(struct pcm_channel *c, struct uio *buf) +chn_write(struct pcm_channel *c, struct uio *buf, int ioflag) { struct snd_dbuf *bs = c->bufsoft; void *off; @@ -483,6 +483,11 @@ chn_write(struct pcm_channel *c, struct uio *buf) ret = 0; timeout = chn_timeout * hz; + if (ioflag & O_NONBLOCK) + c->flags |= CHN_F_NBIO; + else + c->flags &= ~CHN_F_NBIO; + while (ret == 0 && buf->uio_resid > 0) { sz = min(buf->uio_resid, sndbuf_getfree(bs)); if (sz > 0) { @@ -507,7 +512,7 @@ chn_write(struct pcm_channel *c, struct uio *buf) if (ret != 0) c->flags |= CHN_F_DEAD; } - } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) { + } else if ((ioflag & O_NONBLOCK) || (c->flags & CHN_F_NOTRIGGER)) { /** * @todo Evaluate whether EAGAIN is truly desirable. * 4Front drivers behave like this, but I'm @@ -602,7 +607,7 @@ chn_rdintr(struct pcm_channel *c) */ int -chn_read(struct pcm_channel *c, struct uio *buf) +chn_read(struct pcm_channel *c, struct uio *buf, int ioflag) { struct snd_dbuf *bs = c->bufsoft; void *off; @@ -610,6 +615,11 @@ chn_read(struct pcm_channel *c, struct uio *buf) CHN_LOCKASSERT(c); + if (ioflag & O_NONBLOCK) + c->flags |= CHN_F_NBIO; + else + c->flags &= ~CHN_F_NBIO; + if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) { ret = chn_start(c, 0); if (ret != 0) { @@ -640,9 +650,9 @@ chn_read(struct pcm_channel *c, struct uio *buf) sndbuf_dispose(bs, NULL, t); } ret = 0; - } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) + } else if ((ioflag & O_NONBLOCK) || (c->flags & CHN_F_NOTRIGGER)) { ret = EAGAIN; - else { + } else { ret = chn_sleep(c, timeout); if (ret == EAGAIN) { ret = EINVAL; diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index dcdc782..c2da759 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -254,8 +254,8 @@ struct pcm_channel { #include "channel_if.h" int chn_reinit(struct pcm_channel *c); -int chn_write(struct pcm_channel *c, struct uio *buf); -int chn_read(struct pcm_channel *c, struct uio *buf); +int chn_write(struct pcm_channel *c, struct uio *buf, int ioflag); +int chn_read(struct pcm_channel *c, struct uio *buf, int ioflag); u_int32_t chn_start(struct pcm_channel *c, int force); int chn_sync(struct pcm_channel *c, int threshold); int chn_flush(struct pcm_channel *c); diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 6677ce4..44c62b6 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -834,11 +834,11 @@ dsp_close(struct dev_close_args *ap) } static __inline int -dsp_io_ops(struct cdev *i_dev, struct uio *buf) +dsp_io_ops(struct cdev *i_dev, struct uio *buf, int ioflag) { struct snddev_info *d; struct pcm_channel **ch, *rdch, *wrch; - int (*chn_io)(struct pcm_channel *, struct uio *); + int (*chn_io)(struct pcm_channel *, struct uio *, int); int prio, ret; pid_t runpid; @@ -895,7 +895,7 @@ dsp_io_ops(struct cdev *i_dev, struct uio *buf) * someone else doesn't come along and muss up the buffer. */ ++(*ch)->inprog; - ret = chn_io(*ch, buf); + ret = chn_io(*ch, buf, ioflag); --(*ch)->inprog; CHN_BROADCAST(&(*ch)->cv); @@ -913,7 +913,7 @@ dsp_read(struct dev_read_args *ap) struct cdev *i_dev = ap->a_head.a_dev; struct uio *buf = ap->a_uio; - return (dsp_io_ops(i_dev, buf)); + return (dsp_io_ops(i_dev, buf, ap->a_ioflag)); } static int @@ -922,7 +922,7 @@ dsp_write(struct dev_write_args *ap) struct cdev *i_dev = ap->a_head.a_dev; struct uio *buf = ap->a_uio; - return (dsp_io_ops(i_dev, buf)); + return (dsp_io_ops(i_dev, buf, ap->a_ioflag)); } static int