buffer.c revision 70291
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/sound/pcm/buffer.c 70291 2000-12-23 03:16:13Z cg $ 27 */ 28 29#include <dev/sound/pcm/sound.h> 30 31static void 32sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 33{ 34 snd_dbuf *b = (snd_dbuf *)arg; 35 36 if (bootverbose) { 37 printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr, 38 (unsigned long)segs->ds_len); 39 printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf)); 40 } 41} 42 43/* 44 * Allocate memory for DMA buffer. If the device do not perform DMA transfer, 45 * the driver can call malloc(9) by its own. 46 */ 47int 48sndbuf_alloc(snd_dbuf *b, bus_dma_tag_t dmatag, int size) 49{ 50 b->dmatag = dmatag; 51 b->maxsize = size; 52 b->bufsize = b->maxsize; 53 if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT, &b->dmamap)) 54 return ENOSPC; 55 if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, sndbuf_setmap, b, 0)) 56 return ENOSPC; 57 return sndbuf_resize(b, 2, b->maxsize / 2); 58} 59 60int 61sndbuf_setup(snd_dbuf *b, void *buf, int size) 62{ 63 bzero(b, sizeof(*b)); 64 b->buf = buf; 65 b->maxsize = size; 66 b->bufsize = b->maxsize; 67 return sndbuf_resize(b, 2, b->maxsize / 2); 68} 69 70void 71sndbuf_free(snd_dbuf *b) 72{ 73 bus_dmamap_unload(b->dmatag, b->dmamap); 74 bus_dmamem_free(b->dmatag, b->buf, b->dmamap); 75} 76 77int 78sndbuf_resize(snd_dbuf *b, int blkcnt, int blksz) 79{ 80 if (blkcnt == 0) 81 blkcnt = b->blkcnt; 82 if (blksz == 0) 83 blksz = b->blksz; 84 if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize)) 85 return EINVAL; 86 b->blkcnt = blkcnt; 87 b->blksz = blksz; 88 b->bufsize = blkcnt * blksz; 89 sndbuf_reset(b); 90 return 0; 91} 92 93void 94sndbuf_clear(snd_dbuf *b, int length) 95{ 96 int i; 97 u_int16_t data, *p; 98 99 if (length == 0) 100 return; 101 102 if (b->fmt & AFMT_SIGNED) 103 data = 0x00; 104 else 105 data = 0x80; 106 107 if (b->fmt & AFMT_16BIT) 108 data <<= 8; 109 else 110 data |= data << 8; 111 112 if (b->fmt & AFMT_BIGENDIAN) 113 data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); 114 115 i = b->fp; 116 p = (u_int16_t *)(b->buf + b->fp); 117 while (length > 1) { 118 *p++ = data; 119 length -= 2; 120 i += 2; 121 if (i >= b->bufsize) { 122 p = (u_int16_t *)b->buf; 123 i = 0; 124 } 125 } 126 if (length == 1) 127 *(b->buf + i) = data & 0xff; 128} 129 130void 131sndbuf_reset(snd_dbuf *b) 132{ 133 b->rp = b->fp = 0; 134 b->dl = b->rl = 0; 135 b->fl = b->bufsize; 136 b->prev_total = b->total = 0; 137 b->prev_int_count = b->int_count = 0; 138 b->underflow = 0; 139 if (b->buf && b->bufsize > 0) 140 sndbuf_clear(b, b->bufsize); 141} 142 143int 144sndbuf_setfmt(snd_dbuf *b, u_int32_t fmt) 145{ 146 b->fmt = fmt; 147 b->bps = 1; 148 b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0; 149 b->bps <<= (b->fmt & AFMT_16BIT)? 1 : 0; 150 b->bps <<= (b->fmt & AFMT_32BIT)? 2 : 0; 151 return 0; 152} 153 154int 155sndbuf_getbps(snd_dbuf *b) 156{ 157 return b->bps; 158} 159 160void * 161sndbuf_getbuf(snd_dbuf *b) 162{ 163 return b->buf; 164} 165 166int 167sndbuf_getsize(snd_dbuf *b) 168{ 169 return b->bufsize; 170} 171 172int 173sndbuf_runsz(snd_dbuf *b) 174{ 175 return b->dl; 176} 177 178int 179sndbuf_isadmasetup(snd_dbuf *b, struct resource *drq) 180{ 181 /* should do isa_dma_acquire/isa_dma_release here */ 182 if (drq == NULL) { 183 b->flags &= ~SNDBUF_F_ISADMA; 184 b->chan = -1; 185 } else { 186 b->flags &= ~SNDBUF_F_ISADMA; 187 b->chan = rman_get_start(drq); 188 } 189 return 0; 190} 191 192int 193sndbuf_isadmasetdir(snd_dbuf *b, int dir) 194{ 195 b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ; 196 return 0; 197} 198 199void 200sndbuf_isadma(snd_dbuf *b, int go) 201{ 202 KASSERT(b, ("sndbuf_isadma called with b == NULL")); 203 KASSERT(ISA_DMA(b), ("sndbuf_isadma called on non-ISA channel")); 204 205 switch (go) { 206 case PCMTRIG_START: 207 /* isa_dmainit(b->chan, size); */ 208 isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->chan); 209 break; 210 211 case PCMTRIG_STOP: 212 case PCMTRIG_ABORT: 213 isa_dmastop(b->chan); 214 isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->chan); 215 break; 216 } 217 218 DEB(printf("buf 0x%p ISA DMA %s, channel %d\n", 219 b, 220 (go == PCMTRIG_START)? "started" : "stopped", 221 b->chan)); 222} 223 224int 225sndbuf_isadmaptr(snd_dbuf *b) 226{ 227 if (ISA_DMA(b)) { 228 int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; 229 if (i < 0) 230 i = 0; 231 return b->bufsize - i; 232 } else KASSERT(1, ("sndbuf_isadmaptr called on invalid channel")); 233 return -1; 234} 235 236void 237sndbuf_isadmabounce(snd_dbuf *b) 238{ 239 if (ISA_DMA(b)) { 240 /* tell isa_dma to bounce data in/out */ 241 } else 242 KASSERT(1, ("chn_isadmabounce called on invalid channel")); 243} 244 245