Annotation of Gnu-Mach/chips/audio.c, revision 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.