diff options
author | cg <cg@FreeBSD.org> | 2000-04-23 18:09:18 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2000-04-23 18:09:18 +0000 |
commit | ea94bdbf08f0b50261c68faad13d97157358eccb (patch) | |
tree | 37cc9f31f754fa22ec52c9253330cd48a807a75e /sys | |
parent | ce5fa178d7bf24d666f6de95407c5c2d42a0e0af (diff) | |
download | FreeBSD-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.c | 50 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.h | 1 | ||||
-rw-r--r-- | sys/dev/sound/pcm/dsp.c | 16 |
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; |