channel.c revision 65340
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: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 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 65340 2000-09-01 20:09:24Z 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#define ROUND(x) ((x) & DMA_ALIGN_MASK) 39/* 40#define DEB(x) x 41*/ 42static void buf_clear(snd_dbuf *b, u_int32_t fmt, int length); 43static void chn_dmaupdate(pcm_channel *c); 44static void chn_wrintr(pcm_channel *c); 45static void chn_rdintr(pcm_channel *c); 46static u_int32_t chn_start(pcm_channel *c); 47/* 48 * SOUND OUTPUT 49 50We use a circular buffer to store samples directed to the DAC. 51The buffer is split into two variable-size regions, each identified 52by an offset in the buffer (rp,fp) and a length (rl,fl): 53 54 0 rp,rl fp,fl bufsize 55 |__________>____________>________| 56 FREE d READY w FREE 57 58 READY: data written from the process and ready to be sent to the DAC; 59 FREE: free part of the buffer. 60 61Both regions can wrap around the end of the buffer. At initialization, 62READY is empty, FREE takes all the available space, and dma is 63idle. dl contains the length of the current DMA transfer, dl=0 64means that the dma is idle. 65 66The two boundaries (rp,fp) in the buffers are advanced by DMA [d] 67and write() [w] operations. The first portion of the READY region 68is used for DMA transfers. The transfer is started at rp and with 69chunks of length dl. During DMA operations, dsp_wr_dmaupdate() 70updates rp, rl and fl tracking the ISA DMA engine as the transfer 71makes progress. 72When a new block is written, fp advances and rl,fl are updated 73accordingly. 74 75The code works as follows: the user write routine dsp_write_body() 76fills up the READY region with new data (reclaiming space from the 77FREE region) and starts the write DMA engine if inactive. When a 78DMA transfer is complete, an interrupt causes dsp_wrintr() to be 79called which extends the FREE region and possibly starts the next 80transfer. 81 82In some cases, the code tries to track the current status of DMA 83operations by calling dsp_wr_dmaupdate() which changes rp, rl and fl. 84 85The system tries to make all DMA transfers use the same size, 86play_blocksize or rec_blocksize. The size is either selected by 87the user, or computed by the system to correspond to about .25s of 88audio. The blocksize must be within a range which is currently: 89 90 min(5ms, 40 bytes) ... 1/2 buffer size. 91 92When there aren't enough data (write) or space (read), a transfer 93is started with a reduced size. 94 95To reduce problems in case of overruns, the routine which fills up 96the buffer should initialize (e.g. by repeating the last value) a 97reasonably long area after the last block so that no noise is 98produced on overruns. 99 100 * 101 */ 102 103 104/* XXX this is broken: in the event a bounce buffer is used, data never 105 * gets copied in or out of the real buffer. fix requires mods to isa_dma.c 106 * and possibly fixes to other autodma mode clients 107 */ 108static void 109chn_isadmabounce(pcm_channel *c) 110{ 111 if (ISA_DMA(&c->buffer)) { 112 /* tell isa_dma to bounce data in/out */ 113 } else KASSERT(1, ("chn_isadmabounce called on invalid channel")); 114} 115 116static int 117chn_polltrigger(pcm_channel *c) 118{ 119 snd_dbuf *bs = &c->buffer2nd; 120 unsigned lim = (c->flags & CHN_F_HAS_SIZE)? bs->blksz : 0; 121 int trig = 0; 122 123 if (c->flags & CHN_F_MAPPED) 124 trig = ((bs->int_count > bs->prev_int_count) || bs->prev_int_count == 0); 125 else 126 trig = (((c->direction == PCMDIR_PLAY)? bs->fl : bs->rl) > lim); 127 return trig; 128} 129 130static int 131chn_pollreset(pcm_channel *c) 132{ 133 snd_dbuf *bs = &c->buffer2nd; 134 135 if (c->flags & CHN_F_MAPPED) 136 bs->prev_int_count = bs->int_count; 137 return 1; 138} 139 140/* 141 * chn_dmadone() updates pointers and wakes up any process waiting 142 * on a select(). Must be called at spltty(). 143 */ 144static void 145chn_dmadone(pcm_channel *c) 146{ 147 snd_dbuf *b = &c->buffer; 148 149 if (c->direction == PCMDIR_PLAY) 150 chn_checkunderflow(c); 151 else 152 chn_dmaupdate(c); 153 if (ISA_DMA(b)) 154 chn_isadmabounce(c); /* sync bounce buffer */ 155 b->int_count++; 156} 157 158/* 159 * chn_dmawakeup() wakes up any process sleeping. Separated from 160 * chn_dmadone() so that wakeup occurs only when feed from a 161 * secondary buffer to a DMA buffer takes place. Must be called 162 * at spltty(). 163 */ 164static void 165chn_dmawakeup(pcm_channel *c) 166{ 167 snd_dbuf *b = &c->buffer; 168 169 wakeup(b); 170} 171 172/* 173 * chn_dmaupdate() tracks the status of a dma transfer, 174 * updating pointers. It must be called at spltty(). 175 * 176 * NOTE: when we are using auto dma in the device, rl might become 177 * negative. 178 */ 179DEB (static int chn_updatecount=0); 180 181static void 182chn_dmaupdate(pcm_channel *c) 183{ 184 snd_dbuf *b = &c->buffer; 185 int delta, hwptr; 186 DEB (int b_rl=b->rl; int b_fl=b->fl; int b_rp=b->rp; int b_fp=b->fp); 187 188 hwptr = chn_getptr(c); 189 delta = (b->bufsize + hwptr - b->hp) % b->bufsize; 190 if (delta >= ((b->bufsize * 15) / 16)) { 191 if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING))) 192 device_printf(c->parent->dev, "hwptr went backwards %d -> %d\n", b->hp, hwptr); 193 } 194 if (c->direction == PCMDIR_PLAY) { 195 delta = (b->bufsize + hwptr - b->rp) % b->bufsize; 196 b->rp = hwptr; 197 b->rl -= delta; 198 b->fl += delta; 199 200 if (b->rl < 0) { 201 DEB(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)); 202 } 203 } else { 204 delta = (b->bufsize + hwptr - b->fp) % b->bufsize; 205 b->fp = hwptr; 206 b->rl += delta; 207 b->fl -= delta; 208 if (b->fl < 0) { 209 DEB(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)); 210 } 211 } 212 b->hp = hwptr; 213 b->total += delta; 214} 215 216/* 217 * Check channel for underflow occured. Reset DMA buffer in case of 218 * underflow, so that new data can go into the buffer. It must be 219 * called at spltty(). 220 */ 221void 222chn_checkunderflow(pcm_channel *c) 223{ 224 snd_dbuf *b = &c->buffer; 225 226 if (b->underflow) { 227 DEB(printf("Clear underflow condition\n")); 228 /* 229 * The DMA keeps running even after underflow occurs. 230 * Hence the value returned by chn_getptr() here soon 231 * gets a lag when we get back to chn_write(). Although 232 * there are no easy and precise methods to figure out 233 * the lag, a quarter of b->bufsize would be a fair 234 * choice, provided that a DMA interrupt generates upon 235 * each transfer of a half b->bufsize. 236 */ 237 b->rp = chn_getptr(c); 238 b->fp = (b->rp + b->bufsize / 4) % b->bufsize; 239 b->rl = b->bufsize / 4; 240 b->fl = b->bufsize - b->rl; 241 b->underflow = 0; 242 } else { 243 chn_dmaupdate(c); 244 } 245} 246 247/* 248 * Feeds new data to the write dma buffer. Can be called in the bottom half. 249 * Hence must be called at spltty. 250 */ 251int 252chn_wrfeed(pcm_channel *c) 253{ 254 snd_dbuf *b = &c->buffer; 255 snd_dbuf *bs = &c->buffer2nd; 256 int a, l, lacc; 257 258 /* ensure we always have a whole number of samples */ 259 a = (1 << c->align) - 1; 260 lacc = 0; 261 if (c->flags & CHN_F_MAPPED) { 262 bs->rl = min(b->blksz, b->fl); 263 bs->fl = 0; 264 a = 0; 265 } 266 /* 267 printf("b: [rl: %d, rp %d, fl %d, fp %d]; bs: [rl: %d, rp %d, fl %d, fp %d]\n", 268 b->rl, b->rp, b->fl, b->fp, bs->rl, bs->rp, bs->fl, bs->fp); 269 */ 270 /* Don't allow write unaligned data */ 271 while (bs->rl > a && b->fl > a) { 272 /* ensure we always have a whole number of samples */ 273 l = min(min(bs->rl, bs->bufsize - bs->rp), min(b->fl, b->bufsize - b->fp)) & ~a; 274 if (l == 0) 275 return lacc; 276 /* Move the samples, update the markers and pointers. */ 277 bcopy(bs->buf + bs->rp, b->buf + b->fp, l); 278 bs->fl += l; 279 bs->rl -= l; 280 bs->rp = (bs->rp + l) % bs->bufsize; 281 b->rl += l; 282 b->fl -= l; 283 b->fp = (b->fp + l) % b->bufsize; 284 /* Clear the new space in the secondary buffer. */ 285 buf_clear(bs, bs->fmt, l); 286 /* Accumulate the total bytes of the moved samples. */ 287 lacc += l; 288 /* A feed to the DMA buffer is equivalent to an interrupt. */ 289 bs->total += l; 290 if (c->flags & CHN_F_MAPPED) { 291 if (bs->total - bs->prev_total >= bs->blksz) { 292 bs->prev_total = bs->total; 293 bs->int_count++; 294 c->blocks++; 295 } 296 } else 297 bs->int_count++; 298 if (bs->sel.si_pid && chn_polltrigger(c)) 299 selwakeup(&bs->sel); 300 } 301 302 return lacc; 303} 304 305/* Feeds new data to the secondary write buffer. */ 306static int 307chn_wrfeed2nd(pcm_channel *c, struct uio *buf) 308{ 309 snd_dbuf *bs = &c->buffer2nd; 310 int l, w, wacc; 311 312 /* The DMA buffer may have some space. */ 313 while (chn_wrfeed(c) > 0); 314 315 /* ensure we always have a whole number of samples */ 316 wacc = 0; 317 while (buf->uio_resid > 0 && bs->fl > 0) { 318 /* 319 * The size of the data to move here does not have to be 320 * aligned. We take care of it upon moving the data to a 321 * DMA buffer. 322 */ 323 l = min(bs->fl, bs->bufsize - bs->fp); 324 /* Move the samples, update the markers and pointers. */ 325 w = c->feeder->feed(c->feeder, c, bs->buf + bs->fp, l, buf); 326 if (w == 0) 327 panic("no feed"); 328 bs->rl += w; 329 bs->fl -= w; 330 bs->fp = (bs->fp + w) % bs->bufsize; 331 /* Accumulate the total bytes of the moved samples. */ 332 wacc += w; 333 334 /* If any pcm data gets moved, push it to the DMA buffer. */ 335 if (w > 0) 336 while (chn_wrfeed(c) > 0); 337 } 338 339 return wacc; 340} 341 342/* 343 * Write interrupt routine. Can be called from other places (e.g. 344 * to start a paused transfer), but with interrupts disabled. 345 */ 346static void 347chn_wrintr(pcm_channel *c) 348{ 349 snd_dbuf *b = &c->buffer; 350 351 if (b->underflow && !(c->flags & CHN_F_MAPPED)) { 352/* printf("underflow return\n"); 353*/ return; /* nothing new happened */ 354 } 355 if (b->dl) 356 chn_dmadone(c); 357 358 /* 359 * start another dma operation only if have ready data in the buffer, 360 * there is no pending abort, have a full-duplex device, or have a 361 * half duplex device and there is no pending op on the other side. 362 * 363 * Force transfers to be aligned to a boundary of 4, which is 364 * needed when doing stereo and 16-bit. 365 */ 366 367 /* Check underflow and update the pointers. */ 368 chn_checkunderflow(c); 369 370 /* 371 * Fill up the DMA buffer, followed by waking up the top half. 372 * If some of the pcm data in uio are still left, the top half 373 * goes to sleep by itself. 374 */ 375 if (c->flags & CHN_F_MAPPED) 376 chn_wrfeed(c); 377 else { 378 while (chn_wrfeed(c) > 0); 379 buf_clear(b, b->fmt, b->fl); 380 } 381 chn_dmawakeup(c); 382 if (c->flags & CHN_F_TRIGGERED) { 383 chn_dmaupdate(c); 384 /* 385 * check if we need to reprogram the DMA on the sound card. 386 * This happens if the size has changed from zero 387 */ 388 if (b->dl == 0) { 389 /* Start DMA operation */ 390 b->dl = b->blksz; /* record new transfer size */ 391 chn_trigger(c, PCMTRIG_START); 392 } 393 /* 394 * Emulate writing by DMA, i.e. transfer the pcm data from 395 * the emulated-DMA buffer to the device itself. 396 */ 397 chn_trigger(c, PCMTRIG_EMLDMAWR); 398 if (b->rl < b->dl) { 399 DEB(printf("near underflow (%d < %d), %d\n", b->rl, b->dl, b->fl)); 400 /* 401 * we are near to underflow condition, so to prevent 402 * audio 'clicks' clear next b->fl bytes 403 */ 404 buf_clear(b, b->fmt, b->fl); 405 if (b->rl < DMA_ALIGN_THRESHOLD) 406 b->underflow = 1; 407 } 408 } else { 409 /* cannot start a new dma transfer */ 410 DEB(printf("underflow, flags 0x%08x rp %d rl %d\n", c->flags, b->rp, b->rl)); 411 if (b->dl) { /* DMA was active */ 412 b->underflow = 1; /* set underflow flag */ 413 buf_clear(b, b->fmt, b->bufsize); 414 } 415 } 416} 417 418/* 419 * user write routine 420 * 421 * advance the boundary between READY and FREE, fill the space with 422 * uiomove(), and possibly start DMA. Do the above until the transfer 423 * is complete. 424 * 425 * To minimize latency in case a pending DMA transfer is about to end, 426 * we do the transfer in pieces of increasing sizes, extending the 427 * READY area at every checkpoint. In the (necessary) assumption that 428 * memory bandwidth is larger than the rate at which the dma consumes 429 * data, we reduce the latency to something proportional to the length 430 * of the first piece, while keeping the overhead low and being able 431 * to feed the DMA with large blocks. 432 */ 433 434int 435chn_write(pcm_channel *c, struct uio *buf) 436{ 437 int ret = 0, timeout, res, newsize, count; 438 long s; 439 snd_dbuf *b = &c->buffer; 440 snd_dbuf *bs = &c->buffer2nd; 441 442 if (c->flags & CHN_F_WRITING) { 443 /* This shouldn't happen and is actually silly 444 * - will never wake up, just timeout; why not sleep on b? 445 */ 446 tsleep(&s, PZERO, "pcmwrW", hz); 447 return EBUSY; 448 } 449 c->flags |= CHN_F_WRITING; 450 c->flags &= ~CHN_F_ABORTING; 451 s = spltty(); 452 453 /* 454 * XXX Certain applications attempt to write larger size 455 * of pcm data than c->blocksize2nd without blocking, 456 * resulting partial write. Expand the block size so that 457 * the write operation avoids blocking. 458 */ 459 if ((c->flags & CHN_F_NBIO) && buf->uio_resid > bs->blksz) { 460 DEB(printf("pcm warning: broken app, nbio and tried to write %d bytes with fragsz %d\n", 461 buf->uio_resid, bs->blksz)); 462 newsize = 16; 463 while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2)) 464 newsize <<= 1; 465 chn_setblocksize(c, bs->blkcnt, newsize); 466 DEB(printf("pcm warning: frags reset to %d x %d\n", bs->blkcnt, bs->blksz)); 467 } 468 469 /* 470 * Fill up the secondary and DMA buffer. 471 * chn_wrfeed*() takes care of the alignment. 472 */ 473 474 /* Check for underflow before writing into the buffers. */ 475 chn_checkunderflow(c); 476 while (chn_wrfeed2nd(c, buf) > 0); 477 if ((c->flags & CHN_F_NBIO) && (buf->uio_resid > 0)) 478 ret = EAGAIN; 479 480 /* Start playing if not yet. */ 481 if (!b->dl) 482 chn_start(c); 483 484 if (ret == 0) { 485 count = hz; 486 /* Wait until all samples are played in blocking mode. */ 487 while ((buf->uio_resid > 0) && (count > 0)) { 488 /* Check for underflow before writing into the buffers. */ 489 chn_checkunderflow(c); 490 /* Fill up the buffers with new pcm data. */ 491 res = buf->uio_resid; 492 while (chn_wrfeed2nd(c, buf) > 0); 493 if (buf->uio_resid < res) 494 count = hz; 495 else 496 count--; 497 498 /* Have we finished to feed the secondary buffer? */ 499 if (buf->uio_resid == 0) 500 break; 501 502 /* Wait for new free space to write new pcm samples. */ 503 /* splx(s); */ 504 timeout = 1; /*(buf->uio_resid >= b->dl)? hz / 20 : 1; */ 505 ret = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout); 506 /* s = spltty(); */ 507 /* if (ret == EINTR) chn_abort(c); */ 508 if (ret == EINTR || ret == ERESTART) 509 break; 510 } 511 if (count == 0) { 512 c->flags |= CHN_F_DEAD; 513 device_printf(c->parent->dev, "play interrupt timeout, channel dead\n"); 514 } 515 } else 516 ret = 0; 517 c->flags &= ~CHN_F_WRITING; 518 splx(s); 519 return ret; 520} 521 522/* 523 * SOUND INPUT 524 * 525 526The input part is similar to the output one, with a circular buffer 527split in two regions, and boundaries advancing because of read() calls 528[r] or dma operation [d]. At initialization, as for the write 529routine, READY is empty, and FREE takes all the space. 530 531 0 rp,rl fp,fl bufsize 532 |__________>____________>________| 533 FREE r READY d FREE 534 535Operation is as follows: upon user read (dsp_read_body()) a DMA read 536is started if not already active (marked by b->dl > 0), 537then as soon as data are available in the READY region they are 538transferred to the user buffer, thus advancing the boundary between FREE 539and READY. Upon interrupts, caused by a completion of a DMA transfer, 540the READY region is extended and possibly a new transfer is started. 541 542When necessary, dsp_rd_dmaupdate() is called to advance fp (and update 543rl,fl accordingly). Upon user reads, rp is advanced and rl,fl are 544updated accordingly. 545 546The rules to choose the size of the new DMA area are similar to 547the other case, with a preferred constant transfer size equal to 548rec_blocksize, and fallback to smaller sizes if no space is available. 549 550 */ 551 552static int 553chn_rddump(pcm_channel *c, int cnt) 554{ 555 snd_dbuf *b = &c->buffer; 556 int maxover, ss; 557 558 ss = 1; 559 ss <<= (b->fmt & AFMT_STEREO)? 1 : 0; 560 ss <<= (b->fmt & AFMT_16BIT)? 1 : 0; 561 maxover = c->speed * ss; 562 563 b->overrun += cnt; 564 if (b->overrun > maxover) { 565 device_printf(c->parent->dev, "record overrun, dumping %d bytes\n", 566 b->overrun); 567 b->overrun = 0; 568 } 569 b->rl -= cnt; 570 b->fl += cnt; 571 b->rp = (b->rp + cnt) % b->bufsize; 572 return cnt; 573} 574 575/* 576 * Feed new data from the read buffer. Can be called in the bottom half. 577 * Hence must be called at spltty. 578 */ 579int 580chn_rdfeed(pcm_channel *c) 581{ 582 snd_dbuf *b = &c->buffer; 583 snd_dbuf *bs = &c->buffer2nd; 584 int l, lacc; 585 586 /* 587 printf("b: [rl: %d, rp %d, fl %d, fp %d]; bs: [rl: %d, rp %d, fl %d, fp %d]\n", 588 b->rl, b->rp, b->fl, b->fp, bs->rl, bs->rp, bs->fl, bs->fp); 589 */ 590 /* ensure we always have a whole number of samples */ 591 lacc = 0; 592 while (bs->fl >= DMA_ALIGN_THRESHOLD && b->rl >= DMA_ALIGN_THRESHOLD) { 593 l = min(min(bs->fl, bs->bufsize - bs->fp), min(b->rl, b->bufsize - b->rp)) & DMA_ALIGN_MASK; 594 /* Move the samples, update the markers and pointers. */ 595 bcopy(b->buf + b->rp, bs->buf + bs->fp, l); 596 bs->fl -= l; 597 bs->rl += l; 598 bs->fp = (bs->fp + l) % bs->bufsize; 599 b->rl -= l; 600 b->fl += l; 601 b->rp = (b->rp + l) % b->bufsize; 602 /* Accumulate the total bytes of the moved samples. */ 603 lacc += l; 604 /* A feed from the DMA buffer is equivalent to an interrupt. */ 605 bs->int_count++; 606 if (bs->sel.si_pid && chn_polltrigger(c)) 607 selwakeup(&bs->sel); 608 } 609 610 return lacc; 611} 612 613/* Feeds new data from the secondary read buffer. */ 614static int 615chn_rdfeed2nd(pcm_channel *c, struct uio *buf) 616{ 617 snd_dbuf *bs = &c->buffer2nd; 618 int l, w, wacc; 619 620 /* ensure we always have a whole number of samples */ 621 wacc = 0; 622 while ((buf->uio_resid > 0) && (bs->rl > 0)) { 623 /* The DMA buffer may have pcm data. */ 624 /* while (chn_rdfeed(c) > 0); */ 625 /* 626 * The size of the data to move here does not have to be 627 * aligned. We take care of it upon moving the data to a 628 * DMA buffer. 629 */ 630 l = min(bs->rl, bs->bufsize - bs->rp); 631 /* Move the samples, update the markers and pointers. */ 632 w = c->feeder->feed(c->feeder, c, bs->buf + bs->rp, l, buf); 633 if (w == 0) 634 panic("no feed"); 635 bs->fl += w; 636 bs->rl -= w; 637 bs->rp = (bs->rp + w) % bs->bufsize; 638 /* Clear the new space in the secondary buffer. */ 639 buf_clear(bs, bs->fmt, l); 640 /* Accumulate the total bytes of the moved samples. */ 641 bs->total += w; 642 wacc += w; 643 } 644 645 return wacc; 646} 647 648/* read interrupt routine. Must be called with interrupts blocked. */ 649static void 650chn_rdintr(pcm_channel *c) 651{ 652 snd_dbuf *b = &c->buffer; 653 654 if (b->dl) chn_dmadone(c); 655 656 DEB(printf("rdintr: start dl %d, rp:rl %d:%d, fp:fl %d:%d\n", 657 b->dl, b->rp, b->rl, b->fp, b->fl)); 658 659 /* Update the pointers. */ 660 chn_dmaupdate(c); 661 662 /* 663 * Suck up the DMA buffer, followed by waking up the top half. 664 * If some of the pcm data in the secondary buffer are still left, 665 * the top half goes to sleep by itself. 666 */ 667 while(chn_rdfeed(c) > 0); 668 chn_dmawakeup(c); 669 670 if (b->fl < b->dl) { 671 DEB(printf("near overflow (%d < %d), %d\n", b->fl, b->dl, b->rl)); 672 chn_rddump(c, b->blksz - b->fl); 673 } 674 675 if (c->flags & CHN_F_TRIGGERED) { 676 /* 677 * check if we need to reprogram the DMA on the sound card. 678 * This happens if the size has changed from zero 679 */ 680 if (b->dl == 0) { 681 /* Start DMA operation */ 682 b->dl = b->blksz; /* record new transfer size */ 683 chn_trigger(c, PCMTRIG_START); 684 } 685 /* 686 * Emulate writing by DMA, i.e. transfer the pcm data from 687 * the emulated-DMA buffer to the device itself. 688 */ 689 chn_trigger(c, PCMTRIG_EMLDMARD); 690 } else { 691 if (b->dl) { /* was active */ 692 b->dl = 0; 693 chn_trigger(c, PCMTRIG_STOP); 694 chn_dmaupdate(c); 695 } 696 } 697} 698 699/* 700 * body of user-read routine 701 * 702 * Start DMA if not active; wait for READY not empty. 703 * Transfer data from READY region using uiomove(), advance boundary 704 * between FREE and READY. Repeat until transfer is complete. 705 * 706 * To avoid excessive latency in freeing up space for the DMA 707 * engine, transfers are done in blocks of increasing size, so that 708 * the latency is proportional to the size of the smallest block, but 709 * we have a low overhead and are able to feed the dma engine with 710 * large blocks. 711 * 712 * NOTE: in the current version, read will not return more than 713 * blocksize bytes at once (unless more are already available), to 714 * avoid that requests using very large buffers block for too long. 715 */ 716 717int 718chn_read(pcm_channel *c, struct uio *buf) 719{ 720 int ret = 0, timeout, limit, res, count; 721 long s; 722 snd_dbuf *b = &c->buffer; 723 snd_dbuf *bs = &c->buffer2nd; 724 725 if (c->flags & CHN_F_READING) { 726 /* This shouldn't happen and is actually silly */ 727 tsleep(&s, PZERO, "pcmrdR", hz); 728 return (EBUSY); 729 } 730 731 s = spltty(); 732 733 /* Store the initial size in the uio. */ 734 res = buf->uio_resid; 735 736 c->flags |= CHN_F_READING; 737 c->flags &= ~CHN_F_ABORTING; 738 739 /* suck up the DMA and secondary buffers. */ 740 while (chn_rdfeed2nd(c, buf) > 0); 741 742 if (buf->uio_resid == 0) 743 goto skip; 744 745 limit = res - b->blksz; 746 if (limit < 0) 747 limit = 0; 748 749 /* Start capturing if not yet. */ 750 if ((!bs->rl || !b->rl) && !b->dl) 751 chn_start(c); 752 753 if (!(c->flags & CHN_F_NBIO)) { 754 count = hz; 755 /* Wait until all samples are captured. */ 756 while ((buf->uio_resid > 0) && (count > 0)) { 757 /* Suck up the DMA and secondary buffers. */ 758 chn_dmaupdate(c); 759 res = buf->uio_resid; 760 while (chn_rdfeed(c) > 0); 761 while (chn_rdfeed2nd(c, buf) > 0); 762 if (buf->uio_resid < res) 763 count = hz; 764 else 765 count--; 766 767 /* Have we finished to feed the uio? */ 768 if (buf->uio_resid == 0) 769 break; 770 771 /* Wait for new pcm samples. */ 772 /* splx(s); */ 773 timeout = (buf->uio_resid - limit >= b->dl)? hz / 20 : 1; 774 ret = tsleep(b, PRIBIO | PCATCH, "pcmrd", 1); 775 /* s = spltty(); */ 776 /* if (ret == EINTR) chn_abort(c); */ 777 if (ret == EINTR || ret == ERESTART) 778 break; 779 } 780 if (count == 0) { 781 c->flags |= CHN_F_DEAD; 782 device_printf(c->parent->dev, "record interrupt timeout, channel dead\n"); 783 } 784 } else { 785 /* If no pcm data was read on nonblocking, return EAGAIN. */ 786 if (buf->uio_resid == res) 787 ret = EAGAIN; 788 } 789 790skip: 791 c->flags &= ~CHN_F_READING; 792 splx(s); 793 return ret; 794} 795 796void 797chn_intr(pcm_channel *c) 798{ 799 if (c->flags & CHN_F_INIT) 800 chn_reinit(c); 801 if (c->direction == PCMDIR_PLAY) 802 chn_wrintr(c); 803 else 804 chn_rdintr(c); 805} 806 807u_int32_t 808chn_start(pcm_channel *c) 809{ 810 u_int32_t r, s; 811 snd_dbuf *b = &c->buffer; 812 813 r = 0; 814 s = spltty(); 815 if (b->dl == 0 && !(c->flags & (CHN_F_MAPPED | CHN_F_NOTRIGGER))) { 816 if (c->direction == PCMDIR_PLAY) { 817 /* Fill up the DMA buffer. */ 818 while (chn_wrfeed(c) > 0); 819 if (b->rl >= b->blksz) 820 r = CHN_F_TRIGGERED; 821 } else { 822 /* Suck up the DMA buffer. */ 823 while (chn_rdfeed(c) > 0); 824 if (b->fl >= b->blksz) 825 r = CHN_F_TRIGGERED; 826 } 827 c->flags |= r; 828 chn_intr(c); 829 } 830 splx(s); 831 return r; 832} 833 834static void 835chn_dma_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 836{ 837 snd_dbuf *b = (snd_dbuf *)arg; 838 839 if (bootverbose) { 840 printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr, 841 (unsigned long)segs->ds_len); 842 printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf)); 843 } 844} 845 846/* 847 * Allocate memory for DMA buffer. If the device do not perform DMA transfer, 848 * the drvier can call malloc(9) by its own. 849 */ 850int 851chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat) 852{ 853 b->parent_dmat = parent_dmat; 854 if (bus_dmamem_alloc(b->parent_dmat, (void **)&b->buf, 855 BUS_DMA_NOWAIT, &b->dmamap)) return -1; 856 if (bus_dmamap_load(b->parent_dmat, b->dmamap, b->buf, 857 b->bufsize, chn_dma_setmap, b, 0)) return -1; 858 return 0; 859} 860 861void 862chn_freebuf(snd_dbuf *b) 863{ 864 bus_dmamem_free(b->parent_dmat, b->buf, b->dmamap); 865} 866 867static void 868buf_clear(snd_dbuf *b, u_int32_t fmt, int length) 869{ 870 int i; 871 u_int16_t data, *p; 872 873 if (length == 0) 874 return; 875 876 if (fmt & AFMT_SIGNED) 877 data = 0x00; 878 else 879 data = 0x80; 880 881 if (fmt & AFMT_16BIT) 882 data <<= 8; 883 else 884 data |= data << 8; 885 886 if (fmt & AFMT_BIGENDIAN) 887 data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); 888 889 i = b->fp; 890 p = (u_int16_t *)(b->buf + b->fp); 891 while (length > 1) { 892 *p++ = data; 893 length -= 2; 894 i += 2; 895 if (i >= b->bufsize) { 896 p = (u_int16_t *)b->buf; 897 i = 0; 898 } 899 } 900 if (length == 1) 901 *(b->buf + i) = data & 0xff; 902} 903 904void 905chn_resetbuf(pcm_channel *c) 906{ 907 snd_dbuf *b = &c->buffer; 908 snd_dbuf *bs = &c->buffer2nd; 909 910 c->blocks = 0; 911 b->rp = b->fp = 0; 912 b->dl = b->rl = 0; 913 b->fl = b->bufsize; 914 b->prev_total = b->total = 0; 915 b->prev_int_count = b->int_count = 0; 916 b->underflow = 0; 917 if (b->buf && b->bufsize > 0) 918 buf_clear(b, b->fmt, b->bufsize); 919 920 bs->rp = bs->fp = 0; 921 bs->dl = bs->rl = 0; 922 bs->fl = bs->bufsize; 923 bs->prev_total = bs->total = 0; 924 bs->prev_int_count = bs->int_count = 0; 925 bs->underflow = 0; 926 if (bs->buf && bs->bufsize > 0) 927 buf_clear(bs, bs->fmt, bs->bufsize); 928} 929 930void 931buf_isadma(snd_dbuf *b, int go) 932{ 933 if (ISA_DMA(b)) { 934 switch (go) { 935 case PCMTRIG_START: 936 DEB(printf("buf 0x%p ISA DMA started\n", b)); 937 isa_dmastart(b->dir | ISADMA_RAW, b->buf, 938 b->bufsize, b->chan); 939 break; 940 case PCMTRIG_STOP: 941 case PCMTRIG_ABORT: 942 DEB(printf("buf 0x%p ISA DMA stopped\n", b)); 943 isa_dmastop(b->chan); 944 isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, 945 b->chan); 946 break; 947 } 948 } else KASSERT(1, ("buf_isadma called on invalid channel")); 949} 950 951int 952buf_isadmaptr(snd_dbuf *b) 953{ 954 if (ISA_DMA(b)) { 955 int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; 956 if (i < 0) 957 i = 0; 958 return b->bufsize - i; 959 } else KASSERT(1, ("buf_isadmaptr called on invalid channel")); 960 return -1; 961} 962 963/* 964 * chn_sync waits until the space in the given channel goes above 965 * a threshold. The threshold is checked against fl or rl respectively. 966 * Assume that the condition can become true, do not check here... 967 */ 968int 969chn_sync(pcm_channel *c, int threshold) 970{ 971 u_long s, rdy; 972 int ret; 973 snd_dbuf *b = &c->buffer; 974 snd_dbuf *bs = &c->buffer2nd; 975 976 for (;;) { 977 s = spltty(); 978 chn_checkunderflow(c); 979 while (chn_wrfeed(c) > 0); 980 rdy = (c->direction == PCMDIR_PLAY)? bs->fl : bs->rl; 981 if (rdy <= threshold) { 982 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1); 983 splx(s); 984 if (ret == ERESTART || ret == EINTR) { 985 DEB(printf("chn_sync: tsleep returns %d\n", ret)); 986 return -1; 987 } 988 } else break; 989 } 990 splx(s); 991 return 0; 992} 993 994int 995chn_poll(pcm_channel *c, int ev, struct proc *p) 996{ 997 snd_dbuf *b = &c->buffer; 998 snd_dbuf *bs = &c->buffer2nd; 999 u_long s; 1000 int ret; 1001 1002 s = spltty(); 1003 if (!(c->flags & CHN_F_MAPPED)) { 1004 if (c->direction == PCMDIR_PLAY) { 1005 /* Fill up the DMA buffer. */ 1006 chn_checkunderflow(c); 1007 while (chn_wrfeed(c) > 0); 1008 } else { 1009 /* Suck up the DMA buffer. */ 1010 chn_dmaupdate(c); 1011 while (chn_rdfeed(c) > 0); 1012 } 1013 if (!b->dl) 1014 chn_start(c); 1015 } 1016 ret = 0; 1017 if (chn_polltrigger(c) && chn_pollreset(c)) 1018 ret = ev; 1019 else 1020 selrecord(p, &bs->sel); 1021 splx(s); 1022 return ret; 1023} 1024 1025/* 1026 * chn_abort is a non-blocking function which aborts a pending 1027 * DMA transfer and flushes the buffers. 1028 * It returns the number of bytes that have not been transferred. 1029 */ 1030int 1031chn_abort(pcm_channel *c) 1032{ 1033 int missing = 0, cnt = 0; 1034 snd_dbuf *b = &c->buffer; 1035 snd_dbuf *bs = &c->buffer2nd; 1036 1037 if (!b->dl) 1038 return 0; 1039 c->flags |= CHN_F_ABORTING; 1040 c->flags &= ~CHN_F_TRIGGERED; 1041 cnt = 10; 1042 while (!b->underflow && (cnt-- > 0)) 1043 tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmabr", hz / 50); 1044 chn_trigger(c, PCMTRIG_ABORT); 1045 b->dl = 0; 1046 chn_dmaupdate(c); 1047 missing = bs->rl + b->rl; 1048 return missing; 1049} 1050 1051/* 1052 * this routine tries to flush the dma transfer. It is called 1053 * on a close. We immediately abort any read DMA 1054 * operation, and then wait for the play buffer to drain. 1055 */ 1056 1057int 1058chn_flush(pcm_channel *c) 1059{ 1060 int ret, count, s, resid, resid_p; 1061 snd_dbuf *b = &c->buffer; 1062 snd_dbuf *bs = &c->buffer2nd; 1063 1064 DEB(printf("chn_flush c->flags 0x%08x\n", c->flags)); 1065 c->flags |= CHN_F_CLOSING; 1066 if (c->direction == PCMDIR_REC) 1067 chn_abort(c); 1068 else if (b->dl) { 1069 resid_p = resid = b->rl + bs->rl; 1070 count = 10; 1071 while ((count > 0) && (resid > 0) && !b->underflow) { 1072 /* still pending output data. */ 1073 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz / 10); 1074 if (ret == EINTR || ret == ERESTART) { 1075 DEB(printf("chn_flush: tsleep returns %d\n", ret)); 1076 return ret; 1077 } 1078 s = spltty(); 1079 chn_dmaupdate(c); 1080 splx(s); 1081 DEB(printf("chn_flush: now rl = %d, fl = %d\n", b->rl, b->fl)); 1082 resid = b->rl + bs->rl; 1083 if (resid >= resid_p) 1084 count--; 1085 resid_p = resid; 1086 } 1087 if (count == 0) 1088 DEB(printf("chn_flush: timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n", b->rl, c->flags)); 1089 if (c->direction == PCMDIR_PLAY && b->dl) 1090 chn_abort(c); 1091 } 1092 c->flags &= ~CHN_F_CLOSING; 1093 return 0; 1094} 1095 1096int 1097chn_reset(pcm_channel *c, u_int32_t fmt) 1098{ 1099 int r = 0; 1100 1101 chn_abort(c); 1102 c->flags &= CHN_F_RESET; 1103 r = chn_setblocksize(c, CHN_2NDBUFBLKNUM, CHN_2NDBUFBLKSIZE); 1104 if (r) 1105 return r; 1106 if (fmt) { 1107 r = chn_setformat(c, fmt); 1108 if (r == 0) 1109 r = chn_setspeed(c, DSP_DEFAULT_SPEED); 1110 if (r == 0) 1111 r = chn_setvolume(c, 100, 100); 1112 } 1113 chn_resetbuf(c); 1114 /* c->flags |= CHN_F_INIT; */ 1115 return 0; 1116} 1117 1118int 1119chn_reinit(pcm_channel *c) 1120{ 1121 if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) { 1122 chn_setformat(c, c->format); 1123 chn_setspeed(c, c->speed); 1124 chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff); 1125 c->flags &= ~CHN_F_INIT; 1126 return 1; 1127 } 1128 return 0; 1129} 1130 1131int 1132chn_init(pcm_channel *c, void *devinfo, int dir) 1133{ 1134 snd_dbuf *bs = &c->buffer2nd; 1135 1136 /* Initialize the hardware and DMA buffer first. */ 1137 c->feeder = malloc(sizeof(*(c->feeder)), M_DEVBUF, M_NOWAIT); 1138 *(c->feeder) = *feeder_getroot(); 1139 c->feederdesc = malloc(sizeof(*(c->feeder)), M_DEVBUF, M_NOWAIT); 1140 c->feederdesc->type = FEEDER_ROOT; 1141 c->feederdesc->in = 0; 1142 c->feederdesc->out = 0; 1143 c->feederdesc->flags = 0; 1144 c->feederdesc->idx = 0; 1145 c->feeder->desc = c->feederdesc; 1146 c->feeder->source = NULL; 1147 1148 c->flags = 0; 1149 c->buffer.chan = -1; 1150 c->devinfo = c->init(devinfo, &c->buffer, c, dir); 1151 if (c->devinfo == NULL || c->buffer.bufsize == 0) 1152 return 1; 1153 chn_setdir(c, dir); 1154 1155 /* And the secondary buffer. */ 1156 bs->buf = NULL; 1157 bs->bufsize = 0; 1158 return 0; 1159} 1160 1161int 1162chn_kill(pcm_channel *c) 1163{ 1164 chn_trigger(c, PCMTRIG_ABORT); 1165 while (chn_removefeeder(c) == 0); 1166 free(c->feeder->desc, M_DEVBUF); 1167 free(c->feeder, M_DEVBUF); 1168 if (c->free) 1169 c->free(c->devinfo); 1170 else 1171 chn_freebuf(&c->buffer); 1172 c->flags |= CHN_F_DEAD; 1173 return 0; 1174} 1175 1176int 1177chn_setdir(pcm_channel *c, int dir) 1178{ 1179 int r; 1180 1181 c->direction = dir; 1182 r = c->setdir(c->devinfo, c->direction); 1183 if (!r && ISA_DMA(&c->buffer)) 1184 c->buffer.dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ; 1185 return r; 1186} 1187 1188int 1189chn_setvolume(pcm_channel *c, int left, int right) 1190{ 1191 /* could add a feeder for volume changing if channel returns -1 */ 1192 if (CANCHANGE(c)) { 1193 c->volume = (left << 8) | right; 1194 return 0; 1195 } 1196 c->volume = (left << 8) | right; 1197 c->flags |= CHN_F_INIT; 1198 return 0; 1199} 1200 1201int 1202chn_setspeed(pcm_channel *c, int speed) 1203{ 1204 if (speed <= 0) 1205 return EINVAL; 1206 /* could add a feeder for rate conversion */ 1207 if (CANCHANGE(c)) { 1208 c->speed = c->setspeed(c->devinfo, speed); 1209 return 0; 1210 } 1211 c->speed = speed; 1212 c->flags |= CHN_F_INIT; 1213 return 0; 1214} 1215 1216int 1217fmtvalid(u_int32_t fmt, u_int32_t *fmtlist) 1218{ 1219 int i; 1220 1221 for (i = 0; fmtlist[i]; i++) 1222 if (fmt == fmtlist[i]) 1223 return 1; 1224 1225 return 0; 1226} 1227 1228int 1229chn_setformat(pcm_channel *c, u_int32_t fmt) 1230{ 1231 snd_dbuf *b = &c->buffer; 1232 snd_dbuf *bs = &c->buffer2nd; 1233 1234 u_int32_t hwfmt; 1235 if (CANCHANGE(c)) { 1236 while (chn_removefeeder(c) == 0); 1237 c->format = fmt; 1238 c->feederdesc->out = c->format; 1239 hwfmt = c->format; 1240 if (!fmtvalid(hwfmt, chn_getcaps(c)->fmtlist)) { 1241 if (c->flags & CHN_F_MAPPED) 1242 return EINVAL; 1243 hwfmt = chn_feedchain(c, chn_getcaps(c)->fmtlist); 1244 if (hwfmt == 0) 1245 return EINVAL; 1246 } 1247 b->fmt = hwfmt; 1248 bs->fmt = hwfmt; 1249 chn_resetbuf(c); 1250 c->setformat(c->devinfo, hwfmt); 1251 return 0; 1252 } 1253 c->format = fmt; 1254 c->flags |= CHN_F_INIT; 1255 return 0; 1256} 1257 1258int 1259chn_setblocksize(pcm_channel *c, int blkcnt, int blksz) 1260{ 1261 snd_dbuf *b = &c->buffer; 1262 snd_dbuf *bs = &c->buffer2nd; 1263 int s, ss, bufsz; 1264 1265 if (bs->blkcnt == blkcnt && bs->blksz == blksz) 1266 return 0; 1267 if (c->flags & CHN_F_MAPPED) { 1268 DEB(printf("chn_setblocksize: can't work on mapped channel")); 1269 return EINVAL; 1270 } 1271 c->flags &= ~CHN_F_HAS_SIZE; 1272 1273 ss = 1; 1274 ss <<= (bs->fmt & AFMT_STEREO)? 1 : 0; 1275 ss <<= (bs->fmt & AFMT_16BIT)? 1 : 0; 1276 1277 if (blksz >= 2) 1278 c->flags |= CHN_F_HAS_SIZE; 1279 /* let us specify blksz without setting CHN_F_HAS_SIZE */ 1280 if (blksz < 0) 1281 blksz = -blksz; 1282 /* default to blksz = ~0.25s */ 1283 if (blksz < 16) 1284 blksz = (ss * c->speed) >> 2; 1285 if (blksz > CHN_2NDBUFMAXSIZE / 2) 1286 blksz = CHN_2NDBUFMAXSIZE / 2; 1287 if (blkcnt < 2) 1288 blkcnt = 2; 1289 1290 if (blkcnt * blksz > CHN_2NDBUFMAXSIZE) 1291 blkcnt = CHN_2NDBUFMAXSIZE / blksz; 1292 bufsz = blkcnt * blksz; 1293 1294 s = spltty(); 1295 if (bs->buf != NULL) 1296 free(bs->buf, M_DEVBUF); 1297 bs->buf = malloc(bufsz, M_DEVBUF, M_WAITOK); 1298 if (bs->buf == NULL) { 1299 splx(s); 1300 DEB(printf("chn_setblocksize: out of memory.")); 1301 return ENOSPC; 1302 } 1303 bs->bufsize = bufsz; 1304 bs->rl = bs->rp = bs->fp = 0; 1305 bs->fl = bs->bufsize; 1306 buf_clear(bs, bs->fmt, bs->bufsize); 1307 bs->blkcnt = blkcnt; 1308 bs->blksz = blksz; 1309 RANGE(blksz, 16, b->bufsize / 2); 1310 b->blksz = c->setblocksize(c->devinfo, blksz); 1311 splx(s); 1312 1313 return 0; 1314} 1315 1316int 1317chn_trigger(pcm_channel *c, int go) 1318{ 1319 return c->trigger(c->devinfo, go); 1320} 1321 1322int 1323chn_getptr(pcm_channel *c) 1324{ 1325 int hwptr; 1326 int a = (1 << c->align) - 1; 1327 snd_dbuf *b = &c->buffer; 1328 1329 hwptr = b->dl? c->getptr(c->devinfo) : 0; 1330 /* don't allow unaligned values in the hwa ptr */ 1331 hwptr &= ~a ; /* Apply channel align mask */ 1332 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ 1333 return hwptr; 1334} 1335 1336pcmchan_caps * 1337chn_getcaps(pcm_channel *c) 1338{ 1339 return c->getcaps(c->devinfo); 1340} 1341 1342u_int32_t 1343chn_getformats(pcm_channel *c) 1344{ 1345 u_int32_t *fmtlist, fmts; 1346 int i; 1347 1348 fmtlist = chn_getcaps(c)->fmtlist; 1349 fmts = 0; 1350 for (i = 0; fmtlist[i]; i++) 1351 fmts |= fmtlist[i]; 1352 1353 return fmts; 1354} 1355 1356 1357