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