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