Annotation of Gnu-Mach/chips/audio.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.