diff options
author | cg <cg@FreeBSD.org> | 2000-04-15 05:04:12 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2000-04-15 05:04:12 +0000 |
commit | 6dcc92e9d30b104c9b7b5cb5dd7a0196735c50b1 (patch) | |
tree | f42ea1ef2636bf6e0eeb79e6acf3632afd5fc802 /sys/dev | |
parent | 15ae5954179254ef21d7d580dae9975aa707623d (diff) | |
download | FreeBSD-src-6dcc92e9d30b104c9b7b5cb5dd7a0196735c50b1.zip FreeBSD-src-6dcc92e9d30b104c9b7b5cb5dd7a0196735c50b1.tar.gz |
make mmap sort-of work. there seem to be interactions with certain hw
drivers, so still work in progress.
do various mmap-related ioctls right.
improve blocksize control.
bits of cleanup.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/sound/pcm/channel.c | 231 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.h | 4 | ||||
-rw-r--r-- | sys/dev/sound/pcm/datatypes.h | 11 | ||||
-rw-r--r-- | sys/dev/sound/pcm/dsp.c | 75 | ||||
-rw-r--r-- | sys/dev/sound/pcm/feeder.c | 5 |
5 files changed, 172 insertions, 154 deletions
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 91a5cd6..52fa581 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -38,7 +38,7 @@ /* #define DEB(x) x */ -static void chn_clearbuf(pcm_channel *c, snd_dbuf *b, int length); +static void buf_clear(snd_dbuf *b, u_int32_t fmt, int length); static void chn_dmaupdate(pcm_channel *c); static void chn_wrintr(pcm_channel *c); static void chn_rdintr(pcm_channel *c); @@ -127,7 +127,7 @@ chn_polltrigger(pcm_channel *c) static int chn_pollreset(pcm_channel *c) { - snd_dbuf *bs = &c->buffer; + snd_dbuf *bs = &c->buffer2nd; if (c->flags & CHN_F_MAPPED) bs->prev_int_count = bs->int_count; bs->first_poll = 0; @@ -248,6 +248,15 @@ chn_wrfeed(pcm_channel *c) /* ensure we always have a whole number of samples */ a = (1 << c->align) - 1; lacc = 0; + if (c->flags & CHN_F_MAPPED) { + bs->rl = min(c->blocksize, b->fl); + bs->fl = 0; + a = 0; + } + /* + printf("b: [rl: %d, rp %d, fl %d, fp %d]; bs: [rl: %d, rp %d, fl %d, fp %d]\n", + b->rl, b->rp, b->fl, b->fp, bs->rl, bs->rp, bs->fl, bs->fp); + */ /* Don't allow write unaligned data */ while (bs->rl > a && b->fl > a) { /* ensure we always have a whole number of samples */ @@ -263,11 +272,19 @@ chn_wrfeed(pcm_channel *c) b->fl -= l; b->fp = (b->fp + l) % b->bufsize; /* Clear the new space in the secondary buffer. */ - chn_clearbuf(c, bs, l); + buf_clear(bs, c->hwfmt, l); /* Accumulate the total bytes of the moved samples. */ lacc += l; /* A feed to the DMA buffer is equivalent to an interrupt. */ - bs->int_count++; + bs->total += l; + if (c->flags & CHN_F_MAPPED) { + if (bs->total - bs->prev_total >= c->blocksize2nd) { + bs->prev_total = bs->total; + bs->int_count++; + c->blocks++; + } + } else + bs->int_count++; if (bs->sel.si_pid && chn_polltrigger(c)) selwakeup(&bs->sel); } @@ -340,14 +357,15 @@ chn_wrintr(pcm_channel *c) * Prepare new space of at least c->blocksize in the DMA * buffer for mmap. */ + /* if (c->flags & CHN_F_MAPPED && b->fl < c->blocksize) { dl = c->blocksize - b->fl; b->fl += dl; b->rl -= dl; b->rp = (b->rp + dl) % b->bufsize; - chn_clearbuf(c, b, dl); + buf_clear(b, c->hwfmt, dl); } - + */ /* Check underflow and update the pointers. */ chn_checkunderflow(c); @@ -356,8 +374,12 @@ chn_wrintr(pcm_channel *c) * If some of the pcm data in uio are still left, the top half * goes to sleep by itself. */ - while (chn_wrfeed(c) > 0); - chn_clearbuf(c, b, b->fl); + if (c->flags & CHN_F_MAPPED) + chn_wrfeed(c); + else { + while (chn_wrfeed(c) > 0); + buf_clear(b, c->hwfmt, b->fl); + } chn_dmawakeup(c); if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED; @@ -389,14 +411,14 @@ chn_wrintr(pcm_channel *c) * we are near to underflow condition, so to prevent * audio 'clicks' clear next b->fl bytes */ - chn_clearbuf(c, b, b->fl); + buf_clear(b, c->hwfmt, b->fl); } } else { /* cannot start a new dma transfer */ DEB(printf("underflow, flags 0x%08x rp %d rl %d\n", c->flags, b->rp, b->rl)); if (b->dl) { /* DMA was active */ b->underflow = 1; /* set underflow flag */ - chn_clearbuf(c, b, b->bufsize); /* and clear all DMA buffer */ + buf_clear(b, c->hwfmt, b->bufsize); } } } @@ -443,10 +465,10 @@ chn_write(pcm_channel *c, struct uio *buf) * the write operation avoids blocking. */ if ((c->flags & CHN_F_NBIO) && buf->uio_resid > c->blocksize2nd) { - for (newsize = 1 ; newsize < min(buf->uio_resid, CHN_2NDBUFWHOLESIZE) ; newsize <<= 1); - chn_setblocksize(c, newsize * c->fragments); - c->blocksize2nd = newsize; - c->fragments = bs->bufsize / c->blocksize2nd; + newsize = 16; + while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / c->fragments)) + newsize <<= 1; + chn_setblocksize(c, c->fragments, c->fragments); } /* Store the initial size in the uio. */ @@ -553,7 +575,7 @@ chn_rdfeed(pcm_channel *c) b->fl += l; b->rp = (b->rp + l) % b->bufsize; /* Clear the new space in the DMA buffer. */ - chn_clearbuf(c, b, l); + buf_clear(b, c->hwfmt, l); /* Accumulate the total bytes of the moved samples. */ lacc += l; /* A feed from the DMA buffer is equivalent to an interrupt. */ @@ -590,7 +612,7 @@ chn_rdfeed2nd(pcm_channel *c, struct uio *buf) bs->rl -= w; bs->rp = (bs->rp + w) % bs->bufsize; /* Clear the new space in the secondary buffer. */ - chn_clearbuf(c, bs, l); + buf_clear(bs, c->hwfmt, l); /* Accumulate the total bytes of the moved samples. */ bs->total += w; wacc += w; @@ -626,7 +648,7 @@ chn_rdintr(pcm_channel *c) bs->fl += dl; bs->rl -= dl; bs->rp = (bs->rp + dl) % bs->bufsize; - chn_clearbuf(c, bs, dl); + buf_clear(bs, c->hwfmt, dl); } /* Update the pointers. */ @@ -783,23 +805,40 @@ chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat) } static void -chn_clearbuf(pcm_channel *c, snd_dbuf *b, int length) +buf_clear(snd_dbuf *b, u_int32_t fmt, int length) { int i; u_int16_t data, *p; /* rely on length & DMA_ALIGN_MASK == 0 */ - length&=DMA_ALIGN_MASK; - if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80; - if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8; - if (c->hwfmt & AFMT_BIGENDIAN) + length &= DMA_ALIGN_MASK; + if (length == 0) + return; + + if (fmt & AFMT_SIGNED) + data = 0x00; + else + data = 0x80; + + if (fmt & AFMT_16BIT) + data <<= 8; + else + data |= data << 8; + + if (fmt & AFMT_BIGENDIAN) data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); - for (i = b->fp, p=(u_int16_t*)(b->buf+b->fp) ; i < b->bufsize && length; i += 2, length-=2) - *p++ = data; - for (i = 0, p=(u_int16_t*)b->buf; i < b->bufsize && length; i += 2, length-=2) - *p++ = data; - return; + i = b->fp; + p = (u_int16_t *)(b->buf + b->fp); + while (length > 0) { + *p++ = data; + length -= 2; + i += 2; + if (i >= b->bufsize) { + p = (u_int16_t *)b->buf; + i = 0; + } + } } void @@ -808,8 +847,7 @@ chn_resetbuf(pcm_channel *c) snd_dbuf *b = &c->buffer; snd_dbuf *bs = &c->buffer2nd; - c->smegcnt = 0; - + c->blocks = 0; b->sample_size = 1; b->sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0; b->sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0; @@ -821,7 +859,8 @@ chn_resetbuf(pcm_channel *c) b->prev_int_count = b->int_count = 0; b->first_poll = 1; b->underflow = 0; - chn_clearbuf(c, b, b->bufsize); + if (b->buf && b->bufsize > 0) + buf_clear(b, c->hwfmt, b->bufsize); bs->rp = bs->fp = 0; bs->dl = bs->rl = 0; @@ -830,7 +869,8 @@ chn_resetbuf(pcm_channel *c) b->prev_int_count = b->int_count = 0; b->first_poll = 1; b->underflow = 0; - chn_clearbuf(c, bs, bs->bufsize); + if (bs->buf && bs->bufsize > 0) + buf_clear(bs, c->hwfmt, bs->bufsize); } void @@ -905,24 +945,24 @@ chn_poll(pcm_channel *c, int ev, struct proc *p) int ret; s = spltty(); - if (c->direction == PCMDIR_PLAY) { - /* Fill up the DMA buffer. */ - chn_checkunderflow(c); - while(chn_wrfeed(c) > 0); - if (!b->dl) chn_wrintr(c); - } else { - /* Suck up the DMA buffer. */ - chn_dmaupdate(c); - while(chn_rdfeed(c) > 0); - if (!b->dl) chn_rdintr(c); + if (!(c->flags & CHN_F_MAPPED)) { + if (c->direction == PCMDIR_PLAY) { + /* Fill up the DMA buffer. */ + chn_checkunderflow(c); + while(chn_wrfeed(c) > 0); + if (!b->dl) chn_wrintr(c); + } else { + /* Suck up the DMA buffer. */ + chn_dmaupdate(c); + while(chn_rdfeed(c) > 0); + if (!b->dl) chn_rdintr(c); + } } ret = 0; if (chn_polltrigger(c) && chn_pollreset(c)) ret = ev; - else { + else selrecord(p, &bs->sel); - ret = 0; - } splx(s); return ret; } @@ -969,6 +1009,7 @@ chn_flush(pcm_channel *c) DEB(printf("chn_flush c->flags 0x%08x\n", c->flags)); c->flags |= CHN_F_CLOSING; + c->flags &= ~CHN_F_TRIGGERED; if (c->direction == PCMDIR_REC) chn_abort(c); else if (b->dl) { @@ -988,15 +1029,23 @@ chn_flush(pcm_channel *c) if (count == 0) DEB(printf("chn_flush: timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n", b->rl, c->flags)); c->flags &= ~CHN_F_CLOSING; - if (c->direction == PCMDIR_PLAY) chn_abort(c); + if (c->direction == PCMDIR_PLAY && b->dl) chn_abort(c); return 0; } int chn_reset(pcm_channel *c) { + int r; + chn_abort(c); c->flags &= CHN_F_RESET; + r = chn_setblocksize(c, CHN_2NDBUFBLKNUM, CHN_2NDBUFBLKSIZE); + if (r) + return r; + c->format = AFMT_U8; + c->speed = 8000; + c->volume = (100 << 8) | 100; chn_resetbuf(c); c->flags |= CHN_F_INIT; return 0; @@ -1025,20 +1074,13 @@ chn_init(pcm_channel *c, void *devinfo, int dir) c->feeder = &feeder_root; c->buffer.chan = -1; c->devinfo = c->init(devinfo, &c->buffer, c, dir); - if (c->devinfo == NULL) + if (c->devinfo == NULL || c->buffer.bufsize == 0) return 1; chn_setdir(c, dir); /* And the secondary buffer. */ - c->blocksize2nd = CHN_2NDBUFBLKSIZE; - c->fragments = CHN_2NDBUFBLKNUM; - bs->bufsize = c->blocksize2nd * c->fragments; - bs->buf = malloc(bs->bufsize, M_DEVBUF, M_NOWAIT); - if (bs->buf == NULL) - return 1; - bzero(bs->buf, bs->bufsize); - bs->rl = bs->rp = bs->fp = 0; - bs->fl = bs->bufsize; + bs->buf = NULL; + bs->bufsize = 0; return 0; } @@ -1094,63 +1136,47 @@ chn_setformat(pcm_channel *c, u_int32_t fmt) return 0; } -/* - * The seconday buffer is modified only during interrupt. - * Hence the size of the secondary buffer can be changed - * at any time as long as an interrupt is disabled. - */ int -chn_setblocksize(pcm_channel *c, int blksz) +chn_setblocksize(pcm_channel *c, int blkcnt, int blksz) { snd_dbuf *bs = &c->buffer2nd; - u_int8_t *tmpbuf; - int s, tmpbuf_fl, tmpbuf_fp, l; + int s, bufsz; + if (c->flags & CHN_F_MAPPED) { + DEB(printf("chn_setblocksize: can't work on mapped channel")); + return EINVAL; + } 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 < 2) blksz = c->buffer.sample_size * (c->speed >> 2); - /* XXX How small can the lower bound be? */ - RANGE(blksz, 64, CHN_2NDBUFWHOLESIZE); + /* default to blksz = ~0.25s */ + if (blksz < 16) blksz = (c->buffer.sample_size * c->speed) >> 2; + + bufsz = blkcnt * blksz; + if (blksz < 16 || bufsz > CHN_2NDBUFMAXSIZE) + return EINVAL; - /* - * Allocate a temporary buffer. It holds the pcm data - * until the size of the secondary buffer gets changed. - * bs->buf is not affected, so mmap should work fine. - */ - tmpbuf = malloc(blksz, M_TEMP, M_NOWAIT); - if (tmpbuf == NULL) { - DEB(printf("chn_setblocksize: out of memory.")); - return 1; - } - bzero(tmpbuf, blksz); - tmpbuf_fl = blksz; - tmpbuf_fp = 0; s = spltty(); - while (bs->rl > 0 && tmpbuf_fl > 0) { - l = min(min(bs->rl, bs->bufsize - bs->rp), tmpbuf_fl); - bcopy(bs->buf + bs->rp, tmpbuf + tmpbuf_fp, l); - tmpbuf_fl -= l; - tmpbuf_fp = (tmpbuf_fp + l) % blksz; - bs->rl -= l; - bs->fl += l; - bs->rp = (bs->rp + l) % bs->bufsize; + if (bs->buf != NULL) + free(bs->buf, M_DEVBUF); + bs->buf = malloc(bufsz, M_DEVBUF, M_WAITOK); + if (bs->buf == NULL) { + splx(s); + DEB(printf("chn_setblocksize: out of memory.")); + return ENOSPC; } - /* Change the size of the seconary buffer. */ - bs->bufsize = blksz; - c->fragments = CHN_2NDBUFBLKNUM; - c->blocksize2nd = bs->bufsize / c->fragments; - /* Clear the secondary buffer and restore the pcm data. */ - bzero(bs->buf, bs->bufsize); - bs->rl = bs->bufsize - tmpbuf_fl; - bs->rp = 0; - bs->fl = tmpbuf_fl; - bs->fp = tmpbuf_fp; - bcopy(tmpbuf, bs->buf, bs->rl); - - free(tmpbuf, M_TEMP); + bs->bufsize = bufsz; + bs->rl = bs->rp = bs->fp = 0; + bs->fl = bs->bufsize; + buf_clear(bs, c->hwfmt, bs->bufsize); + c->fragments = blkcnt; + c->blocksize2nd = blksz; + RANGE(blksz, 16, c->buffer.bufsize / 2); + c->blocksize = c->setblocksize(c->devinfo, blksz); splx(s); - return c->blocksize2nd; + + return 0; } int @@ -1164,8 +1190,9 @@ chn_getptr(pcm_channel *c) { int hwptr; int a = (1 << c->align) - 1; + snd_dbuf *b = &c->buffer; - hwptr=c->getptr(c->devinfo); + hwptr = b->dl? c->getptr(c->devinfo) : 0; /* don't allow unaligned values in the hwa ptr */ hwptr &= ~a ; /* Apply channel align mask */ hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index dd1ee01..c323fe4 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -39,7 +39,7 @@ int chn_reset(pcm_channel *c); int chn_setvolume(pcm_channel *c, int left, int right); int chn_setspeed(pcm_channel *c, int speed); int chn_setformat(pcm_channel *c, u_int32_t fmt); -int chn_setblocksize(pcm_channel *c, int blksz); +int chn_setblocksize(pcm_channel *c, int blkcnt, int blksz); int chn_trigger(pcm_channel *c, int go); int chn_getptr(pcm_channel *c); pcmchan_caps *chn_getcaps(pcm_channel *c); @@ -92,4 +92,4 @@ extern pcm_feeder feeder_root; /* The total number of blocks per secondary buffer. */ #define CHN_2NDBUFBLKNUM (32) /* The size of a whole secondary buffer. */ -#define CHN_2NDBUFWHOLESIZE (CHN_2NDBUFBLKSIZE * CHN_2NDBUFBLKNUM) +#define CHN_2NDBUFMAXSIZE (131072) diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h index 6aba9c2..550d0b7 100644 --- a/sys/dev/sound/pcm/datatypes.h +++ b/sys/dev/sound/pcm/datatypes.h @@ -119,17 +119,12 @@ struct _pcm_channel { u_int32_t speed; u_int32_t flags; u_int32_t format, hwfmt; - u_int32_t blocksize; - u_int32_t blocksize2nd; - u_int32_t fragments; + u_int32_t blocksize, blocksize2nd; + u_int32_t fragments, blocks; int direction; - snd_dbuf buffer; -#define SMEGBUFSZ 4 - u_int8_t smegbuf[SMEGBUFSZ]; - u_int32_t smegcnt; + snd_dbuf buffer, buffer2nd; void *devinfo; - snd_dbuf buffer2nd; }; typedef void (pcm_swap_t)(void *data, int dir); diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 5ad60bd..3ea13a6 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -130,7 +130,6 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype) rdch->volume = (100 << 8) | 100; rdch->format = fmt; rdch->speed = DSP_DEFAULT_SPEED; - rdch->blocksize = 2048; } } if (wrch && (oflags & FWRITE)) { @@ -140,7 +139,6 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype) wrch->volume = (100 << 8) | 100; wrch->format = fmt; wrch->speed = DSP_DEFAULT_SPEED; - wrch->blocksize = 2048; } } return 0; @@ -160,10 +158,12 @@ dsp_close(snddev_info *d, int chan, int devtype) if (rdch) { chn_abort(rdch); rdch->flags &= ~(CHN_F_BUSY | CHN_F_RUNNING | CHN_F_MAPPED); + chn_reset(rdch); } if (wrch) { chn_flush(wrch); wrch->flags &= ~(CHN_F_BUSY | CHN_F_RUNNING | CHN_F_MAPPED); + chn_reset(wrch); } d->aplay[chan] = NULL; d->arec[chan] = NULL; @@ -222,7 +222,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) */ s = spltty(); switch(cmd) { - +#ifdef OLDPCM_IOCTL /* * we start with the new ioctl interface. */ @@ -317,9 +317,11 @@ 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) { @@ -343,8 +345,9 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) break ; case SNDCTL_DSP_SETBLKSIZE: - if (wrch) chn_setblocksize(wrch, *arg_i); - if (rdch) chn_setblocksize(rdch, *arg_i); + RANGE(*arg_i, 16, 65536); + if (wrch) chn_setblocksize(wrch, 2, *arg_i); + if (rdch) chn_setblocksize(rdch, 2, *arg_i); break; case SNDCTL_DSP_RESET: @@ -411,32 +414,29 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) /* XXX watch out, this is RW! */ DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg)); { - int bytes = 1 << min(*arg_i & 0xffff, 16); - int count = (*arg_i >> 16) & 0xffff; pcm_channel *c = wrch? wrch : rdch; - if (count == 0) - count = CHN_2NDBUFWHOLESIZE / bytes; - if (count < 2) { + u_int32_t fragln = (*arg_i) & 0x0000ffff; + u_int32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16; + u_int32_t fragsz; + + RANGE(fragln, 4, 16); + fragsz = 1 << fragln; + + if (maxfrags == 0) + maxfrags = CHN_2NDBUFMAXSIZE / fragsz; + if (maxfrags < 2) { ret = EINVAL; break; } - if (rdch) { - chn_setblocksize(rdch, bytes * count); - rdch->blocksize2nd = bytes; - rdch->fragments = rdch->buffer2nd.bufsize / rdch->blocksize2nd; - } - if (wrch) { - chn_setblocksize(wrch, bytes * count); - wrch->blocksize2nd = bytes; - wrch->fragments = wrch->buffer2nd.bufsize / wrch->blocksize2nd; - } + if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE) + maxfrags = CHN_2NDBUFMAXSIZE / fragsz; - /* eg: 4dwave can only interrupt at buffer midpoint, so - * it will force blocksize == bufsize/2 - */ - count = c->buffer2nd.bufsize / c->blocksize2nd; - bytes = ffs(c->blocksize2nd) - 1; - *arg_i = (count << 16) | bytes; + if (rdch) + ret = chn_setblocksize(rdch, maxfrags, fragsz); + if (wrch && ret == 0) + ret = chn_setblocksize(wrch, maxfrags, fragsz); + + *arg_i = (c->fragments << 16) | fragsz; } break; @@ -447,7 +447,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) if (rdch) { snd_dbuf *b = &rdch->buffer; snd_dbuf *bs = &rdch->buffer2nd; - if (b->dl) + if (b->dl && !(rdch->flags & CHN_F_MAPPED)) /* * Suck up the secondary and DMA buffer. * chn_rdfeed*() takes care of the alignment. @@ -455,7 +455,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) while (chn_rdfeed(rdch) > 0); a->bytes = bs->rl; a->fragments = a->bytes / rdch->blocksize2nd; - a->fragstotal = bs->bufsize / rdch->blocksize2nd; + a->fragstotal = rdch->fragments; a->fragsize = rdch->blocksize2nd; } } @@ -468,7 +468,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) if (wrch) { snd_dbuf *b = &wrch->buffer; snd_dbuf *bs = &wrch->buffer2nd; - if (b->dl) { + if (b->dl && !(wrch->flags & CHN_F_MAPPED)) { /* * Fill up the secondary and DMA buffer. * chn_wrfeed*() takes care of the alignment. @@ -479,7 +479,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) } a->bytes = bs->fl; a->fragments = a->bytes / wrch->blocksize2nd; - a->fragstotal = bs->bufsize / wrch->blocksize2nd; + a->fragstotal = wrch->fragments; a->fragsize = wrch->blocksize2nd; } } @@ -491,7 +491,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) if (rdch) { snd_dbuf *b = &rdch->buffer; snd_dbuf *bs = &rdch->buffer2nd; - if (b->dl) + if (b->dl && !(rdch->flags & CHN_F_MAPPED)) /* * Suck up the secondary and DMA buffer. * chn_rdfeed*() takes care of the alignment. @@ -510,7 +510,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) if (wrch) { snd_dbuf *b = &wrch->buffer; snd_dbuf *bs = &wrch->buffer2nd; - if (b->dl) { + if (b->dl && !(wrch->flags & CHN_F_MAPPED)) { /* * Fill up the secondary and DMA buffer. * chn_wrfeed*() takes care of the alignment. @@ -520,8 +520,9 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) while (chn_wrfeed(wrch) > 0); } a->bytes = bs->total; - a->blocks = bs->rl / wrch->blocksize2nd; - a->ptr = bs->fl % wrch->blocksize2nd; + a->blocks = wrch->blocks; + a->ptr = bs->rp; + wrch->blocks = 0; } else ret = EINVAL; } break; @@ -564,7 +565,8 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) snd_dbuf *b = &wrch->buffer; if (b->dl) { chn_checkunderflow(wrch); - while (chn_wrfeed(wrch) > 0); + if (!(wrch->flags & CHN_F_MAPPED)) + while (chn_wrfeed(wrch) > 0); } *arg = b->total; } else @@ -613,7 +615,6 @@ dsp_mmap(snddev_info *d, int chan, vm_offset_t offset, int nprot) if (1 || (wrch && (nprot & PROT_WRITE))) c = wrch; else if (rdch && (nprot & PROT_READ)) c = rdch; if (c) { - printf("dsp_mmap.\n"); c->flags |= CHN_F_MAPPED; return atop(vtophys(c->buffer2nd.buf + offset)); } diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c index cc45a5c..5eaf89a 100644 --- a/sys/dev/sound/pcm/feeder.c +++ b/sys/dev/sound/pcm/feeder.c @@ -113,11 +113,6 @@ feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count count &= ~((1 << ch->align) - 1); KASSERT(count, ("feed_root: aligned count == 0")); s = spltty(); - if (ch->smegcnt > 0) { - c = min(ch->smegcnt, count); - bcopy(ch->smegbuf, buffer, c); - ch->smegcnt -= c; - } count = min(count, stream->uio_resid); if (count) { ret = uiomove(buffer, count, stream); |