summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-12-23 03:16:13 +0000
committercg <cg@FreeBSD.org>2000-12-23 03:16:13 +0000
commitd0b795f25b705ff883368ba3e49f31c3541d3b11 (patch)
tree076eb63fe5bbf4764062f83df117a0ee11cfc3ed /sys
parent818087b543b4be6d1211cb39cb7b7204e9ae9f6c (diff)
downloadFreeBSD-src-d0b795f25b705ff883368ba3e49f31c3541d3b11.zip
FreeBSD-src-d0b795f25b705ff883368ba3e49f31c3541d3b11.tar.gz
update code dealing with snd_dbuf objects to do so using a functional interface
modify chn_setblocksize() to pick a default soft-blocksize appropriate to the sample rate and format in use. it will aim for a power of two size small enough to generate block sizes of at most 20ms. it will also set the hard-blocksize taking into account rate/format conversions in use. update drivers to implement setblocksize correctly: updated, tested: sb16, emu10k1, maestro, solo updated, untested: ad1816, ess, mss, sb8, csa not updated: ds1, es137x, fm801, neomagic, t4dwave, via82c686 i lack hardware to test: ad1816, csa, fm801, neomagic others will be updated/tested in the next few days.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/isa/ad1816.c23
-rw-r--r--sys/dev/sound/isa/ess.c22
-rw-r--r--sys/dev/sound/isa/mss.c82
-rw-r--r--sys/dev/sound/isa/sb16.c77
-rw-r--r--sys/dev/sound/isa/sb8.c22
-rw-r--r--sys/dev/sound/pci/aureal.c5
-rw-r--r--sys/dev/sound/pci/csapcm.c18
-rw-r--r--sys/dev/sound/pci/ds1.c14
-rw-r--r--sys/dev/sound/pci/emu10k1.c69
-rw-r--r--sys/dev/sound/pci/es137x.c20
-rw-r--r--sys/dev/sound/pci/fm801.c5
-rw-r--r--sys/dev/sound/pci/maestro.c21
-rw-r--r--sys/dev/sound/pci/neomagic.c3
-rw-r--r--sys/dev/sound/pci/solo.c16
-rw-r--r--sys/dev/sound/pci/t4dwave.c24
-rw-r--r--sys/dev/sound/pci/via82c686.c13
-rw-r--r--sys/dev/sound/pcm/buffer.c244
-rw-r--r--sys/dev/sound/pcm/buffer.h49
-rw-r--r--sys/dev/sound/pcm/channel.c276
-rw-r--r--sys/dev/sound/pcm/channel.h7
-rw-r--r--sys/dev/sound/pcm/datatypes.h9
-rw-r--r--sys/dev/sound/pcm/dsp.c14
-rw-r--r--sys/dev/sound/pcm/mixer.c4
-rw-r--r--sys/dev/sound/pcm/sound.h1
24 files changed, 638 insertions, 400 deletions
diff --git a/sys/dev/sound/isa/ad1816.c b/sys/dev/sound/isa/ad1816.c
index d6e1dd7..f83aafb 100644
--- a/sys/dev/sound/isa/ad1816.c
+++ b/sys/dev/sound/isa/ad1816.c
@@ -39,7 +39,7 @@ struct ad1816_chinfo {
struct ad1816_info *parent;
pcm_channel *channel;
snd_dbuf *buffer;
- int dir;
+ int dir, blksz;
};
struct ad1816_info {
@@ -131,12 +131,12 @@ ad1816_intr(void *arg)
c &= AD1816_INTRCI | AD1816_INTRPI;
}
/* check for capture interupt */
- if (ad1816->rch.buffer->dl && (c & AD1816_INTRCI)) {
+ if (sndbuf_runsz(ad1816->rch.buffer) && (c & AD1816_INTRCI)) {
chn_intr(ad1816->rch.channel);
served |= AD1816_INTRCI; /* cp served */
}
/* check for playback interupt */
- if (ad1816->pch.buffer->dl && (c & AD1816_INTRPI)) {
+ if (sndbuf_runsz(ad1816->pch.buffer) && (c & AD1816_INTRPI)) {
chn_intr(ad1816->pch.channel);
served |= AD1816_INTRPI; /* pb served */
}
@@ -311,8 +311,7 @@ ad1816chan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = ad1816;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = DSP_BUFFSIZE;
- if (chn_allocbuf(ch->buffer, ad1816->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, DSP_BUFFSIZE) == -1) return NULL;
return ch;
}
@@ -322,8 +321,7 @@ ad1816chan_setdir(kobj_t obj, void *data, int dir)
struct ad1816_chinfo *ch = data;
struct ad1816_info *ad1816 = ch->parent;
- ch->buffer->chan = rman_get_start((dir == PCMDIR_PLAY)?
- ad1816->drq1 : ad1816->drq2);
+ sndbuf_isadmasetup(ch->buffer, (dir == PCMDIR_PLAY)? ad1816->drq1 : ad1816->drq2);
ch->dir = dir;
return 0;
}
@@ -384,7 +382,10 @@ ad1816chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
ad1816chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
- return blocksize;
+ struct ad1816_chinfo *ch = data;
+
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
@@ -397,14 +398,14 @@ ad1816chan_trigger(kobj_t obj, void *data, int go)
if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
return 0;
- buf_isadma(ch->buffer, go);
+ sndbuf_isadma(ch->buffer, go);
wr = (ch->dir == PCMDIR_PLAY);
reg = wr? AD1816_PLAY : AD1816_CAPT;
switch (go) {
case PCMTRIG_START:
/* start only if not already running */
if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) {
- int cnt = ((ch->buffer->dl) >> 2) - 1;
+ int cnt = ((ch->blksz) >> 2) - 1;
ad1816_write(ad1816, wr? 8 : 10, cnt); /* count */
ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */
ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) |
@@ -441,7 +442,7 @@ static int
ad1816chan_getptr(kobj_t obj, void *data)
{
struct ad1816_chinfo *ch = data;
- return buf_isadmaptr(ch->buffer);
+ return sndbuf_isadmaptr(ch->buffer);
}
static pcmchan_caps *
diff --git a/sys/dev/sound/isa/ess.c b/sys/dev/sound/isa/ess.c
index f353289..b9c8362 100644
--- a/sys/dev/sound/isa/ess.c
+++ b/sys/dev/sound/isa/ess.c
@@ -82,7 +82,7 @@ struct ess_chinfo {
pcm_channel *channel;
snd_dbuf *buffer;
int dir, hwch, stopping, run;
- u_int32_t fmt, spd;
+ u_int32_t fmt, spd, blksz;
};
struct ess_info {
@@ -358,7 +358,7 @@ ess_intr(void *arg)
printf("ess: play intr while not running\n");
if (sc->pch.stopping) {
sc->pch.run = 0;
- buf_isadma(sc->pch.buffer, PCMTRIG_STOP);
+ sndbuf_isadma(sc->pch.buffer, PCMTRIG_STOP);
sc->pch.stopping = 0;
if (sc->pch.hwch == 1)
ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
@@ -373,7 +373,7 @@ ess_intr(void *arg)
printf("ess: record intr while not running\n");
if (sc->rch.stopping) {
sc->rch.run = 0;
- buf_isadma(sc->rch.buffer, PCMTRIG_STOP);
+ sndbuf_isadma(sc->rch.buffer, PCMTRIG_STOP);
sc->rch.stopping = 0;
/* XXX: will this stop audio2? */
ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
@@ -509,7 +509,7 @@ ess_start(struct ess_chinfo *ch)
struct ess_info *sc = ch->parent;
int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
- ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->buffer->dl);
+ ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz);
ch->stopping = 0;
if (ch->hwch == 1)
ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01);
@@ -547,14 +547,13 @@ esschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = sc;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = ESS_BUFFSIZE;
- if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, ESS_BUFFSIZE) == -1)
return NULL;
ch->dir = dir;
ch->hwch = 1;
if ((dir == PCMDIR_PLAY) && (sc->duplex))
ch->hwch = 2;
- ch->buffer->chan = rman_get_start((ch->hwch == 1)? sc->drq1 : sc->drq2);
+ sndbuf_isadmasetup(ch->buffer, (ch->hwch == 1)? sc->drq1 : sc->drq2);
return ch;
}
@@ -584,7 +583,10 @@ esschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
- return blocksize;
+ struct ess_chinfo *ch = data;
+
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
@@ -598,7 +600,7 @@ esschan_trigger(kobj_t obj, void *data, int go)
switch (go) {
case PCMTRIG_START:
ch->run = 1;
- buf_isadma(ch->buffer, go);
+ sndbuf_isadma(ch->buffer, go);
ess_start(ch);
break;
@@ -616,7 +618,7 @@ esschan_getptr(kobj_t obj, void *data)
{
struct ess_chinfo *ch = data;
- return buf_isadmaptr(ch->buffer);
+ return sndbuf_isadmaptr(ch->buffer);
}
static pcmchan_caps *
diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c
index 3c6a126..a1802d4 100644
--- a/sys/dev/sound/isa/mss.c
+++ b/sys/dev/sound/isa/mss.c
@@ -48,7 +48,7 @@ struct mss_chinfo {
pcm_channel *channel;
snd_dbuf *buffer;
int dir;
- u_int32_t fmt;
+ u_int32_t fmt, blksz;
};
struct mss_info {
@@ -67,7 +67,6 @@ struct mss_info {
char mss_indexed_regs[MSS_INDEXED_REGS];
char opl_indexed_regs[OPL_INDEXED_REGS];
- int pdma, rdma;
int bd_id; /* used to hold board-id info, eg. sb version,
* mss codec type, etc. etc.
*/
@@ -242,19 +241,17 @@ mss_release_resources(struct mss_info *mss, device_t dev)
mss->irq);
mss->irq = 0;
}
- if (mss->drq1) {
- bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid,
- mss->drq1);
- mss->drq1 = 0;
- mss->pdma = -1;
- }
- if (mss->drq2) {
+ if (mss->drq2 && mss->drq2 != mss->drq1) {
bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid,
mss->drq2);
mss->drq2 = 0;
- mss->rdma = -1;
}
- if (mss->io_base) {
+ if (mss->drq1) {
+ bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid,
+ mss->drq1);
+ mss->drq1 = 0;
+ }
+ if (mss->io_base) {
bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid,
mss->io_base);
mss->io_base = 0;
@@ -274,7 +271,7 @@ mss_release_resources(struct mss_info *mss, device_t dev)
static int
mss_alloc_resources(struct mss_info *mss, device_t dev)
{
- int ok = 1;
+ int pdma, rdma, ok = 1;
if (!mss->io_base)
mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid,
0, ~0, 1, RF_ACTIVE);
@@ -296,16 +293,16 @@ mss_alloc_resources(struct mss_info *mss, device_t dev)
if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0;
if (ok) {
- mss->pdma = rman_get_start(mss->drq1);
- isa_dma_acquire(mss->pdma);
- isa_dmainit(mss->pdma, MSS_BUFFSIZE);
+ pdma = rman_get_start(mss->drq1);
+ isa_dma_acquire(pdma);
+ isa_dmainit(pdma, MSS_BUFFSIZE);
mss->bd_flags &= ~BD_F_DUPLEX;
if (mss->drq2) {
- mss->rdma = rman_get_start(mss->drq2);
- isa_dma_acquire(mss->rdma);
- isa_dmainit(mss->rdma, MSS_BUFFSIZE);
+ rdma = rman_get_start(mss->drq2);
+ isa_dma_acquire(rdma);
+ isa_dmainit(rdma, MSS_BUFFSIZE);
mss->bd_flags |= BD_F_DUPLEX;
- } else mss->rdma = mss->pdma;
+ } else mss->drq2 = mss->drq1;
}
return ok;
}
@@ -691,11 +688,11 @@ mss_intr(void *arg)
/* get exact reason for full-duplex boards */
c = FULL_DUPLEX(mss)? ad_read(mss, 24) : 0x30;
c &= ~served;
- if (mss->pch.buffer->dl && (c & 0x10)) {
+ if (sndbuf_runsz(mss->pch.buffer) && (c & 0x10)) {
served |= 0x10;
chn_intr(mss->pch.channel);
}
- if (mss->rch.buffer->dl && (c & 0x20)) {
+ if (sndbuf_runsz(mss->rch.buffer) && (c & 0x20)) {
served |= 0x20;
chn_intr(mss->rch.channel);
}
@@ -935,7 +932,7 @@ mss_trigger(struct mss_chinfo *ch, int go)
m = ad_read(mss, 9);
switch (go) {
case PCMTRIG_START:
- cnt = (ch->buffer->dl / ss) - 1;
+ cnt = (ch->blksz / ss) - 1;
DEB(if (m & 4) printf("OUCH! reg 9 0x%02x\n", m););
m |= wr? I9_PEN : I9_CEN; /* enable DMA */
@@ -1015,8 +1012,8 @@ opti931_intr(void *arg)
return;
}
- if (mss->rch.buffer->dl && (mc11 & 8)) chn_intr(mss->rch.channel);
- if (mss->pch.buffer->dl && (mc11 & 4)) chn_intr(mss->pch.channel);
+ if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) chn_intr(mss->rch.channel);
+ if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) chn_intr(mss->pch.channel);
opti_wr(mss, 11, ~mc11); /* ack */
if (--loops) goto again;
DEB(printf("xxx too many loops\n");)
@@ -1033,10 +1030,9 @@ msschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = mss;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = MSS_BUFFSIZE;
- ch->buffer->chan = (dir == PCMDIR_PLAY)? mss->pdma : mss->rdma;
ch->dir = dir;
- if (chn_allocbuf(ch->buffer, mss->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, mss->parent_dmat, MSS_BUFFSIZE) == -1) return NULL;
+ sndbuf_isadmasetup(ch->buffer, (dir == PCMDIR_PLAY)? mss->drq1 : mss->drq2);
return ch;
}
@@ -1060,7 +1056,10 @@ msschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
msschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
- return blocksize;
+ struct mss_chinfo *ch = data;
+
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
@@ -1071,7 +1070,7 @@ msschan_trigger(kobj_t obj, void *data, int go)
if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
return 0;
- buf_isadma(ch->buffer, go);
+ sndbuf_isadma(ch->buffer, go);
mss_trigger(ch, go);
return 0;
}
@@ -1080,7 +1079,7 @@ static int
msschan_getptr(kobj_t obj, void *data)
{
struct mss_chinfo *ch = data;
- return buf_isadmaptr(ch->buffer);
+ return sndbuf_isadmaptr(ch->buffer);
}
static pcmchan_caps *
@@ -1496,11 +1495,13 @@ ymf_test(device_t dev, struct mss_info *mss)
static int
mss_doattach(device_t dev, struct mss_info *mss)
{
- int flags = device_get_flags(dev);
+ int pdma, rdma, flags = device_get_flags(dev);
char status[SND_STATUSLEN];
if (!mss_alloc_resources(mss, dev)) goto no;
mss_init(mss, dev);
+ pdma = rman_get_start(mss->drq1);
+ rdma = rman_get_start(mss->drq2);
if (flags & DV_F_TRUE_MSS) {
/* has IRQ/DMA registers, set IRQ and DMA addr */
#ifdef PC98 /* CS423[12] in PC98 can use IRQ3,5,10,12 */
@@ -1521,13 +1522,12 @@ mss_doattach(device_t dev, struct mss_info *mss)
if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?\n");
#endif
/* Write IRQ+DMA setup */
- if (pdma_bits[mss->pdma] == -1) goto no;
- bits |= pdma_bits[mss->pdma];
- if (mss->pdma != mss->rdma) {
- if (mss->rdma == valid_rdma[mss->pdma]) bits |= 4;
+ if (pdma_bits[pdma] == -1) goto no;
+ bits |= pdma_bits[pdma];
+ if (pdma != rdma) {
+ if (rdma == valid_rdma[pdma]) bits |= 4;
else {
- printf("invalid dual dma config %d:%d\n",
- mss->pdma, mss->rdma);
+ printf("invalid dual dma config %d:%d\n", pdma, rdma);
goto no;
}
}
@@ -1542,7 +1542,7 @@ mss_doattach(device_t dev, struct mss_info *mss)
default:
bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, mss_intr, mss, &mss->ih);
}
- if (mss->pdma == mss->rdma)
+ if (pdma == rdma)
pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
@@ -1555,9 +1555,9 @@ mss_doattach(device_t dev, struct mss_info *mss)
goto no;
}
snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d",
- rman_get_start(mss->io_base), rman_get_start(mss->irq), mss->pdma);
- if (mss->pdma != mss->rdma) snprintf(status + strlen(status),
- SND_STATUSLEN - strlen(status), ":%d", mss->rdma);
+ rman_get_start(mss->io_base), rman_get_start(mss->irq), pdma);
+ if (pdma != rdma) snprintf(status + strlen(status),
+ SND_STATUSLEN - strlen(status), ":%d", rdma);
if (pcm_register(dev, mss, 1, 1)) goto no;
pcm_addchan(dev, PCMDIR_REC, &msschan_class, mss);
diff --git a/sys/dev/sound/isa/sb16.c b/sys/dev/sound/isa/sb16.c
index e1485fa..ce69b54 100644
--- a/sys/dev/sound/isa/sb16.c
+++ b/sys/dev/sound/isa/sb16.c
@@ -84,7 +84,7 @@ struct sb_info {
int bd_id;
u_long bd_flags; /* board-specific flags */
- int dl, dh, prio, prio16;
+ int prio, prio16;
struct sb_chinfo pch, rch;
};
@@ -370,15 +370,15 @@ sb16_release_resources(struct sb_info *sb, device_t dev)
bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
sb->irq = 0;
}
- if (sb->drq1) {
- bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
- sb->drq1 = 0;
- }
- if (sb->drq2) {
+ if (sb->drq2 && (sb->drq2 != sb->drq2)) {
bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
sb->drq2 = 0;
}
- if (sb->io_base) {
+ if (sb->drq1) {
+ bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
+ sb->drq1 = 0;
+ }
+ if (sb->io_base) {
bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
sb->io_base = 0;
}
@@ -419,6 +419,9 @@ sb16_alloc_resources(struct sb_info *sb, device_t dev)
if (sb->drq2) {
isa_dma_acquire(rman_get_start(sb->drq2));
isa_dmainit(rman_get_start(sb->drq2), bs);
+ } else {
+ sb->drq2 = sb->drq1;
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
}
return 0;
} else return ENXIO;
@@ -458,15 +461,15 @@ sb_intr(void *arg)
}
} else {
if (c & 1) { /* 8-bit dma */
- if (sb->pch.dch == sb->dl)
+ if (sb->pch.dch == 1)
reason |= 1;
- if (sb->rch.dch == sb->dl)
+ if (sb->rch.dch == 1)
reason |= 2;
}
if (c & 2) { /* 16-bit dma */
- if (sb->pch.dch == sb->dh)
+ if (sb->pch.dch == 2)
reason |= 1;
- if (sb->rch.dch == sb->dh)
+ if (sb->rch.dch == 2)
reason |= 2;
}
}
@@ -494,38 +497,43 @@ sb_setup(struct sb_info *sb)
int l, pprio;
if (sb->bd_flags & BD_F_DMARUN)
- buf_isadma(sb->pch.buffer, PCMTRIG_STOP);
+ sndbuf_isadma(sb->pch.buffer, PCMTRIG_STOP);
if (sb->bd_flags & BD_F_DMARUN2)
- buf_isadma(sb->rch.buffer, PCMTRIG_STOP);
+ sndbuf_isadma(sb->rch.buffer, PCMTRIG_STOP);
sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2);
sb_reset_dsp(sb);
if (sb->bd_flags & BD_F_SB16X) {
pprio = sb->pch.run? 1 : 0;
- sb->pch.buffer->chan = pprio? sb->dl : -1;
- sb->rch.buffer->chan = pprio? sb->dh : sb->dl;
+ sndbuf_isadmasetup(sb->pch.buffer, pprio? sb->drq1 : NULL);
+ sb->pch.dch = pprio? 1 : 0;
+ sndbuf_isadmasetup(sb->rch.buffer, pprio? sb->drq2 : sb->drq1);
+ sb->rch.dch = pprio? 2 : 1;
} else {
if (sb->pch.run && sb->rch.run) {
pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1;
- sb->pch.buffer->chan = pprio? sb->dh : sb->dl;
- sb->rch.buffer->chan = pprio? sb->dl : sb->dh;
+ sndbuf_isadmasetup(sb->pch.buffer, pprio? sb->drq2 : sb->drq1);
+ sb->pch.dch = pprio? 2 : 1;
+ sndbuf_isadmasetup(sb->rch.buffer, pprio? sb->drq1 : sb->drq2);
+ sb->rch.dch = pprio? 1 : 2;
} else {
if (sb->pch.run) {
- sb->pch.buffer->chan = (sb->pch.fmt & AFMT_16BIT)? sb->dh : sb->dl;
- sb->rch.buffer->chan = (sb->pch.fmt & AFMT_16BIT)? sb->dl : sb->dh;
+ sndbuf_isadmasetup(sb->pch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
+ sb->pch.dch = (sb->pch.fmt & AFMT_16BIT)? 2 : 1;
+ sndbuf_isadmasetup(sb->rch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
+ sb->rch.dch = (sb->pch.fmt & AFMT_16BIT)? 1 : 2;
} else if (sb->rch.run) {
- sb->pch.buffer->chan = (sb->rch.fmt & AFMT_16BIT)? sb->dl : sb->dh;
- sb->rch.buffer->chan = (sb->rch.fmt & AFMT_16BIT)? sb->dh : sb->dl;
+ sndbuf_isadmasetup(sb->pch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
+ sb->pch.dch = (sb->rch.fmt & AFMT_16BIT)? 1 : 2;
+ sndbuf_isadmasetup(sb->rch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
+ sb->rch.dch = (sb->rch.fmt & AFMT_16BIT)? 2 : 1;
}
}
}
- sb->pch.dch = sb->pch.buffer->chan;
- sb->rch.dch = sb->rch.buffer->chan;
-
- sb->pch.buffer->dir = ISADMA_WRITE;
- sb->rch.buffer->dir = ISADMA_READ;
+ sndbuf_isadmasetdir(sb->pch.buffer, PCMDIR_PLAY);
+ sndbuf_isadmasetdir(sb->rch.buffer, PCMDIR_REC);
/*
printf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]\n",
@@ -553,7 +561,7 @@ sb_setup(struct sb_info *sb)
v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
sb_cmd2(sb, v, l);
- buf_isadma(ch->buffer, PCMTRIG_START);
+ sndbuf_isadma(ch->buffer, PCMTRIG_START);
sb->bd_flags |= BD_F_DMARUN;
}
@@ -578,7 +586,7 @@ sb_setup(struct sb_info *sb)
v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
sb_cmd2(sb, v, l);
- buf_isadma(ch->buffer, PCMTRIG_START);
+ sndbuf_isadma(ch->buffer, PCMTRIG_START);
sb->bd_flags |= BD_F_DMARUN2;
}
@@ -595,10 +603,9 @@ sb16chan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = sb;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = SB16_BUFFSIZE;
ch->dir = dir;
- if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sb->parent_dmat, SB16_BUFFSIZE) == -1)
return NULL;
return ch;
@@ -632,7 +639,7 @@ sb16chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
struct sb_chinfo *ch = data;
ch->blksz = blocksize;
- return blocksize;
+ return ch->blksz;
}
static int
@@ -659,7 +666,7 @@ sb16chan_getptr(kobj_t obj, void *data)
{
struct sb_chinfo *ch = data;
- return buf_isadmaptr(ch->buffer);
+ return sndbuf_isadmaptr(ch->buffer);
}
static pcmchan_caps *
@@ -749,11 +756,9 @@ sb16_attach(device_t dev)
if (bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &sb->ih))
goto no;
- if (!sb->drq2 || (sb->bd_flags & BD_F_SB16X))
+ if (sb->bd_flags & BD_F_SB16X)
pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
- sb->dl = rman_get_start(sb->drq1);
- sb->dh = sb->drq2? rman_get_start(sb->drq2) : sb->dl;
sb->prio = 0;
if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
@@ -770,7 +775,7 @@ sb16_attach(device_t dev)
snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld",
rman_get_start(sb->io_base), rman_get_start(sb->irq),
rman_get_start(sb->drq1));
- if (sb->drq2)
+ if (!(pcm_getflags(dev) & SD_F_SIMPLEX))
snprintf(status + strlen(status), SND_STATUSLEN - strlen(status),
":%ld", rman_get_start(sb->drq2));
diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c
index b2e66b3..39a8f95 100644
--- a/sys/dev/sound/isa/sb8.c
+++ b/sys/dev/sound/isa/sb8.c
@@ -64,7 +64,7 @@ struct sb_chinfo {
pcm_channel *channel;
snd_dbuf *buffer;
int dir;
- u_int32_t fmt, spd;
+ u_int32_t fmt, spd, blksz;
};
struct sb_info {
@@ -463,10 +463,10 @@ sb_intr(void *arg)
{
struct sb_info *sb = (struct sb_info *)arg;
- if (sb->pch.buffer->dl > 0)
+ if (sndbuf_runsz(sb->pch.buffer) > 0)
chn_intr(sb->pch.channel);
- if (sb->rch.buffer->dl > 0)
+ if (sndbuf_runsz(sb->rch.buffer) > 0)
chn_intr(sb->rch.channel);
sb_rd(sb, DSP_DATA_AVAIL); /* int ack */
@@ -517,7 +517,7 @@ sb_start(struct sb_chinfo *ch)
struct sb_info *sb = ch->parent;
int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
- int l = ch->buffer->dl;
+ int l = ch->blksz;
u_char i;
l--;
@@ -566,10 +566,9 @@ sbchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->channel = c;
ch->dir = dir;
ch->buffer = b;
- ch->buffer->bufsize = SB_BUFFSIZE;
- ch->buffer->chan = rman_get_start(sb->drq);
- if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sb->parent_dmat, SB_BUFFSIZE) == -1)
return NULL;
+ sndbuf_isadmasetup(ch->buffer, sb->drq);
return ch;
}
@@ -594,7 +593,10 @@ sbchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
sbchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
- return blocksize;
+ struct sb_chinfo *ch = data;
+
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
@@ -605,7 +607,7 @@ sbchan_trigger(kobj_t obj, void *data, int go)
if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
return 0;
- buf_isadma(ch->buffer, go);
+ sndbuf_isadma(ch->buffer, go);
if (go == PCMTRIG_START)
sb_start(ch);
else
@@ -618,7 +620,7 @@ sbchan_getptr(kobj_t obj, void *data)
{
struct sb_chinfo *ch = data;
- return buf_isadmaptr(ch->buffer);
+ return sndbuf_isadmaptr(ch->buffer);
}
static pcmchan_caps *
diff --git a/sys/dev/sound/pci/aureal.c b/sys/dev/sound/pci/aureal.c
index e957b07..09ead9f 100644
--- a/sys/dev/sound/pci/aureal.c
+++ b/sys/dev/sound/pci/aureal.c
@@ -242,7 +242,7 @@ au_prepareoutput(struct au_chinfo *ch, u_int32_t format)
{
struct au_info *au = ch->parent;
int i, stereo = (format & AFMT_STEREO)? 1 : 0;
- u_int32_t baseaddr = vtophys(ch->buffer->buf);
+ u_int32_t baseaddr = vtophys(sndbuf_getbuf(ch->buffer));
au_wr(au, 0, 0x1061c, 0, 4);
au_wr(au, 0, 0x10620, 0, 4);
@@ -301,9 +301,8 @@ auchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = au;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = AU_BUFFSIZE;
ch->dir = dir;
- if (chn_allocbuf(ch->buffer, au->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, au->parent_dmat, AU_BUFFSIZE) == -1) return NULL;
return ch;
}
diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c
index c3ae93e..8bad7b5 100644
--- a/sys/dev/sound/pci/csapcm.c
+++ b/sys/dev/sound/pci/csapcm.c
@@ -523,8 +523,7 @@ csachan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = csa;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = CS461x_BUFFSIZE;
- if (chn_allocbuf(ch->buffer, csa->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, csa->parent_dmat, CS461x_BUFFSIZE) == -1) return NULL;
return ch;
}
@@ -538,9 +537,9 @@ csachan_setdir(kobj_t obj, void *data, int dir)
resp = &csa->res;
if (dir == PCMDIR_PLAY)
- csa_writemem(resp, BA1_PBA, vtophys(ch->buffer->buf));
+ csa_writemem(resp, BA1_PBA, vtophys(sndbuf_getbuf(ch->buffer)));
else
- csa_writemem(resp, BA1_CBA, vtophys(ch->buffer->buf));
+ csa_writemem(resp, BA1_CBA, vtophys(sndbuf_getbuf(ch->buffer)));
ch->dir = dir;
return 0;
}
@@ -606,12 +605,7 @@ csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-#if notdef
- return blocksize;
-#else
- struct csa_chinfo *ch = data;
- return ch->buffer->bufsize / 2;
-#endif /* notdef */
+ return CS461x_BUFFSIZE / 2;
}
static int
@@ -648,11 +642,11 @@ csachan_getptr(kobj_t obj, void *data)
resp = &csa->res;
if (ch->dir == PCMDIR_PLAY) {
- ptr = csa_readmem(resp, BA1_PBA) - vtophys(ch->buffer->buf);
+ ptr = csa_readmem(resp, BA1_PBA) - vtophys(sndbuf_getbuf(ch->buffer));
if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
ptr >>= 1;
} else {
- ptr = csa_readmem(resp, BA1_CBA) - vtophys(ch->buffer->buf);
+ ptr = csa_readmem(resp, BA1_CBA) - vtophys(sndbuf_getbuf(ch->buffer));
if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
ptr >>= 1;
}
diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c
index c215b5a..5d76502 100644
--- a/sys/dev/sound/pci/ds1.c
+++ b/sys/dev/sound/pci/ds1.c
@@ -431,8 +431,8 @@ ds_setuppch(struct sc_pchinfo *ch)
stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
c = stereo? 1 : 0;
- buf = ch->buffer->buf;
- sz = ch->buffer->bufsize;
+ buf = sndbuf_getbuf(ch->buffer);
+ sz = sndbuf_getsize(ch->buffer);
ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, buf, sz);
ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, buf, sz);
@@ -450,8 +450,8 @@ ds_setuprch(struct sc_rchinfo *ch)
stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
- buf = ch->buffer->buf;
- sz = ch->buffer->bufsize;
+ buf = sndbuf_getbuf(ch->buffer);
+ sz = sndbuf_getsize(ch->buffer);
pri = (ch->num == DS1_RECPRIMARY)? 1 : 0;
for (i = 0; i < 2; i++) {
@@ -480,14 +480,13 @@ ds1pchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch = &sc->pch[sc->pchn++];
ch->buffer = b;
- ch->buffer->bufsize = 4096;
ch->parent = sc;
ch->channel = c;
ch->dir = dir;
ch->fmt = AFMT_U8;
ch->spd = 8000;
ch->run = 0;
- if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 4096) == -1)
return NULL;
else {
ch->lsnum = sc->pslotfree;
@@ -602,13 +601,12 @@ ds1rchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch = &sc->rch[sc->rchn];
ch->num = sc->rchn++;
ch->buffer = b;
- ch->buffer->bufsize = 4096;
ch->parent = sc;
ch->channel = c;
ch->dir = dir;
ch->fmt = AFMT_U8;
ch->spd = 8000;
- if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 4096) == -1)
return NULL;
else {
ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank;
diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c
index e199446..e816572 100644
--- a/sys/dev/sound/pci/emu10k1.c
+++ b/sys/dev/sound/pci/emu10k1.c
@@ -68,7 +68,7 @@ struct sc_info;
/* channel registers */
struct sc_pchinfo {
- int spd, fmt, run;
+ int spd, fmt, blksz, run;
struct emu_voice *master, *slave;
snd_dbuf *buffer;
pcm_channel *channel;
@@ -76,7 +76,7 @@ struct sc_pchinfo {
};
struct sc_rchinfo {
- int spd, fmt, run, num;
+ int spd, fmt, run, blksz, num;
u_int32_t idxreg, basereg, sizereg, setupreg, irqmask;
snd_dbuf *buffer;
pcm_channel *channel;
@@ -97,7 +97,7 @@ struct sc_info {
int regtype, regid, irqid;
void *ih;
- int timer;
+ int timer, timerinterval;
int pnum, rnum;
struct emu_mem mem;
struct emu_voice voice[64];
@@ -303,12 +303,39 @@ emu_enaint(struct sc_info *sc, char channel, int enable)
/* stuff */
static int
+emu_settimer(struct sc_info *sc)
+{
+ struct sc_pchinfo *pch;
+ struct sc_rchinfo *rch;
+ int i, tmp, rate;
+
+ rate = 0;
+ for (i = 0; i < EMU_CHANS; i++) {
+ pch = &sc->pch[i];
+ tmp = (pch->spd * sndbuf_getbps(pch->buffer)) / pch->blksz;
+ if (tmp > rate)
+ rate = tmp;
+ }
+
+ for (i = 0; i < 3; i++) {
+ rch = &sc->rch[i];
+ tmp = (rch->spd * sndbuf_getbps(rch->buffer)) / rch->blksz;
+ if (tmp > rate)
+ rate = tmp;
+ }
+ RANGE(rate, 48, 9600);
+ sc->timerinterval = 48000 / rate;
+ emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
+
+ return sc->timerinterval;
+}
+
+static int
emu_enatimer(struct sc_info *sc, int go)
{
u_int32_t x;
if (go) {
if (sc->timer++ == 0) {
- emu_wr(sc, TIMER, 256, 2);
x = emu_rd(sc, INTE, 4);
x |= INTE_INTERVALTIMERENB;
emu_wr(sc, INTE, x, 4);
@@ -430,10 +457,8 @@ emu_vinit(struct sc_info *sc, struct emu_voice *m, struct emu_voice *s,
buf = emu_memalloc(sc, sz);
if (buf == NULL)
return -1;
- if (c != NULL) {
- c->buffer.buf = buf;
- c->buffer.bufsize = sz;
- }
+ if (c != NULL)
+ sndbuf_setup(&c->buffer, buf, sz);
m->start = emu_memstart(sc, buf) * EMUPAGESIZE;
m->end = m->start + sz;
m->channel = NULL;
@@ -631,6 +656,9 @@ emupchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->buffer = b;
ch->parent = sc;
ch->channel = c;
+ ch->blksz = EMU_BUFFSIZE / 2;
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
ch->master = emu_valloc(sc);
ch->slave = emu_valloc(sc);
if (emu_vinit(sc, ch->master, ch->slave, EMU_BUFFSIZE, ch->channel))
@@ -645,7 +673,7 @@ emupchan_free(kobj_t obj, void *data)
struct sc_pchinfo *ch = data;
struct sc_info *sc = ch->parent;
- return emu_memfree(sc, ch->buffer->buf);
+ return emu_memfree(sc, sndbuf_getbuf(ch->buffer));
}
static int
@@ -669,6 +697,14 @@ emupchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
emupchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int irqrate, blksz;
+
+ ch->blksz = blocksize;
+ emu_settimer(sc);
+ irqrate = 48000 / sc->timerinterval;
+ blksz = (ch->spd * sndbuf_getbps(ch->buffer)) / irqrate;
return blocksize;
}
@@ -684,6 +720,7 @@ emupchan_trigger(kobj_t obj, void *data, int go)
if (go == PCMTRIG_START) {
emu_vsetup(ch);
emu_vwrite(sc, ch->master);
+ emu_settimer(sc);
emu_enatimer(sc, 1);
#ifdef EMUDEBUG
printf("start [%d bit, %s, %d hz]\n",
@@ -737,9 +774,9 @@ emurchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
KASSERT(dir == PCMDIR_REC, ("emurchan_init: bad direction"));
ch = &sc->rch[sc->rnum];
ch->buffer = b;
- ch->buffer->bufsize = EMU_BUFFSIZE;
ch->parent = sc;
ch->channel = c;
+ ch->blksz = EMU_BUFFSIZE / 2;
ch->fmt = AFMT_U8;
ch->spd = 8000;
ch->num = sc->rnum;
@@ -769,10 +806,10 @@ emurchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
break;
}
sc->rnum++;
- if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, EMU_BUFFSIZE) == -1)
return NULL;
else {
- emu_wrptr(sc, 0, ch->basereg, vtophys(ch->buffer->buf));
+ emu_wrptr(sc, 0, ch->basereg, vtophys(sndbuf_getbuf(ch->buffer)));
emu_wrptr(sc, 0, ch->sizereg, 0); /* off */
return ch;
}
@@ -805,6 +842,14 @@ emurchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
emurchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int irqrate, blksz;
+
+ ch->blksz = blocksize;
+ emu_settimer(sc);
+ irqrate = 48000 / sc->timerinterval;
+ blksz = (ch->spd * sndbuf_getbps(ch->buffer)) / irqrate;
return blocksize;
}
diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c
index 15779e8..0206dce 100644
--- a/sys/dev/sound/pci/es137x.c
+++ b/sys/dev/sound/pci/es137x.c
@@ -253,9 +253,8 @@ eschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = es;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = ES_BUFFSIZE;
ch->num = ch->parent->num++;
- if (chn_allocbuf(ch->buffer, es->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, es->parent_dmat, ES_BUFFSIZE) == -1) return NULL;
return ch;
}
@@ -269,16 +268,16 @@ eschan_setdir(kobj_t obj, void *data, int dir)
bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE,
ES1370_REG_DAC2_FRAMEADR >> 8);
bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMEADR & 0xff,
- vtophys(ch->buffer->buf));
+ vtophys(sndbuf_getbuf(ch->buffer)));
bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff,
- (ch->buffer->bufsize >> 2) - 1);
+ (sndbuf_getsize(ch->buffer) >> 2) - 1);
} else {
bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE,
ES1370_REG_ADC_FRAMEADR >> 8);
bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMEADR & 0xff,
- vtophys(ch->buffer->buf));
+ vtophys(sndbuf_getbuf(ch->buffer)));
bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff,
- (ch->buffer->bufsize >> 2) - 1);
+ (sndbuf_getsize(ch->buffer) >> 2) - 1);
}
ch->dir = dir;
return 0;
@@ -346,10 +345,7 @@ eschan_trigger(kobj_t obj, void *data, int go)
if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
return 0;
- ss = 1;
- ss <<= (ch->fmt & AFMT_STEREO)? 1 : 0;
- ss <<= (ch->fmt & AFMT_16BIT)? 1 : 0;
- cnt = ch->buffer->dl / ss - 1;
+ cnt = (sndbuf_runsz(ch->buffer) / sndbuf_getbps(ch->buffer)) - 1;
if (ch->dir == PCMDIR_PLAY) {
if (go == PCMTRIG_START) {
@@ -366,7 +362,7 @@ eschan_trigger(kobj_t obj, void *data, int go)
ES1370_REG_DAC2_FRAMECNT >> 8);
bus_space_write_4(es->st, es->sh,
ES1370_REG_DAC2_FRAMECNT & 0xff,
- (ch->buffer->bufsize >> 2) - 1);
+ (sndbuf_getsize(ch->buffer) >> 2) - 1);
} else es->ctrl &= ~CTRL_DAC2_EN;
} else {
if (go == PCMTRIG_START) {
@@ -380,7 +376,7 @@ eschan_trigger(kobj_t obj, void *data, int go)
ES1370_REG_ADC_FRAMECNT >> 8);
bus_space_write_4(es->st, es->sh,
ES1370_REG_ADC_FRAMECNT & 0xff,
- (ch->buffer->bufsize >> 2) - 1);
+ (sndbuf_getsize(ch->buffer) >> 2) - 1);
} else es->ctrl &= ~CTRL_ADC_EN;
}
bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
diff --git a/sys/dev/sound/pci/fm801.c b/sys/dev/sound/pci/fm801.c
index a01ea8e..33b9915 100644
--- a/sys/dev/sound/pci/fm801.c
+++ b/sys/dev/sound/pci/fm801.c
@@ -331,9 +331,8 @@ fm801ch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = fm801;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = FM801_BUFFSIZE;
ch->dir = dir;
- if( chn_allocbuf(ch->buffer, fm801->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, fm801->parent_dmat, FM801_BUFFSIZE) == -1) return NULL;
return (void *)ch;
}
@@ -435,7 +434,7 @@ fm801ch_trigger(kobj_t obj, void *data, int go)
{
struct fm801_chinfo *ch = data;
struct fm801_info *fm801 = ch->parent;
- u_int32_t baseaddr = vtophys(ch->buffer->buf);
+ u_int32_t baseaddr = vtophys(sndbuf_getbuf(ch->buffer));
snd_dbuf *b = ch->buffer;
u_int32_t k1;
diff --git a/sys/dev/sound/pci/maestro.c b/sys/dev/sound/pci/maestro.c
index 5955f77..82e84bf 100644
--- a/sys/dev/sound/pci/maestro.c
+++ b/sys/dev/sound/pci/maestro.c
@@ -85,6 +85,7 @@ struct agg_chinfo {
snd_dbuf *buffer;
bus_addr_t offset;
u_int32_t blocksize;
+ u_int32_t speed;
int dir;
u_int num;
u_int16_t aputype;
@@ -518,9 +519,9 @@ aggch_start_dac(struct agg_chinfo *ch)
{
u_int wpwa = APU_USE_SYSMEM | (ch->offset >> 9);
u_int size = AGG_BUFSIZ >> 1;
- u_int speed = ch->channel->speed;
+ u_int speed = ch->speed;
u_int offset = ch->offset >> 1;
- u_int cp = ch->buffer->rp >> 1;
+ u_int cp = 0;
u_int16_t apuch = ch->num << 1;
u_int dv;
int pan = 0;
@@ -613,7 +614,7 @@ calc_timer_freq(struct agg_chinfo *ch)
if (ch->aputype == APUTYPE_8BITLINEAR)
ss >>= 1;
- return (ch->channel->speed * ss + ch->blocksize - 1) / ch->blocksize;
+ return (ch->speed * ss) / ch->blocksize;
}
static void
@@ -641,6 +642,7 @@ aggch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
struct agg_info *ess = devinfo;
struct agg_chinfo *ch;
bus_addr_t physaddr;
+ void *p;
ch = (dir == PCMDIR_PLAY)? ess->pch + ess->playchns : &ess->rch;
@@ -650,9 +652,10 @@ aggch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->num = ess->playchns;
ch->dir = dir;
- b->buf = dma_malloc(ess, AGG_BUFSIZ, &physaddr);
- if (b->buf == NULL)
+ p = dma_malloc(ess, AGG_BUFSIZ, &physaddr);
+ if (p == NULL)
return NULL;
+ sndbuf_setup(b, p, AGG_BUFSIZ);
ch->offset = physaddr - ess->baseaddr;
if (physaddr < ess->baseaddr || ch->offset > WPWA_MAXADDR) {
@@ -663,7 +666,6 @@ aggch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
return NULL;
}
- b->bufsize = AGG_BUFSIZ;
ch->wcreg_tpl = (physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
if (dir == PCMDIR_PLAY) {
@@ -683,7 +685,7 @@ aggch_free(kobj_t obj, void *data)
struct agg_info *ess = ch->parent;
/* free up buffer - called after channel stopped */
- dma_free(ess, ch->buffer->buf);
+ dma_free(ess, sndbuf_getbuf(ch->buffer));
/* return 0 if ok */
return 0;
@@ -719,7 +721,10 @@ aggch_setplayformat(kobj_t obj, void *data, u_int32_t format)
static int
aggch_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
- return speed;
+ struct agg_chinfo *ch = data;
+
+ ch->speed = speed;
+ return ch->speed;
}
static int
diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c
index 1e2760c..5a6ca8c 100644
--- a/sys/dev/sound/pci/neomagic.c
+++ b/sys/dev/sound/pci/neomagic.c
@@ -338,8 +338,7 @@ nmchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
ch->buffer = b;
- ch->buffer->bufsize = NM_BUFFSIZE;
- ch->buffer->buf = (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf;
+ sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
if (bootverbose)
device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
"play" : "rec", ch->buffer->buf);
diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c
index 7cb10f3..71a00f1 100644
--- a/sys/dev/sound/pci/solo.c
+++ b/sys/dev/sound/pci/solo.c
@@ -80,7 +80,7 @@ struct ess_chinfo {
pcm_channel *channel;
snd_dbuf *buffer;
int dir, hwch, stopping;
- u_int32_t fmt, spd;
+ u_int32_t fmt, spd, blksz;
};
struct ess_info {
@@ -477,7 +477,7 @@ ess_start(struct ess_chinfo *ch)
struct ess_info *sc = ch->parent;
DEB(printf("ess_start\n"););
- ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->buffer->dl);
+ ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz);
ch->stopping = 0;
if (ch->hwch == 1) {
ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01);
@@ -519,9 +519,8 @@ esschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = sc;
ch->channel = c;
ch->buffer = b;
- ch->buffer->bufsize = ESS_BUFFSIZE;
ch->dir = dir;
- if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, ESS_BUFFSIZE) == -1)
return NULL;
ch->hwch = 1;
if ((dir == PCMDIR_PLAY) && (sc->duplex))
@@ -555,7 +554,10 @@ esschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
static int
esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
- return blocksize;
+ struct ess_chinfo *ch = data;
+
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
@@ -570,7 +572,7 @@ esschan_trigger(kobj_t obj, void *data, int go)
switch (go) {
case PCMTRIG_START:
- ess_dmasetup(sc, ch->hwch, vtophys(ch->buffer->buf), ch->buffer->bufsize, ch->dir);
+ ess_dmasetup(sc, ch->hwch, vtophys(sndbuf_getbuf(ch->buffer)), sndbuf_getsize(ch->buffer), ch->dir);
ess_dmatrigger(sc, ch->hwch, 1);
ess_start(ch);
break;
@@ -780,7 +782,7 @@ ess_dmapos(struct ess_info *sc, int ch)
i, p);
i = port_rd(sc->vc, 0x4, 2) + 1;
p = port_rd(sc->vc, 0x4, 2) + 1;
- } while ((p > sc->dmasz[ch -1 ] || i < p || (p - i) > 0x8) && j++ < 1000);
+ } while ((p > sc->dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000);
ess_dmatrigger(sc, ch, 1);
}
else if (ch == 2)
diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c
index dee0f9f..1dace66 100644
--- a/sys/dev/sound/pci/t4dwave.c
+++ b/sys/dev/sound/pci/t4dwave.c
@@ -52,7 +52,7 @@ struct tr_chinfo {
u_int32_t eso, delta;
u_int32_t rvol, cvol;
u_int32_t gvsel, pan, vol, ctrl;
- int index, ss;
+ int index;
snd_dbuf *buffer;
pcm_channel *channel;
struct tr_info *parent;
@@ -391,10 +391,9 @@ trchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->index = -1;
}
ch->buffer = b;
- ch->buffer->bufsize = TR_BUFFSIZE;
ch->parent = tr;
ch->channel = c;
- if (chn_allocbuf(ch->buffer, tr->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, tr->parent_dmat, TR_BUFFSIZE) == -1) return NULL;
else return ch;
}
@@ -405,9 +404,9 @@ trchan_setdir(kobj_t obj, void *data, int dir)
struct tr_info *tr = ch->parent;
if (dir == PCMDIR_PLAY && ch->index >= 0) {
ch->fmc = ch->fms = ch->ec = ch->alpha = 0;
- ch->lba = vtophys(ch->buffer->buf);
+ ch->lba = vtophys(sndbuf_getbuf(ch->buffer));
ch->cso = 0;
- ch->eso = ch->buffer->bufsize - 1;
+ ch->eso = sndbuf_getsize(ch->buffer) - 1;
ch->rvol = ch->cvol = 0;
ch->gvsel = 0;
ch->pan = 0;
@@ -423,10 +422,10 @@ trchan_setdir(kobj_t obj, void *data, int dir)
i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03;
tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1);
/* set up base address */
- tr_wr(tr, TR_REG_DMAR0, vtophys(ch->buffer->buf), 4);
+ tr_wr(tr, TR_REG_DMAR0, vtophys(sndbuf_getbuf(ch->buffer)), 4);
/* set up buffer size */
i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff;
- tr_wr(tr, TR_REG_DMAR4, i | (ch->buffer->bufsize - 1), 4);
+ tr_wr(tr, TR_REG_DMAR4, i | (sndbuf_getsize(ch->buffer) - 1), 4);
} else return -1;
return 0;
}
@@ -438,12 +437,9 @@ trchan_setformat(kobj_t obj, void *data, u_int32_t format)
struct tr_info *tr = ch->parent;
u_int32_t bits = tr_fmttobits(format);
- ch->ss = 1;
- ch->ss <<= (format & AFMT_STEREO)? 1 : 0;
- ch->ss <<= (format & AFMT_16BIT)? 1 : 0;
if (ch->index >= 0) {
tr_rdch(tr, ch->index, ch);
- ch->eso = (ch->buffer->bufsize / ch->ss) - 1;
+ ch->eso = (sndbuf_getsize(ch->buffer) / sndbuf_getbps(ch->buffer)) - 1;
ch->ctrl = bits | 0x01;
tr_wrch(tr, ch->index, ch);
} else {
@@ -482,7 +478,7 @@ static int
trchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct tr_chinfo *ch = data;
- return ch->buffer->bufsize / 2;
+ return sndbuf_getsize(ch->buffer) / 2;
}
static int
@@ -516,8 +512,8 @@ trchan_getptr(kobj_t obj, void *data)
if (ch->index >= 0) {
tr_rdch(tr, ch->index, ch);
- return ch->cso * ch->ss;
- } else return tr_rd(tr, TR_REG_DMAR0, 4) - vtophys(ch->buffer->buf);
+ return ch->cso * sndbuf_getbps(ch->buffer);
+ } else return tr_rd(tr, TR_REG_DMAR0, 4) - vtophys(sndbuf_getbuf(ch->buffer));
}
static pcmchan_caps *
diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c
index 27d7aef..70dd9db 100644
--- a/sys/dev/sound/pci/via82c686.c
+++ b/sys/dev/sound/pci/via82c686.c
@@ -217,9 +217,8 @@ viachan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
ch->parent = via;
ch->channel = c;
ch->buffer = b;
- b->bufsize = VIA_BUFFSIZE;
- if (chn_allocbuf(ch->buffer, via->parent_dmat) == -1) return NULL;
+ if (sndbuf_alloc(ch->buffer, via->parent_dmat, VIA_BUFFSIZE) == -1) return NULL;
return ch;
}
@@ -240,14 +239,14 @@ viachan_setdir(kobj_t obj, void *data, int dir)
* is feeding.
*/
ado = via->sgd_table;
- chunk_size = ch->buffer->bufsize / SEGS_PER_CHAN;
+ chunk_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN;
if (dir == PCMDIR_REC) {
ado += SEGS_PER_CHAN;
}
DEB(printf("SGD table located at va %p\n", ado));
- phys_addr = vtophys(ch->buffer->buf);
+ phys_addr = vtophys(sndbuf_getbuf(ch->buffer));
for (i = 0; i < SEGS_PER_CHAN; i++) {
ado->ptr = phys_addr;
flag = (i == SEGS_PER_CHAN-1) ?
@@ -339,7 +338,7 @@ viachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct via_chinfo *ch = data;
- return ch->buffer->bufsize / 2;
+ return sndbuf_getsize(ch->buffer) / 2;
}
static int
@@ -409,7 +408,7 @@ DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
if (seg == 0) seg = SEGS_PER_CHAN;
/* Now work out offset: seg less count */
- ptr = seg * ch->buffer->bufsize / SEGS_PER_CHAN - len;
+ ptr = seg * sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN - len;
DEB(printf("return ptr=%d\n", ptr));
return ptr;
}
@@ -430,7 +429,7 @@ DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
if (seg == 0) seg = SEGS_PER_CHAN;
/* Now work out offset: seg less count */
- ptr = seg * ch->buffer->bufsize / SEGS_PER_CHAN - len;
+ ptr = seg * sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN - len;
/* DMA appears to operate on memory 'lines' of 32 bytes */
/* so don't return any part line - it isn't in RAM yet */
diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c
new file mode 100644
index 0000000..81b4037
--- /dev/null
+++ b/sys/dev/sound/pcm/buffer.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <dev/sound/pcm/sound.h>
+
+static void
+sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ snd_dbuf *b = (snd_dbuf *)arg;
+
+ if (bootverbose) {
+ printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr,
+ (unsigned long)segs->ds_len);
+ printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf));
+ }
+}
+
+/*
+ * Allocate memory for DMA buffer. If the device do not perform DMA transfer,
+ * the driver can call malloc(9) by its own.
+ */
+int
+sndbuf_alloc(snd_dbuf *b, bus_dma_tag_t dmatag, int size)
+{
+ b->dmatag = dmatag;
+ b->maxsize = size;
+ b->bufsize = b->maxsize;
+ if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT, &b->dmamap))
+ return ENOSPC;
+ if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, sndbuf_setmap, b, 0))
+ return ENOSPC;
+ return sndbuf_resize(b, 2, b->maxsize / 2);
+}
+
+int
+sndbuf_setup(snd_dbuf *b, void *buf, int size)
+{
+ bzero(b, sizeof(*b));
+ b->buf = buf;
+ b->maxsize = size;
+ b->bufsize = b->maxsize;
+ return sndbuf_resize(b, 2, b->maxsize / 2);
+}
+
+void
+sndbuf_free(snd_dbuf *b)
+{
+ bus_dmamap_unload(b->dmatag, b->dmamap);
+ bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
+}
+
+int
+sndbuf_resize(snd_dbuf *b, int blkcnt, int blksz)
+{
+ if (blkcnt == 0)
+ blkcnt = b->blkcnt;
+ if (blksz == 0)
+ blksz = b->blksz;
+ if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize))
+ return EINVAL;
+ b->blkcnt = blkcnt;
+ b->blksz = blksz;
+ b->bufsize = blkcnt * blksz;
+ sndbuf_reset(b);
+ return 0;
+}
+
+void
+sndbuf_clear(snd_dbuf *b, int length)
+{
+ int i;
+ u_int16_t data, *p;
+
+ if (length == 0)
+ return;
+
+ if (b->fmt & AFMT_SIGNED)
+ data = 0x00;
+ else
+ data = 0x80;
+
+ if (b->fmt & AFMT_16BIT)
+ data <<= 8;
+ else
+ data |= data << 8;
+
+ if (b->fmt & AFMT_BIGENDIAN)
+ data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00);
+
+ i = b->fp;
+ p = (u_int16_t *)(b->buf + b->fp);
+ while (length > 1) {
+ *p++ = data;
+ length -= 2;
+ i += 2;
+ if (i >= b->bufsize) {
+ p = (u_int16_t *)b->buf;
+ i = 0;
+ }
+ }
+ if (length == 1)
+ *(b->buf + i) = data & 0xff;
+}
+
+void
+sndbuf_reset(snd_dbuf *b)
+{
+ b->rp = b->fp = 0;
+ b->dl = b->rl = 0;
+ b->fl = b->bufsize;
+ b->prev_total = b->total = 0;
+ b->prev_int_count = b->int_count = 0;
+ b->underflow = 0;
+ if (b->buf && b->bufsize > 0)
+ sndbuf_clear(b, b->bufsize);
+}
+
+int
+sndbuf_setfmt(snd_dbuf *b, u_int32_t fmt)
+{
+ b->fmt = fmt;
+ b->bps = 1;
+ b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0;
+ b->bps <<= (b->fmt & AFMT_16BIT)? 1 : 0;
+ b->bps <<= (b->fmt & AFMT_32BIT)? 2 : 0;
+ return 0;
+}
+
+int
+sndbuf_getbps(snd_dbuf *b)
+{
+ return b->bps;
+}
+
+void *
+sndbuf_getbuf(snd_dbuf *b)
+{
+ return b->buf;
+}
+
+int
+sndbuf_getsize(snd_dbuf *b)
+{
+ return b->bufsize;
+}
+
+int
+sndbuf_runsz(snd_dbuf *b)
+{
+ return b->dl;
+}
+
+int
+sndbuf_isadmasetup(snd_dbuf *b, struct resource *drq)
+{
+ /* should do isa_dma_acquire/isa_dma_release here */
+ if (drq == NULL) {
+ b->flags &= ~SNDBUF_F_ISADMA;
+ b->chan = -1;
+ } else {
+ b->flags &= ~SNDBUF_F_ISADMA;
+ b->chan = rman_get_start(drq);
+ }
+ return 0;
+}
+
+int
+sndbuf_isadmasetdir(snd_dbuf *b, int dir)
+{
+ b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ;
+ return 0;
+}
+
+void
+sndbuf_isadma(snd_dbuf *b, int go)
+{
+ KASSERT(b, ("sndbuf_isadma called with b == NULL"));
+ KASSERT(ISA_DMA(b), ("sndbuf_isadma called on non-ISA channel"));
+
+ switch (go) {
+ case PCMTRIG_START:
+ /* isa_dmainit(b->chan, size); */
+ isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->chan);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ isa_dmastop(b->chan);
+ isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->chan);
+ break;
+ }
+
+ DEB(printf("buf 0x%p ISA DMA %s, channel %d\n",
+ b,
+ (go == PCMTRIG_START)? "started" : "stopped",
+ b->chan));
+}
+
+int
+sndbuf_isadmaptr(snd_dbuf *b)
+{
+ if (ISA_DMA(b)) {
+ int i = b->dl? isa_dmastatus(b->chan) : b->bufsize;
+ if (i < 0)
+ i = 0;
+ return b->bufsize - i;
+ } else KASSERT(1, ("sndbuf_isadmaptr called on invalid channel"));
+ return -1;
+}
+
+void
+sndbuf_isadmabounce(snd_dbuf *b)
+{
+ if (ISA_DMA(b)) {
+ /* tell isa_dma to bounce data in/out */
+ } else
+ KASSERT(1, ("chn_isadmabounce called on invalid channel"));
+}
+
diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h
new file mode 100644
index 0000000..62058ce
--- /dev/null
+++ b/sys/dev/sound/pcm/buffer.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8))
+
+int sndbuf_alloc(snd_dbuf *b, bus_dma_tag_t dmatag, int size);
+int sndbuf_setup(snd_dbuf *b, void *buf, int size);
+void sndbuf_free(snd_dbuf *b);
+int sndbuf_resize(snd_dbuf *b, int blkcnt, int blksz);
+void sndbuf_reset(snd_dbuf *b);
+void sndbuf_clear(snd_dbuf *b, int length);
+int sndbuf_setfmt(snd_dbuf *b, u_int32_t fmt);
+int sndbuf_getbps(snd_dbuf *b);
+void *sndbuf_getbuf(snd_dbuf *b);
+int sndbuf_getsize(snd_dbuf *b);
+int sndbuf_runsz(snd_dbuf *b);
+
+int sndbuf_isadmasetup(snd_dbuf *b, struct resource *drq);
+int sndbuf_isadmasetdir(snd_dbuf *b, int dir);
+void sndbuf_isadma(snd_dbuf *b, int go);
+int sndbuf_isadmaptr(snd_dbuf *b);
+void sndbuf_isadmabounce(snd_dbuf *b);
+
+
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 4030028..da4aa14 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -36,7 +36,6 @@ MALLOC_DEFINE(M_CHANNEL, "channel", "pcm channel");
#define DMA_ALIGN_THRESHOLD 4
#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
-#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8))
#define CANCHANGE(c) (!(c)->buffer.dl)
#define ROUND(x) ((x) & DMA_ALIGN_MASK)
@@ -44,7 +43,6 @@ MALLOC_DEFINE(M_CHANNEL, "channel", "pcm channel");
#define DEB(x) x
*/
-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);
@@ -110,14 +108,6 @@ produced on overruns.
* gets copied in or out of the real buffer. fix requires mods to isa_dma.c
* and possibly fixes to other autodma mode clients
*/
-static void
-chn_isadmabounce(pcm_channel *c)
-{
- if (ISA_DMA(&c->buffer)) {
- /* tell isa_dma to bounce data in/out */
- } else KASSERT(1, ("chn_isadmabounce called on invalid channel"));
-}
-
static int
chn_polltrigger(pcm_channel *c)
{
@@ -156,7 +146,7 @@ chn_dmadone(pcm_channel *c)
else
chn_dmaupdate(c);
if (ISA_DMA(b))
- chn_isadmabounce(c); /* sync bounce buffer */
+ sndbuf_isadmabounce(b); /* sync bounce buffer */
b->int_count++;
}
@@ -286,7 +276,7 @@ chn_wrfeed(pcm_channel *c)
b->fl -= l;
b->fp = (b->fp + l) % b->bufsize;
/* Clear the new space in the secondary buffer. */
- buf_clear(bs, bs->fmt, l);
+ sndbuf_clear(bs, l);
/* Accumulate the total bytes of the moved samples. */
lacc += l;
/* A feed to the DMA buffer is equivalent to an interrupt. */
@@ -389,7 +379,7 @@ chn_wrintr(pcm_channel *c)
chn_wrfeed(c);
else {
while (chn_wrfeed(c) > 0);
- buf_clear(b, b->fmt, b->fl);
+ sndbuf_clear(b, b->fl);
}
chn_dmawakeup(c);
if (c->flags & CHN_F_TRIGGERED) {
@@ -414,7 +404,7 @@ chn_wrintr(pcm_channel *c)
* we are near to underflow condition, so to prevent
* audio 'clicks' clear next b->fl bytes
*/
- buf_clear(b, b->fmt, b->fl);
+ sndbuf_clear(b, b->fl);
if (b->rl < DMA_ALIGN_THRESHOLD)
b->underflow = 1;
}
@@ -423,7 +413,7 @@ chn_wrintr(pcm_channel *c)
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 */
- buf_clear(b, b->fmt, b->bufsize);
+ sndbuf_clear(b, b->bufsize);
}
}
}
@@ -649,7 +639,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. */
- buf_clear(bs, bs->fmt, l);
+ sndbuf_clear(bs, l);
/* Accumulate the total bytes of the moved samples. */
bs->total += w;
wacc += w;
@@ -844,76 +834,6 @@ chn_start(pcm_channel *c, int force)
return r;
}
-static void
-chn_dma_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- snd_dbuf *b = (snd_dbuf *)arg;
-
- if (bootverbose) {
- printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr,
- (unsigned long)segs->ds_len);
- printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf));
- }
-}
-
-/*
- * Allocate memory for DMA buffer. If the device do not perform DMA transfer,
- * the drvier can call malloc(9) by its own.
- */
-int
-chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat)
-{
- b->parent_dmat = parent_dmat;
- if (bus_dmamem_alloc(b->parent_dmat, (void **)&b->buf,
- BUS_DMA_NOWAIT, &b->dmamap)) return -1;
- if (bus_dmamap_load(b->parent_dmat, b->dmamap, b->buf,
- b->bufsize, chn_dma_setmap, b, 0)) return -1;
- return 0;
-}
-
-void
-chn_freebuf(snd_dbuf *b)
-{
- bus_dmamem_free(b->parent_dmat, b->buf, b->dmamap);
-}
-
-static void
-buf_clear(snd_dbuf *b, u_int32_t fmt, int length)
-{
- int i;
- u_int16_t data, *p;
-
- 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);
-
- i = b->fp;
- p = (u_int16_t *)(b->buf + b->fp);
- while (length > 1) {
- *p++ = data;
- length -= 2;
- i += 2;
- if (i >= b->bufsize) {
- p = (u_int16_t *)b->buf;
- i = 0;
- }
- }
- if (length == 1)
- *(b->buf + i) = data & 0xff;
-}
-
void
chn_resetbuf(pcm_channel *c)
{
@@ -921,59 +841,8 @@ chn_resetbuf(pcm_channel *c)
snd_dbuf *bs = &c->buffer2nd;
c->blocks = 0;
- b->rp = b->fp = 0;
- b->dl = b->rl = 0;
- b->fl = b->bufsize;
- b->prev_total = b->total = 0;
- b->prev_int_count = b->int_count = 0;
- b->underflow = 0;
- if (b->buf && b->bufsize > 0)
- buf_clear(b, b->fmt, b->bufsize);
-
- bs->rp = bs->fp = 0;
- bs->dl = bs->rl = 0;
- bs->fl = bs->bufsize;
- bs->prev_total = bs->total = 0;
- bs->prev_int_count = bs->int_count = 0;
- bs->underflow = 0;
- if (bs->buf && bs->bufsize > 0)
- buf_clear(bs, bs->fmt, bs->bufsize);
-}
-
-void
-buf_isadma(snd_dbuf *b, int go)
-{
- KASSERT(b, ("buf_isadma called with b == NULL"));
- KASSERT(ISA_DMA(b), ("buf_isadma called on non-ISA channel"));
-
- switch (go) {
- case PCMTRIG_START:
- isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->chan);
- break;
-
- case PCMTRIG_STOP:
- case PCMTRIG_ABORT:
- isa_dmastop(b->chan);
- isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->chan);
- break;
- }
-
- DEB(printf("buf 0x%p ISA DMA %s, channel %d\n",
- b,
- (go == PCMTRIG_START)? "started" : "stopped",
- b->chan));
-}
-
-int
-buf_isadmaptr(snd_dbuf *b)
-{
- if (ISA_DMA(b)) {
- int i = b->dl? isa_dmastatus(b->chan) : b->bufsize;
- if (i < 0)
- i = 0;
- return b->bufsize - i;
- } else KASSERT(1, ("buf_isadmaptr called on invalid channel"));
- return -1;
+ sndbuf_reset(b);
+ sndbuf_reset(bs);
}
/*
@@ -1132,9 +1001,6 @@ chn_reset(pcm_channel *c, u_int32_t fmt)
chn_abort(c);
c->flags &= CHN_F_RESET;
CHANNEL_RESET(c->methods, c->devinfo);
- r = chn_setblocksize(c, CHN_2NDBUFBLKNUM, CHN_2NDBUFBLKSIZE);
- if (r)
- return r;
if (fmt) {
hwspd = DSP_DEFAULT_SPEED;
RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
@@ -1146,6 +1012,9 @@ chn_reset(pcm_channel *c, u_int32_t fmt)
if (r == 0)
r = chn_setvolume(c, 100, 100);
}
+ r = chn_setblocksize(c, 0, 0);
+ if (r)
+ return r;
chn_resetbuf(c);
CHANNEL_RESETDONE(c->methods, c->devinfo);
/* c->flags |= CHN_F_INIT; */
@@ -1169,6 +1038,7 @@ int
chn_init(pcm_channel *c, void *devinfo, int dir)
{
struct feeder_class *fc;
+ snd_dbuf *b = &c->buffer;
snd_dbuf *bs = &c->buffer2nd;
/* Initialize the hardware and DMA buffer first. */
@@ -1191,6 +1061,8 @@ chn_init(pcm_channel *c, void *devinfo, int dir)
/* And the secondary buffer. */
bs->buf = NULL;
+ sndbuf_setfmt(b, AFMT_U8);
+ sndbuf_setfmt(bs, AFMT_U8);
bs->bufsize = 0;
return 0;
}
@@ -1202,7 +1074,7 @@ chn_kill(pcm_channel *c)
chn_trigger(c, PCMTRIG_ABORT);
while (chn_removefeeder(c) == 0);
if (CHANNEL_FREE(c->methods, c->devinfo))
- chn_freebuf(&c->buffer);
+ sndbuf_free(&c->buffer);
c->flags |= CHN_F_DEAD;
return 0;
}
@@ -1236,44 +1108,59 @@ int
chn_setspeed(pcm_channel *c, int speed)
{
pcm_feeder *f;
- int r, hwspd, delta;
+ snd_dbuf *b = &c->buffer;
+ snd_dbuf *bs = &c->buffer2nd;
+ int r, delta;
DEB(printf("want speed %d, ", speed));
if (speed <= 0)
return EINVAL;
if (CANCHANGE(c)) {
c->speed = speed;
- hwspd = speed;
- RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
- DEB(printf("try speed %d, ", hwspd));
- hwspd = CHANNEL_SETSPEED(c->methods, c->devinfo, hwspd);
- DEB(printf("got speed %d, ", hwspd));
- delta = hwspd - speed;
+ b->spd = speed;
+ bs->spd = speed;
+ RANGE(b->spd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
+ DEB(printf("try speed %d, ", b->spd));
+ b->spd = CHANNEL_SETSPEED(c->methods, c->devinfo, b->spd);
+ DEB(printf("got speed %d, ", b->spd));
+
+ delta = b->spd - bs->spd;
if (delta < 0)
delta = -delta;
+
c->feederflags &= ~(1 << FEEDER_RATE);
if (delta > 500)
c->feederflags |= 1 << FEEDER_RATE;
else
- speed = hwspd;
+ bs->spd = b->spd;
+
r = chn_buildfeeder(c);
DEB(printf("r = %d\n", r));
if (r)
return r;
+
+ r = chn_setblocksize(c, 0, 0);
+ if (r)
+ return r;
+
if (!(c->feederflags & (1 << FEEDER_RATE)))
return 0;
+
f = chn_findfeeder(c, FEEDER_RATE);
DEB(printf("feedrate = %p\n", f));
if (f == NULL)
return EINVAL;
- r = FEEDER_SET(f, FEEDRATE_SRC, speed);
- DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", speed, r));
+
+ r = FEEDER_SET(f, FEEDRATE_SRC, bs->spd);
+ DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", bs->spd, r));
if (r)
return r;
- r = FEEDER_SET(f, FEEDRATE_DST, hwspd);
- DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", hwspd, r));
+
+ r = FEEDER_SET(f, FEEDRATE_DST, b->spd);
+ DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", b->spd, r));
if (r)
return r;
+
return 0;
}
c->speed = speed;
@@ -1287,8 +1174,8 @@ chn_setformat(pcm_channel *c, u_int32_t fmt)
snd_dbuf *b = &c->buffer;
snd_dbuf *bs = &c->buffer2nd;
int r;
-
u_int32_t hwfmt;
+
if (CANCHANGE(c)) {
DEB(printf("want format %d\n", fmt));
c->format = fmt;
@@ -1300,8 +1187,8 @@ chn_setformat(pcm_channel *c, u_int32_t fmt)
if (r)
return r;
hwfmt = c->feeder->desc->out;
- b->fmt = hwfmt;
- bs->fmt = hwfmt;
+ sndbuf_setfmt(b, hwfmt);
+ sndbuf_setfmt(bs, hwfmt);
chn_resetbuf(c);
CHANNEL_SETFORMAT(c->methods, c->devinfo, hwfmt);
return chn_setspeed(c, c->speed);
@@ -1316,54 +1203,65 @@ chn_setblocksize(pcm_channel *c, int blkcnt, int blksz)
{
snd_dbuf *b = &c->buffer;
snd_dbuf *bs = &c->buffer2nd;
- int s, ss, bufsz;
+ int s, bufsz, irqhz, tmp;
- if (bs->blkcnt == blkcnt && bs->blksz == blksz)
- return 0;
- if (c->flags & CHN_F_MAPPED) {
- DEB(printf("chn_setblocksize: can't work on mapped channel"));
+ if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED))
return EINVAL;
- }
- c->flags &= ~CHN_F_HAS_SIZE;
-
- ss = 1;
- ss <<= (bs->fmt & AFMT_STEREO)? 1 : 0;
- ss <<= (bs->fmt & AFMT_16BIT)? 1 : 0;
- if (blksz >= 2)
+ if (blksz == 0 || blksz == -1) {
+ if (blksz == -1)
+ c->flags &= ~CHN_F_HAS_SIZE;
+ if (c->flags & CHN_F_HAS_SIZE)
+ return 0;
+ blksz = (bs->bps * bs->spd) / CHN_DEFAULT_HZ;
+ tmp = 32;
+ while (tmp <= blksz)
+ tmp <<= 1;
+ tmp >>= 1;
+ blksz = tmp;
+
+ RANGE(blksz, 16, CHN_2NDBUFMAXSIZE / 2);
+ RANGE(blkcnt, 2, CHN_2NDBUFMAXSIZE / blksz);
+ } else {
+ if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE))
+ return EINVAL;
c->flags |= CHN_F_HAS_SIZE;
- /* let us specify blksz without setting CHN_F_HAS_SIZE */
- if (blksz < 0)
- blksz = -blksz;
- /* default to blksz = ~0.25s */
- if (blksz < 16)
- blksz = (ss * c->speed) >> 2;
- if (blksz > CHN_2NDBUFMAXSIZE / 2)
- blksz = CHN_2NDBUFMAXSIZE / 2;
- if (blkcnt < 2)
- blkcnt = 2;
-
- if (blkcnt * blksz > CHN_2NDBUFMAXSIZE)
- blkcnt = CHN_2NDBUFMAXSIZE / blksz;
+ }
+
bufsz = blkcnt * blksz;
s = spltty();
+
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."));
+ DEB(printf("chn_setblocksize: out of memory\n"));
return ENOSPC;
}
+
bs->bufsize = bufsz;
- bs->rl = bs->rp = bs->fp = 0;
- bs->fl = bs->bufsize;
- buf_clear(bs, bs->fmt, bs->bufsize);
bs->blkcnt = blkcnt;
bs->blksz = blksz;
+
+ /* adjust for different hw format/speed */
+ irqhz = (bs->bps * bs->spd) / bs->blksz;
+
+ b->blksz = (b->bps * b->spd) / irqhz;
+
+ /* round down to 2^x */
+ blksz = 32;
+ while (blksz <= b->blksz)
+ blksz <<= 1;
+ blksz >>= 1;
+
+ /* round down to fit hw buffer size */
RANGE(blksz, 16, b->bufsize / 2);
+
b->blksz = CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz);
+
+ chn_resetbuf(c);
splx(s);
return 0;
@@ -1439,7 +1337,7 @@ chn_buildfeeder(pcm_channel *c)
desc.flags = 0;
DEB(printf("find feeder type %d, ", type));
fc = feeder_getclass(&desc);
- DEB(printf("got %p\n", f));
+ DEB(printf("got %p\n", fc));
if (fc == NULL)
return EINVAL;
dst = fc->desc->in;
@@ -1454,7 +1352,7 @@ chn_buildfeeder(pcm_channel *c)
if (chn_addfeeder(c, fc, fc->desc))
return EINVAL;
src = fc->desc->out;
- DEB(printf("added feeder %p, output %x\n", f, src));
+ DEB(printf("added feeder %p, output %x\n", fc, src));
dst = 0;
flags &= ~(1 << type);
}
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index 243c207..73c1b8c 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -49,8 +49,6 @@ int chn_getptr(pcm_channel *c);
pcmchan_caps *chn_getcaps(pcm_channel *c);
u_int32_t chn_getformats(pcm_channel *c);
-int chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat);
-void chn_freebuf(snd_dbuf *b);
void chn_resetbuf(pcm_channel *c);
void chn_intr(pcm_channel *c);
void chn_checkunderflow(pcm_channel *c);
@@ -60,9 +58,6 @@ int chn_abort(pcm_channel *c);
int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist);
-void buf_isadma(snd_dbuf *b, int go);
-int buf_isadmaptr(snd_dbuf *b);
-
#define PCMDIR_PLAY 1
#define PCMDIR_REC -1
@@ -102,4 +97,6 @@ int buf_isadmaptr(snd_dbuf *b);
/* The size of a whole secondary buffer. */
#define CHN_2NDBUFMAXSIZE (131072)
+#define CHN_DEFAULT_HZ 50
+
#define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h
index aaa17a3..55f4111 100644
--- a/sys/dev/sound/pcm/datatypes.h
+++ b/sys/dev/sound/pcm/datatypes.h
@@ -57,7 +57,7 @@ struct _snd_mixer {
struct _snd_dbuf {
u_int8_t *buf;
- int bufsize;
+ int bufsize, maxsize;
volatile int dl; /* transfer size */
volatile int rp, fp; /* pointers to the ready and free area */
volatile int rl, fl; /* lenght of ready and free areas. */
@@ -65,12 +65,15 @@ struct _snd_dbuf {
volatile u_int32_t int_count, prev_int_count;
volatile u_int32_t total, prev_total;
int chan, dir; /* dma channel */
- int fmt, blksz, blkcnt;
+ int fmt, spd, bps;
+ int blksz, blkcnt;
int underflow, overrun;
+ u_int32_t flags;
bus_dmamap_t dmamap;
- bus_dma_tag_t parent_dmat;
+ bus_dma_tag_t dmatag;
struct selinfo sel;
};
+#define SNDBUF_F_ISADMA 0x00000001
/*****************************************************************************/
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 59c14e9..9728afd 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -240,8 +240,10 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
case AIOGSIZE: /* get the current blocksize */
{
struct snd_size *p = (struct snd_size *)arg;
- if (wrch) p->play_size = wrch->buffer2nd.blksz;
- if (rdch) p->rec_size = rdch->buffer2nd.blksz;
+ if (wrch)
+ p->play_size = wrch->buffer2nd.blksz;
+ if (rdch)
+ p->rec_size = rdch->buffer2nd.blksz;
}
break;
@@ -287,14 +289,16 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
if (rdch && wrch)
p->formats |= (d->flags & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
p->mixers = 1; /* default: one mixer */
- p->inputs = d->mixer->devs;
+ p->inputs = mix_getdevs(d->mixer);
p->left = p->right = 100;
}
break;
case AIOSTOP:
- if (*arg_i == AIOSYNC_PLAY && wrch) *arg_i = chn_abort(wrch);
- else if (*arg_i == AIOSYNC_CAPTURE && rdch) *arg_i = chn_abort(rdch);
+ if (*arg_i == AIOSYNC_PLAY && wrch)
+ *arg_i = chn_abort(wrch);
+ else if (*arg_i == AIOSYNC_CAPTURE && rdch)
+ *arg_i = chn_abort(rdch);
else {
printf("AIOSTOP: bad channel 0x%x\n", *arg_i);
*arg_i = 0;
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
index ddb161b..22e1d41 100644
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -234,11 +234,11 @@ mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg)
case SOUND_MIXER_DEVMASK:
case SOUND_MIXER_CAPS:
case SOUND_MIXER_STEREODEVS:
- v = m->devs;
+ v = mix_getdevs(m);
break;
case SOUND_MIXER_RECMASK:
- v = m->recdevs;
+ v = mix_getrecdevs(m);
break;
case SOUND_MIXER_RECSRC:
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index 01cdb93..c3e77de 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -81,6 +81,7 @@ struct isa_device { int dummy; };
#include <dev/sound/pcm/datatypes.h>
#include <dev/sound/pcm/channel.h>
+#include <dev/sound/pcm/buffer.h>
#include <dev/sound/pcm/feeder.h>
#include <dev/sound/pcm/mixer.h>
#include <dev/sound/pcm/dsp.h>
OpenPOWER on IntegriCloud