buffer.c revision 74763
170291Scg/*
270291Scg * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
370291Scg * All rights reserved.
470291Scg *
570291Scg * Redistribution and use in source and binary forms, with or without
670291Scg * modification, are permitted provided that the following conditions
770291Scg * are met:
870291Scg * 1. Redistributions of source code must retain the above copyright
970291Scg *    notice, this list of conditions and the following disclaimer.
1070291Scg * 2. Redistributions in binary form must reproduce the above copyright
1170291Scg *    notice, this list of conditions and the following disclaimer in the
1270291Scg *    documentation and/or other materials provided with the distribution.
1370291Scg *
1470291Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1570291Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1670291Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1770291Scg * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1870291Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1970291Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2070291Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2170291Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2270291Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2370291Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2470291Scg * SUCH DAMAGE.
2570291Scg *
2670291Scg * $FreeBSD: head/sys/dev/sound/pcm/buffer.c 74763 2001-03-24 23:10:29Z cg $
2770291Scg */
2870291Scg
2970291Scg#include <dev/sound/pcm/sound.h>
3070291Scg
3174763Scg#include "feeder_if.h"
3274763Scg
3374763Scg#define	MIN(x, y) (((x) < (y))? (x) : (y))
3474763Scg
3574763Scg#define SNDBUF_NAMELEN	48
3674763Scgstruct snd_dbuf {
3774763Scg        u_int8_t *buf, *tmpbuf;
3874763Scg        unsigned int bufsize, maxsize;
3974763Scg        volatile int dl; /* transfer size */
4074763Scg        volatile int rp; /* pointers to the ready area */
4174763Scg	volatile int rl; /* length of ready area */
4274763Scg	volatile int hp;
4374763Scg	volatile u_int32_t total, prev_total;
4474763Scg	int isadmachan, dir;       /* dma channel */
4574763Scg	u_int32_t fmt, spd, bps;
4674763Scg	unsigned int blksz, blkcnt;
4774763Scg	int xrun;
4874763Scg	u_int32_t flags;
4974763Scg	bus_dmamap_t dmamap;
5074763Scg	bus_dma_tag_t dmatag;
5174763Scg	struct selinfo sel;
5274763Scg	char name[SNDBUF_NAMELEN];
5374763Scg};
5474763Scg
5574763Scgstruct snd_dbuf *
5674763Scgsndbuf_create(char *drv, char *desc)
5774763Scg{
5874763Scg	struct snd_dbuf *b;
5974763Scg
6074763Scg	b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO);
6174763Scg	snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc);
6274763Scg	return b;
6374763Scg}
6474763Scg
6574763Scgvoid
6674763Scgsndbuf_destroy(struct snd_dbuf *b)
6774763Scg{
6874763Scg	free(b, M_DEVBUF);
6974763Scg}
7074763Scg
7170291Scgstatic void
7270291Scgsndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
7370291Scg{
7474763Scg	struct snd_dbuf *b = (struct snd_dbuf *)arg;
7570291Scg
7670291Scg	if (bootverbose) {
7770291Scg		printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr,
7870291Scg		       (unsigned long)segs->ds_len);
7970291Scg		printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf));
8070291Scg	}
8170291Scg}
8270291Scg
8370291Scg/*
8474763Scg * Allocate memory for DMA buffer. If the device does not use DMA transfers,
8574763Scg * the driver can call malloc(9) and sndbuf_setup() itself.
8670291Scg */
8770291Scgint
8874763Scgsndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size)
8970291Scg{
9070291Scg	b->dmatag = dmatag;
9170291Scg	b->maxsize = size;
9270291Scg	b->bufsize = b->maxsize;
9370291Scg	if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT, &b->dmamap))
9470291Scg		return ENOSPC;
9570291Scg	if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, sndbuf_setmap, b, 0))
9670291Scg		return ENOSPC;
9770291Scg	return sndbuf_resize(b, 2, b->maxsize / 2);
9870291Scg}
9970291Scg
10070291Scgint
10174763Scgsndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
10270291Scg{
10370291Scg	bzero(b, sizeof(*b));
10470291Scg	b->buf = buf;
10570291Scg	b->maxsize = size;
10670291Scg	b->bufsize = b->maxsize;
10770291Scg	return sndbuf_resize(b, 2, b->maxsize / 2);
10870291Scg}
10970291Scg
11070291Scgvoid
11174763Scgsndbuf_free(struct snd_dbuf *b)
11270291Scg{
11374763Scg	if (b->tmpbuf)
11474763Scg		free(b->tmpbuf, M_DEVBUF);
11574763Scg	b->tmpbuf = NULL;
11674763Scg
11774763Scg	if (b->dmamap)
11870291Scg	bus_dmamap_unload(b->dmatag, b->dmamap);
11974763Scg
12074763Scg	if (b->dmamap && b->buf)
12170291Scg	bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
12270291Scg}
12370291Scg
12470291Scgint
12574763Scgsndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
12670291Scg{
12774763Scg	if (b->maxsize == 0)
12874763Scg		return 0;
12970291Scg	if (blkcnt == 0)
13070291Scg		blkcnt = b->blkcnt;
13170291Scg	if (blksz == 0)
13270291Scg		blksz = b->blksz;
13370291Scg	if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize))
13470291Scg		return EINVAL;
13570291Scg	b->blkcnt = blkcnt;
13670291Scg	b->blksz = blksz;
13770291Scg	b->bufsize = blkcnt * blksz;
13874763Scg	if (b->tmpbuf)
13974763Scg		free(b->tmpbuf, M_DEVBUF);
14074763Scg	b->tmpbuf = malloc(b->bufsize, M_DEVBUF, M_WAITOK);
14170291Scg	sndbuf_reset(b);
14270291Scg	return 0;
14370291Scg}
14470291Scg
14574763Scgint
14674763Scgsndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
14774763Scg{
14874763Scg	if (blkcnt < 2 || blksz < 16)
14974763Scg		return EINVAL;
15074763Scg
15174763Scg	b->blkcnt = blkcnt;
15274763Scg	b->blksz = blksz;
15374763Scg
15474763Scg	b->maxsize = blkcnt * blksz;
15574763Scg	b->bufsize = b->maxsize;
15674763Scg
15774763Scg	if (b->buf)
15874763Scg		free(b->buf, M_DEVBUF);
15974763Scg	b->buf = malloc(b->bufsize, M_DEVBUF, M_WAITOK);
16074763Scg	if (b->buf == NULL)
16174763Scg		return ENOMEM;
16274763Scg
16374763Scg	if (b->tmpbuf)
16474763Scg		free(b->tmpbuf, M_DEVBUF);
16574763Scg	b->tmpbuf = malloc(b->bufsize, M_DEVBUF, M_WAITOK);
16674763Scg	if (b->tmpbuf == NULL)
16774763Scg		return ENOMEM;
16874763Scg
16974763Scg	sndbuf_reset(b);
17074763Scg	return 0;
17174763Scg}
17274763Scg
17370291Scgvoid
17474763Scgsndbuf_clear(struct snd_dbuf *b, unsigned int length)
17570291Scg{
17670291Scg	int i;
17773768Scg	u_char data, *p;
17870291Scg
17970291Scg	if (length == 0)
18070291Scg		return;
18173768Scg	if (length > b->bufsize)
18273768Scg		length = b->bufsize;
18370291Scg
18470291Scg	if (b->fmt & AFMT_SIGNED)
18570291Scg		data = 0x00;
18670291Scg	else
18770291Scg		data = 0x80;
18870291Scg
18974763Scg	if (b->fmt & AFMT_16BIT)
19074763Scg		data <<= 8;
19174763Scg	else
19274763Scg		data |= data << 8;
19374763Scg
19474763Scg	i = sndbuf_getfreeptr(b);
19574763Scg	p = sndbuf_getbuf(b);
19673768Scg	while (length > 0) {
19773768Scg		p[i] = data;
19873768Scg		length--;
19973768Scg		i++;
20073768Scg		if (i >= b->bufsize)
20170291Scg			i = 0;
20270291Scg	}
20370291Scg}
20470291Scg
20570291Scgvoid
20674763Scgsndbuf_reset(struct snd_dbuf *b)
20770291Scg{
20874763Scg	b->hp = 0;
20974763Scg	b->rp = 0;
21074763Scg	b->rl = 0;
21174763Scg	b->dl = 0;
21274763Scg	b->prev_total = 0;
21374763Scg	b->total = 0;
21474763Scg	b->xrun = 0;
21570291Scg	if (b->buf && b->bufsize > 0)
21670291Scg		sndbuf_clear(b, b->bufsize);
21770291Scg}
21870291Scg
21974763Scgu_int32_t
22074763Scgsndbuf_getfmt(struct snd_dbuf *b)
22174763Scg{
22274763Scg	return b->fmt;
22374763Scg}
22474763Scg
22570291Scgint
22674763Scgsndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt)
22770291Scg{
22870291Scg	b->fmt = fmt;
22970291Scg	b->bps = 1;
23070291Scg	b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0;
23170291Scg	b->bps <<= (b->fmt & AFMT_16BIT)? 1 : 0;
23270291Scg	b->bps <<= (b->fmt & AFMT_32BIT)? 2 : 0;
23370291Scg	return 0;
23470291Scg}
23570291Scg
23674763Scgunsigned int
23774763Scgsndbuf_getspd(struct snd_dbuf *b)
23870291Scg{
23974763Scg	return b->spd;
24074763Scg}
24174763Scg
24274763Scgvoid
24374763Scgsndbuf_setspd(struct snd_dbuf *b, unsigned int spd)
24474763Scg{
24574763Scg	b->spd = spd;
24674763Scg}
24774763Scg
24874763Scgunsigned int
24974763Scgsndbuf_getalign(struct snd_dbuf *b)
25074763Scg{
25174763Scg	static int align[] = {0, 1, 1, 2, 2, 2, 2, 3};
25274763Scg
25374763Scg	return align[b->bps - 1];
25474763Scg}
25574763Scg
25674763Scgunsigned int
25774763Scgsndbuf_getblkcnt(struct snd_dbuf *b)
25874763Scg{
25974763Scg	return b->blkcnt;
26074763Scg}
26174763Scg
26274763Scgvoid
26374763Scgsndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt)
26474763Scg{
26574763Scg	b->blkcnt = blkcnt;
26674763Scg}
26774763Scg
26874763Scgunsigned int
26974763Scgsndbuf_getblksz(struct snd_dbuf *b)
27074763Scg{
27174763Scg	return b->blksz;
27274763Scg}
27374763Scg
27474763Scgvoid
27574763Scgsndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz)
27674763Scg{
27774763Scg	b->blksz = blksz;
27874763Scg}
27974763Scg
28074763Scgunsigned int
28174763Scgsndbuf_getbps(struct snd_dbuf *b)
28274763Scg{
28370291Scg	return b->bps;
28470291Scg}
28570291Scg
28670291Scgvoid *
28774763Scgsndbuf_getbuf(struct snd_dbuf *b)
28870291Scg{
28970291Scg	return b->buf;
29070291Scg}
29170291Scg
29274763Scgvoid *
29374763Scgsndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs)
29470291Scg{
29574763Scg	KASSERT((ofs >= 0) && (ofs <= b->bufsize), ("%s: ofs invalid %d", __FUNCTION__, ofs));
29674763Scg
29774763Scg	return b->buf + ofs;
29874763Scg}
29974763Scg
30074763Scgunsigned int
30174763Scgsndbuf_getsize(struct snd_dbuf *b)
30274763Scg{
30370291Scg	return b->bufsize;
30470291Scg}
30570291Scg
30674763Scgunsigned int
30774763Scgsndbuf_getmaxsize(struct snd_dbuf *b)
30870291Scg{
30974763Scg	return b->maxsize;
31074763Scg}
31174763Scg
31274763Scgunsigned int
31374763Scgsndbuf_runsz(struct snd_dbuf *b)
31474763Scg{
31570291Scg	return b->dl;
31670291Scg}
31770291Scg
31874763Scgvoid
31974763Scgsndbuf_setrun(struct snd_dbuf *b, int go)
32074763Scg{
32174763Scg	b->dl = go? b->blksz : 0;
32274763Scg}
32374763Scg
32474763Scgstruct selinfo *
32574763Scgsndbuf_getsel(struct snd_dbuf *b)
32674763Scg{
32774763Scg	return &b->sel;
32874763Scg}
32974763Scg
33074763Scg/************************************************************/
33174763Scgunsigned int
33274763Scgsndbuf_getxrun(struct snd_dbuf *b)
33374763Scg{
33474763Scg	SNDBUF_LOCKASSERT(b);
33574763Scg
33674763Scg	return b->xrun;
33774763Scg}
33874763Scg
33974763Scgvoid
34074763Scgsndbuf_setxrun(struct snd_dbuf *b, unsigned int cnt)
34174763Scg{
34274763Scg	SNDBUF_LOCKASSERT(b);
34374763Scg
34474763Scg	b->xrun = cnt;
34574763Scg}
34674763Scg
34774763Scgunsigned int
34874763Scgsndbuf_gethwptr(struct snd_dbuf *b)
34974763Scg{
35074763Scg	SNDBUF_LOCKASSERT(b);
35174763Scg
35274763Scg	return b->hp;
35374763Scg}
35474763Scg
35574763Scgvoid
35674763Scgsndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr)
35774763Scg{
35874763Scg	SNDBUF_LOCKASSERT(b);
35974763Scg
36074763Scg	b->hp = ptr;
36174763Scg}
36274763Scg
36374763Scgunsigned int
36474763Scgsndbuf_getready(struct snd_dbuf *b)
36574763Scg{
36674763Scg	SNDBUF_LOCKASSERT(b);
36774763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __FUNCTION__, b->rl));
36874763Scg
36974763Scg	return b->rl;
37074763Scg}
37174763Scg
37274763Scgunsigned int
37374763Scgsndbuf_getreadyptr(struct snd_dbuf *b)
37474763Scg{
37574763Scg	SNDBUF_LOCKASSERT(b);
37674763Scg	KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __FUNCTION__, b->rp));
37774763Scg
37874763Scg	return b->rp;
37974763Scg}
38074763Scg
38174763Scgunsigned int
38274763Scgsndbuf_getfree(struct snd_dbuf *b)
38374763Scg{
38474763Scg	SNDBUF_LOCKASSERT(b);
38574763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __FUNCTION__, b->rl));
38674763Scg
38774763Scg	return b->bufsize - b->rl;
38874763Scg}
38974763Scg
39074763Scgunsigned int
39174763Scgsndbuf_getfreeptr(struct snd_dbuf *b)
39274763Scg{
39374763Scg	SNDBUF_LOCKASSERT(b);
39474763Scg	KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __FUNCTION__, b->rp));
39574763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __FUNCTION__, b->rl));
39674763Scg
39774763Scg	return (b->rp + b->rl) % b->bufsize;
39874763Scg}
39974763Scg
40074763Scgunsigned int
40174763Scgsndbuf_getblocks(struct snd_dbuf *b)
40274763Scg{
40374763Scg	SNDBUF_LOCKASSERT(b);
40474763Scg
40574763Scg	return b->total / b->blksz;
40674763Scg}
40774763Scg
40874763Scgunsigned int
40974763Scgsndbuf_getprevblocks(struct snd_dbuf *b)
41074763Scg{
41174763Scg	SNDBUF_LOCKASSERT(b);
41274763Scg
41374763Scg	return b->prev_total / b->blksz;
41474763Scg}
41574763Scg
41674763Scgunsigned int
41774763Scgsndbuf_gettotal(struct snd_dbuf *b)
41874763Scg{
41974763Scg	SNDBUF_LOCKASSERT(b);
42074763Scg
42174763Scg	return b->total;
42274763Scg}
42374763Scg
42474763Scgvoid
42574763Scgsndbuf_updateprevtotal(struct snd_dbuf *b)
42674763Scg{
42774763Scg	SNDBUF_LOCKASSERT(b);
42874763Scg
42974763Scg	b->prev_total = b->total;
43074763Scg}
43174763Scg
43274763Scg/************************************************************/
43374763Scg
43470291Scgint
43574763Scgsndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count)
43670291Scg{
43774763Scg	int l;
43874763Scg
43974763Scg	KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __FUNCTION__, count, sndbuf_getfree(b)));
44074763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __FUNCTION__, b->rl));
44174763Scg	b->total += count;
44274763Scg	if (from != NULL) {
44374763Scg		while (count > 0) {
44474763Scg			l = MIN(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b));
44574763Scg			bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l);
44674763Scg			from += l;
44774763Scg			b->rl += l;
44874763Scg			count -= l;
44974763Scg		}
45074763Scg	} else
45174763Scg		b->rl += count;
45274763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __FUNCTION__, b->rl, count));
45374763Scg
45474763Scg	return 0;
45574763Scg}
45674763Scg
45774763Scgint
45874763Scgsndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count)
45974763Scg{
46074763Scg	int l;
46174763Scg
46274763Scg	KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __FUNCTION__, count, sndbuf_getready(b)));
46374763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __FUNCTION__, b->rl));
46474763Scg	if (to != NULL) {
46574763Scg		while (count > 0) {
46674763Scg			l = MIN(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b));
46774763Scg			bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l);
46874763Scg			to += l;
46974763Scg			b->rl -= l;
47074763Scg			b->rp = (b->rp + l) % b->bufsize;
47174763Scg			count -= l;
47274763Scg		}
47374763Scg	} else {
47474763Scg		b->rl -= count;
47574763Scg		b->rp = (b->rp + count) % b->bufsize;
47674763Scg	}
47774763Scg	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __FUNCTION__, b->rl, count));
47874763Scg
47974763Scg	return 0;
48074763Scg}
48174763Scg
48274763Scgint
48374763Scgsndbuf_uiomove(struct snd_dbuf *b, struct uio *uio, unsigned int count)
48474763Scg{
48574763Scg	int x, c, p, rd, err;
48674763Scg
48774763Scg	err = 0;
48874763Scg	rd = (uio->uio_rw == UIO_READ)? 1 : 0;
48974763Scg	if (count > uio->uio_resid)
49074763Scg		return EINVAL;
49174763Scg
49274763Scg	if (count > (rd? sndbuf_getready(b) : sndbuf_getfree(b))) {
49374763Scg		return EINVAL;
49474763Scg	}
49574763Scg
49674763Scg	while (err == 0 && count > 0) {
49774763Scg		p = rd? sndbuf_getreadyptr(b) : sndbuf_getfreeptr(b);
49874763Scg		c = MIN(count, sndbuf_getsize(b) - p);
49974763Scg		x = uio->uio_resid;
50074763Scg		err = uiomove(sndbuf_getbufofs(b, p), c, uio);
50174763Scg		x -= uio->uio_resid;
50274763Scg		count -= x;
50374763Scg		x = rd? sndbuf_dispose(b, NULL, x) : sndbuf_acquire(b, NULL, x);
50474763Scg	}
50574763Scg
50674763Scg	return 0;
50774763Scg}
50874763Scg
50974763Scg/* count is number of bytes we want added to destination buffer */
51074763Scgint
51174763Scgsndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count)
51274763Scg{
51374763Scg	if (sndbuf_getfree(to) < count)
51474763Scg		return EINVAL;
51574763Scg
51674763Scg	count = FEEDER_FEED(feeder, channel, to->tmpbuf, count, from);
51774763Scg	sndbuf_acquire(to, to->tmpbuf, count);
51874763Scg	/* the root feeder has called sndbuf_dispose(from, , bytes fetched) */
51974763Scg
52074763Scg	return 0;
52174763Scg}
52274763Scg
52374763Scg/************************************************************/
52474763Scg
52574763Scgvoid
52674763Scgsndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what)
52774763Scg{
52874763Scg	printf("%s: [", s);
52974763Scg	if (what & 0x01)
53074763Scg		printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize);
53174763Scg	if (what & 0x02)
53274763Scg		printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp);
53374763Scg	if (what & 0x04)
53474763Scg		printf(" total: %d, prev_total: %d, xrun: %d", b->total, b->prev_total, b->xrun);
53574763Scg   	if (what & 0x08)
53674763Scg		printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd);
53774763Scg	if (what & 0x10)
53874763Scg		printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags);
53974763Scg	printf(" ]\n");
54074763Scg}
54174763Scg
54274763Scg/************************************************************/
54374763Scgu_int32_t
54474763Scgsndbuf_getflags(struct snd_dbuf *b)
54574763Scg{
54674763Scg	return b->flags;
54774763Scg}
54874763Scg
54974763Scgvoid
55074763Scgsndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on)
55174763Scg{
55274763Scg	b->flags &= ~flags;
55374763Scg	if (on)
55474763Scg		b->flags |= flags;
55574763Scg}
55674763Scg
55774763Scg/************************************************************/
55874763Scg
55974763Scgint
56074763Scgsndbuf_isadmasetup(struct snd_dbuf *b, struct resource *drq)
56174763Scg{
56270291Scg	/* should do isa_dma_acquire/isa_dma_release here */
56370291Scg	if (drq == NULL) {
56474763Scg		b->isadmachan = -1;
56570291Scg	} else {
56674763Scg		sndbuf_setflags(b, SNDBUF_F_ISADMA, 1);
56774763Scg		b->isadmachan = rman_get_start(drq);
56870291Scg	}
56970291Scg	return 0;
57070291Scg}
57170291Scg
57270291Scgint
57374763Scgsndbuf_isadmasetdir(struct snd_dbuf *b, int dir)
57470291Scg{
57574763Scg	KASSERT(b, ("sndbuf_isadmasetdir called with b == NULL"));
57674763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadmasetdir called on non-ISA buffer"));
57774763Scg
57870291Scg	b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ;
57970291Scg	return 0;
58070291Scg}
58170291Scg
58270291Scgvoid
58374763Scgsndbuf_isadma(struct snd_dbuf *b, int go)
58470291Scg{
58570291Scg	KASSERT(b, ("sndbuf_isadma called with b == NULL"));
58674763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadma called on non-ISA buffer"));
58770291Scg
58870291Scg	switch (go) {
58970291Scg	case PCMTRIG_START:
59070291Scg		/* isa_dmainit(b->chan, size); */
59174763Scg		isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->isadmachan);
59270291Scg		break;
59370291Scg
59470291Scg	case PCMTRIG_STOP:
59570291Scg	case PCMTRIG_ABORT:
59674763Scg		isa_dmastop(b->isadmachan);
59774763Scg		isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->isadmachan);
59870291Scg		break;
59970291Scg	}
60070291Scg
60170291Scg	DEB(printf("buf 0x%p ISA DMA %s, channel %d\n",
60270291Scg		b,
60370291Scg		(go == PCMTRIG_START)? "started" : "stopped",
60470291Scg		b->chan));
60570291Scg}
60670291Scg
60770291Scgint
60874763Scgsndbuf_isadmaptr(struct snd_dbuf *b)
60970291Scg{
61074763Scg	int i;
61174763Scg
61274763Scg	KASSERT(b, ("sndbuf_isadmaptr called with b == NULL"));
61374763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadmaptr called on non-ISA buffer"));
61474763Scg
61574763Scg	if (!sndbuf_runsz(b))
61674763Scg		return 0;
61774763Scg	i = isa_dmastatus(b->isadmachan);
61874763Scg	KASSERT(i >= 0, ("isa_dmastatus returned %d", i));
61970291Scg		return b->bufsize - i;
62070291Scg}
62170291Scg
62270291Scgvoid
62374763Scgsndbuf_isadmabounce(struct snd_dbuf *b)
62470291Scg{
62574763Scg	KASSERT(b, ("sndbuf_isadmabounce called with b == NULL"));
62674763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadmabounce called on non-ISA buffer"));
62774763Scg
62870291Scg		/* tell isa_dma to bounce data in/out */
62970291Scg}
63070291Scg
631