summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-04-23 18:09:18 +0000
committercg <cg@FreeBSD.org>2000-04-23 18:09:18 +0000
commitea94bdbf08f0b50261c68faad13d97157358eccb (patch)
tree37cc9f31f754fa22ec52c9253330cd48a807a75e /sys
parentce5fa178d7bf24d666f6de95407c5c2d42a0e0af (diff)
downloadFreeBSD-src-ea94bdbf08f0b50261c68faad13d97157358eccb.zip
FreeBSD-src-ea94bdbf08f0b50261c68faad13d97157358eccb.tar.gz
implement settrigger according to spec
fixes for non-blocking mode
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/pcm/channel.c50
-rw-r--r--sys/dev/sound/pcm/channel.h1
-rw-r--r--sys/dev/sound/pcm/dsp.c16
3 files changed, 40 insertions, 27 deletions
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index e08477e..464fa66 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -115,12 +115,14 @@ static int
chn_polltrigger(pcm_channel *c)
{
snd_dbuf *bs = &c->buffer2nd;
- unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize2nd : 1;
+ unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize2nd : 0;
int trig = 0;
+ lim = 0;
if (c->flags & CHN_F_MAPPED)
trig = ((bs->int_count > bs->prev_int_count) || bs->first_poll);
- else trig = (((c->direction == PCMDIR_PLAY)? bs->fl : bs->rl) > lim);
+ else
+ trig = (((c->direction == PCMDIR_PLAY)? bs->fl : bs->rl) > lim);
return trig;
}
@@ -387,7 +389,7 @@ chn_wrintr(pcm_channel *c)
/* printf("%d >= %d && !(%x & %x)\n", b->rl, DMA_ALIGN_THRESHOLD, c->flags, CHN_F_ABORTING | CHN_F_CLOSING);
*/ start = (b->rl >= DMA_ALIGN_THRESHOLD && !(c->flags & CHN_F_ABORTING));
}
- if (start) {
+ if (start & !(c->flags & CHN_F_NOTRIGGER)) {
chn_dmaupdate(c);
if (c->flags & CHN_F_MAPPED) l = c->blocksize;
else l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK;
@@ -465,10 +467,13 @@ chn_write(pcm_channel *c, struct uio *buf)
* the write operation avoids blocking.
*/
if ((c->flags & CHN_F_NBIO) && buf->uio_resid > c->blocksize2nd) {
+ DEB(printf("pcm warning: broken app, nbio and tried to write %d bytes with fragsz %d\n",
+ buf->uio_resid, c->blocksize2nd));
newsize = 16;
- while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / c->fragments))
+ while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2))
newsize <<= 1;
- chn_setblocksize(c, c->fragments, c->fragments);
+ chn_setblocksize(c, c->fragments, newsize);
+ DEB(printf("pcm warning: frags reset to %d x %d\n", c->fragments, c->blocksize2nd));
}
/* Store the initial size in the uio. */
@@ -482,18 +487,15 @@ chn_write(pcm_channel *c, struct uio *buf)
/* Check for underflow before writing into the buffers. */
chn_checkunderflow(c);
while (chn_wrfeed2nd(c, buf) > 0);
+ if (c->flags & CHN_F_NBIO && buf->uio_resid > 0)
+ ret = EAGAIN;
/* Start playing if not yet. */
- if ((bs->rl || b->rl) && !b->dl) {
+ if ((bs->rl || b->rl) && !b->dl)
chn_intr(c);
- }
- if (c->flags & CHN_F_NBIO) {
- /* If no pcm data was written on nonblocking, return EAGAIN. */
- if (buf->uio_resid == res)
- ret = EAGAIN;
- } else {
- /* Wait until all samples are played in blocking mode. */
+ if (ret == 0) {
+ /* Wait until all samples are played in blocking mode. */
while (buf->uio_resid > 0) {
/* Check for underflow before writing into the buffers. */
chn_checkunderflow(c);
@@ -501,7 +503,8 @@ chn_write(pcm_channel *c, struct uio *buf)
while (chn_wrfeed2nd(c, buf) > 0);
/* Start playing if necessary. */
- if ((bs->rl || b->rl) && !b->dl) chn_intr(c);
+ if ((bs->rl || b->rl) && !b->dl)
+ chn_intr(c);
/* Have we finished to feed the secondary buffer? */
if (buf->uio_resid == 0)
@@ -513,9 +516,11 @@ chn_write(pcm_channel *c, struct uio *buf)
ret = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout);
s = spltty();
/* if (ret == EINTR) chn_abort(c); */
- if (ret == EINTR || ret == ERESTART) break;
+ if (ret == EINTR || ret == ERESTART)
+ break;
}
- }
+ } else
+ ret = 0;
c->flags &= ~CHN_F_WRITING;
splx(s);
return ret;
@@ -1156,15 +1161,18 @@ chn_setblocksize(pcm_channel *c, int blkcnt, int blksz)
return EINVAL;
}
c->flags &= ~CHN_F_HAS_SIZE;
- if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE;
+ if (blksz >= 2)
+ c->flags |= CHN_F_HAS_SIZE;
/* let us specify blksz without setting CHN_F_HAS_SIZE */
- if (blksz < 0) blksz = -blksz;
+ if (blksz < 0)
+ blksz = -blksz;
/* default to blksz = ~0.25s */
- if (blksz < 16) blksz = (c->buffer.sample_size * c->speed) >> 2;
+ if (blksz < 16)
+ blksz = (c->buffer.sample_size * c->speed) >> 2;
+ if (blkcnt * blksz > CHN_2NDBUFMAXSIZE)
+ blkcnt = CHN_2NDBUFMAXSIZE / blksz;
bufsz = blkcnt * blksz;
- if (blksz < 16 || bufsz > CHN_2NDBUFMAXSIZE)
- return EINVAL;
s = spltty();
if (bs->buf != NULL)
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index 846511c..edc3096 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -73,6 +73,7 @@ extern pcm_feeder feeder_root;
#define CHN_F_PENDING_IO (CHN_F_READING | CHN_F_WRITING)
#define CHN_F_RUNNING 0x00000010 /* dma is running */
#define CHN_F_TRIGGERED 0x00000020
+#define CHN_F_NOTRIGGER 0x00000040
#define CHN_F_BUSY 0x00001000 /* has been opened */
#define CHN_F_HAS_SIZE 0x00002000 /* user set block size */
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 457dc6a..21e121a 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -291,6 +291,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos);
break;
+#endif
/*
* here follow the standard ioctls (filio.h etc.)
*/
@@ -303,11 +304,9 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
case FIOASYNC: /*set/clear async i/o */
DEB( printf("FIOASYNC\n") ; )
break;
-#endif
+
case SNDCTL_DSP_NONBLOCK:
-#ifdef OLDPCM_IOCTL
case FIONBIO: /* set/clear non-blocking i/o */
-#endif
if (rdch) rdch->flags &= ~CHN_F_NBIO;
if (wrch) wrch->flags &= ~CHN_F_NBIO;
if (*arg_i) {
@@ -417,12 +416,13 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE)
maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
+ DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz));
if (rdch)
ret = chn_setblocksize(rdch, maxfrags, fragsz);
if (wrch && ret == 0)
ret = chn_setblocksize(wrch, maxfrags, fragsz);
- *arg_i = (c->fragments << 16) | fragsz;
+ *arg_i = (c->fragments << 16) | c->blocksize;
}
break;
@@ -525,15 +525,19 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
case SNDCTL_DSP_SETTRIGGER:
if (rdch) {
- rdch->flags &= ~CHN_F_TRIGGERED;
+ rdch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
if (*arg_i & PCM_ENABLE_INPUT)
rdch->flags |= CHN_F_TRIGGERED;
+ else
+ rdch->flags |= CHN_F_NOTRIGGER;
chn_intr(rdch);
}
if (wrch) {
- wrch->flags &= ~CHN_F_TRIGGERED;
+ wrch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
if (*arg_i & PCM_ENABLE_OUTPUT)
wrch->flags |= CHN_F_TRIGGERED;
+ else
+ wrch->flags |= CHN_F_NOTRIGGER;
chn_intr(wrch);
}
break;
OpenPOWER on IntegriCloud