|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /*- ! 27: * Copyright (c) 1991, 1992 The Regents of the University of California. ! 28: * All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the Computer Systems ! 41: * Engineering Group at Lawrence Berkeley Laboratory. ! 42: * 4. The name of the Laboratory may not be used to endorse or promote ! 43: * products derived from this software without specific prior written ! 44: * permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: */ ! 58: ! 59: #include <audio.h> ! 60: #if NAUDIO > 0 ! 61: ! 62: #include <mach_kdb.h> ! 63: #include <platforms.h> ! 64: ! 65: #include <mach/std_types.h> ! 66: #include <machine/machspl.h> ! 67: #include <kern/kalloc.h> ! 68: #include <kern/sched_prim.h> ! 69: #include <chips/busses.h> ! 70: ! 71: #include <device/device_types.h> ! 72: #include <device/io_req.h> ! 73: #include <device/ds_routines.h> ! 74: #include <device/audio_status.h> /* user interface */ ! 75: #include <chips/audio_defs.h> /* chip interface */ ! 76: #include <chips/audio_config.h> /* machdep config */ ! 77: ! 78: #define private static ! 79: ! 80: /* ! 81: * Exported functions and data structures ! 82: * [see header file for listing] ! 83: */ ! 84: int audio_blocksize = DEFBLKSIZE; /* patchable */ ! 85: int audio_backlog = 400; /* 50ms in samples */ ! 86: ! 87: /* ! 88: * Software state, per AMD79C30 audio chip. ! 89: */ ! 90: private ! 91: struct audio_softc { ! 92: void *hw; /* chip status */ ! 93: audio_switch_t *ops; /* chip operations */ ! 94: au_io_t *sc_au; /* recv and xmit buffers, etc */ ! 95: ! 96: ! 97: unsigned int sc_wseek; /* timestamp of last frame written */ ! 98: unsigned int sc_rseek; /* timestamp of last frame read */ ! 99: #if 0 ! 100: struct selinfo sc_wsel; /* write selector */ ! 101: struct selinfo sc_rsel; /* read selector */ ! 102: #endif ! 103: ! 104: } audio_softc_data[NAUDIO]; ! 105: ! 106: #define unit_to_softc(u) &audio_softc_data[u] ! 107: ! 108: ! 109: /* forward declarations */ ! 110: private int audio_sleep (au_cb_t *cb, int thresh); ! 111: private void audio_swintr (struct audio_softc *sc); ! 112: ! 113: /* ! 114: * Audio chip found. ! 115: */ ! 116: void ! 117: audio_attach( ! 118: void *hw, /* IN, chip status */ ! 119: audio_switch_t *ops, ! 120: void **audio_status) /* OUT, audio status */ ! 121: { ! 122: register struct audio_softc *sc; ! 123: static int next = 0; ! 124: ! 125: if (next >= NAUDIO) ! 126: panic("Please configure more than %d audio devices\n", NAUDIO); ! 127: sc = &audio_softc_data[next++]; ! 128: ! 129: printf(" audio"); ! 130: ! 131: sc->hw = hw; ! 132: sc->ops = ops; ! 133: ! 134: *audio_status = (void *)sc; ! 135: } ! 136: ! 137: ! 138: private int audio_setinfo (struct audio_softc *, audio_info_t *); ! 139: private int audio_getinfo (struct audio_softc *, audio_info_t *); ! 140: ! 141: io_return_t ! 142: audio_open( ! 143: int unit, ! 144: int mode, ! 145: io_req_t req) ! 146: { ! 147: register struct audio_softc *sc; ! 148: register au_io_t *au; ! 149: ! 150: sc = unit_to_softc(unit); ! 151: if (unit > NAUDIO || (!sc->hw)) ! 152: return (D_NO_SUCH_DEVICE); ! 153: ! 154: if (!sc->sc_au) { ! 155: sc->sc_au = (au_io_t *) kalloc(sizeof(au_io_t)); ! 156: bzero(sc->sc_au, sizeof(au_io_t)); ! 157: } ! 158: au = sc->sc_au; ! 159: ! 160: au->au_lowat = audio_blocksize; ! 161: au->au_hiwat = AUCB_SIZE - au->au_lowat; ! 162: au->au_blksize = audio_blocksize; ! 163: au->au_backlog = audio_backlog; ! 164: ! 165: /* set up read and write blocks and `dead sound' zero value. */ ! 166: AUCB_INIT(&au->au_rb); ! 167: au->au_rb.cb_thresh = AUCB_SIZE; ! 168: AUCB_INIT(&au->au_wb); ! 169: au->au_wb.cb_thresh = -1; ! 170: ! 171: /* nothing read or written yet */ ! 172: sc->sc_rseek = 0; ! 173: sc->sc_wseek = 0; ! 174: ! 175: (*sc->ops->init)(sc->hw); ! 176: ! 177: return (0); ! 178: } ! 179: ! 180: private int ! 181: audio_drain( ! 182: register au_io_t *au) ! 183: { ! 184: register int error; ! 185: ! 186: while (!AUCB_EMPTY(&au->au_wb)) ! 187: if ((error = audio_sleep(&au->au_wb, 0)) != 0) ! 188: return (error); ! 189: return (0); ! 190: } ! 191: ! 192: /* ! 193: * Close an audio chip. ! 194: */ ! 195: /* ARGSUSED */ ! 196: io_return_t ! 197: audio_close( ! 198: int unit) ! 199: { ! 200: register struct audio_softc *sc = unit_to_softc(unit); ! 201: register au_cb_t *cb; ! 202: register spl_t s; ! 203: ! 204: /* ! 205: * Block until output drains, but allow ^C interrupt. ! 206: */ ! 207: sc->sc_au->au_lowat = 0; /* avoid excessive wakeups */ ! 208: ! 209: /* ! 210: * If there is pending output, let it drain (unless ! 211: * the output is paused). ! 212: */ ! 213: cb = &sc->sc_au->au_wb; ! 214: s = splaudio(); ! 215: if (!AUCB_EMPTY(cb) && !cb->cb_pause) ! 216: (void)audio_drain(sc->sc_au); ! 217: /* ! 218: * Disable interrupts, and done. ! 219: */ ! 220: (*sc->ops->close)(sc->hw); ! 221: splx(s); ! 222: return (D_SUCCESS); ! 223: } ! 224: ! 225: private int ! 226: audio_sleep( ! 227: register au_cb_t *cb, ! 228: register int thresh) ! 229: { ! 230: register spl_t s = splaudio(); ! 231: ! 232: cb->cb_thresh = thresh; ! 233: assert_wait((event_t)cb, TRUE); ! 234: splx(s); ! 235: thread_block((void (*)()) 0); ! 236: return (0); /* XXXX */ ! 237: } ! 238: ! 239: io_return_t ! 240: audio_read( ! 241: int unit, ! 242: io_req_t ior) ! 243: { ! 244: register struct audio_softc *sc = unit_to_softc(unit); ! 245: register au_cb_t *cb; ! 246: register int n, head, taildata; ! 247: register int blocksize = sc->sc_au->au_blksize; ! 248: io_return_t rc; ! 249: unsigned char *data; ! 250: ! 251: /* ! 252: * Allocate read buffer ! 253: */ ! 254: rc = device_read_alloc(ior, (vm_size_t)ior->io_count); ! 255: if (rc != KERN_SUCCESS) ! 256: return rc; ! 257: data = (unsigned char *) ior->io_data; ! 258: ior->io_residual = ior->io_count; ! 259: ! 260: cb = &sc->sc_au->au_rb; ! 261: cb->cb_drops = 0; ! 262: sc->sc_rseek = sc->sc_au->au_stamp - AUCB_LEN(cb); ! 263: do { ! 264: while (AUCB_LEN(cb) < blocksize) { ! 265: ! 266: if (ior->io_mode & D_NODELAY) ! 267: return (D_WOULD_BLOCK); ! 268: ! 269: if ((rc = audio_sleep(cb, blocksize)) != 0) ! 270: return(rc); ! 271: } ! 272: /* ! 273: * The space calculation can only err on the short ! 274: * side if an interrupt occurs during processing: ! 275: * only cb_tail is altered in the interrupt code. ! 276: */ ! 277: head = cb->cb_head; ! 278: if ((n = AUCB_LEN(cb)) > ior->io_residual) ! 279: n = ior->io_residual; ! 280: taildata = AUCB_SIZE - head; ! 281: ! 282: if (n > taildata) { ! 283: bcopy(cb->cb_data + head, data, taildata); ! 284: bcopy(cb->cb_data, data + taildata, n - taildata); ! 285: } else ! 286: bcopy(cb->cb_data + head, data, n); ! 287: data += n; ! 288: ior->io_residual -= n; ! 289: ! 290: head = AUCB_MOD(head + n); ! 291: cb->cb_head = head; ! 292: } while (ior->io_residual >= blocksize); ! 293: ! 294: return (rc); ! 295: } ! 296: ! 297: io_return_t ! 298: audio_write( ! 299: int unit, ! 300: io_req_t ior) ! 301: { ! 302: register struct audio_softc *sc = unit_to_softc(unit); ! 303: register au_io_t *au = sc->sc_au; ! 304: register au_cb_t *cb = &au->au_wb; ! 305: register int n, tail, tailspace, first, watermark; ! 306: io_return_t rc; ! 307: unsigned char *data; ! 308: vm_offset_t addr = 0; ! 309: ! 310: if (!(ior->io_op & IO_INBAND)) { ! 311: /* ! 312: * Copy out-of-line data into kernel address space. ! 313: * Since data is copied as page list, it will be ! 314: * accessible. ! 315: */ ! 316: vm_map_copy_t copy = (vm_map_copy_t) ior->io_data; ! 317: kern_return_t kr; ! 318: ! 319: kr = vm_map_copyout(device_io_map, &addr, copy); ! 320: if (kr != KERN_SUCCESS) ! 321: return kr; ! 322: data = (unsigned char *) addr; ! 323: } else ! 324: data = (unsigned char *) ior->io_data; ! 325: ior->io_residual = ior->io_count; ! 326: ! 327: rc = D_SUCCESS; ! 328: first = 1; ! 329: while (ior->io_residual > 0) { ! 330: watermark = au->au_hiwat; ! 331: while (AUCB_LEN(cb) > watermark) { ! 332: ! 333: if (ior->io_mode & D_NODELAY) { ! 334: rc = D_WOULD_BLOCK; ! 335: goto out; ! 336: } ! 337: ! 338: if ((rc = audio_sleep(cb, watermark)) != 0) ! 339: goto out; ! 340: ! 341: watermark = au->au_lowat; ! 342: } ! 343: /* ! 344: * The only value that can change on an interrupt is ! 345: * cb->cb_head. We only pull that out once to decide ! 346: * how much to write into cb_data; if we lose a race ! 347: * and cb_head changes, we will merely be overly ! 348: * conservative. For a legitimate time stamp, ! 349: * however, we need to synchronize the accesses to ! 350: * au_stamp and cb_head at a high ipl below. ! 351: */ ! 352: tail = cb->cb_tail; ! 353: if ((n = (AUCB_SIZE - 1) - AUCB_LEN(cb)) > ior->io_residual) { ! 354: n = ior->io_residual; ! 355: if (cb->cb_head == tail && ! 356: n <= au->au_blksize && ! 357: au->au_stamp - sc->sc_wseek > 400) { ! 358: /* ! 359: * the write is 'small', the buffer is empty ! 360: * and we have been silent for at least 50ms ! 361: * so we might be dealing with an application ! 362: * that writes frames synchronously with ! 363: * reading them. If so, we need an output ! 364: * backlog to cover scheduling delays or ! 365: * there will be gaps in the sound output. ! 366: * Also take this opportunity to reset the ! 367: * buffer pointers in case we ended up on ! 368: * a bad boundary (odd byte, blksize bytes ! 369: * from end, etc.). ! 370: */ ! 371: register unsigned long *ip; ! 372: register unsigned long muzero; ! 373: spl_t s; ! 374: register int i; ! 375: ! 376: s = splaudio(); ! 377: cb->cb_head = cb->cb_tail = 0; ! 378: splx(s); ! 379: ! 380: tail = au->au_backlog; ! 381: ip = (unsigned long *)cb->cb_data; ! 382: muzero = sample_rpt_long(0x7fL); ! 383: for (i = tail / sizeof muzero; --i >= 0; ) ! 384: *ip++ = muzero; ! 385: } ! 386: } ! 387: tailspace = AUCB_SIZE - tail; ! 388: if (n > tailspace) { ! 389: /* write first part at tail and rest at head */ ! 390: bcopy(data, cb->cb_data + tail, tailspace); ! 391: bcopy(data + tailspace, cb->cb_data, ! 392: n - tailspace); ! 393: } else ! 394: bcopy(data, cb->cb_data + tail, n); ! 395: data += n; ! 396: ior->io_residual -= n; ! 397: ! 398: tail = AUCB_MOD(tail + n); ! 399: if (first) { ! 400: register spl_t s = splaudio(); ! 401: sc->sc_wseek = AUCB_LEN(cb) + au->au_stamp + 1; ! 402: /* ! 403: * To guarantee that a write is contiguous in the ! 404: * sample space, we clear the drop count the first ! 405: * time through. If we later get drops, we will ! 406: * break out of the loop below, before writing ! 407: * a new frame. ! 408: */ ! 409: cb->cb_drops = 0; ! 410: cb->cb_tail = tail; ! 411: splx(s); ! 412: first = 0; ! 413: } else { ! 414: #if 0 ! 415: if (cb->cb_drops != 0) ! 416: break; ! 417: #endif ! 418: cb->cb_tail = tail; ! 419: } ! 420: } ! 421: out: ! 422: if (!(ior->io_op & IO_INBAND)) ! 423: (void) vm_deallocate(device_io_map, addr, ior->io_count); ! 424: return (rc); ! 425: } ! 426: ! 427: #include <sys/ioctl.h> ! 428: ! 429: io_return_t ! 430: audio_get_status( ! 431: int unit, ! 432: dev_flavor_t flavor, ! 433: dev_status_t status, ! 434: natural_t *status_count) ! 435: { ! 436: register struct audio_softc *sc = unit_to_softc(unit); ! 437: register au_io_t *au = sc->sc_au; ! 438: io_return_t rc = D_SUCCESS; ! 439: spl_t s; ! 440: ! 441: switch (flavor) { ! 442: ! 443: case AUDIO_GETMAP: ! 444: case AUDIOGETREG: ! 445: rc = (*sc->ops->getstate)(sc->hw, flavor, ! 446: (void *)status, status_count); ! 447: break; ! 448: ! 449: /* ! 450: * Number of read samples dropped. We don't know where or ! 451: * when they were dropped. ! 452: */ ! 453: case AUDIO_RERROR: ! 454: *(int *)status = au->au_rb.cb_drops; ! 455: *status_count = 1; ! 456: break; ! 457: ! 458: case AUDIO_WERROR: ! 459: *(int *)status = au->au_wb.cb_drops; ! 460: *status_count = 1; ! 461: break; ! 462: ! 463: /* ! 464: * How many samples will elapse until mike hears the first ! 465: * sample of what we last wrote? ! 466: */ ! 467: case AUDIO_WSEEK: ! 468: s = splaudio(); ! 469: *(unsigned int *)status = sc->sc_wseek - au->au_stamp ! 470: + AUCB_LEN(&au->au_rb); ! 471: splx(s); ! 472: *status_count = 1; ! 473: break; ! 474: ! 475: case AUDIO_GETINFO: ! 476: rc = audio_getinfo(sc, (audio_info_t *)status); ! 477: *status_count = sizeof(audio_info_t) / sizeof(int); ! 478: break; ! 479: ! 480: default: ! 481: rc = D_INVALID_OPERATION; ! 482: break; ! 483: } ! 484: return (rc); ! 485: } ! 486: ! 487: io_return_t ! 488: audio_set_status( ! 489: int unit, ! 490: dev_flavor_t flavor, ! 491: dev_status_t status, ! 492: natural_t status_count) ! 493: { ! 494: register struct audio_softc *sc = unit_to_softc(unit); ! 495: register au_io_t *au = sc->sc_au; ! 496: io_return_t rc = D_SUCCESS; ! 497: spl_t s; ! 498: ! 499: switch (flavor) { ! 500: ! 501: case AUDIO_SETMAP: ! 502: case AUDIOSETREG: ! 503: rc = (*sc->ops->setstate)(sc->hw, flavor, ! 504: (void *)status, status_count); ! 505: break; ! 506: ! 507: case AUDIO_FLUSH: ! 508: s = splaudio(); ! 509: AUCB_INIT(&au->au_rb); ! 510: AUCB_INIT(&au->au_wb); ! 511: au->au_stamp = 0; ! 512: splx(s); ! 513: sc->sc_wseek = 0; ! 514: sc->sc_rseek = 0; ! 515: break; ! 516: ! 517: case AUDIO_SETINFO: ! 518: rc = audio_setinfo(sc, (audio_info_t *)status); ! 519: break; ! 520: ! 521: case AUDIO_DRAIN: ! 522: rc = audio_drain(au); ! 523: break; ! 524: ! 525: default: ! 526: rc = D_INVALID_OPERATION; ! 527: break; ! 528: } ! 529: return (rc); ! 530: } ! 531: ! 532: ! 533: /* ! 534: * Interrupt routine ! 535: */ ! 536: boolean_t ! 537: audio_hwintr( ! 538: void *status, ! 539: unsigned int s_in, ! 540: unsigned int *s_out) ! 541: { ! 542: register au_io_t *au = ((struct audio_softc *) status)->sc_au; ! 543: register au_cb_t *cb; ! 544: register int h, t, k; ! 545: register boolean_t wakeit = FALSE; ! 546: ! 547: ++au->au_stamp; ! 548: ! 549: /* receive incoming data */ ! 550: cb = &au->au_rb; ! 551: h = cb->cb_head; ! 552: t = cb->cb_tail; ! 553: k = AUCB_MOD(t + 1); ! 554: if (h == k) ! 555: cb->cb_drops++; ! 556: else if (cb->cb_pause != 0) ! 557: cb->cb_pdrops++; ! 558: else { ! 559: cb->cb_data[t] = s_in; ! 560: cb->cb_tail = t = k; ! 561: } ! 562: if (AUCB_MOD(t - h) >= cb->cb_thresh) { ! 563: cb->cb_thresh = AUCB_SIZE; ! 564: cb->cb_waking = 1; ! 565: wakeit = TRUE; ! 566: } ! 567: /* send outgoing data */ ! 568: cb = &au->au_wb; ! 569: h = cb->cb_head; ! 570: t = cb->cb_tail; ! 571: k = 0; ! 572: if (h == t) ! 573: cb->cb_drops++; ! 574: else if (cb->cb_pause != 0) ! 575: cb->cb_pdrops++; ! 576: else { ! 577: cb->cb_head = h = AUCB_MOD(h + 1); ! 578: *s_out = cb->cb_data[h]; ! 579: k = 1; ! 580: } ! 581: if (AUCB_MOD(t - h) <= cb->cb_thresh) { ! 582: cb->cb_thresh = -1; ! 583: cb->cb_waking = 1; ! 584: wakeit = TRUE; ! 585: } ! 586: if (wakeit) ! 587: audio_swintr((struct audio_softc *) status); ! 588: return (k == 1); ! 589: } ! 590: ! 591: private void ! 592: audio_swintr( ! 593: register struct audio_softc *sc) ! 594: { ! 595: register au_io_t *au = sc->sc_au; ! 596: ! 597: if (au->au_rb.cb_waking != 0) { ! 598: au->au_rb.cb_waking = 0; ! 599: wakeup(&au->au_rb); ! 600: } ! 601: if (au->au_wb.cb_waking != 0) { ! 602: au->au_wb.cb_waking = 0; ! 603: wakeup(&au->au_wb); ! 604: } ! 605: } ! 606: ! 607: private int ! 608: audio_setinfo( ! 609: struct audio_softc *sc, ! 610: audio_info_t *ai) ! 611: { ! 612: struct audio_prinfo *r = &ai->record, *p = &ai->play; ! 613: register int bsize; ! 614: register au_io_t *au = sc->sc_au; ! 615: spl_t s; ! 616: ! 617: (*sc->ops->setgains)(sc->hw, p->gain, r->gain, ai->monitor_gain ); ! 618: ! 619: if (p->pause != (unsigned char)~0) ! 620: au->au_wb.cb_pause = p->pause; ! 621: if (r->pause != (unsigned char)~0) ! 622: au->au_rb.cb_pause = r->pause; ! 623: ! 624: if (p->port != ~0) ! 625: (*sc->ops->setport)(sc->hw, p->port); ! 626: ! 627: if (ai->blocksize != ~0) { ! 628: if (ai->blocksize == 0) ! 629: bsize = ai->blocksize = DEFBLKSIZE; ! 630: else if (ai->blocksize > MAXBLKSIZE) ! 631: bsize = ai->blocksize = MAXBLKSIZE; ! 632: else ! 633: bsize = ai->blocksize; ! 634: ! 635: s = splaudio(); ! 636: au->au_blksize = bsize; ! 637: /* AUDIO_FLUSH */ ! 638: AUCB_INIT(&au->au_rb); ! 639: AUCB_INIT(&au->au_wb); ! 640: splx(s); ! 641: ! 642: } ! 643: if (ai->hiwat != ~0 && (unsigned)ai->hiwat < AUCB_SIZE) ! 644: au->au_hiwat = ai->hiwat; ! 645: if (ai->lowat != ~0 && ai->lowat < AUCB_SIZE) ! 646: au->au_lowat = ai->lowat; ! 647: if (ai->backlog != ~0 && ai->backlog < (AUCB_SIZE/2)) ! 648: au->au_backlog = ai->backlog; ! 649: ! 650: return (0); ! 651: } ! 652: ! 653: private int ! 654: audio_getinfo( ! 655: struct audio_softc *sc, ! 656: audio_info_t *ai) ! 657: { ! 658: struct audio_prinfo *r = &ai->record, *p = &ai->play; ! 659: register au_io_t *au = sc->sc_au; ! 660: ! 661: p->sample_rate = r->sample_rate = 8000; ! 662: p->channels = r->channels = 1; ! 663: p->precision = r->precision = 8; ! 664: p->encoding = r->encoding = AUDIO_ENCODING_ULAW; ! 665: ! 666: (*sc->ops->getgains)(sc->hw, &p->gain, &r->gain, &ai->monitor_gain ); ! 667: ! 668: r->port = AUDIO_MIKE; ! 669: p->port = (*sc->ops->getport)(sc->hw); ! 670: ! 671: p->pause = au->au_wb.cb_pause; ! 672: r->pause = au->au_rb.cb_pause; ! 673: p->error = au->au_wb.cb_drops != 0; ! 674: r->error = au->au_rb.cb_drops != 0; ! 675: ! 676: /* Now this is funny. If you got here it means you must have ! 677: opened the device, so how could it possibly be closed ? ! 678: Unless we upgrade the berkeley code to check if the chip ! 679: is currently playing and/or recording... Later. */ ! 680: p->open = TRUE; ! 681: r->open = TRUE; ! 682: ! 683: p->samples = au->au_stamp - au->au_wb.cb_pdrops; ! 684: r->samples = au->au_stamp - au->au_rb.cb_pdrops; ! 685: ! 686: p->seek = sc->sc_wseek; ! 687: r->seek = sc->sc_rseek; ! 688: ! 689: ai->blocksize = au->au_blksize; ! 690: ai->hiwat = au->au_hiwat; ! 691: ai->lowat = au->au_lowat; ! 692: ai->backlog = au->au_backlog; ! 693: ! 694: return (0); ! 695: } ! 696: ! 697: #if MACH_KDB ! 698: #include <ddb/db_output.h> ! 699: ! 700: void audio_queue_status( au_cb_t *cb, char *logo) ! 701: { ! 702: db_printf("%s ring status:\n", logo); ! 703: db_printf(" h %x t %x sh %x w %d p %d d %x pd %x\n", ! 704: cb->cb_head, cb->cb_tail, cb->cb_thresh, ! 705: cb->cb_waking, cb->cb_pause, (long)cb->cb_drops, ! 706: (long)cb->cb_pdrops); ! 707: } ! 708: ! 709: int audio_status(int unit) ! 710: { ! 711: struct audio_softc *sc = unit_to_softc(unit); ! 712: au_io_t *au; ! 713: ! 714: if (!sc) { ! 715: db_printf("No such thing\n"); ! 716: return 0; ! 717: } ! 718: db_printf("@%lx: wseek %d rseek %d, au @%lx\n", ! 719: sc, sc->sc_wseek, sc->sc_rseek, sc->sc_au); ! 720: if (!(au = sc->sc_au)) return 0; ! 721: ! 722: db_printf("au: stamp %x lo %x hi %x blk %x blg %x\n", ! 723: au->au_stamp, au->au_lowat, au->au_hiwat, ! 724: au->au_blksize, au->au_backlog); ! 725: audio_queue_status(&au->au_rb, "read"); ! 726: audio_queue_status(&au->au_wb, "write"); ! 727: ! 728: return 0; ! 729: } ! 730: #endif /* MACH_KDB */ ! 731: ! 732: #endif /* NAUDIO > 0 */ ! 733:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.