channel.c (53603) | channel.c (54155) |
---|---|
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * Portions Copyright by Luigi Rizzo - 1997-99 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * | 1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * Portions Copyright by Luigi Rizzo - 1997-99 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/sys/dev/sound/pcm/channel.c 53603 1999-11-22 21:16:01Z cg $ | 27 * $FreeBSD: head/sys/dev/sound/pcm/channel.c 54155 1999-12-05 19:09:13Z cg $ |
28 */ 29 30#include <dev/sound/pcm/sound.h> 31 32#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ 33#define DMA_ALIGN_THRESHOLD 4 34#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1)) 35 36#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8)) 37#define CANCHANGE(c) (!(c)->buffer.dl) 38 39static void chn_stintr(pcm_channel *c); | 28 */ 29 30#include <dev/sound/pcm/sound.h> 31 32#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ 33#define DMA_ALIGN_THRESHOLD 4 34#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1)) 35 36#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8)) 37#define CANCHANGE(c) (!(c)->buffer.dl) 38 39static void chn_stintr(pcm_channel *c); |
40static void chn_clearbuf(pcm_channel *c, int length); |
|
40/* 41 * SOUND OUTPUT 42 43We use a circular buffer to store samples directed to the DAC. 44The buffer is split into two variable-size regions, each identified 45by an offset in the buffer (rp,fp) and a length (rl,fl): 46 47 0 rp,rl fp,fl bufsize --- 50 unchanged lines hidden (view full) --- 98 * gets copied in or out of the real buffer. fix requires mods to isa_dma.c 99 * and possibly fixes to other autodma mode clients 100 */ 101static void 102chn_isadmabounce(pcm_channel *c) 103{ 104 if (ISA_DMA(&c->buffer)) { 105 /* tell isa_dma to bounce data in/out */ | 41/* 42 * SOUND OUTPUT 43 44We use a circular buffer to store samples directed to the DAC. 45The buffer is split into two variable-size regions, each identified 46by an offset in the buffer (rp,fp) and a length (rl,fl): 47 48 0 rp,rl fp,fl bufsize --- 50 unchanged lines hidden (view full) --- 99 * gets copied in or out of the real buffer. fix requires mods to isa_dma.c 100 * and possibly fixes to other autodma mode clients 101 */ 102static void 103chn_isadmabounce(pcm_channel *c) 104{ 105 if (ISA_DMA(&c->buffer)) { 106 /* tell isa_dma to bounce data in/out */ |
106 } else panic("chn_isadmabounce called on invalid channel"); | 107 } else KASSERT(1, ("chn_isadmabounce called on invalid channel")); |
107} 108 109static int 110chn_polltrigger(pcm_channel *c) 111{ 112 snd_dbuf *b = &c->buffer; 113 unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize : 1; 114 int trig = 0; --- 33 unchanged lines hidden (view full) --- 148 149/* 150 * chn_dmaupdate() tracks the status of a dma transfer, 151 * updating pointers. It must be called at spltty(). 152 * 153 * NOTE: when we are using auto dma in the device, rl might become 154 * negative. 155 */ | 108} 109 110static int 111chn_polltrigger(pcm_channel *c) 112{ 113 snd_dbuf *b = &c->buffer; 114 unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize : 1; 115 int trig = 0; --- 33 unchanged lines hidden (view full) --- 149 150/* 151 * chn_dmaupdate() tracks the status of a dma transfer, 152 * updating pointers. It must be called at spltty(). 153 * 154 * NOTE: when we are using auto dma in the device, rl might become 155 * negative. 156 */ |
157DEB (static int chn_updatecount=0); 158 |
|
156void 157chn_dmaupdate(pcm_channel *c) 158{ 159 snd_dbuf *b = &c->buffer; | 159void 160chn_dmaupdate(pcm_channel *c) 161{ 162 snd_dbuf *b = &c->buffer; |
160 int delta, hwptr = chn_getptr(c); | 163 int delta, hwptr; 164 DEB (int b_rl=b->rl; int b_fl=b->fl; int b_rp=b->rp; int b_fp=b->fp); |
161 | 165 |
166 hwptr = chn_getptr(c); |
|
162 if (c->direction == PCMDIR_PLAY) { 163 delta = (b->bufsize + hwptr - b->rp) % b->bufsize; 164 b->rp = hwptr; 165 b->rl -= delta; 166 b->fl += delta; | 167 if (c->direction == PCMDIR_PLAY) { 168 delta = (b->bufsize + hwptr - b->rp) % b->bufsize; 169 b->rp = hwptr; 170 b->rl -= delta; 171 b->fl += delta; |
172 DEB(if (b->rl<0) printf("OUCH!(%d) rl %d(%d) delta %d bufsize %d hwptr %d rp %d(%d)\n", chn_updatecount++, b->rl, b_rl, delta, b->bufsize, hwptr, b->rp, b_rp)); |
|
167 } else { 168 delta = (b->bufsize + hwptr - b->fp) % b->bufsize; 169 b->fp = hwptr; 170 b->rl += delta; 171 b->fl -= delta; | 173 } else { 174 delta = (b->bufsize + hwptr - b->fp) % b->bufsize; 175 b->fp = hwptr; 176 b->rl += delta; 177 b->fl -= delta; |
178 DEB(if (b->fl<0) printf("OUCH!(%d) fl %d(%d) delta %d bufsize %d hwptr %d fp %d(%d)\n", chn_updatecount++, b->fl, b_fl, delta, b->bufsize, hwptr, b->fp, b_fp)); |
|
172 } 173 b->total += delta; 174} 175 176/* | 179 } 180 b->total += delta; 181} 182 183/* |
184 * Check channel for underflow occured, reset DMA buffer in case of 185 * underflow. It must be called at spltty(). 186 */ 187static void 188chn_checkunderflow(pcm_channel *c) 189{ 190 snd_dbuf *b = &c->buffer; 191 192 if (b->underflow) { 193 DEB(printf("Clear underflow condition\n")); 194 b->rp = b->fp = chn_getptr(c); 195 b->rl = 0; 196 b->fl = b->bufsize; 197 b->underflow=0; 198 } else { 199 chn_dmaupdate(c); 200 } 201} 202 203/* |
|
177 * Write interrupt routine. Can be called from other places (e.g. 178 * to start a paused transfer), but with interrupts disabled. 179 */ 180static void 181chn_wrintr(pcm_channel *c) 182{ 183 snd_dbuf *b = &c->buffer; 184 int start; 185 | 204 * Write interrupt routine. Can be called from other places (e.g. 205 * to start a paused transfer), but with interrupts disabled. 206 */ 207static void 208chn_wrintr(pcm_channel *c) 209{ 210 snd_dbuf *b = &c->buffer; 211 int start; 212 |
186 if (b->dl) chn_dmadone(c); | 213 if (b->underflow) return; /* nothing new happened */ 214 if (b->dl) chn_dmadone(c); |
187 188 /* 189 * start another dma operation only if have ready data in the buffer, 190 * there is no pending abort, have a full-duplex device, or have a 191 * half duplex device and there is no pending op on the other side. 192 * 193 * Force transfers to be aligned to a boundary of 4, which is 194 * needed when doing stereo and 16-bit. 195 */ 196 if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED; 197 else start = (b->rl >= DMA_ALIGN_THRESHOLD && !(c->flags & CHN_F_ABORTING)); 198 if (start) { 199 int l; 200 chn_dmaupdate(c); | 215 216 /* 217 * start another dma operation only if have ready data in the buffer, 218 * there is no pending abort, have a full-duplex device, or have a 219 * half duplex device and there is no pending op on the other side. 220 * 221 * Force transfers to be aligned to a boundary of 4, which is 222 * needed when doing stereo and 16-bit. 223 */ 224 if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED; 225 else start = (b->rl >= DMA_ALIGN_THRESHOLD && !(c->flags & CHN_F_ABORTING)); 226 if (start) { 227 int l; 228 chn_dmaupdate(c); |
201 l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK; | |
202 if (c->flags & CHN_F_MAPPED) l = c->blocksize; | 229 if (c->flags & CHN_F_MAPPED) l = c->blocksize; |
230 else l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK; |
|
203 /* 204 * check if we need to reprogram the DMA on the sound card. | 231 /* 232 * check if we need to reprogram the DMA on the sound card. |
205 * This happens if the size has changed _and_ the new size 206 * is smaller, or it matches the blocksize. | 233 * This happens if the size has changed from zero |
207 * | 234 * |
208 * 0 <= l <= blocksize 209 * 0 <= dl <= blocksize 210 * reprog if (dl == 0 || l != dl) 211 * was: 212 * l != b->dl && (b->dl == 0 || l < b->dl || l == c->blocksize) | |
213 */ | 235 */ |
214 if (b->dl == 0 || l != b->dl) { 215 /* size has changed. Stop and restart */ 216 DEB(printf("wrintr: bsz %d -> %d, rp %d rl %d\n", 217 b->dl, l, b->rp, b->rl)); 218 if (b->dl) chn_trigger(c, PCMTRIG_STOP); 219 b->dl = l; /* record new transfer size */ | 236 if (b->dl == 0) { 237 /* Start DMA operation */ 238 b->dl = c->blocksize ; /* record new transfer size */ |
220 chn_trigger(c, PCMTRIG_START); | 239 chn_trigger(c, PCMTRIG_START); |
240 } else if (b->dl != l) { 241 /* 242 * we are near to underflow condition, so to prevent 243 * audio 'clicks' clear next 1.5*dl bytes 244 */ 245 chn_clearbuf(c, (b->dl*3)/2); |
|
221 } 222 } else { 223 /* cannot start a new dma transfer */ 224 DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n", 225 c->flags, b->rp, b->rl)); | 246 } 247 } else { 248 /* cannot start a new dma transfer */ 249 DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n", 250 c->flags, b->rp, b->rl)); |
226 if (b->dl) { /* was active */ 227 b->dl = 0; 228 chn_trigger(c, PCMTRIG_STOP); 229#if 0 230 if (c->flags & CHN_F_WRITING) 231 DEB(printf("got wrint while reloading\n")); 232 else if (b->rl <= 0) /* XXX added 980110 lr */ 233 chn_resetbuf(c); 234#endif | 251 if (b->dl) { /* DMA was active */ 252 b->underflow = 1; /* set underflow flag */ 253 chn_clearbuf(c, b->bufsize); /* and clear all DMA buffer */ |
235 } 236 } 237} 238 239/* 240 * user write routine 241 * 242 * advance the boundary between READY and FREE, fill the space with --- 7 unchanged lines hidden (view full) --- 250 * data, we reduce the latency to something proportional to the length 251 * of the first piece, while keeping the overhead low and being able 252 * to feed the DMA with large blocks. 253 */ 254 255int 256chn_write(pcm_channel *c, struct uio *buf) 257{ | 254 } 255 } 256} 257 258/* 259 * user write routine 260 * 261 * advance the boundary between READY and FREE, fill the space with --- 7 unchanged lines hidden (view full) --- 269 * data, we reduce the latency to something proportional to the length 270 * of the first piece, while keeping the overhead low and being able 271 * to feed the DMA with large blocks. 272 */ 273 274int 275chn_write(pcm_channel *c, struct uio *buf) 276{ |
258 int a, l, w, timeout, ret = 0; | 277 int a, l, w, timeout, ret = 0, rc; |
259 long s; 260 snd_dbuf *b = &c->buffer; | 278 long s; 279 snd_dbuf *b = &c->buffer; |
280 int threshold, maxthreshold, minthreshold; |
|
261 262 if (c->flags & CHN_F_WRITING) { 263 /* This shouldn't happen and is actually silly 264 * - will never wake up, just timeout; why not sleep on b? 265 */ 266 tsleep(&s, PZERO, "pcmwrW", hz); 267 return EBUSY; 268 } 269 a = (1 << c->align) - 1; | 281 282 if (c->flags & CHN_F_WRITING) { 283 /* This shouldn't happen and is actually silly 284 * - will never wake up, just timeout; why not sleep on b? 285 */ 286 tsleep(&s, PZERO, "pcmwrW", hz); 287 return EBUSY; 288 } 289 a = (1 << c->align) - 1; |
290 maxthreshold = (b->dl / 4 + a) & ~a; 291 minthreshold = a; |
|
270 c->flags |= CHN_F_WRITING; | 292 c->flags |= CHN_F_WRITING; |
271 while ((c->smegcnt + buf->uio_resid) > a) { 272 s = spltty(); 273 chn_dmaupdate(c); 274 splx(s); 275 if (b->fl < DMA_ALIGN_THRESHOLD) { | 293 s = spltty(); 294 chn_checkunderflow(c); 295 splx(s); 296 while ((buf->uio_resid + c->smegcnt) > minthreshold ) { /* Don't allow write unaligned data */ 297 threshold = min((buf->uio_resid + c->smegcnt), maxthreshold); 298 if (b->fl < threshold) { |
276 if (c->flags & CHN_F_NBIO) { 277 ret = -1; 278 break; 279 } 280 timeout = (buf->uio_resid >= b->dl)? hz : 1; | 299 if (c->flags & CHN_F_NBIO) { 300 ret = -1; 301 break; 302 } 303 timeout = (buf->uio_resid >= b->dl)? hz : 1; |
281 ret = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout); 282 if (ret == EINTR) chn_abort(c); 283 if (ret == EINTR || ret == ERESTART) break; 284 ret = 0; 285 continue; | 304 rc = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout); 305 if (rc == 0 || rc == EWOULDBLOCK) { 306 s = spltty(); 307 chn_checkunderflow(c); 308 splx(s); 309 if (b->fl < minthreshold) continue; /* write only alligned chunk of data */ 310 } else { 311#if 0 312 if (ret == EINTR) chn_abort(c); 313#endif 314 ret = rc; 315 break; 316 } |
286 } 287 /* ensure we always have a whole number of samples */ 288 l = min(b->fl, b->bufsize - b->fp) & ~a; 289 if (l == 0) continue; 290 w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf); | 317 } 318 /* ensure we always have a whole number of samples */ 319 l = min(b->fl, b->bufsize - b->fp) & ~a; 320 if (l == 0) continue; 321 w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf); |
291 if (w == 0) panic("no feed"); | 322 KASSERT(w, ("chn_write: no feed")); |
292 s = spltty(); 293 b->rl += w; 294 b->fl -= w; 295 b->fp = (b->fp + w) % b->bufsize; 296 splx(s); | 323 s = spltty(); 324 b->rl += w; 325 b->fl -= w; 326 b->fp = (b->fp + w) % b->bufsize; 327 splx(s); |
297 if (b->rl && !b->dl) chn_stintr(c); | 328 DEB(if(1) printf("write %d bytes fp %d rl %d\n",w ,b->fp, b->rl)); 329 if (!b->dl) chn_stintr(c); |
298 } 299 if ((ret == 0) && (buf->uio_resid > 0)) { | 330 } 331 if ((ret == 0) && (buf->uio_resid > 0)) { |
332 s = spltty(); |
|
300 l = buf->uio_resid; | 333 l = buf->uio_resid; |
301 if ((c->smegcnt + l) >= SMEGBUFSZ) panic("resid overflow %d", l); | 334 KASSERT( (c->smegcnt + l) < SMEGBUFSZ, ("resid overflow %d", l)); |
302 uiomove(c->smegbuf + c->smegcnt, l, buf); 303 c->smegcnt += l; | 335 uiomove(c->smegbuf + c->smegcnt, l, buf); 336 c->smegcnt += l; |
337 splx(s); |
|
304 } 305 c->flags &= ~CHN_F_WRITING; 306 return (ret > 0)? ret : 0; 307} 308 309/* 310 * SOUND INPUT 311 * --- 158 unchanged lines hidden (view full) --- 470{ 471 if (bus_dmamem_alloc(parent_dmat, (void **)&b->buf, 472 BUS_DMA_NOWAIT, &b->dmamap)) return -1; 473 if (bus_dmamap_load(parent_dmat, b->dmamap, b->buf, 474 b->bufsize, chn_dma_setmap, b, 0)) return -1; 475 return 0; 476} 477 | 338 } 339 c->flags &= ~CHN_F_WRITING; 340 return (ret > 0)? ret : 0; 341} 342 343/* 344 * SOUND INPUT 345 * --- 158 unchanged lines hidden (view full) --- 504{ 505 if (bus_dmamem_alloc(parent_dmat, (void **)&b->buf, 506 BUS_DMA_NOWAIT, &b->dmamap)) return -1; 507 if (bus_dmamap_load(parent_dmat, b->dmamap, b->buf, 508 b->bufsize, chn_dma_setmap, b, 0)) return -1; 509 return 0; 510} 511 |
512static void 513chn_clearbuf(pcm_channel *c, int length) 514{ 515int i; 516u_int16_t data, *p; 517 518 snd_dbuf *b = &c->buffer; 519 /* rely on length & DMA_ALIGN_MASK == 0 */ 520 length&=DMA_ALIGN_MASK; 521 if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80; 522 if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8; 523 if (c->hwfmt & AFMT_BIGENDIAN) 524 data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); 525 for (i = b->fp, p=(u_int16_t*)(b->buf+b->fp) ; i < b->bufsize && length; i += 2, length-=2) 526 *p++ = data; 527 for (i = 0, p=(u_int16_t*)b->buf; i < b->bufsize && length; i += 2, length-=2) 528 *p++ = data; 529 530 return; 531} 532 |
|
478void 479chn_resetbuf(pcm_channel *c) 480{ 481 snd_dbuf *b = &c->buffer; | 533void 534chn_resetbuf(pcm_channel *c) 535{ 536 snd_dbuf *b = &c->buffer; |
482 u_int16_t data, *p; 483 u_int32_t i; | |
484 485 c->smegcnt = 0; 486 c->buffer.sample_size = 1; 487 c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0; 488 c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0; | 537 538 c->smegcnt = 0; 539 c->buffer.sample_size = 1; 540 c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0; 541 c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0; |
489 /* rely on bufsize & 3 == 0 */ 490 if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80; 491 if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8; 492 if (c->hwfmt & AFMT_BIGENDIAN) 493 data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); 494 for (i = 0, p = (u_int16_t *)b->buf; i < b->bufsize; i += 2) 495 *p++ = data; | |
496 b->rp = b->fp = 0; 497 b->dl = b->rl = 0; | 542 b->rp = b->fp = 0; 543 b->dl = b->rl = 0; |
544 b->fl = b->bufsize; 545 chn_clearbuf(c, b->bufsize); |
|
498 b->prev_total = b->total = 0; 499 b->prev_int_count = b->int_count = 0; 500 b->first_poll = 1; | 546 b->prev_total = b->total = 0; 547 b->prev_int_count = b->int_count = 0; 548 b->first_poll = 1; |
501 b->fl = b->bufsize; | 549 b->underflow=0; |
502} 503 504void 505buf_isadma(snd_dbuf *b, int go) 506{ 507 if (ISA_DMA(b)) { | 550} 551 552void 553buf_isadma(snd_dbuf *b, int go) 554{ 555 if (ISA_DMA(b)) { |
508 if (go == PCMTRIG_START) isa_dmastart(b->dir | B_RAW, b->buf, 509 b->bufsize, b->chan); 510 else { | 556 if (go == PCMTRIG_START) { 557 DEB(printf("buf 0x%p ISA DMA started\n", b)); 558 isa_dmastart(b->dir | B_RAW, b->buf, 559 b->bufsize, b->chan); 560 } else { 561 DEB(printf("buf 0x%p ISA DMA stopped\n", b)); |
511 isa_dmastop(b->chan); 512 isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize, 513 b->chan); 514 } | 562 isa_dmastop(b->chan); 563 isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize, 564 b->chan); 565 } |
515 } else panic("buf_isadma called on invalid channel"); | 566 } else KASSERT(1, ("buf_isadma called on invalid channel")); |
516} 517 518int 519buf_isadmaptr(snd_dbuf *b) 520{ 521 if (ISA_DMA(b)) { 522 int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; 523 if (i < 0) i = 0; 524 return b->bufsize - i; | 567} 568 569int 570buf_isadmaptr(snd_dbuf *b) 571{ 572 if (ISA_DMA(b)) { 573 int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; 574 if (i < 0) i = 0; 575 return b->bufsize - i; |
525 } else panic("buf_isadmaptr called on invalid channel"); | 576 } else KASSERT(1, ("buf_isadmaptr called on invalid channel")); |
526 return -1; 527} 528 529/* 530 * snd_sync waits until the space in the given channel goes above 531 * a threshold. The threshold is checked against fl or rl respectively. 532 * Assume that the condition can become true, do not check here... 533 */ --- 7 unchanged lines hidden (view full) --- 541 for (;;) { 542 s = spltty(); 543 chn_dmaupdate(c); 544 rdy = (c->direction == PCMDIR_PLAY)? b->fl : b->rl; 545 if (rdy <= threshold) { 546 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1); 547 splx(s); 548 if (ret == ERESTART || ret == EINTR) { | 577 return -1; 578} 579 580/* 581 * snd_sync waits until the space in the given channel goes above 582 * a threshold. The threshold is checked against fl or rl respectively. 583 * Assume that the condition can become true, do not check here... 584 */ --- 7 unchanged lines hidden (view full) --- 592 for (;;) { 593 s = spltty(); 594 chn_dmaupdate(c); 595 rdy = (c->direction == PCMDIR_PLAY)? b->fl : b->rl; 596 if (rdy <= threshold) { 597 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1); 598 splx(s); 599 if (ret == ERESTART || ret == EINTR) { |
549 printf("tsleep returns %d\n", ret); | 600 DEB(printf("chn_sync: tsleep returns %d\n", ret)); |
550 return -1; 551 } 552 } else break; 553 } 554 splx(s); 555 return 0; 556} 557 --- 45 unchanged lines hidden (view full) --- 603chn_flush(pcm_channel *c) 604{ 605 int ret, count = 10; 606 snd_dbuf *b = &c->buffer; 607 608 DEB(printf("snd_flush c->flags 0x%08x\n", c->flags)); 609 c->flags |= CHN_F_CLOSING; 610 if (c->direction != PCMDIR_PLAY) chn_abort(c); | 601 return -1; 602 } 603 } else break; 604 } 605 splx(s); 606 return 0; 607} 608 --- 45 unchanged lines hidden (view full) --- 654chn_flush(pcm_channel *c) 655{ 656 int ret, count = 10; 657 snd_dbuf *b = &c->buffer; 658 659 DEB(printf("snd_flush c->flags 0x%08x\n", c->flags)); 660 c->flags |= CHN_F_CLOSING; 661 if (c->direction != PCMDIR_PLAY) chn_abort(c); |
611 else while (b->dl) { | 662 else if (b->dl) while (!b->underflow) { |
612 /* still pending output data. */ 613 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz); | 663 /* still pending output data. */ 664 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz); |
614 chn_dmaupdate(c); | 665 DEB(chn_dmaupdate(c)); |
615 DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl)); | 666 DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl)); |
616 if (ret == EINTR) { 617 printf("tsleep returns %d\n", ret); | 667 if (ret == EINTR || ret == ERESTART) { 668 DEB(printf("chn_flush: tsleep returns %d\n", ret)); |
618 return -1; 619 } 620 if (ret && --count == 0) { | 669 return -1; 670 } 671 if (ret && --count == 0) { |
621 printf("timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n", 622 b->rl, c->flags); | 672 DEB(printf("chn_flush: timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n",\ 673 b->rl, c->flags)); |
623 break; 624 } 625 } 626 c->flags &= ~CHN_F_CLOSING; 627 if (c->direction == PCMDIR_PLAY) chn_abort(c); 628 return 0; 629} 630 --- 8 unchanged lines hidden (view full) --- 639} 640 641int 642chn_reinit(pcm_channel *c) 643{ 644 if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) { 645 chn_setformat(c, c->format); 646 chn_setspeed(c, c->speed); | 674 break; 675 } 676 } 677 c->flags &= ~CHN_F_CLOSING; 678 if (c->direction == PCMDIR_PLAY) chn_abort(c); 679 return 0; 680} 681 --- 8 unchanged lines hidden (view full) --- 690} 691 692int 693chn_reinit(pcm_channel *c) 694{ 695 if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) { 696 chn_setformat(c, c->format); 697 chn_setspeed(c, c->speed); |
647 chn_setblocksize(c, c->blocksize); | 698 chn_setblocksize(c, (c->flags & CHN_F_HAS_SIZE) ? c->blocksize : 0); |
648 chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff); 649 c->flags &= ~CHN_F_INIT; 650 return 1; 651 } | 699 chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff); 700 c->flags &= ~CHN_F_INIT; 701 return 1; 702 } |
703 if (CANCHANGE(c) && !(c->flags & CHN_F_HAS_SIZE) ) 704 chn_setblocksize(c, 0); /* Apply new block size */ |
|
652 return 0; 653} 654 655int 656chn_init(pcm_channel *c, void *devinfo, int dir) 657{ 658 c->flags = 0; 659 c->feeder = &feeder_root; --- 54 unchanged lines hidden (view full) --- 714 715int 716chn_setblocksize(pcm_channel *c, int blksz) 717{ 718 if (CANCHANGE(c)) { 719 c->flags &= ~CHN_F_HAS_SIZE; 720 if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE; 721 if (blksz < 0) blksz = -blksz; | 705 return 0; 706} 707 708int 709chn_init(pcm_channel *c, void *devinfo, int dir) 710{ 711 c->flags = 0; 712 c->feeder = &feeder_root; --- 54 unchanged lines hidden (view full) --- 767 768int 769chn_setblocksize(pcm_channel *c, int blksz) 770{ 771 if (CANCHANGE(c)) { 772 c->flags &= ~CHN_F_HAS_SIZE; 773 if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE; 774 if (blksz < 0) blksz = -blksz; |
722 if (blksz < 2) blksz = (c->buffer.sample_size * c->speed) >> 2; | 775 if (blksz < 2) blksz = c->buffer.sample_size * (c->speed >> 2); |
723 RANGE(blksz, 1024, c->buffer.bufsize / 4); | 776 RANGE(blksz, 1024, c->buffer.bufsize / 4); |
724 blksz &= ~3; 725 c->blocksize = c->setblocksize(c->devinfo, blksz); | 777 blksz &= DMA_ALIGN_MASK; 778 c->blocksize = c->setblocksize(c->devinfo, blksz) & DMA_ALIGN_MASK; |
726 return c->blocksize; 727 } 728 c->blocksize = blksz; 729 c->flags |= CHN_F_INIT; 730 return 0; 731} 732 733int 734chn_trigger(pcm_channel *c, int go) 735{ 736 return c->trigger(c->devinfo, go); 737} 738 739int 740chn_getptr(pcm_channel *c) 741{ | 779 return c->blocksize; 780 } 781 c->blocksize = blksz; 782 c->flags |= CHN_F_INIT; 783 return 0; 784} 785 786int 787chn_trigger(pcm_channel *c, int go) 788{ 789 return c->trigger(c->devinfo, go); 790} 791 792int 793chn_getptr(pcm_channel *c) 794{ |
742 return c->getptr(c->devinfo); | 795 int hwptr; 796 int a = (1 << c->align) - 1; 797 798 hwptr=c->getptr(c->devinfo); 799 /* don't allow unaligned values in the hwa ptr */ 800 hwptr &= ~a ; /* Apply channel align mask */ 801 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ 802 return hwptr; |
743} 744 745pcmchan_caps * 746chn_getcaps(pcm_channel *c) 747{ 748 return c->getcaps(c->devinfo); 749} | 803} 804 805pcmchan_caps * 806chn_getcaps(pcm_channel *c) 807{ 808 return c->getcaps(c->devinfo); 809} |