buffer.c revision 89771
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
2770291Scg#include <dev/sound/pcm/sound.h>
2870291Scg
2974763Scg#include "feeder_if.h"
3074763Scg
3182180ScgSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/buffer.c 89771 2002-01-25 02:39:34Z cg $");
3282180Scg
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	b->buf = buf;
10470291Scg	b->maxsize = size;
10570291Scg	b->bufsize = b->maxsize;
10670291Scg	return sndbuf_resize(b, 2, b->maxsize / 2);
10770291Scg}
10870291Scg
10970291Scgvoid
11074763Scgsndbuf_free(struct snd_dbuf *b)
11170291Scg{
11274763Scg	if (b->tmpbuf)
11374763Scg		free(b->tmpbuf, M_DEVBUF);
11474763Scg	b->tmpbuf = NULL;
11574763Scg
11674763Scg	if (b->dmamap)
11774797Scg		bus_dmamap_unload(b->dmatag, b->dmamap);
11874763Scg
11974763Scg	if (b->dmamap && b->buf)
12074797Scg		bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
12177265Scg	b->dmamap = NULL;
12277265Scg	b->buf = NULL;
12370291Scg}
12470291Scg
12570291Scgint
12674763Scgsndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
12770291Scg{
12874763Scg	if (b->maxsize == 0)
12974763Scg		return 0;
13070291Scg	if (blkcnt == 0)
13170291Scg		blkcnt = b->blkcnt;
13270291Scg	if (blksz == 0)
13370291Scg		blksz = b->blksz;
13470291Scg	if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize))
13570291Scg		return EINVAL;
13670291Scg	b->blkcnt = blkcnt;
13770291Scg	b->blksz = blksz;
13870291Scg	b->bufsize = blkcnt * blksz;
13974763Scg	if (b->tmpbuf)
14074763Scg		free(b->tmpbuf, M_DEVBUF);
14174763Scg	b->tmpbuf = malloc(b->bufsize, M_DEVBUF, M_WAITOK);
14270291Scg	sndbuf_reset(b);
14370291Scg	return 0;
14470291Scg}
14570291Scg
14674763Scgint
14774763Scgsndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
14874763Scg{
14974763Scg	if (blkcnt < 2 || blksz < 16)
15074763Scg		return EINVAL;
15174763Scg
15274763Scg	b->blkcnt = blkcnt;
15374763Scg	b->blksz = blksz;
15474763Scg
15574763Scg	b->maxsize = blkcnt * blksz;
15674763Scg	b->bufsize = b->maxsize;
15774763Scg
15874763Scg	if (b->buf)
15974763Scg		free(b->buf, M_DEVBUF);
16074763Scg	b->buf = malloc(b->bufsize, M_DEVBUF, M_WAITOK);
16174763Scg	if (b->buf == NULL)
16274763Scg		return ENOMEM;
16374763Scg
16474763Scg	if (b->tmpbuf)
16574763Scg		free(b->tmpbuf, M_DEVBUF);
16674763Scg	b->tmpbuf = malloc(b->bufsize, M_DEVBUF, M_WAITOK);
16774763Scg	if (b->tmpbuf == NULL)
16874763Scg		return ENOMEM;
16974763Scg
17074763Scg	sndbuf_reset(b);
17174763Scg	return 0;
17274763Scg}
17374763Scg
17470291Scgvoid
17574763Scgsndbuf_clear(struct snd_dbuf *b, unsigned int length)
17670291Scg{
17770291Scg	int i;
17873768Scg	u_char data, *p;
17970291Scg
18070291Scg	if (length == 0)
18170291Scg		return;
18273768Scg	if (length > b->bufsize)
18373768Scg		length = b->bufsize;
18470291Scg
18570291Scg	if (b->fmt & AFMT_SIGNED)
18670291Scg		data = 0x00;
18770291Scg	else
18870291Scg		data = 0x80;
18970291Scg
19074763Scg	i = sndbuf_getfreeptr(b);
19174763Scg	p = sndbuf_getbuf(b);
19273768Scg	while (length > 0) {
19373768Scg		p[i] = data;
19473768Scg		length--;
19573768Scg		i++;
19673768Scg		if (i >= b->bufsize)
19770291Scg			i = 0;
19870291Scg	}
19970291Scg}
20070291Scg
20170291Scgvoid
20277265Scgsndbuf_fillsilence(struct snd_dbuf *b)
20377265Scg{
20477265Scg	int i;
20577265Scg	u_char data, *p;
20677265Scg
20777265Scg	if (b->fmt & AFMT_SIGNED)
20877265Scg		data = 0x00;
20977265Scg	else
21077265Scg		data = 0x80;
21177265Scg
21277265Scg	i = 0;
21377265Scg	p = sndbuf_getbuf(b);
21477265Scg	while (i < b->bufsize)
21577265Scg		p[i++] = data;
21677265Scg	b->rp = 0;
21777265Scg	b->rl = b->bufsize;
21877265Scg}
21977265Scg
22077265Scgvoid
22174763Scgsndbuf_reset(struct snd_dbuf *b)
22270291Scg{
22374763Scg	b->hp = 0;
22474763Scg	b->rp = 0;
22574763Scg	b->rl = 0;
22674763Scg	b->dl = 0;
22774763Scg	b->prev_total = 0;
22874763Scg	b->total = 0;
22974763Scg	b->xrun = 0;
23070291Scg	if (b->buf && b->bufsize > 0)
23170291Scg		sndbuf_clear(b, b->bufsize);
23270291Scg}
23370291Scg
23474763Scgu_int32_t
23574763Scgsndbuf_getfmt(struct snd_dbuf *b)
23674763Scg{
23774763Scg	return b->fmt;
23874763Scg}
23974763Scg
24070291Scgint
24174763Scgsndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt)
24270291Scg{
24370291Scg	b->fmt = fmt;
24470291Scg	b->bps = 1;
24570291Scg	b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0;
24670291Scg	b->bps <<= (b->fmt & AFMT_16BIT)? 1 : 0;
24770291Scg	b->bps <<= (b->fmt & AFMT_32BIT)? 2 : 0;
24870291Scg	return 0;
24970291Scg}
25070291Scg
25174763Scgunsigned int
25274763Scgsndbuf_getspd(struct snd_dbuf *b)
25370291Scg{
25474763Scg	return b->spd;
25574763Scg}
25674763Scg
25774763Scgvoid
25874763Scgsndbuf_setspd(struct snd_dbuf *b, unsigned int spd)
25974763Scg{
26074763Scg	b->spd = spd;
26174763Scg}
26274763Scg
26374763Scgunsigned int
26474763Scgsndbuf_getalign(struct snd_dbuf *b)
26574763Scg{
26674763Scg	static int align[] = {0, 1, 1, 2, 2, 2, 2, 3};
26774763Scg
26874763Scg	return align[b->bps - 1];
26974763Scg}
27074763Scg
27174763Scgunsigned int
27274763Scgsndbuf_getblkcnt(struct snd_dbuf *b)
27374763Scg{
27474763Scg	return b->blkcnt;
27574763Scg}
27674763Scg
27774763Scgvoid
27874763Scgsndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt)
27974763Scg{
28074763Scg	b->blkcnt = blkcnt;
28174763Scg}
28274763Scg
28374763Scgunsigned int
28474763Scgsndbuf_getblksz(struct snd_dbuf *b)
28574763Scg{
28674763Scg	return b->blksz;
28774763Scg}
28874763Scg
28974763Scgvoid
29074763Scgsndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz)
29174763Scg{
29274763Scg	b->blksz = blksz;
29374763Scg}
29474763Scg
29574763Scgunsigned int
29674763Scgsndbuf_getbps(struct snd_dbuf *b)
29774763Scg{
29870291Scg	return b->bps;
29970291Scg}
30070291Scg
30170291Scgvoid *
30274763Scgsndbuf_getbuf(struct snd_dbuf *b)
30370291Scg{
30470291Scg	return b->buf;
30570291Scg}
30670291Scg
30774763Scgvoid *
30874763Scgsndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs)
30970291Scg{
31089771Scg	KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs));
31174763Scg
31274763Scg	return b->buf + ofs;
31374763Scg}
31474763Scg
31574763Scgunsigned int
31674763Scgsndbuf_getsize(struct snd_dbuf *b)
31774763Scg{
31870291Scg	return b->bufsize;
31970291Scg}
32070291Scg
32174763Scgunsigned int
32274763Scgsndbuf_getmaxsize(struct snd_dbuf *b)
32370291Scg{
32474763Scg	return b->maxsize;
32574763Scg}
32674763Scg
32774763Scgunsigned int
32874763Scgsndbuf_runsz(struct snd_dbuf *b)
32974763Scg{
33070291Scg	return b->dl;
33170291Scg}
33270291Scg
33374763Scgvoid
33474763Scgsndbuf_setrun(struct snd_dbuf *b, int go)
33574763Scg{
33674763Scg	b->dl = go? b->blksz : 0;
33774763Scg}
33874763Scg
33974763Scgstruct selinfo *
34074763Scgsndbuf_getsel(struct snd_dbuf *b)
34174763Scg{
34274763Scg	return &b->sel;
34374763Scg}
34474763Scg
34574763Scg/************************************************************/
34674763Scgunsigned int
34774763Scgsndbuf_getxrun(struct snd_dbuf *b)
34874763Scg{
34974763Scg	SNDBUF_LOCKASSERT(b);
35074763Scg
35174763Scg	return b->xrun;
35274763Scg}
35374763Scg
35474763Scgvoid
35574763Scgsndbuf_setxrun(struct snd_dbuf *b, unsigned int cnt)
35674763Scg{
35774763Scg	SNDBUF_LOCKASSERT(b);
35874763Scg
35974763Scg	b->xrun = cnt;
36074763Scg}
36174763Scg
36274763Scgunsigned int
36374763Scgsndbuf_gethwptr(struct snd_dbuf *b)
36474763Scg{
36574763Scg	SNDBUF_LOCKASSERT(b);
36674763Scg
36774763Scg	return b->hp;
36874763Scg}
36974763Scg
37074763Scgvoid
37174763Scgsndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr)
37274763Scg{
37374763Scg	SNDBUF_LOCKASSERT(b);
37474763Scg
37574763Scg	b->hp = ptr;
37674763Scg}
37774763Scg
37874763Scgunsigned int
37974763Scgsndbuf_getready(struct snd_dbuf *b)
38074763Scg{
38174763Scg	SNDBUF_LOCKASSERT(b);
38287599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
38374763Scg
38474763Scg	return b->rl;
38574763Scg}
38674763Scg
38774763Scgunsigned int
38874763Scgsndbuf_getreadyptr(struct snd_dbuf *b)
38974763Scg{
39074763Scg	SNDBUF_LOCKASSERT(b);
39187599Sobrien	KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
39274763Scg
39374763Scg	return b->rp;
39474763Scg}
39574763Scg
39674763Scgunsigned int
39774763Scgsndbuf_getfree(struct snd_dbuf *b)
39874763Scg{
39974763Scg	SNDBUF_LOCKASSERT(b);
40087599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
40174763Scg
40274763Scg	return b->bufsize - b->rl;
40374763Scg}
40474763Scg
40574763Scgunsigned int
40674763Scgsndbuf_getfreeptr(struct snd_dbuf *b)
40774763Scg{
40874763Scg	SNDBUF_LOCKASSERT(b);
40987599Sobrien	KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
41087599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
41174763Scg
41274763Scg	return (b->rp + b->rl) % b->bufsize;
41374763Scg}
41474763Scg
41574763Scgunsigned int
41674763Scgsndbuf_getblocks(struct snd_dbuf *b)
41774763Scg{
41874763Scg	SNDBUF_LOCKASSERT(b);
41974763Scg
42074763Scg	return b->total / b->blksz;
42174763Scg}
42274763Scg
42374763Scgunsigned int
42474763Scgsndbuf_getprevblocks(struct snd_dbuf *b)
42574763Scg{
42674763Scg	SNDBUF_LOCKASSERT(b);
42774763Scg
42874763Scg	return b->prev_total / b->blksz;
42974763Scg}
43074763Scg
43174763Scgunsigned int
43274763Scgsndbuf_gettotal(struct snd_dbuf *b)
43374763Scg{
43474763Scg	SNDBUF_LOCKASSERT(b);
43574763Scg
43674763Scg	return b->total;
43774763Scg}
43874763Scg
43974763Scgvoid
44074763Scgsndbuf_updateprevtotal(struct snd_dbuf *b)
44174763Scg{
44274763Scg	SNDBUF_LOCKASSERT(b);
44374763Scg
44474763Scg	b->prev_total = b->total;
44574763Scg}
44674763Scg
44774763Scg/************************************************************/
44874763Scg
44970291Scgint
45074763Scgsndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count)
45170291Scg{
45274763Scg	int l;
45374763Scg
45487599Sobrien	KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b)));
45587599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
45674763Scg	b->total += count;
45774763Scg	if (from != NULL) {
45874763Scg		while (count > 0) {
45974763Scg			l = MIN(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b));
46074763Scg			bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l);
46174763Scg			from += l;
46274763Scg			b->rl += l;
46374763Scg			count -= l;
46474763Scg		}
46574763Scg	} else
46674763Scg		b->rl += count;
46787599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
46874763Scg
46974763Scg	return 0;
47074763Scg}
47174763Scg
47274763Scgint
47374763Scgsndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count)
47474763Scg{
47574763Scg	int l;
47674763Scg
47787599Sobrien	KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b)));
47887599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
47974763Scg	if (to != NULL) {
48074763Scg		while (count > 0) {
48174763Scg			l = MIN(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b));
48274763Scg			bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l);
48374763Scg			to += l;
48474763Scg			b->rl -= l;
48574763Scg			b->rp = (b->rp + l) % b->bufsize;
48674763Scg			count -= l;
48774763Scg		}
48874763Scg	} else {
48974763Scg		b->rl -= count;
49074763Scg		b->rp = (b->rp + count) % b->bufsize;
49174763Scg	}
49287599Sobrien	KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
49374763Scg
49474763Scg	return 0;
49574763Scg}
49674763Scg
49774763Scgint
49874763Scgsndbuf_uiomove(struct snd_dbuf *b, struct uio *uio, unsigned int count)
49974763Scg{
50074763Scg	int x, c, p, rd, err;
50174763Scg
50274763Scg	err = 0;
50374763Scg	rd = (uio->uio_rw == UIO_READ)? 1 : 0;
50474763Scg	if (count > uio->uio_resid)
50574763Scg		return EINVAL;
50674763Scg
50774763Scg	if (count > (rd? sndbuf_getready(b) : sndbuf_getfree(b))) {
50874763Scg		return EINVAL;
50974763Scg	}
51074763Scg
51174763Scg	while (err == 0 && count > 0) {
51274763Scg		p = rd? sndbuf_getreadyptr(b) : sndbuf_getfreeptr(b);
51374763Scg		c = MIN(count, sndbuf_getsize(b) - p);
51474763Scg		x = uio->uio_resid;
51574763Scg		err = uiomove(sndbuf_getbufofs(b, p), c, uio);
51674763Scg		x -= uio->uio_resid;
51774763Scg		count -= x;
51874763Scg		x = rd? sndbuf_dispose(b, NULL, x) : sndbuf_acquire(b, NULL, x);
51974763Scg	}
52074763Scg
52174763Scg	return 0;
52274763Scg}
52374763Scg
52474763Scg/* count is number of bytes we want added to destination buffer */
52574763Scgint
52674763Scgsndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count)
52774763Scg{
52877265Scg	KASSERT(count > 0, ("can't feed 0 bytes"));
52977265Scg
53074763Scg	if (sndbuf_getfree(to) < count)
53174763Scg		return EINVAL;
53274763Scg
53374763Scg	count = FEEDER_FEED(feeder, channel, to->tmpbuf, count, from);
53475317Scg	if (count)
53575317Scg		sndbuf_acquire(to, to->tmpbuf, count);
53674763Scg	/* the root feeder has called sndbuf_dispose(from, , bytes fetched) */
53774763Scg
53874763Scg	return 0;
53974763Scg}
54074763Scg
54174763Scg/************************************************************/
54274763Scg
54374763Scgvoid
54474763Scgsndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what)
54574763Scg{
54674763Scg	printf("%s: [", s);
54774763Scg	if (what & 0x01)
54874763Scg		printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize);
54974763Scg	if (what & 0x02)
55074763Scg		printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp);
55174763Scg	if (what & 0x04)
55274763Scg		printf(" total: %d, prev_total: %d, xrun: %d", b->total, b->prev_total, b->xrun);
55374763Scg   	if (what & 0x08)
55474763Scg		printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd);
55574763Scg	if (what & 0x10)
55674763Scg		printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags);
55774763Scg	printf(" ]\n");
55874763Scg}
55974763Scg
56074763Scg/************************************************************/
56174763Scgu_int32_t
56274763Scgsndbuf_getflags(struct snd_dbuf *b)
56374763Scg{
56474763Scg	return b->flags;
56574763Scg}
56674763Scg
56774763Scgvoid
56874763Scgsndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on)
56974763Scg{
57074763Scg	b->flags &= ~flags;
57174763Scg	if (on)
57274763Scg		b->flags |= flags;
57374763Scg}
57474763Scg
57574763Scg/************************************************************/
57674763Scg
57774763Scgint
57874763Scgsndbuf_isadmasetup(struct snd_dbuf *b, struct resource *drq)
57974763Scg{
58070291Scg	/* should do isa_dma_acquire/isa_dma_release here */
58170291Scg	if (drq == NULL) {
58274763Scg		b->isadmachan = -1;
58370291Scg	} else {
58474763Scg		sndbuf_setflags(b, SNDBUF_F_ISADMA, 1);
58574763Scg		b->isadmachan = rman_get_start(drq);
58670291Scg	}
58770291Scg	return 0;
58870291Scg}
58970291Scg
59070291Scgint
59174763Scgsndbuf_isadmasetdir(struct snd_dbuf *b, int dir)
59270291Scg{
59374763Scg	KASSERT(b, ("sndbuf_isadmasetdir called with b == NULL"));
59474763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadmasetdir called on non-ISA buffer"));
59574763Scg
59670291Scg	b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ;
59770291Scg	return 0;
59870291Scg}
59970291Scg
60070291Scgvoid
60174763Scgsndbuf_isadma(struct snd_dbuf *b, int go)
60270291Scg{
60370291Scg	KASSERT(b, ("sndbuf_isadma called with b == NULL"));
60474763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadma called on non-ISA buffer"));
60570291Scg
60670291Scg	switch (go) {
60770291Scg	case PCMTRIG_START:
60870291Scg		/* isa_dmainit(b->chan, size); */
60974763Scg		isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->isadmachan);
61070291Scg		break;
61170291Scg
61270291Scg	case PCMTRIG_STOP:
61370291Scg	case PCMTRIG_ABORT:
61474763Scg		isa_dmastop(b->isadmachan);
61574763Scg		isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->isadmachan);
61670291Scg		break;
61770291Scg	}
61870291Scg
61970291Scg	DEB(printf("buf 0x%p ISA DMA %s, channel %d\n",
62070291Scg		b,
62170291Scg		(go == PCMTRIG_START)? "started" : "stopped",
62270291Scg		b->chan));
62370291Scg}
62470291Scg
62570291Scgint
62674763Scgsndbuf_isadmaptr(struct snd_dbuf *b)
62770291Scg{
62874763Scg	int i;
62974763Scg
63074763Scg	KASSERT(b, ("sndbuf_isadmaptr called with b == NULL"));
63174763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadmaptr called on non-ISA buffer"));
63274763Scg
63374763Scg	if (!sndbuf_runsz(b))
63474763Scg		return 0;
63574763Scg	i = isa_dmastatus(b->isadmachan);
63674763Scg	KASSERT(i >= 0, ("isa_dmastatus returned %d", i));
63774797Scg	return b->bufsize - i;
63870291Scg}
63970291Scg
64070291Scgvoid
64174763Scgsndbuf_isadmabounce(struct snd_dbuf *b)
64270291Scg{
64374763Scg	KASSERT(b, ("sndbuf_isadmabounce called with b == NULL"));
64474763Scg	KASSERT(sndbuf_getflags(b) & SNDBUF_F_ISADMA, ("sndbuf_isadmabounce called on non-ISA buffer"));
64574763Scg
64674797Scg	/* tell isa_dma to bounce data in/out */
64770291Scg}
64870291Scg
649