[BACK]Return to audio.c CVS log [TXT][DIR] Up to [local] / sys / dev

Annotation of sys/dev/audio.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: audio.c,v 1.72 2007/08/08 05:51:23 jakemsr Exp $      */
                      2: /*     $NetBSD: audio.c,v 1.119 1999/11/09 16:50:47 augustss Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (c) 1991-1993 Regents of the University of California.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the Computer Systems
                     19:  *     Engineering Group at Lawrence Berkeley Laboratory.
                     20:  * 4. Neither the name of the University nor of the Laboratory may be used
                     21:  *    to endorse or promote products derived from this software without
                     22:  *    specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: /*
                     38:  * This is a (partially) SunOS-compatible /dev/audio driver for NetBSD.
                     39:  *
                     40:  * This code tries to do something half-way sensible with
                     41:  * half-duplex hardware, such as with the SoundBlaster hardware.  With
                     42:  * half-duplex hardware allowing O_RDWR access doesn't really make
                     43:  * sense.  However, closing and opening the device to "turn around the
                     44:  * line" is relatively expensive and costs a card reset (which can
                     45:  * take some time, at least for the SoundBlaster hardware).  Instead
                     46:  * we allow O_RDWR access, and provide an ioctl to set the "mode",
                     47:  * i.e. playing or recording.
                     48:  *
                     49:  * If you write to a half-duplex device in record mode, the data is
                     50:  * tossed.  If you read from the device in play mode, you get silence
                     51:  * filled buffers at the rate at which samples are naturally
                     52:  * generated.
                     53:  *
                     54:  * If you try to set both play and record mode on a half-duplex
                     55:  * device, playing takes precedence.
                     56:  */
                     57:
                     58: /*
                     59:  * Todo:
                     60:  * - Add softaudio() isr processing for wakeup, poll, signals,
                     61:  *   and silence fill.
                     62:  */
                     63:
                     64: #include "audio.h"
                     65: #if NAUDIO > 0
                     66:
                     67: #include <sys/param.h>
                     68: #include <sys/ioctl.h>
                     69: #include <sys/fcntl.h>
                     70: #include <sys/vnode.h>
                     71: #include <sys/selinfo.h>
                     72: #include <sys/poll.h>
                     73: #include <sys/malloc.h>
                     74: #include <sys/proc.h>
                     75: #include <sys/systm.h>
                     76: #include <sys/syslog.h>
                     77: #include <sys/kernel.h>
                     78: #include <sys/signalvar.h>
                     79: #include <sys/conf.h>
                     80: #include <sys/audioio.h>
                     81: #include <sys/device.h>
                     82:
                     83: #include <dev/audio_if.h>
                     84: #include <dev/audiovar.h>
                     85:
                     86: #include <dev/rndvar.h>
                     87:
                     88: #include <machine/endian.h>
                     89:
                     90: #include "wskbd.h"     /* NWSKBD (mixer tuning using keyboard) */
                     91:
                     92: #ifdef AUDIO_DEBUG
                     93: #define DPRINTF(x)     if (audiodebug) printf x
                     94: #define DPRINTFN(n,x)  if (audiodebug>(n)) printf x
                     95: int    audiodebug = 0;
                     96: #else
                     97: #define DPRINTF(x)
                     98: #define DPRINTFN(n,x)
                     99: #endif
                    100:
                    101: #define ROUNDSIZE(x) x &= -16  /* round to nice boundary */
                    102:
                    103: int    audio_blk_ms = AUDIO_BLK_MS;
                    104:
                    105: int    audiosetinfo(struct audio_softc *, struct audio_info *);
                    106: int    audiogetinfo(struct audio_softc *, struct audio_info *);
                    107:
                    108: int    audio_open(dev_t, struct audio_softc *, int, int, struct proc *);
                    109: int    audio_close(dev_t, int, int, struct proc *);
                    110: int    audio_read(dev_t, struct uio *, int);
                    111: int    audio_write(dev_t, struct uio *, int);
                    112: int    audio_ioctl(dev_t, u_long, caddr_t, int, struct proc *);
                    113: int    audio_poll(dev_t, int, struct proc *);
                    114: paddr_t        audio_mmap(dev_t, off_t, int);
                    115:
                    116: int    mixer_open(dev_t, struct audio_softc *, int, int, struct proc *);
                    117: int    mixer_close(dev_t, int, int, struct proc *);
                    118: int    mixer_ioctl(dev_t, u_long, caddr_t, int, struct proc *);
                    119: static void mixer_remove(struct audio_softc *, struct proc *p);
                    120: static void mixer_signal(struct audio_softc *);
                    121:
                    122: void   audio_init_record(struct audio_softc *);
                    123: void   audio_init_play(struct audio_softc *);
                    124: int    audiostartr(struct audio_softc *);
                    125: int    audiostartp(struct audio_softc *);
                    126: void   audio_rint(void *);
                    127: void   audio_pint(void *);
                    128: int    audio_check_params(struct audio_params *);
                    129:
                    130: void   audio_calc_blksize(struct audio_softc *, int);
                    131: void   audio_fill_silence(struct audio_params *, u_char *, int);
                    132: int    audio_silence_copyout(struct audio_softc *, int, struct uio *);
                    133:
                    134: void   audio_init_ringbuffer(struct audio_ringbuffer *);
                    135: int    audio_initbufs(struct audio_softc *);
                    136: void   audio_calcwater(struct audio_softc *);
                    137: static __inline int audio_sleep_timo(int *, char *, int);
                    138: static __inline int audio_sleep(int *, char *);
                    139: static __inline void audio_wakeup(int *);
                    140: void   audio_selwakeup(struct audio_softc *sc, int play);
                    141: int    audio_drain(struct audio_softc *);
                    142: void   audio_clear(struct audio_softc *);
                    143: static __inline void audio_pint_silence(struct audio_softc *, struct audio_ringbuffer *, u_char *, int);
                    144:
                    145: int    audio_alloc_ring(struct audio_softc *, struct audio_ringbuffer *, int, int);
                    146: void   audio_free_ring(struct audio_softc *, struct audio_ringbuffer *);
                    147:
                    148: int    audioprint(void *, const char *);
                    149:
                    150: int    audioprobe(struct device *, void *, void *);
                    151: void   audioattach(struct device *, struct device *, void *);
                    152: int    audiodetach(struct device *, int);
                    153: int    audioactivate(struct device *, enum devact);
                    154:
                    155: struct portname {
                    156:        char    *name;
                    157:        int     mask;
                    158: };
                    159: static struct portname itable[] = {
                    160:        { AudioNmicrophone,     AUDIO_MICROPHONE },
                    161:        { AudioNline,           AUDIO_LINE_IN },
                    162:        { AudioNcd,             AUDIO_CD },
                    163:        { 0 }
                    164: };
                    165: static struct portname otable[] = {
                    166:        { AudioNspeaker,        AUDIO_SPEAKER },
                    167:        { AudioNheadphone,      AUDIO_HEADPHONE },
                    168:        { AudioNline,           AUDIO_LINE_OUT },
                    169:        { 0 }
                    170: };
                    171: void   au_check_ports(struct audio_softc *, struct au_mixer_ports *,
                    172:                            mixer_devinfo_t *, int, char *, char *,
                    173:                            struct portname *);
                    174: int    au_set_gain(struct audio_softc *, struct au_mixer_ports *,
                    175:                         int, int);
                    176: void   au_get_gain(struct audio_softc *, struct au_mixer_ports *,
                    177:                         u_int *, u_char *);
                    178: int    au_set_port(struct audio_softc *, struct au_mixer_ports *,
                    179:                         u_int);
                    180: int    au_get_port(struct audio_softc *, struct au_mixer_ports *);
                    181: int    au_get_lr_value(struct audio_softc *, mixer_ctrl_t *,
                    182:                             int *, int *r);
                    183: int    au_set_lr_value(struct audio_softc *, mixer_ctrl_t *,
                    184:                             int, int);
                    185: int    au_portof(struct audio_softc *, char *);
                    186:
                    187:
                    188: /* The default audio mode: 8 kHz mono ulaw */
                    189: struct audio_params audio_default =
                    190:        { 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1 };
                    191:
                    192: struct cfattach audio_ca = {
                    193:        sizeof(struct audio_softc), audioprobe, audioattach,
                    194:        audiodetach, audioactivate
                    195: };
                    196:
                    197: struct cfdriver audio_cd = {
                    198:        NULL, "audio", DV_DULL
                    199: };
                    200:
                    201: void filt_audiowdetach(struct knote *);
                    202: int filt_audiowrite(struct knote *, long);
                    203:
                    204: struct filterops audiowrite_filtops =
                    205:        { 1, NULL, filt_audiowdetach, filt_audiowrite};
                    206:
                    207: void filt_audiordetach(struct knote *);
                    208: int filt_audioread(struct knote *, long);
                    209:
                    210: struct filterops audioread_filtops =
                    211:        { 1, NULL, filt_audiordetach, filt_audioread};
                    212:
                    213: #if NWSKBD > 0
                    214: /* Mixer manipulation using keyboard */
                    215: int wskbd_get_mixerdev(struct audio_softc *, int, int *);
                    216: int wskbd_set_mixervolume(long);
                    217: #endif
                    218:
                    219: int
                    220: audioprobe(struct device *parent, void *match, void *aux)
                    221: {
                    222:        struct audio_attach_args *sa = aux;
                    223:
                    224:        DPRINTF(("audioprobe: type=%d sa=%p hw=%p\n",
                    225:                   sa->type, sa, sa->hwif));
                    226:        return (sa->type == AUDIODEV_TYPE_AUDIO) ? 1 : 0;
                    227: }
                    228:
                    229: void
                    230: audioattach(struct device *parent, struct device *self, void *aux)
                    231: {
                    232:        struct audio_softc *sc = (void *)self;
                    233:        struct audio_attach_args *sa = aux;
                    234:        struct audio_hw_if *hwp = sa->hwif;
                    235:        void *hdlp = sa->hdl;
                    236:        int error;
                    237:        mixer_devinfo_t mi;
                    238:        int iclass, oclass, mclass;
                    239:
                    240:        printf("\n");
                    241:
                    242: #ifdef DIAGNOSTIC
                    243:        if (hwp == 0 ||
                    244:            hwp->open == 0 ||
                    245:            hwp->close == 0 ||
                    246:            hwp->query_encoding == 0 ||
                    247:            hwp->set_params == 0 ||
                    248:            (hwp->start_output == 0 && hwp->trigger_output == 0) ||
                    249:            (hwp->start_input == 0 && hwp->trigger_input == 0) ||
                    250:            hwp->halt_output == 0 ||
                    251:            hwp->halt_input == 0 ||
                    252:            hwp->getdev == 0 ||
                    253:            hwp->set_port == 0 ||
                    254:            hwp->get_port == 0 ||
                    255:            hwp->query_devinfo == 0 ||
                    256:            hwp->get_props == 0) {
                    257:                printf("audio: missing method\n");
                    258:                sc->hw_if = 0;
                    259:                return;
                    260:        }
                    261: #endif
                    262:
                    263:        sc->hw_if = hwp;
                    264:        sc->hw_hdl = hdlp;
                    265:        sc->sc_dev = parent;
                    266:
                    267:        error = audio_alloc_ring(sc, &sc->sc_pr, AUMODE_PLAY, AU_RING_SIZE);
                    268:        if (error) {
                    269:                sc->hw_if = 0;
                    270:                printf("audio: could not allocate play buffer\n");
                    271:                return;
                    272:        }
                    273:        error = audio_alloc_ring(sc, &sc->sc_rr, AUMODE_RECORD, AU_RING_SIZE);
                    274:        if (error) {
                    275:                audio_free_ring(sc, &sc->sc_pr);
                    276:                sc->hw_if = 0;
                    277:                printf("audio: could not allocate record buffer\n");
                    278:                return;
                    279:        }
                    280:
                    281:        /*
                    282:         * Set default softc params
                    283:         */
                    284:        sc->sc_pparams = audio_default;
                    285:        sc->sc_rparams = audio_default;
                    286:
                    287:        /* Set up some default values */
                    288:        sc->sc_blkset = 0;
                    289:        audio_calc_blksize(sc, AUMODE_RECORD);
                    290:        audio_calc_blksize(sc, AUMODE_PLAY);
                    291:        audio_init_ringbuffer(&sc->sc_rr);
                    292:        audio_init_ringbuffer(&sc->sc_pr);
                    293:        audio_calcwater(sc);
                    294:
                    295:        iclass = oclass = mclass = -1;
                    296:        sc->sc_inports.index = -1;
                    297:        sc->sc_inports.nports = 0;
                    298:        sc->sc_inports.isenum = 0;
                    299:        sc->sc_inports.allports = 0;
                    300:        sc->sc_outports.index = -1;
                    301:        sc->sc_outports.nports = 0;
                    302:        sc->sc_outports.isenum = 0;
                    303:        sc->sc_outports.allports = 0;
                    304:        sc->sc_monitor_port = -1;
                    305:        for(mi.index = 0; ; mi.index++) {
                    306:                if (hwp->query_devinfo(hdlp, &mi) != 0)
                    307:                        break;
                    308:                if (mi.type == AUDIO_MIXER_CLASS &&
                    309:                    strcmp(mi.label.name, AudioCrecord) == 0)
                    310:                        iclass = mi.index;
                    311:                if (mi.type == AUDIO_MIXER_CLASS &&
                    312:                    strcmp(mi.label.name, AudioCmonitor) == 0)
                    313:                        mclass = mi.index;
                    314:                if (mi.type == AUDIO_MIXER_CLASS &&
                    315:                    strcmp(mi.label.name, AudioCoutputs) == 0)
                    316:                        oclass = mi.index;
                    317:        }
                    318:        for(mi.index = 0; ; mi.index++) {
                    319:                if (hwp->query_devinfo(hdlp, &mi) != 0)
                    320:                        break;
                    321:                if (mi.type == AUDIO_MIXER_CLASS)
                    322:                        continue;
                    323:                au_check_ports(sc, &sc->sc_inports,  &mi, iclass,
                    324:                    AudioNsource, AudioNrecord, itable);
                    325:                au_check_ports(sc, &sc->sc_outports, &mi, oclass,
                    326:                    AudioNoutput, AudioNmaster, otable);
                    327:                if (mi.mixer_class == mclass &&
                    328:                    (strcmp(mi.label.name, AudioNmonitor) == 0))
                    329:                        sc->sc_monitor_port = mi.index;
                    330:                if ((sc->sc_monitor_port == -1) && (mi.mixer_class == oclass) &&
                    331:                    (strcmp(mi.label.name, AudioNmonitor) == 0))
                    332:                        sc->sc_monitor_port = mi.index;
                    333:        }
                    334:        DPRINTF(("audio_attach: inputs ports=0x%x, output ports=0x%x\n",
                    335:                 sc->sc_inports.allports, sc->sc_outports.allports));
                    336: }
                    337:
                    338: int
                    339: audioactivate(struct device *self, enum devact act)
                    340: {
                    341:        struct audio_softc *sc = (struct audio_softc *)self;
                    342:
                    343:        switch (act) {
                    344:        case DVACT_ACTIVATE:
                    345:                break;
                    346:
                    347:        case DVACT_DEACTIVATE:
                    348:                sc->sc_dying = 1;
                    349:                break;
                    350:        }
                    351:        return (0);
                    352: }
                    353:
                    354: int
                    355: audiodetach(struct device *self, int flags)
                    356: {
                    357:        struct audio_softc *sc = (struct audio_softc *)self;
                    358:        int maj, mn;
                    359:        int s;
                    360:
                    361:        DPRINTF(("audio_detach: sc=%p flags=%d\n", sc, flags));
                    362:
                    363:        sc->sc_dying = 1;
                    364:
                    365:        wakeup(&sc->sc_wchan);
                    366:        wakeup(&sc->sc_rchan);
                    367:        s = splaudio();
                    368:        if (--sc->sc_refcnt >= 0) {
                    369:                if (tsleep(&sc->sc_refcnt, PZERO, "auddet", hz * 120))
                    370:                        printf("audiodetach: %s didn't detach\n",
                    371:                            sc->dev.dv_xname);
                    372:        }
                    373:        splx(s);
                    374:
                    375:        /* free resources */
                    376:        audio_free_ring(sc, &sc->sc_pr);
                    377:        audio_free_ring(sc, &sc->sc_rr);
                    378:
                    379:        /* locate the major number */
                    380:        for (maj = 0; maj < nchrdev; maj++)
                    381:                if (cdevsw[maj].d_open == audioopen)
                    382:                        break;
                    383:
                    384:        /* Nuke the vnodes for any open instances (calls close). */
                    385:        mn = self->dv_unit;
                    386:        vdevgone(maj, mn | SOUND_DEVICE,    mn | SOUND_DEVICE, VCHR);
                    387:        vdevgone(maj, mn | AUDIO_DEVICE,    mn | AUDIO_DEVICE, VCHR);
                    388:        vdevgone(maj, mn | AUDIOCTL_DEVICE, mn | AUDIOCTL_DEVICE, VCHR);
                    389:        vdevgone(maj, mn | MIXER_DEVICE,    mn | MIXER_DEVICE, VCHR);
                    390:
                    391:        return (0);
                    392: }
                    393:
                    394: int
                    395: au_portof(struct audio_softc *sc, char *name)
                    396: {
                    397:        mixer_devinfo_t mi;
                    398:
                    399:        for(mi.index = 0;
                    400:            sc->hw_if->query_devinfo(sc->hw_hdl, &mi) == 0;
                    401:            mi.index++)
                    402:                if (strcmp(mi.label.name, name) == 0)
                    403:                        return mi.index;
                    404:        return -1;
                    405: }
                    406:
                    407: void
                    408: au_check_ports(struct audio_softc *sc, struct au_mixer_ports *ports,
                    409:     mixer_devinfo_t *mi, int cls, char *name, char *mname, struct portname *tbl)
                    410: {
                    411:        int i, j;
                    412:
                    413:        if (mi->mixer_class != cls)
                    414:                return;
                    415:        if (strcmp(mi->label.name, mname) == 0) {
                    416:                ports->master = mi->index;
                    417:                return;
                    418:        }
                    419:        if (strcmp(mi->label.name, name) != 0)
                    420:                return;
                    421:        if (mi->type == AUDIO_MIXER_ENUM) {
                    422:            ports->index = mi->index;
                    423:            for(i = 0; tbl[i].name; i++) {
                    424:                for(j = 0; j < mi->un.e.num_mem; j++) {
                    425:                    if (strcmp(mi->un.e.member[j].label.name,
                    426:                            tbl[i].name) == 0) {
                    427:                        ports->aumask[ports->nports] = tbl[i].mask;
                    428:                        ports->misel [ports->nports] = mi->un.e.member[j].ord;
                    429:                        ports->miport[ports->nports++] =
                    430:                                au_portof(sc, mi->un.e.member[j].label.name);
                    431:                        ports->allports |= tbl[i].mask;
                    432:                    }
                    433:                }
                    434:            }
                    435:            ports->isenum = 1;
                    436:        } else if (mi->type == AUDIO_MIXER_SET) {
                    437:            ports->index = mi->index;
                    438:            for(i = 0; tbl[i].name; i++) {
                    439:                for(j = 0; j < mi->un.s.num_mem; j++) {
                    440:                    if (strcmp(mi->un.s.member[j].label.name,
                    441:                            tbl[i].name) == 0) {
                    442:                        ports->aumask[ports->nports] = tbl[i].mask;
                    443:                        ports->misel [ports->nports] = mi->un.s.member[j].mask;
                    444:                        ports->miport[ports->nports++] =
                    445:                                au_portof(sc, mi->un.s.member[j].label.name);
                    446:                        ports->allports |= tbl[i].mask;
                    447:                    }
                    448:                }
                    449:            }
                    450:        }
                    451: }
                    452:
                    453: /*
                    454:  * Called from hardware driver.  This is where the MI audio driver gets
                    455:  * probed/attached to the hardware driver.
                    456:  */
                    457: struct device *
                    458: audio_attach_mi(struct audio_hw_if *ahwp, void *hdlp, struct device *dev)
                    459: {
                    460:        struct audio_attach_args arg;
                    461:
                    462: #ifdef DIAGNOSTIC
                    463:        if (ahwp == NULL) {
                    464:                printf ("audio_attach_mi: NULL\n");
                    465:                return 0;
                    466:        }
                    467: #endif
                    468:
                    469:        arg.type = AUDIODEV_TYPE_AUDIO;
                    470:        arg.hwif = ahwp;
                    471:        arg.hdl = hdlp;
                    472:        return config_found(dev, &arg, audioprint);
                    473: }
                    474:
                    475: #if NAUDIO > 0
                    476: int
                    477: audioprint(void *aux, const char *pnp)
                    478: {
                    479:        struct audio_attach_args *arg = aux;
                    480:        const char *type;
                    481:
                    482:        if (pnp != NULL) {
                    483:                switch (arg->type) {
                    484:                case AUDIODEV_TYPE_AUDIO:
                    485:                        type = "audio";
                    486:                        break;
                    487:                case AUDIODEV_TYPE_OPL:
                    488:                        type = "opl";
                    489:                        break;
                    490:                case AUDIODEV_TYPE_MPU:
                    491:                        type = "mpu";
                    492:                        break;
                    493:                default:
                    494:                        panic("audioprint: unknown type %d", arg->type);
                    495:                }
                    496:                printf("%s at %s", type, pnp);
                    497:        }
                    498:        return (UNCONF);
                    499: }
                    500:
                    501: #endif /* NAUDIO > 0 */
                    502:
                    503: #ifdef AUDIO_DEBUG
                    504: void   audio_printsc(struct audio_softc *);
                    505: void   audio_print_params(char *, struct audio_params *);
                    506:
                    507: void
                    508: audio_printsc(struct audio_softc *sc)
                    509: {
                    510:        printf("hwhandle %p hw_if %p ", sc->hw_hdl, sc->hw_if);
                    511:        printf("open 0x%x mode 0x%x\n", sc->sc_open, sc->sc_mode);
                    512:        printf("rchan 0x%x wchan 0x%x ", sc->sc_rchan, sc->sc_wchan);
                    513:        printf("rring used 0x%x pring used=%d\n", sc->sc_rr.used, sc->sc_pr.used);
                    514:        printf("rbus 0x%x pbus 0x%x ", sc->sc_rbus, sc->sc_pbus);
                    515:        printf("blksize %d", sc->sc_pr.blksize);
                    516:        printf("hiwat %d lowat %d\n", sc->sc_pr.usedhigh, sc->sc_pr.usedlow);
                    517: }
                    518:
                    519: void
                    520: audio_print_params(char *s, struct audio_params *p)
                    521: {
                    522:        printf("audio: %s sr=%ld, enc=%d, chan=%d, prec=%d\n", s,
                    523:            p->sample_rate, p->encoding, p->channels, p->precision);
                    524: }
                    525: #endif
                    526:
                    527: int
                    528: audio_alloc_ring(struct audio_softc *sc, struct audio_ringbuffer *r,
                    529:     int direction, int bufsize)
                    530: {
                    531:        struct audio_hw_if *hw = sc->hw_if;
                    532:        void *hdl = sc->hw_hdl;
                    533:        /*
                    534:         * Alloc DMA play and record buffers
                    535:         */
                    536:        if (bufsize < AUMINBUF)
                    537:                bufsize = AUMINBUF;
                    538:        ROUNDSIZE(bufsize);
                    539:        if (hw->round_buffersize)
                    540:                bufsize = hw->round_buffersize(hdl, direction, bufsize);
                    541:        r->bufsize = bufsize;
                    542:        if (hw->allocm)
                    543:                r->start = hw->allocm(hdl, direction, r->bufsize, M_DEVBUF,
                    544:                    M_WAITOK);
                    545:        else
                    546:                r->start = malloc(bufsize, M_DEVBUF, M_WAITOK);
                    547:        if (r->start == 0)
                    548:                return ENOMEM;
                    549:        return 0;
                    550: }
                    551:
                    552: void
                    553: audio_free_ring(struct audio_softc *sc, struct audio_ringbuffer *r)
                    554: {
                    555:        if (sc->hw_if->freem) {
                    556:                sc->hw_if->freem(sc->hw_hdl, r->start, M_DEVBUF);
                    557:        } else {
                    558:                free(r->start, M_DEVBUF);
                    559:        }
                    560: }
                    561:
                    562: int
                    563: audioopen(dev_t dev, int flags, int ifmt, struct proc *p)
                    564: {
                    565:        int unit = AUDIOUNIT(dev);
                    566:        struct audio_softc *sc;
                    567:        int error;
                    568:
                    569:        if (unit >= audio_cd.cd_ndevs ||
                    570:            (sc = audio_cd.cd_devs[unit]) == NULL)
                    571:                return ENXIO;
                    572:
                    573:        if (sc->sc_dying)
                    574:                return (EIO);
                    575:
                    576:        if (!sc->hw_if)
                    577:                return (ENXIO);
                    578:
                    579:        sc->sc_refcnt ++;
                    580:        switch (AUDIODEV(dev)) {
                    581:        case SOUND_DEVICE:
                    582:        case AUDIO_DEVICE:
                    583:        case AUDIOCTL_DEVICE:
                    584:                error = audio_open(dev, sc, flags, ifmt, p);
                    585:                break;
                    586:        case MIXER_DEVICE:
                    587:                error = mixer_open(dev, sc, flags, ifmt, p);
                    588:                break;
                    589:        default:
                    590:                error = ENXIO;
                    591:                break;
                    592:        }
                    593:
                    594:        if (--sc->sc_refcnt < 0)
                    595:                wakeup(&sc->sc_refcnt);
                    596:
                    597:        return (error);
                    598: }
                    599:
                    600: int
                    601: audioclose(dev_t dev, int flags, int ifmt, struct proc *p)
                    602: {
                    603:
                    604:        switch (AUDIODEV(dev)) {
                    605:        case SOUND_DEVICE:
                    606:        case AUDIO_DEVICE:
                    607:                return (audio_close(dev, flags, ifmt, p));
                    608:        case MIXER_DEVICE:
                    609:                return (mixer_close(dev, flags, ifmt, p));
                    610:        case AUDIOCTL_DEVICE:
                    611:                return 0;
                    612:        default:
                    613:                return (ENXIO);
                    614:        }
                    615: }
                    616:
                    617: int
                    618: audioread(dev_t dev, struct uio *uio, int ioflag)
                    619: {
                    620:        int unit = AUDIOUNIT(dev);
                    621:        struct audio_softc *sc;
                    622:        int error;
                    623:
                    624:        if (unit >= audio_cd.cd_ndevs ||
                    625:            (sc = audio_cd.cd_devs[unit]) == NULL)
                    626:                return ENXIO;
                    627:
                    628:        if (sc->sc_dying)
                    629:                return (EIO);
                    630:
                    631:        sc->sc_refcnt ++;
                    632:        switch (AUDIODEV(dev)) {
                    633:        case SOUND_DEVICE:
                    634:        case AUDIO_DEVICE:
                    635:                error = audio_read(dev, uio, ioflag);
                    636:                break;
                    637:        case AUDIOCTL_DEVICE:
                    638:        case MIXER_DEVICE:
                    639:                error = ENODEV;
                    640:                break;
                    641:        default:
                    642:                error = ENXIO;
                    643:                break;
                    644:        }
                    645:
                    646:        if (--sc->sc_refcnt < 0)
                    647:                wakeup(&sc->sc_refcnt);
                    648:        return (error);
                    649: }
                    650:
                    651: int
                    652: audiowrite(dev_t dev, struct uio *uio, int ioflag)
                    653: {
                    654:        int unit = AUDIOUNIT(dev);
                    655:        struct audio_softc *sc;
                    656:        int error;
                    657:
                    658:        if (unit >= audio_cd.cd_ndevs ||
                    659:            (sc = audio_cd.cd_devs[unit]) == NULL)
                    660:                return ENXIO;
                    661:
                    662:        if (sc->sc_dying)
                    663:                return (EIO);
                    664:
                    665:        sc->sc_refcnt ++;
                    666:        switch (AUDIODEV(dev)) {
                    667:        case SOUND_DEVICE:
                    668:        case AUDIO_DEVICE:
                    669:                error = audio_write(dev, uio, ioflag);
                    670:                break;
                    671:        case AUDIOCTL_DEVICE:
                    672:        case MIXER_DEVICE:
                    673:                error = ENODEV;
                    674:                break;
                    675:        default:
                    676:                error = ENXIO;
                    677:                break;
                    678:        }
                    679:
                    680:        if (--sc->sc_refcnt < 0)
                    681:                wakeup(&sc->sc_refcnt);
                    682:        return (error);
                    683: }
                    684:
                    685: int
                    686: audioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
                    687: {
                    688:        int unit = AUDIOUNIT(dev);
                    689:        struct audio_softc *sc;
                    690:        int error;
                    691:
                    692:        if (unit >= audio_cd.cd_ndevs ||
                    693:            (sc = audio_cd.cd_devs[unit]) == NULL)
                    694:                return ENXIO;
                    695:
                    696:        if (sc->sc_dying)
                    697:                return (EIO);
                    698:
                    699:        sc->sc_refcnt ++;
                    700:        switch (AUDIODEV(dev)) {
                    701:        case SOUND_DEVICE:
                    702:        case AUDIO_DEVICE:
                    703:        case AUDIOCTL_DEVICE:
                    704:                error = audio_ioctl(dev, cmd, addr, flag, p);
                    705:                break;
                    706:        case MIXER_DEVICE:
                    707:                error = mixer_ioctl(dev, cmd, addr, flag, p);
                    708:                break;
                    709:        default:
                    710:                error = ENXIO;
                    711:                break;
                    712:        }
                    713:
                    714:        if (--sc->sc_refcnt < 0)
                    715:                wakeup(&sc->sc_refcnt);
                    716:        return (error);
                    717: }
                    718:
                    719: int
                    720: audiopoll(dev_t dev, int events, struct proc *p)
                    721: {
                    722:        int unit = AUDIOUNIT(dev);
                    723:        struct audio_softc *sc;
                    724:        int error;
                    725:
                    726:        if (unit >= audio_cd.cd_ndevs ||
                    727:            (sc = audio_cd.cd_devs[unit]) == NULL)
                    728:                return POLLERR;
                    729:
                    730:        if (sc->sc_dying)
                    731:                return POLLERR;
                    732:
                    733:        sc->sc_refcnt ++;
                    734:        switch (AUDIODEV(dev)) {
                    735:        case SOUND_DEVICE:
                    736:        case AUDIO_DEVICE:
                    737:                error = audio_poll(dev, events, p);
                    738:                break;
                    739:        case AUDIOCTL_DEVICE:
                    740:        case MIXER_DEVICE:
                    741:                error = 0;
                    742:                break;
                    743:        default:
                    744:                error = 0;
                    745:                break;
                    746:        }
                    747:
                    748:        if (--sc->sc_refcnt < 0)
                    749:                wakeup(&sc->sc_refcnt);
                    750:        return (error);
                    751: }
                    752:
                    753: paddr_t
                    754: audiommap(dev_t dev, off_t off, int prot)
                    755: {
                    756:        int unit = AUDIOUNIT(dev);
                    757:        struct audio_softc *sc;
                    758:        int ret;
                    759:
                    760:        if (unit >= audio_cd.cd_ndevs ||
                    761:            (sc = audio_cd.cd_devs[unit]) == NULL)
                    762:                return (-1);
                    763:
                    764:        if (sc->sc_dying)
                    765:                return (-1);
                    766:
                    767:        sc->sc_refcnt ++;
                    768:        switch (AUDIODEV(dev)) {
                    769:        case SOUND_DEVICE:
                    770:        case AUDIO_DEVICE:
                    771:                ret = audio_mmap(dev, off, prot);
                    772:                break;
                    773:        case AUDIOCTL_DEVICE:
                    774:        case MIXER_DEVICE:
                    775:                ret = -1;
                    776:                break;
                    777:        default:
                    778:                ret = -1;
                    779:                break;
                    780:        }
                    781:
                    782:        if (--sc->sc_refcnt < 0)
                    783:                wakeup(&sc->sc_refcnt);
                    784:        return (ret);
                    785: }
                    786:
                    787: /*
                    788:  * Audio driver
                    789:  */
                    790: void
                    791: audio_init_ringbuffer(struct audio_ringbuffer *rp)
                    792: {
                    793:        int nblks;
                    794:        int blksize = rp->blksize;
                    795:
                    796:        if (blksize < AUMINBLK)
                    797:                blksize = AUMINBLK;
                    798:        nblks = rp->bufsize / blksize;
                    799:        if (nblks < AUMINNOBLK) {
                    800:                nblks = AUMINNOBLK;
                    801:                blksize = rp->bufsize / nblks;
                    802:                ROUNDSIZE(blksize);
                    803:        }
                    804:        DPRINTF(("audio_init_ringbuffer: blksize=%d\n", blksize));
                    805:        rp->blksize = blksize;
                    806:        rp->maxblks = nblks;
                    807:        rp->used = 0;
                    808:        rp->end = rp->start + nblks * blksize;
                    809:        rp->inp = rp->outp = rp->start;
                    810:        rp->stamp = 0;
                    811:        rp->stamp_last = 0;
                    812:        rp->drops = 0;
                    813:        rp->pdrops = 0;
                    814:        rp->copying = 0;
                    815:        rp->needfill = 0;
                    816:        rp->mmapped = 0;
                    817: }
                    818:
                    819: int
                    820: audio_initbufs(struct audio_softc *sc)
                    821: {
                    822:        struct audio_hw_if *hw = sc->hw_if;
                    823:        int error;
                    824:
                    825:        DPRINTF(("audio_initbufs: mode=0x%x\n", sc->sc_mode));
                    826:        audio_init_ringbuffer(&sc->sc_rr);
                    827:        if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) {
                    828:                error = hw->init_input(sc->hw_hdl, sc->sc_rr.start,
                    829:                    sc->sc_rr.end - sc->sc_rr.start);
                    830:                if (error)
                    831:                        return error;
                    832:        }
                    833:
                    834:        audio_init_ringbuffer(&sc->sc_pr);
                    835:        sc->sc_sil_count = 0;
                    836:        if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) {
                    837:                error = hw->init_output(sc->hw_hdl, sc->sc_pr.start,
                    838:                                        sc->sc_pr.end - sc->sc_pr.start);
                    839:                if (error)
                    840:                        return error;
                    841:        }
                    842:
                    843: #ifdef AUDIO_INTR_TIME
                    844:        sc->sc_pnintr = 0;
                    845:        sc->sc_pblktime = (u_long)(
                    846:            (u_long)sc->sc_pr.blksize * 100000 /
                    847:            (u_long)(sc->sc_pparams.precision / NBBY *
                    848:                sc->sc_pparams.channels *
                    849:                sc->sc_pparams.sample_rate)) * 10;
                    850:        DPRINTF(("audio: play blktime = %lu for %d\n",
                    851:                 sc->sc_pblktime, sc->sc_pr.blksize));
                    852:        sc->sc_rnintr = 0;
                    853:        sc->sc_rblktime = (u_long)(
                    854:            (u_long)sc->sc_rr.blksize * 100000 /
                    855:            (u_long)(sc->sc_rparams.precision / NBBY *
                    856:                sc->sc_rparams.channels *
                    857:                sc->sc_rparams.sample_rate)) * 10;
                    858:        DPRINTF(("audio: record blktime = %lu for %d\n",
                    859:                 sc->sc_rblktime, sc->sc_rr.blksize));
                    860: #endif
                    861:
                    862:        return 0;
                    863: }
                    864:
                    865: void
                    866: audio_calcwater(struct audio_softc *sc)
                    867: {
                    868:        sc->sc_pr.usedhigh = sc->sc_pr.end - sc->sc_pr.start;
                    869:        sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4; /* set lowater at 75% */
                    870:        if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh)
                    871:                sc->sc_pr.usedlow -= sc->sc_pr.blksize;
                    872:        sc->sc_rr.usedhigh = sc->sc_rr.end - sc->sc_rr.start - sc->sc_rr.blksize;
                    873:        sc->sc_rr.usedlow = 0;
                    874: }
                    875:
                    876: static __inline int
                    877: audio_sleep_timo(int *chan, char *label, int timo)
                    878: {
                    879:        int st;
                    880:
                    881:        if (!label)
                    882:                label = "audio";
                    883:
                    884:        DPRINTFN(3, ("audio_sleep_timo: chan=%p, label=%s, timo=%d\n",
                    885:            chan, label, timo));
                    886:        *chan = 1;
                    887:        st = tsleep(chan, PWAIT | PCATCH, label, timo);
                    888:        *chan = 0;
                    889: #ifdef AUDIO_DEBUG
                    890:        if (st != 0)
                    891:            printf("audio_sleep: woke up st=%d\n", st);
                    892: #endif
                    893:        return (st);
                    894: }
                    895:
                    896: static __inline int
                    897: audio_sleep(int *chan, char *label)
                    898: {
                    899:        return audio_sleep_timo(chan, label, 0);
                    900: }
                    901:
                    902: /* call at splaudio() */
                    903: static __inline void
                    904: audio_wakeup(int *chan)
                    905: {
                    906:        DPRINTFN(3, ("audio_wakeup: chan=%p, *chan=%d\n", chan, *chan));
                    907:        if (*chan) {
                    908:                wakeup(chan);
                    909:                *chan = 0;
                    910:        }
                    911: }
                    912:
                    913: int
                    914: audio_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
                    915:     struct proc *p)
                    916: {
                    917:        int error;
                    918:        int mode;
                    919:        struct audio_info ai;
                    920:
                    921:        DPRINTF(("audio_open: dev=0x%x flags=0x%x sc=%p hdl=%p\n", dev, flags, sc, sc->hw_hdl));
                    922:
                    923:        if (ISDEVAUDIOCTL(dev))
                    924:                return 0;
                    925:
                    926:        if ((sc->sc_open & (AUOPEN_READ|AUOPEN_WRITE)) != 0)
                    927:                return (EBUSY);
                    928:
                    929:        error = sc->hw_if->open(sc->hw_hdl, flags);
                    930:        if (error)
                    931:                return (error);
                    932:
                    933:        sc->sc_async_audio = 0;
                    934:        sc->sc_rchan = 0;
                    935:        sc->sc_wchan = 0;
                    936:        sc->sc_blkset = 0; /* Block sizes not set yet */
                    937:        sc->sc_sil_count = 0;
                    938:        sc->sc_rbus = 0;
                    939:        sc->sc_pbus = 0;
                    940:        sc->sc_eof = 0;
                    941:        sc->sc_playdrop = 0;
                    942:
                    943:        sc->sc_full_duplex = 0;
                    944: /* doesn't always work right on SB.
                    945:                (flags & (FWRITE|FREAD)) == (FWRITE|FREAD) &&
                    946:                (sc->hw_if->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX);
                    947: */
                    948:
                    949:        mode = 0;
                    950:        if (flags & FREAD) {
                    951:                sc->sc_open |= AUOPEN_READ;
                    952:                mode |= AUMODE_RECORD;
                    953:        }
                    954:        if (flags & FWRITE) {
                    955:                sc->sc_open |= AUOPEN_WRITE;
                    956:                mode |= AUMODE_PLAY | AUMODE_PLAY_ALL;
                    957:        }
                    958:
                    959:        /*
                    960:         * Multiplex device: /dev/audio (MU-Law) and /dev/sound (linear)
                    961:         * The /dev/audio is always (re)set to 8-bit MU-Law mono
                    962:         * For the other devices, you get what they were last set to.
                    963:         */
                    964:        if (ISDEVAUDIO(dev)) {
                    965:                /* /dev/audio */
                    966:                sc->sc_rparams = audio_default;
                    967:                sc->sc_pparams = audio_default;
                    968:        }
                    969: #ifdef DIAGNOSTIC
                    970:        /*
                    971:         * Sample rate and precision are supposed to be set to proper
                    972:         * default values by the hardware driver, so that it may give
                    973:         * us these values.
                    974:         */
                    975:        if (sc->sc_rparams.precision == 0 || sc->sc_pparams.precision == 0) {
                    976:                printf("audio_open: 0 precision\n");
                    977:                error = EINVAL;
                    978:                goto bad;
                    979:        }
                    980: #endif
                    981:
                    982:        AUDIO_INITINFO(&ai);
                    983:        ai.record.sample_rate = sc->sc_rparams.sample_rate;
                    984:        ai.record.encoding    = sc->sc_rparams.encoding;
                    985:        ai.record.channels    = sc->sc_rparams.channels;
                    986:        ai.record.precision   = sc->sc_rparams.precision;
                    987:        ai.record.pause       = 0;
                    988:        ai.play.sample_rate   = sc->sc_pparams.sample_rate;
                    989:        ai.play.encoding       = sc->sc_pparams.encoding;
                    990:        ai.play.channels      = sc->sc_pparams.channels;
                    991:        ai.play.precision     = sc->sc_pparams.precision;
                    992:        ai.play.pause         = 0;
                    993:        ai.mode               = mode;
                    994:        sc->sc_pr.blksize = sc->sc_rr.blksize = 0; /* force recalculation */
                    995:        error = audiosetinfo(sc, &ai);
                    996:        if (error)
                    997:                goto bad;
                    998:
                    999:        DPRINTF(("audio_open: done sc_mode = 0x%x\n", sc->sc_mode));
                   1000:
                   1001:        return 0;
                   1002:
                   1003: bad:
                   1004:        sc->hw_if->close(sc->hw_hdl);
                   1005:        sc->sc_open = 0;
                   1006:        sc->sc_mode = 0;
                   1007:        sc->sc_full_duplex = 0;
                   1008:        return error;
                   1009: }
                   1010:
                   1011: /*
                   1012:  * Must be called from task context.
                   1013:  */
                   1014: void
                   1015: audio_init_record(struct audio_softc *sc)
                   1016: {
                   1017:        int s = splaudio();
                   1018:
                   1019:        if (sc->hw_if->speaker_ctl &&
                   1020:            (!sc->sc_full_duplex || (sc->sc_mode & AUMODE_PLAY) == 0))
                   1021:                sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_OFF);
                   1022:        splx(s);
                   1023: }
                   1024:
                   1025: /*
                   1026:  * Must be called from task context.
                   1027:  */
                   1028: void
                   1029: audio_init_play(struct audio_softc *sc)
                   1030: {
                   1031:        int s = splaudio();
                   1032:
                   1033:        sc->sc_wstamp = sc->sc_pr.stamp;
                   1034:        if (sc->hw_if->speaker_ctl)
                   1035:                sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_ON);
                   1036:        splx(s);
                   1037: }
                   1038:
                   1039: int
                   1040: audio_drain(struct audio_softc *sc)
                   1041: {
                   1042:        int error, drops;
                   1043:        struct audio_ringbuffer *cb = &sc->sc_pr;
                   1044:        int s;
                   1045:
                   1046:        DPRINTF(("audio_drain: enter busy=%d used=%d\n",
                   1047:            sc->sc_pbus, sc->sc_pr.used));
                   1048:        if (sc->sc_pr.mmapped || sc->sc_pr.used <= 0)
                   1049:                return 0;
                   1050:        if (!sc->sc_pbus) {
                   1051:                /* We've never started playing, probably because the
                   1052:                 * block was too short.  Pad it and start now.
                   1053:                 */
                   1054:                int cc;
                   1055:                u_char *inp = cb->inp;
                   1056:
                   1057:                cc = cb->blksize - (inp - cb->start) % cb->blksize;
                   1058:                if (sc->sc_pparams.sw_code) {
                   1059:                        int ncc = cc / sc->sc_pparams.factor;
                   1060:                        audio_fill_silence(&sc->sc_pparams, inp, ncc);
                   1061:                        sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
                   1062:                } else
                   1063:                        audio_fill_silence(&sc->sc_pparams, inp, cc);
                   1064:                inp += cc;
                   1065:                if (inp >= cb->end)
                   1066:                        inp = cb->start;
                   1067:                s = splaudio();
                   1068:                cb->used += cc;
                   1069:                cb->inp = inp;
                   1070:                error = audiostartp(sc);
                   1071:                splx(s);
                   1072:                if (error)
                   1073:                        return error;
                   1074:        }
                   1075:        /*
                   1076:         * Play until a silence block has been played, then we
                   1077:         * know all has been drained.
                   1078:         * XXX This should be done some other way to avoid
                   1079:         * playing silence.
                   1080:         */
                   1081: #ifdef DIAGNOSTIC
                   1082:        if (cb->copying) {
                   1083:                printf("audio_drain: copying in progress!?!\n");
                   1084:                cb->copying = 0;
                   1085:        }
                   1086: #endif
                   1087:        drops = cb->drops;
                   1088:        error = 0;
                   1089:        s = splaudio();
                   1090:        while (cb->drops == drops && !error) {
                   1091:                DPRINTF(("audio_drain: used=%d, drops=%ld\n", sc->sc_pr.used, cb->drops));
                   1092:                /*
                   1093:                 * When the process is exiting, it ignores all signals and
                   1094:                 * we can't interrupt this sleep, so we set a timeout just in case.
                   1095:                 */
                   1096:                error = audio_sleep_timo(&sc->sc_wchan, "aud_dr", 30*hz);
                   1097:                if (sc->sc_dying)
                   1098:                        error = EIO;
                   1099:        }
                   1100:        splx(s);
                   1101:        return error;
                   1102: }
                   1103:
                   1104: /*
                   1105:  * Close an audio chip.
                   1106:  */
                   1107: /* ARGSUSED */
                   1108: int
                   1109: audio_close(dev_t dev, int flags, int ifmt, struct proc *p)
                   1110: {
                   1111:        int unit = AUDIOUNIT(dev);
                   1112:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   1113:        struct audio_hw_if *hw = sc->hw_if;
                   1114:        int s;
                   1115:
                   1116:        DPRINTF(("audio_close: unit=%d flags=0x%x\n", unit, flags));
                   1117:
                   1118:        s = splaudio();
                   1119:        /* Stop recording. */
                   1120:        if ((flags & FREAD) && sc->sc_rbus) {
                   1121:                /*
                   1122:                 * XXX Some drivers (e.g. SB) use the same routine
                   1123:                 * to halt input and output so don't halt input if
                   1124:                 * in full duplex mode.  These drivers should be fixed.
                   1125:                 */
                   1126:                if (!sc->sc_full_duplex || sc->hw_if->halt_input != sc->hw_if->halt_output)
                   1127:                        sc->hw_if->halt_input(sc->hw_hdl);
                   1128:                sc->sc_rbus = 0;
                   1129:        }
                   1130:        /*
                   1131:         * Block until output drains, but allow ^C interrupt.
                   1132:         */
                   1133:        sc->sc_pr.usedlow = sc->sc_pr.blksize;  /* avoid excessive wakeups */
                   1134:        /*
                   1135:         * If there is pending output, let it drain (unless
                   1136:         * the output is paused).
                   1137:         */
                   1138:        if ((flags & FWRITE) && sc->sc_pbus) {
                   1139:                if (!sc->sc_pr.pause && !audio_drain(sc) && hw->drain)
                   1140:                        (void)hw->drain(sc->hw_hdl);
                   1141:                sc->hw_if->halt_output(sc->hw_hdl);
                   1142:                sc->sc_pbus = 0;
                   1143:        }
                   1144:
                   1145:        hw->close(sc->hw_hdl);
                   1146:
                   1147:        /*
                   1148:         * If flags has neither read nor write then reset both
                   1149:         * directions. Encountered when someone runs revoke(2).
                   1150:         */
                   1151:
                   1152:        if ((flags & FREAD) || ((flags & (FREAD|FWRITE)) == 0)) {
                   1153:                sc->sc_open &= ~AUOPEN_READ;
                   1154:                sc->sc_mode &= ~AUMODE_RECORD;
                   1155:        }
                   1156:        if ((flags & FWRITE) || ((flags & (FREAD|FWRITE)) == 0)) {
                   1157:                sc->sc_open &= ~AUOPEN_WRITE;
                   1158:                sc->sc_mode &= ~(AUMODE_PLAY|AUMODE_PLAY_ALL);
                   1159:        }
                   1160:
                   1161:        sc->sc_async_audio = 0;
                   1162:        sc->sc_full_duplex = 0;
                   1163:        splx(s);
                   1164:        DPRINTF(("audio_close: done\n"));
                   1165:
                   1166:        return (0);
                   1167: }
                   1168:
                   1169: int
                   1170: audio_read(dev_t dev, struct uio *uio, int ioflag)
                   1171: {
                   1172:        int unit = AUDIOUNIT(dev);
                   1173:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   1174:        struct audio_ringbuffer *cb = &sc->sc_rr;
                   1175:        u_char *outp;
                   1176:        int error, s, used, cc, n;
                   1177:
                   1178:        if (cb->mmapped)
                   1179:                return EINVAL;
                   1180:
                   1181:        DPRINTFN(1,("audio_read: cc=%d mode=%d\n",
                   1182:            uio->uio_resid, sc->sc_mode));
                   1183:
                   1184:        error = 0;
                   1185:        /*
                   1186:         * If hardware is half-duplex and currently playing, return
                   1187:         * silence blocks based on the number of blocks we have output.
                   1188:         */
                   1189:        if (!sc->sc_full_duplex &&
                   1190:            (sc->sc_mode & AUMODE_PLAY)) {
                   1191:                while (uio->uio_resid > 0 && !error) {
                   1192:                        s = splaudio();
                   1193:                        for(;;) {
                   1194:                                cc = sc->sc_pr.stamp - sc->sc_wstamp;
                   1195:                                if (cc > 0)
                   1196:                                        break;
                   1197:                                DPRINTF(("audio_read: stamp=%lu, wstamp=%lu\n",
                   1198:                                         sc->sc_pr.stamp, sc->sc_wstamp));
                   1199:                                if (ioflag & IO_NDELAY) {
                   1200:                                        splx(s);
                   1201:                                        return EWOULDBLOCK;
                   1202:                                }
                   1203:                                error = audio_sleep(&sc->sc_rchan, "aud_hr");
                   1204:                                if (sc->sc_dying)
                   1205:                                        error = EIO;
                   1206:                                if (error) {
                   1207:                                        splx(s);
                   1208:                                        return error;
                   1209:                                }
                   1210:                        }
                   1211:                        splx(s);
                   1212:
                   1213:                        if (uio->uio_resid < cc / sc->sc_rparams.factor)
                   1214:                                cc = uio->uio_resid * sc->sc_rparams.factor;
                   1215:                        DPRINTFN(1, ("audio_read: reading in write mode, cc=%d\n", cc));
                   1216:                        error = audio_silence_copyout(sc,
                   1217:                            cc / sc->sc_rparams.factor, uio);
                   1218:                        sc->sc_wstamp += cc;
                   1219:                }
                   1220:                return (error);
                   1221:        }
                   1222:        while (uio->uio_resid > 0 && !error) {
                   1223:                s = splaudio();
                   1224:                while (cb->used <= 0) {
                   1225:                        if (!sc->sc_rbus && !sc->sc_rr.pause) {
                   1226:                                error = audiostartr(sc);
                   1227:                                if (error) {
                   1228:                                        splx(s);
                   1229:                                        return error;
                   1230:                                }
                   1231:                        }
                   1232:                        if (ioflag & IO_NDELAY) {
                   1233:                                splx(s);
                   1234:                                return (EWOULDBLOCK);
                   1235:                        }
                   1236:                        DPRINTFN(2, ("audio_read: sleep used=%d\n", cb->used));
                   1237:                        error = audio_sleep(&sc->sc_rchan, "aud_rd");
                   1238:                        if (sc->sc_dying)
                   1239:                                error = EIO;
                   1240:                        if (error) {
                   1241:                                splx(s);
                   1242:                                return error;
                   1243:                        }
                   1244:                }
                   1245:                used = cb->used;
                   1246:                outp = cb->outp;
                   1247:                cb->copying = 1;
                   1248:                splx(s);
                   1249:                cc = used - cb->usedlow; /* maximum to read */
                   1250:                n = cb->end - outp;
                   1251:                if (n < cc)
                   1252:                        cc = n; /* don't read beyond end of buffer */
                   1253:
                   1254:                 /* and no more than we want */
                   1255:                if (uio->uio_resid < cc / sc->sc_rparams.factor)
                   1256:                        cc = uio->uio_resid * sc->sc_rparams.factor;
                   1257:
                   1258:                if (sc->sc_rparams.sw_code)
                   1259:                        sc->sc_rparams.sw_code(sc->hw_hdl, outp, cc);
                   1260:                DPRINTFN(1,("audio_read: outp=%p, cc=%d\n", outp, cc));
                   1261:                error = uiomove(outp, cc / sc->sc_rparams.factor, uio);
                   1262:                used -= cc;
                   1263:                outp += cc;
                   1264:                if (outp >= cb->end)
                   1265:                        outp = cb->start;
                   1266:                s = splaudio();
                   1267:                cb->outp = outp;
                   1268:                cb->used = used;
                   1269:                cb->copying = 0;
                   1270:                splx(s);
                   1271:        }
                   1272:        return (error);
                   1273: }
                   1274:
                   1275: void
                   1276: audio_clear(struct audio_softc *sc)
                   1277: {
                   1278:        int s = splaudio();
                   1279:
                   1280:        if (sc->sc_rbus) {
                   1281:                audio_wakeup(&sc->sc_rchan);
                   1282:                sc->hw_if->halt_input(sc->hw_hdl);
                   1283:                sc->sc_rbus = 0;
                   1284:        }
                   1285:        if (sc->sc_pbus) {
                   1286:                audio_wakeup(&sc->sc_wchan);
                   1287:                sc->hw_if->halt_output(sc->hw_hdl);
                   1288:                sc->sc_pbus = 0;
                   1289:        }
                   1290:        splx(s);
                   1291: }
                   1292:
                   1293: void
                   1294: audio_calc_blksize(struct audio_softc *sc, int mode)
                   1295: {
                   1296:        struct audio_hw_if *hw = sc->hw_if;
                   1297:        struct audio_params *parm;
                   1298:        struct audio_ringbuffer *rb;
                   1299:        int bs;
                   1300:
                   1301:        if (sc->sc_blkset)
                   1302:                return;
                   1303:
                   1304:        if (mode == AUMODE_PLAY) {
                   1305:                parm = &sc->sc_pparams;
                   1306:                rb = &sc->sc_pr;
                   1307:        } else {
                   1308:                parm = &sc->sc_rparams;
                   1309:                rb = &sc->sc_rr;
                   1310:        }
                   1311:
                   1312:        bs = parm->sample_rate * audio_blk_ms / 1000 *
                   1313:             parm->channels * parm->precision / NBBY *
                   1314:             parm->factor;
                   1315:        ROUNDSIZE(bs);
                   1316:        if (hw->round_blocksize)
                   1317:                bs = hw->round_blocksize(sc->hw_hdl, bs);
                   1318:        rb->blksize = bs;
                   1319:
                   1320:        DPRINTF(("audio_calc_blksize: %s blksize=%d\n",
                   1321:                 mode == AUMODE_PLAY ? "play" : "record", bs));
                   1322: }
                   1323:
                   1324: void
                   1325: audio_fill_silence(struct audio_params *params, u_char *p, int n)
                   1326: {
                   1327:        u_char auzero0, auzero1 = 0; /* initialize to please gcc */
                   1328:        int nfill = 1;
                   1329:
                   1330:        switch (params->encoding) {
                   1331:        case AUDIO_ENCODING_ULAW:
                   1332:                auzero0 = 0x7f;
                   1333:                break;
                   1334:        case AUDIO_ENCODING_ALAW:
                   1335:                auzero0 = 0x55;
                   1336:                break;
                   1337:        case AUDIO_ENCODING_MPEG_L1_STREAM:
                   1338:        case AUDIO_ENCODING_MPEG_L1_PACKETS:
                   1339:        case AUDIO_ENCODING_MPEG_L1_SYSTEM:
                   1340:        case AUDIO_ENCODING_MPEG_L2_STREAM:
                   1341:        case AUDIO_ENCODING_MPEG_L2_PACKETS:
                   1342:        case AUDIO_ENCODING_MPEG_L2_SYSTEM:
                   1343:        case AUDIO_ENCODING_ADPCM: /* is this right XXX */
                   1344:        case AUDIO_ENCODING_SLINEAR_LE:
                   1345:        case AUDIO_ENCODING_SLINEAR_BE:
                   1346:                auzero0 = 0;    /* fortunately this works for both 8 and 16 bits */
                   1347:                break;
                   1348:        case AUDIO_ENCODING_ULINEAR_LE:
                   1349:        case AUDIO_ENCODING_ULINEAR_BE:
                   1350:                if (params->precision == 16) {
                   1351:                        nfill = 2;
                   1352:                        if (params->encoding == AUDIO_ENCODING_ULINEAR_LE) {
                   1353:                                auzero0 = 0;
                   1354:                                auzero1 = 0x80;
                   1355:                        } else {
                   1356:                                auzero0 = 0x80;
                   1357:                                auzero1 = 0;
                   1358:                        }
                   1359:                } else
                   1360:                        auzero0 = 0x80;
                   1361:                break;
                   1362:        default:
                   1363:                DPRINTF(("audio: bad encoding %d\n", params->encoding));
                   1364:                auzero0 = 0;
                   1365:                break;
                   1366:        }
                   1367:        if (nfill == 1) {
                   1368:                while (--n >= 0)
                   1369:                        *p++ = auzero0; /* XXX memset */
                   1370:        } else /* nfill must be 2 */ {
                   1371:                while (n > 1) {
                   1372:                        *p++ = auzero0;
                   1373:                        *p++ = auzero1;
                   1374:                        n -= 2;
                   1375:                }
                   1376:        }
                   1377: }
                   1378:
                   1379: int
                   1380: audio_silence_copyout(struct audio_softc *sc, int n, struct uio *uio)
                   1381: {
                   1382:        int error;
                   1383:        int k;
                   1384:        u_char zerobuf[128];
                   1385:
                   1386:        audio_fill_silence(&sc->sc_rparams, zerobuf, sizeof zerobuf);
                   1387:
                   1388:        error = 0;
                   1389:        while (n > 0 && uio->uio_resid > 0 && !error) {
                   1390:                k = min(n, min(uio->uio_resid, sizeof zerobuf));
                   1391:                error = uiomove(zerobuf, k, uio);
                   1392:                n -= k;
                   1393:        }
                   1394:        return (error);
                   1395: }
                   1396:
                   1397: int
                   1398: audio_write(dev_t dev, struct uio *uio, int ioflag)
                   1399: {
                   1400:        int unit = AUDIOUNIT(dev);
                   1401:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   1402:        struct audio_ringbuffer *cb = &sc->sc_pr;
                   1403:        u_char *inp, *einp;
                   1404:        int saveerror, error, s, n, cc, used;
                   1405:
                   1406:        DPRINTFN(2, ("audio_write: sc=%p(unit=%d) count=%d used=%d(hi=%d)\n", sc, unit,
                   1407:                 uio->uio_resid, sc->sc_pr.used, sc->sc_pr.usedhigh));
                   1408:
                   1409:        if (cb->mmapped)
                   1410:                return EINVAL;
                   1411:
                   1412:        if (uio->uio_resid == 0) {
                   1413:                sc->sc_eof++;
                   1414:                return 0;
                   1415:        }
                   1416:
                   1417:        /*
                   1418:         * If half-duplex and currently recording, throw away data.
                   1419:         */
                   1420:        if (!sc->sc_full_duplex &&
                   1421:            (sc->sc_mode & AUMODE_RECORD)) {
                   1422:                uio->uio_offset += uio->uio_resid;
                   1423:                uio->uio_resid = 0;
                   1424:                DPRINTF(("audio_write: half-dpx read busy\n"));
                   1425:                return (0);
                   1426:        }
                   1427:
                   1428:        if (!(sc->sc_mode & AUMODE_PLAY_ALL) && sc->sc_playdrop > 0) {
                   1429:                n = min(sc->sc_playdrop, uio->uio_resid * sc->sc_pparams.factor);
                   1430:                DPRINTF(("audio_write: playdrop %d\n", n));
                   1431:                uio->uio_offset += n / sc->sc_pparams.factor;
                   1432:                uio->uio_resid -= n / sc->sc_pparams.factor;
                   1433:                sc->sc_playdrop -= n;
                   1434:                if (uio->uio_resid == 0)
                   1435:                        return 0;
                   1436:        }
                   1437:
                   1438:        DPRINTFN(1, ("audio_write: sr=%ld, enc=%d, prec=%d, chan=%d, sw=%p, fact=%d\n",
                   1439:            sc->sc_pparams.sample_rate, sc->sc_pparams.encoding,
                   1440:            sc->sc_pparams.precision, sc->sc_pparams.channels,
                   1441:            sc->sc_pparams.sw_code, sc->sc_pparams.factor));
                   1442:
                   1443:        error = 0;
                   1444:        while (uio->uio_resid > 0 && !error) {
                   1445:                s = splaudio();
                   1446:                while (cb->used >= cb->usedhigh) {
                   1447:                        DPRINTFN(2, ("audio_write: sleep used=%d lowat=%d hiwat=%d\n",
                   1448:                                 cb->used, cb->usedlow, cb->usedhigh));
                   1449:                        if (ioflag & IO_NDELAY) {
                   1450:                                splx(s);
                   1451:                                return (EWOULDBLOCK);
                   1452:                        }
                   1453:                        error = audio_sleep(&sc->sc_wchan, "aud_wr");
                   1454:                        if (sc->sc_dying)
                   1455:                                error = EIO;
                   1456:                        if (error) {
                   1457:                                splx(s);
                   1458:                                return error;
                   1459:                        }
                   1460:                }
                   1461:                used = cb->used;
                   1462:                inp = cb->inp;
                   1463:                cb->copying = 1;
                   1464:                splx(s);
                   1465:                cc = cb->usedhigh - used;       /* maximum to write */
                   1466:                n = cb->end - inp;
                   1467:                if (sc->sc_pparams.factor != 1) {
                   1468:                        /* Compensate for software coding expansion factor. */
                   1469:                        n /= sc->sc_pparams.factor;
                   1470:                        cc /= sc->sc_pparams.factor;
                   1471:                }
                   1472:                if (n < cc)
                   1473:                        cc = n;                 /* don't write beyond end of buffer */
                   1474:                if (uio->uio_resid < cc)
                   1475:                        cc = uio->uio_resid;    /* and no more than we have */
                   1476:
                   1477: #ifdef DIAGNOSTIC
                   1478:                /*
                   1479:                 * This should never happen since the block size and and
                   1480:                 * block pointers are always nicely aligned.
                   1481:                 */
                   1482:                if (cc == 0) {
                   1483:                        printf("audio_write: cc == 0, swcode=%p, factor=%d\n",
                   1484:                            sc->sc_pparams.sw_code, sc->sc_pparams.factor);
                   1485:                        cb->copying = 0;
                   1486:                        return EINVAL;
                   1487:                }
                   1488: #endif
                   1489:                DPRINTFN(1, ("audio_write: uiomove cc=%d inp=%p, left=%d\n",
                   1490:                    cc, inp, uio->uio_resid));
                   1491:                n = uio->uio_resid;
                   1492:                error = uiomove(inp, cc, uio);
                   1493:                cc = n - uio->uio_resid; /* number of bytes actually moved */
                   1494: #ifdef AUDIO_DEBUG
                   1495:                if (error)
                   1496:                        printf("audio_write:(1) uiomove failed %d; cc=%d inp=%p\n",
                   1497:                            error, cc, inp);
                   1498: #endif
                   1499:                /*
                   1500:                 * Continue even if uiomove() failed because we may have
                   1501:                 * gotten a partial block.
                   1502:                 */
                   1503:
                   1504:                if (sc->sc_pparams.sw_code) {
                   1505:                        sc->sc_pparams.sw_code(sc->hw_hdl, inp, cc);
                   1506:                        /* Adjust count after the expansion. */
                   1507:                        cc *= sc->sc_pparams.factor;
                   1508:                        DPRINTFN(1, ("audio_write: expanded cc=%d\n", cc));
                   1509:                }
                   1510:
                   1511:                einp = cb->inp + cc;
                   1512:                if (einp >= cb->end)
                   1513:                        einp = cb->start;
                   1514:
                   1515:                s = splaudio();
                   1516:                /*
                   1517:                 * This is a very suboptimal way of keeping track of
                   1518:                 * silence in the buffer, but it is simple.
                   1519:                 */
                   1520:                sc->sc_sil_count = 0;
                   1521:
                   1522:                cb->inp = einp;
                   1523:                cb->used += cc;
                   1524:                /* If the interrupt routine wants the last block filled AND
                   1525:                 * the copy did not fill the last block completely it needs to
                   1526:                 * be padded.
                   1527:                 */
                   1528:                if (cb->needfill &&
                   1529:                    (inp  - cb->start) / cb->blksize ==
                   1530:                    (einp - cb->start) / cb->blksize) {
                   1531:                        /* Figure out how many bytes there is to a block boundary. */
                   1532:                        cc = cb->blksize - (einp - cb->start) % cb->blksize;
                   1533:                        DPRINTF(("audio_write: partial fill %d\n", cc));
                   1534:                } else
                   1535:                        cc = 0;
                   1536:                cb->needfill = 0;
                   1537:                cb->copying = 0;
                   1538:                if (!sc->sc_pbus && !cb->pause) {
                   1539:                        saveerror = error;
                   1540:                        error = audiostartp(sc);
                   1541:                        if (saveerror != 0) {
                   1542:                                /* Report the first error that occurred. */
                   1543:                                error = saveerror;
                   1544:                        }
                   1545:                }
                   1546:                splx(s);
                   1547:                if (cc) {
                   1548:                        DPRINTFN(1, ("audio_write: fill %d\n", cc));
                   1549:                        if (sc->sc_pparams.sw_code) {
                   1550:                                int ncc = cc / sc->sc_pparams.factor;
                   1551:                                audio_fill_silence(&sc->sc_pparams, einp, ncc);
                   1552:                                sc->sc_pparams.sw_code(sc->hw_hdl, einp, ncc);
                   1553:                        } else
                   1554:                                audio_fill_silence(&sc->sc_pparams, einp, cc);
                   1555:                }
                   1556:        }
                   1557:        return (error);
                   1558: }
                   1559:
                   1560: int
                   1561: audio_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
                   1562: {
                   1563:        int unit = AUDIOUNIT(dev);
                   1564:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   1565:        struct audio_hw_if *hw = sc->hw_if;
                   1566:        struct audio_offset *ao;
                   1567:        int error = 0, s, offs, fd;
                   1568:        int rbus, pbus;
                   1569:
                   1570:        DPRINTF(("audio_ioctl(%d,'%c',%d)\n",
                   1571:            IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
                   1572:        switch (cmd) {
                   1573:        case FIONBIO:
                   1574:                /* All handled in the upper FS layer. */
                   1575:                break;
                   1576:
                   1577:        case FIOASYNC:
                   1578:                if (*(int *)addr) {
                   1579:                        if (sc->sc_async_audio)
                   1580:                                return (EBUSY);
                   1581:                        sc->sc_async_audio = p;
                   1582:                        DPRINTF(("audio_ioctl: FIOASYNC %p\n", p));
                   1583:                } else
                   1584:                        sc->sc_async_audio = 0;
                   1585:                break;
                   1586:
                   1587:        case AUDIO_FLUSH:
                   1588:                DPRINTF(("AUDIO_FLUSH\n"));
                   1589:                rbus = sc->sc_rbus;
                   1590:                pbus = sc->sc_pbus;
                   1591:                audio_clear(sc);
                   1592:                s = splaudio();
                   1593:                error = audio_initbufs(sc);
                   1594:                if (error) {
                   1595:                        splx(s);
                   1596:                        return error;
                   1597:                }
                   1598:                sc->sc_rr.pause = 0;
                   1599:                sc->sc_pr.pause = 0;
                   1600:                if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_pbus && pbus)
                   1601:                        error = audiostartp(sc);
                   1602:                if (!error &&
                   1603:                    (sc->sc_mode & AUMODE_RECORD) && !sc->sc_rbus && rbus)
                   1604:                        error = audiostartr(sc);
                   1605:                splx(s);
                   1606:                break;
                   1607:
                   1608:        /*
                   1609:         * Number of read (write) samples dropped.  We don't know where or
                   1610:         * when they were dropped.
                   1611:         *
                   1612:         * The audio_ringbuffer->drops count is the number of buffer
                   1613:         * sample size bytes.  Convert it to userland sample size bytes,
                   1614:         * then convert to samples.  There is no easy way to get the
                   1615:         * buffer sample size, but the userland sample size can be
                   1616:         * calculated with userland channels and userland precision.
                   1617:         *
                   1618:         * original formula:
                   1619:         *  sc->sc_rr.drops /
                   1620:         *  sc->sc_rparams.factor /
                   1621:         *  (sc->sc_rparams.channels * (sc->sc_rparams.precision / NBBY))
                   1622:         */
                   1623:        case AUDIO_RERROR:
                   1624:                *(int *)addr = (sc->sc_rr.drops * NBBY) /
                   1625:                    (sc->sc_rparams.factor * sc->sc_rparams.channels *
                   1626:                    sc->sc_rparams.precision);
                   1627:                break;
                   1628:
                   1629:        case AUDIO_PERROR:
                   1630:                *(int *)addr = (sc->sc_pr.drops * NBBY) /
                   1631:                    (sc->sc_pparams.factor * sc->sc_pparams.channels *
                   1632:                    sc->sc_pparams.precision);
                   1633:                break;
                   1634:
                   1635:        /*
                   1636:         * Offsets into buffer.
                   1637:         */
                   1638:        case AUDIO_GETIOFFS:
                   1639:                s = splaudio();
                   1640:                /* figure out where next DMA will start */
                   1641:                ao = (struct audio_offset *)addr;
                   1642:                ao->samples = sc->sc_rr.stamp;
                   1643:                ao->deltablks = (sc->sc_rr.stamp - sc->sc_rr.stamp_last) / sc->sc_rr.blksize;
                   1644:                sc->sc_rr.stamp_last = sc->sc_rr.stamp;
                   1645:                ao->offset = sc->sc_rr.inp - sc->sc_rr.start;
                   1646:                splx(s);
                   1647:                break;
                   1648:
                   1649:        case AUDIO_GETOOFFS:
                   1650:                s = splaudio();
                   1651:                /* figure out where next DMA will start */
                   1652:                ao = (struct audio_offset *)addr;
                   1653:                offs = sc->sc_pr.outp - sc->sc_pr.start + sc->sc_pr.blksize;
                   1654:                if (sc->sc_pr.start + offs >= sc->sc_pr.end)
                   1655:                        offs = 0;
                   1656:                ao->samples = sc->sc_pr.stamp;
                   1657:                ao->deltablks = (sc->sc_pr.stamp - sc->sc_pr.stamp_last) / sc->sc_pr.blksize;
                   1658:                sc->sc_pr.stamp_last = sc->sc_pr.stamp;
                   1659:                ao->offset = offs;
                   1660:                splx(s);
                   1661:                break;
                   1662:
                   1663:        /*
                   1664:         * How many bytes will elapse until mike hears the first
                   1665:         * sample of what we write next?
                   1666:         */
                   1667:        case AUDIO_WSEEK:
                   1668:                *(u_long *)addr = sc->sc_pr.used / sc->sc_pparams.factor;
                   1669:                break;
                   1670:
                   1671:        case AUDIO_SETINFO:
                   1672:                DPRINTF(("AUDIO_SETINFO mode=0x%x\n", sc->sc_mode));
                   1673:                error = audiosetinfo(sc, (struct audio_info *)addr);
                   1674:                break;
                   1675:
                   1676:        case AUDIO_GETINFO:
                   1677:                DPRINTF(("AUDIO_GETINFO\n"));
                   1678:                error = audiogetinfo(sc, (struct audio_info *)addr);
                   1679:                break;
                   1680:
                   1681:        case AUDIO_DRAIN:
                   1682:                DPRINTF(("AUDIO_DRAIN\n"));
                   1683:                error = audio_drain(sc);
                   1684:                if (!error && hw->drain)
                   1685:                    error = hw->drain(sc->hw_hdl);
                   1686:                break;
                   1687:
                   1688:        case AUDIO_GETDEV:
                   1689:                DPRINTF(("AUDIO_GETDEV\n"));
                   1690:                error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
                   1691:                break;
                   1692:
                   1693:        case AUDIO_GETENC:
                   1694:                DPRINTF(("AUDIO_GETENC\n"));
                   1695:                /* Pass read/write info down to query_encoding */
                   1696:                ((struct audio_encoding *)addr)->flags = sc->sc_open;
                   1697:                error = hw->query_encoding(sc->hw_hdl, (struct audio_encoding *)addr);
                   1698:                break;
                   1699:
                   1700:        case AUDIO_GETFD:
                   1701:                DPRINTF(("AUDIO_GETFD\n"));
                   1702:                *(int *)addr = sc->sc_full_duplex;
                   1703:                break;
                   1704:
                   1705:        case AUDIO_SETFD:
                   1706:                DPRINTF(("AUDIO_SETFD\n"));
                   1707:                fd = *(int *)addr;
                   1708:                if (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX) {
                   1709:                        if (hw->setfd)
                   1710:                                error = hw->setfd(sc->hw_hdl, fd);
                   1711:                        else
                   1712:                                error = 0;
                   1713:                        if (!error)
                   1714:                                sc->sc_full_duplex = fd;
                   1715:                } else {
                   1716:                        if (fd)
                   1717:                                error = ENOTTY;
                   1718:                        else
                   1719:                                error = 0;
                   1720:                }
                   1721:                break;
                   1722:
                   1723:        case AUDIO_GETPROPS:
                   1724:                DPRINTF(("AUDIO_GETPROPS\n"));
                   1725:                *(int *)addr = hw->get_props(sc->hw_hdl);
                   1726:                break;
                   1727:
                   1728:        default:
                   1729:                DPRINTF(("audio_ioctl: unknown ioctl\n"));
                   1730:                error = ENOTTY;
                   1731:                break;
                   1732:        }
                   1733:        DPRINTF(("audio_ioctl(%d,'%c',%d) result %d\n",
                   1734:            IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
                   1735:        return (error);
                   1736: }
                   1737:
                   1738: void
                   1739: audio_selwakeup(struct audio_softc *sc, int play)
                   1740: {
                   1741:        struct selinfo *si;
                   1742:
                   1743:        si = play? &sc->sc_wsel : &sc->sc_rsel;
                   1744:
                   1745:        audio_wakeup(play? &sc->sc_wchan : &sc->sc_rchan);
                   1746:        selwakeup(si);
                   1747:        if (sc->sc_async_audio)
                   1748:                psignal(sc->sc_async_audio, SIGIO);
                   1749:        KNOTE(&si->si_note, 0);
                   1750: }
                   1751:
                   1752: #define        AUDIO_FILTREAD(sc) ( \
                   1753:     (!sc->sc_full_duplex && (sc->sc_mode & AUMODE_PLAY)) ? \
                   1754:     sc->sc_pr.stamp > sc->sc_wstamp : sc->sc_rr.used > sc->sc_rr.usedlow)
                   1755:
                   1756: #define        AUDIO_FILTWRITE(sc) ( \
                   1757:     (!sc->sc_full_duplex && (sc->sc_mode & AUMODE_RECORD)) ||          \
                   1758:     (!(sc->sc_mode & AUMODE_PLAY_ALL) && sc->sc_playdrop > 0) ||       \
                   1759:     (sc->sc_pr.used <= sc->sc_pr.usedlow))
                   1760:
                   1761: int
                   1762: audio_poll(dev_t dev, int events, struct proc *p)
                   1763: {
                   1764:        int unit = AUDIOUNIT(dev);
                   1765:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   1766:        int revents = 0, s = splaudio();
                   1767:
                   1768:        DPRINTF(("audio_poll: events=0x%x mode=%d\n", events, sc->sc_mode));
                   1769:
                   1770:        if (events & (POLLIN | POLLRDNORM)) {
                   1771:                if (AUDIO_FILTREAD(sc))
                   1772:                        revents |= events & (POLLIN | POLLRDNORM);
                   1773:        }
                   1774:        if (events & (POLLOUT | POLLWRNORM)) {
                   1775:                if (AUDIO_FILTWRITE(sc))
                   1776:                        revents |= events & (POLLOUT | POLLWRNORM);
                   1777:        }
                   1778:        if (revents == 0) {
                   1779:                if (events & (POLLIN | POLLRDNORM))
                   1780:                        selrecord(p, &sc->sc_rsel);
                   1781:                if (events & (POLLOUT | POLLWRNORM))
                   1782:                        selrecord(p, &sc->sc_wsel);
                   1783:        }
                   1784:        splx(s);
                   1785:        return (revents);
                   1786: }
                   1787:
                   1788: paddr_t
                   1789: audio_mmap(dev_t dev, off_t off, int prot)
                   1790: {
                   1791:        int s;
                   1792:        int unit = AUDIOUNIT(dev);
                   1793:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   1794:        struct audio_hw_if *hw = sc->hw_if;
                   1795:        struct audio_ringbuffer *cb;
                   1796:
                   1797:        DPRINTF(("audio_mmap: off=%d, prot=%d\n", off, prot));
                   1798:
                   1799:        if (!(hw->get_props(sc->hw_hdl) & AUDIO_PROP_MMAP) || !hw->mappage)
                   1800:                return -1;
                   1801: #if 0
                   1802: /* XXX
                   1803:  * The idea here was to use the protection to determine if
                   1804:  * we are mapping the read or write buffer, but it fails.
                   1805:  * The VM system is broken in (at least) two ways.
                   1806:  * 1) If you map memory VM_PROT_WRITE you SIGSEGV
                   1807:  *    when writing to it, so VM_PROT_READ|VM_PROT_WRITE
                   1808:  *    has to be used for mmapping the play buffer.
                   1809:  * 2) Even if calling mmap() with VM_PROT_READ|VM_PROT_WRITE
                   1810:  *    audio_mmap will get called at some point with VM_PROT_READ
                   1811:  *    only.
                   1812:  * So, alas, we always map the play buffer for now.
                   1813:  */
                   1814:        if (prot == (VM_PROT_READ|VM_PROT_WRITE) ||
                   1815:            prot == VM_PROT_WRITE)
                   1816:                cb = &sc->sc_pr;
                   1817:        else if (prot == VM_PROT_READ)
                   1818:                cb = &sc->sc_rr;
                   1819:        else
                   1820:                return -1;
                   1821: #else
                   1822:        cb = &sc->sc_pr;
                   1823: #endif
                   1824:
                   1825:        if ((u_int)off >= cb->bufsize)
                   1826:                return -1;
                   1827:        if (!cb->mmapped) {
                   1828:                cb->mmapped = 1;
                   1829:                if (cb == &sc->sc_pr) {
                   1830:                        audio_fill_silence(&sc->sc_pparams, cb->start, cb->bufsize);
                   1831:                        s = splaudio();
                   1832:                        if (!sc->sc_pbus && !sc->sc_pr.pause)
                   1833:                                (void)audiostartp(sc);
                   1834:                        splx(s);
                   1835:                } else {
                   1836:                        s = splaudio();
                   1837:                        if (!sc->sc_rbus && !sc->sc_rr.pause)
                   1838:                                (void)audiostartr(sc);
                   1839:                        splx(s);
                   1840:                }
                   1841:        }
                   1842:
                   1843:        return hw->mappage(sc->hw_hdl, cb->start, off, prot);
                   1844: }
                   1845:
                   1846: int
                   1847: audiostartr(struct audio_softc *sc)
                   1848: {
                   1849:        int error;
                   1850:
                   1851:        DPRINTF(("audiostartr: start=%p used=%d(hi=%d) mmapped=%d\n",
                   1852:                 sc->sc_rr.start, sc->sc_rr.used, sc->sc_rr.usedhigh,
                   1853:                 sc->sc_rr.mmapped));
                   1854:
                   1855:        if (sc->hw_if->trigger_input)
                   1856:                error = sc->hw_if->trigger_input(sc->hw_hdl, sc->sc_rr.start,
                   1857:                    sc->sc_rr.end, sc->sc_rr.blksize,
                   1858:                    audio_rint, (void *)sc, &sc->sc_rparams);
                   1859:        else
                   1860:                error = sc->hw_if->start_input(sc->hw_hdl, sc->sc_rr.start,
                   1861:                    sc->sc_rr.blksize, audio_rint, (void *)sc);
                   1862:        if (error) {
                   1863:                DPRINTF(("audiostartr failed: %d\n", error));
                   1864:                return error;
                   1865:        }
                   1866:        sc->sc_rbus = 1;
                   1867:        return 0;
                   1868: }
                   1869:
                   1870: int
                   1871: audiostartp(struct audio_softc *sc)
                   1872: {
                   1873:        int error;
                   1874:
                   1875:        DPRINTF(("audiostartp: start=%p used=%d(hi=%d) mmapped=%d\n",
                   1876:                 sc->sc_pr.start, sc->sc_pr.used, sc->sc_pr.usedhigh,
                   1877:                 sc->sc_pr.mmapped));
                   1878:
                   1879:        if (!sc->sc_pr.mmapped && sc->sc_pr.used < sc->sc_pr.blksize)
                   1880:                return 0;
                   1881:
                   1882:        if (sc->hw_if->trigger_output)
                   1883:                error = sc->hw_if->trigger_output(sc->hw_hdl, sc->sc_pr.start,
                   1884:                    sc->sc_pr.end, sc->sc_pr.blksize,
                   1885:                    audio_pint, (void *)sc, &sc->sc_pparams);
                   1886:        else
                   1887:                error = sc->hw_if->start_output(sc->hw_hdl, sc->sc_pr.outp,
                   1888:                    sc->sc_pr.blksize, audio_pint, (void *)sc);
                   1889:        if (error) {
                   1890:                DPRINTF(("audiostartp failed: %d\n", error));
                   1891:                return error;
                   1892:        }
                   1893:        sc->sc_pbus = 1;
                   1894:        return 0;
                   1895: }
                   1896:
                   1897: /*
                   1898:  * When the play interrupt routine finds that the write isn't keeping
                   1899:  * the buffer filled it will insert silence in the buffer to make up
                   1900:  * for this.  The part of the buffer that is filled with silence
                   1901:  * is kept track of in a very approximate way: it starts at sc_sil_start
                   1902:  * and extends sc_sil_count bytes.  If there is already silence in
                   1903:  * the requested area nothing is done; so when the whole buffer is
                   1904:  * silent nothing happens.  When the writer starts again sc_sil_count
                   1905:  * is set to 0.
                   1906:  */
                   1907: /* XXX
                   1908:  * Putting silence into the output buffer should not really be done
                   1909:  * at splaudio, but there is no softaudio level to do it at yet.
                   1910:  */
                   1911: static __inline void
                   1912: audio_pint_silence(struct audio_softc *sc, struct audio_ringbuffer *cb,
                   1913:     u_char *inp, int cc)
                   1914: {
                   1915:        u_char *s, *e, *p, *q;
                   1916:
                   1917:        if (sc->sc_sil_count > 0) {
                   1918:                s = sc->sc_sil_start; /* start of silence */
                   1919:                e = s + sc->sc_sil_count; /* end of silence, may be beyond end */
                   1920:                p = inp;        /* adjusted pointer to area to fill */
                   1921:                if (p < s)
                   1922:                        p += cb->end - cb->start;
                   1923:                q = p+cc;
                   1924:                /* Check if there is already silence. */
                   1925:                if (!(s <= p && p <  e &&
                   1926:                      s <= q && q <= e)) {
                   1927:                        if (s <= p)
                   1928:                                sc->sc_sil_count = max(sc->sc_sil_count, q-s);
                   1929:                        DPRINTFN(5, ("audio_pint_silence: fill cc=%d inp=%p, count=%d size=%d\n",
                   1930:                            cc, inp, sc->sc_sil_count, (int)(cb->end - cb->start)));
                   1931:
                   1932:                        if (sc->sc_pparams.sw_code) {
                   1933:                                int ncc = cc / sc->sc_pparams.factor;
                   1934:                                audio_fill_silence(&sc->sc_pparams, inp, ncc);
                   1935:                                sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
                   1936:                        } else
                   1937:                                audio_fill_silence(&sc->sc_pparams, inp, cc);
                   1938:
                   1939:                } else {
                   1940:                        DPRINTFN(5, ("audio_pint_silence: already silent cc=%d inp=%p\n", cc, inp));
                   1941:
                   1942:                }
                   1943:        } else {
                   1944:                sc->sc_sil_start = inp;
                   1945:                sc->sc_sil_count = cc;
                   1946:                DPRINTFN(5, ("audio_pint_silence: start fill %p %d\n",
                   1947:                    inp, cc));
                   1948:
                   1949:                if (sc->sc_pparams.sw_code) {
                   1950:                        int ncc = cc / sc->sc_pparams.factor;
                   1951:                        audio_fill_silence(&sc->sc_pparams, inp, ncc);
                   1952:                        sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
                   1953:                } else
                   1954:                        audio_fill_silence(&sc->sc_pparams, inp, cc);
                   1955:
                   1956:        }
                   1957: }
                   1958:
                   1959: /*
                   1960:  * Called from HW driver module on completion of dma output.
                   1961:  * Start output of new block, wrap in ring buffer if needed.
                   1962:  * If no more buffers to play, output zero instead.
                   1963:  * Do a wakeup if necessary.
                   1964:  */
                   1965: void
                   1966: audio_pint(void *v)
                   1967: {
                   1968:        struct audio_softc *sc = v;
                   1969:        struct audio_hw_if *hw = sc->hw_if;
                   1970:        struct audio_ringbuffer *cb = &sc->sc_pr;
                   1971:        u_char *inp;
                   1972:        int cc;
                   1973:        int blksize;
                   1974:        int error;
                   1975:
                   1976:        if (!sc->sc_open)
                   1977:                return;         /* ignore interrupt if not open */
                   1978:
                   1979:        blksize = cb->blksize;
                   1980:
                   1981:        add_audio_randomness((long)cb);
                   1982:
                   1983:        cb->outp += blksize;
                   1984:        if (cb->outp >= cb->end)
                   1985:                cb->outp = cb->start;
                   1986:        cb->stamp += blksize;
                   1987:        if (cb->mmapped) {
                   1988:                DPRINTFN(5, ("audio_pint: mmapped outp=%p cc=%d inp=%p\n",
                   1989:                    cb->outp, blksize, cb->inp));
                   1990:                if (!hw->trigger_output)
                   1991:                        (void)hw->start_output(sc->hw_hdl, cb->outp,
                   1992:                            blksize, audio_pint, (void *)sc);
                   1993:                return;
                   1994:        }
                   1995:
                   1996: #ifdef AUDIO_INTR_TIME
                   1997:        {
                   1998:                struct timeval tv;
                   1999:                u_long t;
                   2000:                microtime(&tv);
                   2001:                t = tv.tv_usec + 1000000 * tv.tv_sec;
                   2002:                if (sc->sc_pnintr) {
                   2003:                        long lastdelta, totdelta;
                   2004:                        lastdelta = t - sc->sc_plastintr - sc->sc_pblktime;
                   2005:                        if (lastdelta > sc->sc_pblktime / 3) {
                   2006:                                printf("audio: play interrupt(%d) off relative by %ld us (%lu)\n",
                   2007:                                    sc->sc_pnintr, lastdelta, sc->sc_pblktime);
                   2008:                        }
                   2009:                        totdelta = t - sc->sc_pfirstintr - sc->sc_pblktime * sc->sc_pnintr;
                   2010:                        if (totdelta > sc->sc_pblktime) {
                   2011:                                printf("audio: play interrupt(%d) off absolute by %ld us (%lu) (LOST)\n",
                   2012:                                    sc->sc_pnintr, totdelta, sc->sc_pblktime);
                   2013:                                sc->sc_pnintr++; /* avoid repeated messages */
                   2014:                        }
                   2015:                } else
                   2016:                        sc->sc_pfirstintr = t;
                   2017:                sc->sc_plastintr = t;
                   2018:                sc->sc_pnintr++;
                   2019:        }
                   2020: #endif
                   2021:
                   2022:        cb->used -= blksize;
                   2023:        if (cb->used < blksize) {
                   2024:                /* we don't have a full block to use */
                   2025:                if (cb->copying) {
                   2026:                        /* writer is in progress, don't disturb */
                   2027:                        cb->needfill = 1;
                   2028:                        DPRINTFN(1, ("audio_pint: copying in progress\n"));
                   2029:                } else {
                   2030:                        inp = cb->inp;
                   2031:                        cc = blksize - (inp - cb->start) % blksize;
                   2032:                        if (cb->pause)
                   2033:                                cb->pdrops += cc;
                   2034:                        else {
                   2035:                                cb->drops += cc;
                   2036:                                sc->sc_playdrop += cc;
                   2037:                        }
                   2038:                        audio_pint_silence(sc, cb, inp, cc);
                   2039:                        inp += cc;
                   2040:                        if (inp >= cb->end)
                   2041:                                inp = cb->start;
                   2042:                        cb->inp = inp;
                   2043:                        cb->used += cc;
                   2044:
                   2045:                        /* Clear next block so we keep ahead of the DMA. */
                   2046:                        if (cb->used + cc < cb->usedhigh)
                   2047:                                audio_pint_silence(sc, cb, inp, blksize);
                   2048:                }
                   2049:        }
                   2050:
                   2051:        DPRINTFN(5, ("audio_pint: outp=%p cc=%d\n", cb->outp, blksize));
                   2052:        if (!hw->trigger_output) {
                   2053:                error = hw->start_output(sc->hw_hdl, cb->outp, blksize,
                   2054:                    audio_pint, (void *)sc);
                   2055:                if (error) {
                   2056:                        /* XXX does this really help? */
                   2057:                        DPRINTF(("audio_pint restart failed: %d\n", error));
                   2058:                        audio_clear(sc);
                   2059:                }
                   2060:        }
                   2061:
                   2062:        DPRINTFN(2, ("audio_pint: mode=%d pause=%d used=%d lowat=%d\n",
                   2063:            sc->sc_mode, cb->pause, cb->used, cb->usedlow));
                   2064:        if ((sc->sc_mode & AUMODE_PLAY) && !cb->pause &&
                   2065:            cb->used <= cb->usedlow)
                   2066:                audio_selwakeup(sc, 1);
                   2067:
                   2068:        /* Possible to return one or more "phantom blocks" now. */
                   2069:        if (!sc->sc_full_duplex && sc->sc_rchan)
                   2070:                audio_selwakeup(sc, 0);
                   2071: }
                   2072:
                   2073: /*
                   2074:  * Called from HW driver module on completion of dma input.
                   2075:  * Mark it as input in the ring buffer (fiddle pointers).
                   2076:  * Do a wakeup if necessary.
                   2077:  */
                   2078: void
                   2079: audio_rint(void *v)
                   2080: {
                   2081:        struct audio_softc *sc = v;
                   2082:        struct audio_hw_if *hw = sc->hw_if;
                   2083:        struct audio_ringbuffer *cb = &sc->sc_rr;
                   2084:        int blksize;
                   2085:        int error;
                   2086:
                   2087:        if (!sc->sc_open)
                   2088:                return;         /* ignore interrupt if not open */
                   2089:
                   2090:        add_audio_randomness((long)cb);
                   2091:
                   2092:        blksize = cb->blksize;
                   2093:
                   2094:        cb->inp += blksize;
                   2095:        if (cb->inp >= cb->end)
                   2096:                cb->inp = cb->start;
                   2097:        cb->stamp += blksize;
                   2098:        if (cb->mmapped) {
                   2099:                DPRINTFN(2, ("audio_rint: mmapped inp=%p cc=%d\n",
                   2100:                    cb->inp, blksize));
                   2101:                if (!hw->trigger_input)
                   2102:                        (void)hw->start_input(sc->hw_hdl, cb->inp, blksize,
                   2103:                            audio_rint, (void *)sc);
                   2104:                return;
                   2105:        }
                   2106:
                   2107: #ifdef AUDIO_INTR_TIME
                   2108:        {
                   2109:                struct timeval tv;
                   2110:                u_long t;
                   2111:                microtime(&tv);
                   2112:                t = tv.tv_usec + 1000000 * tv.tv_sec;
                   2113:                if (sc->sc_rnintr) {
                   2114:                        long lastdelta, totdelta;
                   2115:                        lastdelta = t - sc->sc_rlastintr - sc->sc_rblktime;
                   2116:                        if (lastdelta > sc->sc_rblktime / 5) {
                   2117:                                printf("audio: record interrupt(%d) off relative by %ld us (%lu)\n",
                   2118:                                    sc->sc_rnintr, lastdelta, sc->sc_rblktime);
                   2119:                        }
                   2120:                        totdelta = t - sc->sc_rfirstintr - sc->sc_rblktime * sc->sc_rnintr;
                   2121:                        if (totdelta > sc->sc_rblktime / 2) {
                   2122:                                sc->sc_rnintr++;
                   2123:                                printf("audio: record interrupt(%d) off absolute by %ld us (%lu)\n",
                   2124:                                    sc->sc_rnintr, totdelta, sc->sc_rblktime);
                   2125:                                sc->sc_rnintr++; /* avoid repeated messages */
                   2126:                        }
                   2127:                } else
                   2128:                        sc->sc_rfirstintr = t;
                   2129:                sc->sc_rlastintr = t;
                   2130:                sc->sc_rnintr++;
                   2131:        }
                   2132: #endif
                   2133:
                   2134:        cb->used += blksize;
                   2135:        if (cb->pause) {
                   2136:                DPRINTFN(1, ("audio_rint: pdrops %lu\n", cb->pdrops));
                   2137:                cb->pdrops += blksize;
                   2138:                cb->outp += blksize;
                   2139:                cb->used -= blksize;
                   2140:        } else if (cb->used + blksize >= cb->usedhigh && !cb->copying) {
                   2141:                DPRINTFN(1, ("audio_rint: drops %lu\n", cb->drops));
                   2142:                cb->drops += blksize;
                   2143:                cb->outp += blksize;
                   2144:                cb->used -= blksize;
                   2145:        }
                   2146:
                   2147:        DPRINTFN(2, ("audio_rint: inp=%p cc=%d used=%d\n",
                   2148:            cb->inp, blksize, cb->used));
                   2149:        if (!hw->trigger_input) {
                   2150:                error = hw->start_input(sc->hw_hdl, cb->inp, blksize,
                   2151:                    audio_rint, (void *)sc);
                   2152:                if (error) {
                   2153:                        /* XXX does this really help? */
                   2154:                        DPRINTF(("audio_rint: restart failed: %d\n", error));
                   2155:                        audio_clear(sc);
                   2156:                }
                   2157:        }
                   2158:
                   2159:        audio_selwakeup(sc, 0);
                   2160: }
                   2161:
                   2162: int
                   2163: audio_check_params(struct audio_params *p)
                   2164: {
                   2165:        if (p->encoding == AUDIO_ENCODING_PCM16) {
                   2166:                if (p->precision == 8)
                   2167:                        p->encoding = AUDIO_ENCODING_ULINEAR;
                   2168:                else
                   2169:                        p->encoding = AUDIO_ENCODING_SLINEAR;
                   2170:        } else if (p->encoding == AUDIO_ENCODING_PCM8) {
                   2171:                if (p->precision == 8)
                   2172:                        p->encoding = AUDIO_ENCODING_ULINEAR;
                   2173:                else
                   2174:                        return EINVAL;
                   2175:        }
                   2176:
                   2177:        if (p->encoding == AUDIO_ENCODING_SLINEAR)
                   2178: #if BYTE_ORDER == LITTLE_ENDIAN
                   2179:                p->encoding = AUDIO_ENCODING_SLINEAR_LE;
                   2180: #else
                   2181:                p->encoding = AUDIO_ENCODING_SLINEAR_BE;
                   2182: #endif
                   2183:        if (p->encoding == AUDIO_ENCODING_ULINEAR)
                   2184: #if BYTE_ORDER == LITTLE_ENDIAN
                   2185:                p->encoding = AUDIO_ENCODING_ULINEAR_LE;
                   2186: #else
                   2187:                p->encoding = AUDIO_ENCODING_ULINEAR_BE;
                   2188: #endif
                   2189:
                   2190:        switch (p->encoding) {
                   2191:        case AUDIO_ENCODING_ULAW:
                   2192:        case AUDIO_ENCODING_ALAW:
                   2193:        case AUDIO_ENCODING_ADPCM:
                   2194:                if (p->precision != 8)
                   2195:                        return (EINVAL);
                   2196:                break;
                   2197:        case AUDIO_ENCODING_SLINEAR_LE:
                   2198:        case AUDIO_ENCODING_SLINEAR_BE:
                   2199:        case AUDIO_ENCODING_ULINEAR_LE:
                   2200:        case AUDIO_ENCODING_ULINEAR_BE:
                   2201:                if (p->precision != 8 && p->precision != 16)
                   2202:                        return (EINVAL);
                   2203:                break;
                   2204:        case AUDIO_ENCODING_MPEG_L1_STREAM:
                   2205:        case AUDIO_ENCODING_MPEG_L1_PACKETS:
                   2206:        case AUDIO_ENCODING_MPEG_L1_SYSTEM:
                   2207:        case AUDIO_ENCODING_MPEG_L2_STREAM:
                   2208:        case AUDIO_ENCODING_MPEG_L2_PACKETS:
                   2209:        case AUDIO_ENCODING_MPEG_L2_SYSTEM:
                   2210:                break;
                   2211:        default:
                   2212:                return (EINVAL);
                   2213:        }
                   2214:
                   2215:        if (p->channels < 1 || p->channels > 8) /* sanity check # of channels */
                   2216:                return (EINVAL);
                   2217:
                   2218:        return (0);
                   2219: }
                   2220:
                   2221: int
                   2222: au_set_lr_value(struct audio_softc *sc, mixer_ctrl_t *ct, int l, int r)
                   2223: {
                   2224:        ct->type = AUDIO_MIXER_VALUE;
                   2225:        ct->un.value.num_channels = 2;
                   2226:        ct->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
                   2227:        ct->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
                   2228:        if (sc->hw_if->set_port(sc->hw_hdl, ct) == 0)
                   2229:                return 0;
                   2230:        ct->un.value.num_channels = 1;
                   2231:        ct->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r)/2;
                   2232:        return sc->hw_if->set_port(sc->hw_hdl, ct);
                   2233: }
                   2234:
                   2235: int
                   2236: au_set_gain(struct audio_softc *sc, struct au_mixer_ports *ports, int gain,
                   2237:     int balance)
                   2238: {
                   2239:        mixer_ctrl_t ct;
                   2240:        int i, error;
                   2241:        int l, r;
                   2242:        u_int mask;
                   2243:        int nset;
                   2244:
                   2245:        if (balance == AUDIO_MID_BALANCE) {
                   2246:                l = r = gain;
                   2247:        } else if (balance < AUDIO_MID_BALANCE) {
                   2248:                r = gain;
                   2249:                l = (balance * gain) / AUDIO_MID_BALANCE;
                   2250:        } else {
                   2251:                l = gain;
                   2252:                r = ((AUDIO_RIGHT_BALANCE - balance) * gain)
                   2253:                    / AUDIO_MID_BALANCE;
                   2254:        }
                   2255:        DPRINTF(("au_set_gain: gain=%d balance=%d, l=%d r=%d\n",
                   2256:                 gain, balance, l, r));
                   2257:
                   2258:        if (ports->index == -1) {
                   2259:        usemaster:
                   2260:                if (ports->master == -1)
                   2261:                        return 0; /* just ignore it silently */
                   2262:                ct.dev = ports->master;
                   2263:                error = au_set_lr_value(sc, &ct, l, r);
                   2264:        } else {
                   2265:                ct.dev = ports->index;
                   2266:                if (ports->isenum) {
                   2267:                        ct.type = AUDIO_MIXER_ENUM;
                   2268:                        error = sc->hw_if->get_port(sc->hw_hdl, &ct);
                   2269:                        if (error)
                   2270:                                return error;
                   2271:                        for(i = 0; i < ports->nports; i++) {
                   2272:                                if (ports->misel[i] == ct.un.ord) {
                   2273:                                        ct.dev = ports->miport[i];
                   2274:                                        if (ct.dev == -1 ||
                   2275:                                            au_set_lr_value(sc, &ct, l, r))
                   2276:                                                goto usemaster;
                   2277:                                        else
                   2278:                                                break;
                   2279:                                }
                   2280:                        }
                   2281:                } else {
                   2282:                        ct.type = AUDIO_MIXER_SET;
                   2283:                        error = sc->hw_if->get_port(sc->hw_hdl, &ct);
                   2284:                        if (error)
                   2285:                                return error;
                   2286:                        mask = ct.un.mask;
                   2287:                        nset = 0;
                   2288:                        for(i = 0; i < ports->nports; i++) {
                   2289:                                if (ports->misel[i] & mask) {
                   2290:                                    ct.dev = ports->miport[i];
                   2291:                                    if (ct.dev != -1 &&
                   2292:                                        au_set_lr_value(sc, &ct, l, r) == 0)
                   2293:                                            nset++;
                   2294:                                }
                   2295:                        }
                   2296:                        if (nset == 0)
                   2297:                                goto usemaster;
                   2298:                }
                   2299:        }
                   2300:        if (!error)
                   2301:                mixer_signal(sc);
                   2302:        return error;
                   2303: }
                   2304:
                   2305: int
                   2306: au_get_lr_value(struct audio_softc *sc, mixer_ctrl_t *ct, int *l, int *r)
                   2307: {
                   2308:        int error;
                   2309:
                   2310:        ct->un.value.num_channels = 2;
                   2311:        if (sc->hw_if->get_port(sc->hw_hdl, ct) == 0) {
                   2312:                *l = ct->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                   2313:                *r = ct->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                   2314:        } else {
                   2315:                ct->un.value.num_channels = 1;
                   2316:                error = sc->hw_if->get_port(sc->hw_hdl, ct);
                   2317:                if (error)
                   2318:                        return error;
                   2319:                *r = *l = ct->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                   2320:        }
                   2321:        return 0;
                   2322: }
                   2323:
                   2324: void
                   2325: au_get_gain(struct audio_softc *sc, struct au_mixer_ports *ports, u_int *pgain,
                   2326:     u_char *pbalance)
                   2327: {
                   2328:        mixer_ctrl_t ct;
                   2329:        int i, l, r, n;
                   2330:        int lgain = AUDIO_MAX_GAIN/2, rgain = AUDIO_MAX_GAIN/2;
                   2331:
                   2332:        if (ports->index == -1) {
                   2333:        usemaster:
                   2334:                if (ports->master == -1)
                   2335:                        goto bad;
                   2336:                ct.dev = ports->master;
                   2337:                ct.type = AUDIO_MIXER_VALUE;
                   2338:                if (au_get_lr_value(sc, &ct, &lgain, &rgain))
                   2339:                        goto bad;
                   2340:        } else {
                   2341:                ct.dev = ports->index;
                   2342:                if (ports->isenum) {
                   2343:                        ct.type = AUDIO_MIXER_ENUM;
                   2344:                        if (sc->hw_if->get_port(sc->hw_hdl, &ct))
                   2345:                                goto bad;
                   2346:                        ct.type = AUDIO_MIXER_VALUE;
                   2347:                        for(i = 0; i < ports->nports; i++) {
                   2348:                                if (ports->misel[i] == ct.un.ord) {
                   2349:                                        ct.dev = ports->miport[i];
                   2350:                                        if (ct.dev == -1 ||
                   2351:                                            au_get_lr_value(sc, &ct,
                   2352:                                                            &lgain, &rgain))
                   2353:                                                goto usemaster;
                   2354:                                        else
                   2355:                                                break;
                   2356:                                }
                   2357:                        }
                   2358:                } else {
                   2359:                        ct.type = AUDIO_MIXER_SET;
                   2360:                        if (sc->hw_if->get_port(sc->hw_hdl, &ct))
                   2361:                                goto bad;
                   2362:                        ct.type = AUDIO_MIXER_VALUE;
                   2363:                        lgain = rgain = n = 0;
                   2364:                        for(i = 0; i < ports->nports; i++) {
                   2365:                                if (ports->misel[i] & ct.un.mask) {
                   2366:                                        ct.dev = ports->miport[i];
                   2367:                                        if (ct.dev == -1 ||
                   2368:                                            au_get_lr_value(sc, &ct, &l, &r))
                   2369:                                                goto usemaster;
                   2370:                                        else {
                   2371:                                                lgain += l;
                   2372:                                                rgain += r;
                   2373:                                                n++;
                   2374:                                        }
                   2375:                                }
                   2376:                        }
                   2377:                        if (n != 0) {
                   2378:                                lgain /= n;
                   2379:                                rgain /= n;
                   2380:                        }
                   2381:                }
                   2382:        }
                   2383: bad:
                   2384:        if (lgain == rgain) {   /* handles lgain==rgain==0 */
                   2385:                *pgain = lgain;
                   2386:                *pbalance = AUDIO_MID_BALANCE;
                   2387:        } else if (lgain < rgain) {
                   2388:                *pgain = rgain;
                   2389:                *pbalance = (AUDIO_MID_BALANCE * lgain) / rgain;
                   2390:        } else /* lgain > rgain */ {
                   2391:                *pgain = lgain;
                   2392:                *pbalance = AUDIO_RIGHT_BALANCE -
                   2393:                            (AUDIO_MID_BALANCE * rgain) / lgain;
                   2394:        }
                   2395: }
                   2396:
                   2397: int
                   2398: au_set_port(struct audio_softc *sc, struct au_mixer_ports *ports, u_int port)
                   2399: {
                   2400:        mixer_ctrl_t ct;
                   2401:        int i, error;
                   2402:
                   2403:        if (port == 0)  /* allow this special case */
                   2404:                return 0;
                   2405:
                   2406:        if (ports->index == -1)
                   2407:                return EINVAL;
                   2408:        ct.dev = ports->index;
                   2409:        if (ports->isenum) {
                   2410:                if (port & (port-1))
                   2411:                        return EINVAL; /* Only one port allowed */
                   2412:                ct.type = AUDIO_MIXER_ENUM;
                   2413:                error = EINVAL;
                   2414:                for(i = 0; i < ports->nports; i++)
                   2415:                        if (ports->aumask[i] == port) {
                   2416:                                ct.un.ord = ports->misel[i];
                   2417:                                error = sc->hw_if->set_port(sc->hw_hdl, &ct);
                   2418:                                break;
                   2419:                        }
                   2420:        } else {
                   2421:                ct.type = AUDIO_MIXER_SET;
                   2422:                ct.un.mask = 0;
                   2423:                for(i = 0; i < ports->nports; i++)
                   2424:                        if (ports->aumask[i] & port)
                   2425:                                ct.un.mask |= ports->misel[i];
                   2426:                if (port != 0 && ct.un.mask == 0)
                   2427:                        error = EINVAL;
                   2428:                else
                   2429:                        error = sc->hw_if->set_port(sc->hw_hdl, &ct);
                   2430:        }
                   2431:        if (!error)
                   2432:                mixer_signal(sc);
                   2433:        return error;
                   2434: }
                   2435:
                   2436: int
                   2437: au_get_port(struct audio_softc *sc, struct au_mixer_ports *ports)
                   2438: {
                   2439:        mixer_ctrl_t ct;
                   2440:        int i, aumask;
                   2441:
                   2442:        if (ports->index == -1)
                   2443:                return 0;
                   2444:        ct.dev = ports->index;
                   2445:        ct.type = ports->isenum ? AUDIO_MIXER_ENUM : AUDIO_MIXER_SET;
                   2446:        if (sc->hw_if->get_port(sc->hw_hdl, &ct))
                   2447:                return 0;
                   2448:        aumask = 0;
                   2449:        if (ports->isenum) {
                   2450:                for(i = 0; i < ports->nports; i++)
                   2451:                        if (ct.un.ord == ports->misel[i])
                   2452:                                aumask = ports->aumask[i];
                   2453:        } else {
                   2454:                for(i = 0; i < ports->nports; i++)
                   2455:                        if (ct.un.mask & ports->misel[i])
                   2456:                                aumask |= ports->aumask[i];
                   2457:        }
                   2458:        return aumask;
                   2459: }
                   2460:
                   2461: int
                   2462: audiosetinfo(struct audio_softc *sc, struct audio_info *ai)
                   2463: {
                   2464:        struct audio_prinfo *r = &ai->record, *p = &ai->play;
                   2465:        int cleared;
                   2466:        int s, setmode, modechange = 0;
                   2467:        int error;
                   2468:        struct audio_hw_if *hw = sc->hw_if;
                   2469:        struct audio_params pp, rp;
                   2470:        int np, nr;
                   2471:        unsigned int blks;
                   2472:        int oldpblksize, oldrblksize;
                   2473:        int rbus, pbus;
                   2474:        u_int gain;
                   2475:        u_char balance;
                   2476:
                   2477:        if (hw == 0)            /* HW has not attached */
                   2478:                return(ENXIO);
                   2479:
                   2480:        rbus = sc->sc_rbus;
                   2481:        pbus = sc->sc_pbus;
                   2482:        error = 0;
                   2483:        cleared = 0;
                   2484:
                   2485:        pp = sc->sc_pparams;    /* Temporary encoding storage in */
                   2486:        rp = sc->sc_rparams;    /* case setting the modes fails. */
                   2487:        nr = np = 0;
                   2488:
                   2489:        if (p->sample_rate != ~0) {
                   2490:                pp.sample_rate = p->sample_rate;
                   2491:                np++;
                   2492:        }
                   2493:        if (r->sample_rate != ~0) {
                   2494:                rp.sample_rate = r->sample_rate;
                   2495:                nr++;
                   2496:        }
                   2497:        if (p->encoding != ~0) {
                   2498:                pp.encoding = p->encoding;
                   2499:                np++;
                   2500:        }
                   2501:        if (r->encoding != ~0) {
                   2502:                rp.encoding = r->encoding;
                   2503:                nr++;
                   2504:        }
                   2505:        if (p->precision != ~0) {
                   2506:                pp.precision = p->precision;
                   2507:                np++;
                   2508:        }
                   2509:        if (r->precision != ~0) {
                   2510:                rp.precision = r->precision;
                   2511:                nr++;
                   2512:        }
                   2513:        if (p->channels != ~0) {
                   2514:                pp.channels = p->channels;
                   2515:                np++;
                   2516:        }
                   2517:        if (r->channels != ~0) {
                   2518:                rp.channels = r->channels;
                   2519:                nr++;
                   2520:        }
                   2521: #ifdef AUDIO_DEBUG
                   2522:        if (audiodebug && nr)
                   2523:            audio_print_params("Setting record params", &rp);
                   2524:        if (audiodebug && np)
                   2525:            audio_print_params("Setting play params", &pp);
                   2526: #endif
                   2527:        if (nr && (error = audio_check_params(&rp)))
                   2528:                return error;
                   2529:        if (np && (error = audio_check_params(&pp)))
                   2530:                return error;
                   2531:        setmode = 0;
                   2532:        if (nr) {
                   2533:                if (!cleared)
                   2534:                        audio_clear(sc);
                   2535:                modechange = cleared = 1;
                   2536:                rp.sw_code = 0;
                   2537:                rp.factor = 1;
                   2538:                setmode |= AUMODE_RECORD;
                   2539:        }
                   2540:        if (np) {
                   2541:                if (!cleared)
                   2542:                        audio_clear(sc);
                   2543:                modechange = cleared = 1;
                   2544:                pp.sw_code = 0;
                   2545:                pp.factor = 1;
                   2546:                setmode |= AUMODE_PLAY;
                   2547:        }
                   2548:
                   2549:        if (ai->mode != ~0) {
                   2550:                if (!cleared)
                   2551:                        audio_clear(sc);
                   2552:                modechange = cleared = 1;
                   2553:                sc->sc_mode = ai->mode;
                   2554:                if (sc->sc_mode & AUMODE_PLAY_ALL)
                   2555:                        sc->sc_mode |= AUMODE_PLAY;
                   2556:                if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_full_duplex)
                   2557:                        /* Play takes precedence */
                   2558:                        sc->sc_mode &= ~AUMODE_RECORD;
                   2559:        }
                   2560:
                   2561:        if (modechange) {
                   2562:                int indep = hw->get_props(sc->hw_hdl) & AUDIO_PROP_INDEPENDENT;
                   2563:                if (!indep) {
                   2564:                        if (setmode == AUMODE_RECORD)
                   2565:                                pp = rp;
                   2566:                        else if (setmode == AUMODE_PLAY)
                   2567:                                rp = pp;
                   2568:                }
                   2569:                error = hw->set_params(sc->hw_hdl, setmode,
                   2570:                    sc->sc_mode & (AUMODE_PLAY | AUMODE_RECORD), &pp, &rp);
                   2571:                if (error)
                   2572:                        return (error);
                   2573:                if (!indep) {
                   2574:                        if (setmode == AUMODE_RECORD) {
                   2575:                                pp.sample_rate = rp.sample_rate;
                   2576:                                pp.encoding    = rp.encoding;
                   2577:                                pp.channels    = rp.channels;
                   2578:                                pp.precision   = rp.precision;
                   2579:                        } else if (setmode == AUMODE_PLAY) {
                   2580:                                rp.sample_rate = pp.sample_rate;
                   2581:                                rp.encoding    = pp.encoding;
                   2582:                                rp.channels    = pp.channels;
                   2583:                                rp.precision   = pp.precision;
                   2584:                        }
                   2585:                }
                   2586:                sc->sc_rparams = rp;
                   2587:                sc->sc_pparams = pp;
                   2588:        }
                   2589:
                   2590:        oldpblksize = sc->sc_pr.blksize;
                   2591:        oldrblksize = sc->sc_rr.blksize;
                   2592:        /* Play params can affect the record params, so recalculate blksize. */
                   2593:        if (nr || np) {
                   2594:                audio_calc_blksize(sc, AUMODE_RECORD);
                   2595:                audio_calc_blksize(sc, AUMODE_PLAY);
                   2596:        }
                   2597: #ifdef AUDIO_DEBUG
                   2598:        if (audiodebug > 1 && nr)
                   2599:            audio_print_params("After setting record params", &sc->sc_rparams);
                   2600:        if (audiodebug > 1 && np)
                   2601:            audio_print_params("After setting play params", &sc->sc_pparams);
                   2602: #endif
                   2603:
                   2604:        if (p->port != ~0) {
                   2605:                if (!cleared)
                   2606:                        audio_clear(sc);
                   2607:                cleared = 1;
                   2608:
                   2609:                error = au_set_port(sc, &sc->sc_outports, p->port);
                   2610:                if (error)
                   2611:                        return(error);
                   2612:        }
                   2613:        if (r->port != ~0) {
                   2614:                if (!cleared)
                   2615:                        audio_clear(sc);
                   2616:                cleared = 1;
                   2617:
                   2618:                error = au_set_port(sc, &sc->sc_inports, r->port);
                   2619:                if (error)
                   2620:                        return(error);
                   2621:        }
                   2622:        if (p->gain != ~0) {
                   2623:                au_get_gain(sc, &sc->sc_outports, &gain, &balance);
                   2624:                error = au_set_gain(sc, &sc->sc_outports, p->gain, balance);
                   2625:                if (error)
                   2626:                        return(error);
                   2627:        }
                   2628:        if (r->gain != ~0) {
                   2629:                au_get_gain(sc, &sc->sc_inports, &gain, &balance);
                   2630:                error = au_set_gain(sc, &sc->sc_inports, r->gain, balance);
                   2631:                if (error)
                   2632:                        return(error);
                   2633:        }
                   2634:
                   2635:        if (p->balance != (u_char)~0) {
                   2636:                au_get_gain(sc, &sc->sc_outports, &gain, &balance);
                   2637:                error = au_set_gain(sc, &sc->sc_outports, gain, p->balance);
                   2638:                if (error)
                   2639:                        return(error);
                   2640:        }
                   2641:        if (r->balance != (u_char)~0) {
                   2642:                au_get_gain(sc, &sc->sc_inports, &gain, &balance);
                   2643:                error = au_set_gain(sc, &sc->sc_inports, gain, r->balance);
                   2644:                if (error)
                   2645:                        return(error);
                   2646:        }
                   2647:
                   2648:        if (ai->monitor_gain != ~0 &&
                   2649:            sc->sc_monitor_port != -1) {
                   2650:                mixer_ctrl_t ct;
                   2651:
                   2652:                ct.dev = sc->sc_monitor_port;
                   2653:                ct.type = AUDIO_MIXER_VALUE;
                   2654:                ct.un.value.num_channels = 1;
                   2655:                ct.un.value.level[AUDIO_MIXER_LEVEL_MONO] = ai->monitor_gain;
                   2656:                error = sc->hw_if->set_port(sc->hw_hdl, &ct);
                   2657:                if (error)
                   2658:                        return(error);
                   2659:        }
                   2660:
                   2661:        if (ai->blocksize != ~0) {
                   2662:                /* Block size specified explicitly. */
                   2663:                if (!cleared)
                   2664:                        audio_clear(sc);
                   2665:                cleared = 1;
                   2666:
                   2667:                if (ai->blocksize == 0) {
                   2668:                        audio_calc_blksize(sc, AUMODE_RECORD);
                   2669:                        audio_calc_blksize(sc, AUMODE_PLAY);
                   2670:                        sc->sc_blkset = 0;
                   2671:                } else {
                   2672:                        int rbs = ai->blocksize * sc->sc_rparams.factor;
                   2673:                        int pbs = ai->blocksize * sc->sc_pparams.factor;
                   2674:                        if (hw->round_blocksize) {
                   2675:                                rbs = hw->round_blocksize(sc->hw_hdl, rbs);
                   2676:                                pbs = hw->round_blocksize(sc->hw_hdl, pbs);
                   2677:                        }
                   2678:                        sc->sc_rr.blksize = rbs;
                   2679:                        sc->sc_pr.blksize = pbs;
                   2680:                        sc->sc_blkset = 1;
                   2681:                }
                   2682:        }
                   2683:
                   2684:        if (ai->mode != ~0) {
                   2685:                if (sc->sc_mode & AUMODE_PLAY)
                   2686:                        audio_init_play(sc);
                   2687:                if (sc->sc_mode & AUMODE_RECORD)
                   2688:                        audio_init_record(sc);
                   2689:        }
                   2690:
                   2691:        if (hw->commit_settings) {
                   2692:                error = hw->commit_settings(sc->hw_hdl);
                   2693:                if (error)
                   2694:                        return (error);
                   2695:        }
                   2696:
                   2697:        if (cleared) {
                   2698:                s = splaudio();
                   2699:                error = audio_initbufs(sc);
                   2700:                if (error) goto err;
                   2701:                if (sc->sc_pr.blksize != oldpblksize ||
                   2702:                    sc->sc_rr.blksize != oldrblksize)
                   2703:                        audio_calcwater(sc);
                   2704:                if ((sc->sc_mode & AUMODE_PLAY) &&
                   2705:                    pbus && !sc->sc_pbus && !sc->sc_pr.pause)
                   2706:                        error = audiostartp(sc);
                   2707:                if (!error &&
                   2708:                    (sc->sc_mode & AUMODE_RECORD) &&
                   2709:                    rbus && !sc->sc_rbus && !sc->sc_rr.pause)
                   2710:                        error = audiostartr(sc);
                   2711:        err:
                   2712:                splx(s);
                   2713:                if (error)
                   2714:                        return error;
                   2715:        }
                   2716:
                   2717:        /* Change water marks after initializing the buffers. */
                   2718:        if (ai->hiwat != ~0) {
                   2719:                blks = ai->hiwat;
                   2720:                if (blks > sc->sc_pr.maxblks)
                   2721:                        blks = sc->sc_pr.maxblks;
                   2722:                if (blks < 2)
                   2723:                        blks = 2;
                   2724:                sc->sc_pr.usedhigh = blks * sc->sc_pr.blksize;
                   2725:        }
                   2726:        if (ai->lowat != ~0) {
                   2727:                blks = ai->lowat;
                   2728:                if (blks > sc->sc_pr.maxblks - 1)
                   2729:                        blks = sc->sc_pr.maxblks - 1;
                   2730:                sc->sc_pr.usedlow = blks * sc->sc_pr.blksize;
                   2731:        }
                   2732:        if (ai->hiwat != ~0 || ai->lowat != ~0) {
                   2733:                if (sc->sc_pr.usedlow > sc->sc_pr.usedhigh - sc->sc_pr.blksize)
                   2734:                        sc->sc_pr.usedlow = sc->sc_pr.usedhigh - sc->sc_pr.blksize;
                   2735:        }
                   2736:
                   2737:        if (p->pause != (u_char)~0) {
                   2738:                sc->sc_pr.pause = p->pause;
                   2739:                if (!p->pause && !sc->sc_pbus && (sc->sc_mode & AUMODE_PLAY)) {
                   2740:                        s = splaudio();
                   2741:                        error = audiostartp(sc);
                   2742:                        splx(s);
                   2743:                        if (error)
                   2744:                                return error;
                   2745:                }
                   2746:        }
                   2747:        if (r->pause != (u_char)~0) {
                   2748:                sc->sc_rr.pause = r->pause;
                   2749:                if (!r->pause && !sc->sc_rbus && (sc->sc_mode & AUMODE_RECORD)) {
                   2750:                        s = splaudio();
                   2751:                        error = audiostartr(sc);
                   2752:                        splx(s);
                   2753:                        if (error)
                   2754:                                return error;
                   2755:                }
                   2756:        }
                   2757:
                   2758:        return (0);
                   2759: }
                   2760:
                   2761: int
                   2762: audiogetinfo(struct audio_softc *sc, struct audio_info *ai)
                   2763: {
                   2764:        struct audio_prinfo *r = &ai->record, *p = &ai->play;
                   2765:        struct audio_hw_if *hw = sc->hw_if;
                   2766:
                   2767:        if (hw == 0)            /* HW has not attached */
                   2768:                return(ENXIO);
                   2769:
                   2770:        p->sample_rate = sc->sc_pparams.sample_rate;
                   2771:        r->sample_rate = sc->sc_rparams.sample_rate;
                   2772:        p->channels = sc->sc_pparams.channels;
                   2773:        r->channels = sc->sc_rparams.channels;
                   2774:        p->precision = sc->sc_pparams.precision;
                   2775:        r->precision = sc->sc_rparams.precision;
                   2776:        p->encoding = sc->sc_pparams.encoding;
                   2777:        r->encoding = sc->sc_rparams.encoding;
                   2778:
                   2779:        r->port = au_get_port(sc, &sc->sc_inports);
                   2780:        p->port = au_get_port(sc, &sc->sc_outports);
                   2781:
                   2782:        r->avail_ports = sc->sc_inports.allports;
                   2783:        p->avail_ports = sc->sc_outports.allports;
                   2784:
                   2785:        au_get_gain(sc, &sc->sc_inports,  &r->gain, &r->balance);
                   2786:        au_get_gain(sc, &sc->sc_outports, &p->gain, &p->balance);
                   2787:
                   2788:        if (sc->sc_monitor_port != -1) {
                   2789:                mixer_ctrl_t ct;
                   2790:
                   2791:                ct.dev = sc->sc_monitor_port;
                   2792:                ct.type = AUDIO_MIXER_VALUE;
                   2793:                ct.un.value.num_channels = 1;
                   2794:                if (sc->hw_if->get_port(sc->hw_hdl, &ct))
                   2795:                        ai->monitor_gain = 0;
                   2796:                else
                   2797:                        ai->monitor_gain =
                   2798:                                ct.un.value.level[AUDIO_MIXER_LEVEL_MONO];
                   2799:        } else
                   2800:                ai->monitor_gain = 0;
                   2801:
                   2802:        p->seek = sc->sc_pr.used / sc->sc_pparams.factor;
                   2803:        r->seek = sc->sc_rr.used / sc->sc_rparams.factor;
                   2804:
                   2805:        p->samples = sc->sc_pr.stamp - sc->sc_pr.drops;
                   2806:        r->samples = sc->sc_rr.stamp - sc->sc_rr.drops;
                   2807:
                   2808:        p->eof = sc->sc_eof;
                   2809:        r->eof = 0;
                   2810:
                   2811:        p->pause = sc->sc_pr.pause;
                   2812:        r->pause = sc->sc_rr.pause;
                   2813:
                   2814:        p->error = sc->sc_pr.drops != 0;
                   2815:        r->error = sc->sc_rr.drops != 0;
                   2816:
                   2817:        p->waiting = r->waiting = 0;            /* open never hangs */
                   2818:
                   2819:        p->open = (sc->sc_open & AUOPEN_WRITE) != 0;
                   2820:        r->open = (sc->sc_open & AUOPEN_READ) != 0;
                   2821:
                   2822:        p->active = sc->sc_pbus;
                   2823:        r->active = sc->sc_rbus;
                   2824:
                   2825:        p->buffer_size = sc->sc_pr.bufsize / sc->sc_pparams.factor;
                   2826:        r->buffer_size = sc->sc_rr.bufsize / sc->sc_rparams.factor;
                   2827:
                   2828:        if ((ai->blocksize = sc->sc_pr.blksize / sc->sc_pparams.factor) != 0) {
                   2829:                ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize;
                   2830:                ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize;
                   2831:        } else {
                   2832:                ai->hiwat = ai->lowat = 0;
                   2833:        }
                   2834:        ai->mode = sc->sc_mode;
                   2835:
                   2836:        return (0);
                   2837: }
                   2838:
                   2839: /*
                   2840:  * Mixer driver
                   2841:  */
                   2842: int
                   2843: mixer_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
                   2844:     struct proc *p)
                   2845: {
                   2846:        DPRINTF(("mixer_open: dev=0x%x flags=0x%x sc=%p\n", dev, flags, sc));
                   2847:
                   2848:        return (0);
                   2849: }
                   2850:
                   2851: /*
                   2852:  * Remove a process from those to be signalled on mixer activity.
                   2853:  */
                   2854: static void
                   2855: mixer_remove(struct audio_softc *sc, struct proc *p)
                   2856: {
                   2857:        struct mixer_asyncs **pm, *m;
                   2858:
                   2859:        for(pm = &sc->sc_async_mixer; *pm; pm = &(*pm)->next) {
                   2860:                if ((*pm)->proc == p) {
                   2861:                        m = *pm;
                   2862:                        *pm = m->next;
                   2863:                        free(m, M_DEVBUF);
                   2864:                        return;
                   2865:                }
                   2866:        }
                   2867: }
                   2868:
                   2869: /*
                   2870:  * Signal all processes waitinf for the mixer.
                   2871:  */
                   2872: static void
                   2873: mixer_signal(struct audio_softc *sc)
                   2874: {
                   2875:        struct mixer_asyncs *m;
                   2876:
                   2877:        for(m = sc->sc_async_mixer; m; m = m->next)
                   2878:                psignal(m->proc, SIGIO);
                   2879: }
                   2880:
                   2881: /*
                   2882:  * Close a mixer device
                   2883:  */
                   2884: /* ARGSUSED */
                   2885: int
                   2886: mixer_close(dev_t dev, int flags, int ifmt, struct proc *p)
                   2887: {
                   2888:        int unit = AUDIOUNIT(dev);
                   2889:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   2890:
                   2891:        DPRINTF(("mixer_close: unit %d\n", AUDIOUNIT(dev)));
                   2892:
                   2893:        mixer_remove(sc, p);
                   2894:
                   2895:        return (0);
                   2896: }
                   2897:
                   2898: int
                   2899: mixer_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
                   2900: {
                   2901:        int unit = AUDIOUNIT(dev);
                   2902:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   2903:        struct audio_hw_if *hw = sc->hw_if;
                   2904:        int error = EINVAL;
                   2905:
                   2906:        DPRINTF(("mixer_ioctl(%d,'%c',%d)\n",
                   2907:                 IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
                   2908:
                   2909:        switch (cmd) {
                   2910:        case FIOASYNC:
                   2911:                mixer_remove(sc, p); /* remove old entry */
                   2912:                if (*(int *)addr) {
                   2913:                        struct mixer_asyncs *ma;
                   2914:                        ma = malloc(sizeof (struct mixer_asyncs),
                   2915:                            M_DEVBUF, M_WAITOK);
                   2916:                        ma->next = sc->sc_async_mixer;
                   2917:                        ma->proc = p;
                   2918:                        sc->sc_async_mixer = ma;
                   2919:                }
                   2920:                error = 0;
                   2921:                break;
                   2922:
                   2923:        case AUDIO_GETDEV:
                   2924:                DPRINTF(("AUDIO_GETDEV\n"));
                   2925:                error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
                   2926:                break;
                   2927:
                   2928:        case AUDIO_MIXER_DEVINFO:
                   2929:                DPRINTF(("AUDIO_MIXER_DEVINFO\n"));
                   2930:                ((mixer_devinfo_t *)addr)->un.v.delta = 0; /* default */
                   2931:                error = hw->query_devinfo(sc->hw_hdl, (mixer_devinfo_t *)addr);
                   2932:                break;
                   2933:
                   2934:        case AUDIO_MIXER_READ:
                   2935:                DPRINTF(("AUDIO_MIXER_READ\n"));
                   2936:                error = hw->get_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
                   2937:                break;
                   2938:
                   2939:        case AUDIO_MIXER_WRITE:
                   2940:                if (!(flag & FWRITE))
                   2941:                        return (EACCES);
                   2942:                DPRINTF(("AUDIO_MIXER_WRITE\n"));
                   2943:                error = hw->set_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
                   2944:                if (!error && hw->commit_settings)
                   2945:                        error = hw->commit_settings(sc->hw_hdl);
                   2946:                if (!error)
                   2947:                        mixer_signal(sc);
                   2948:                break;
                   2949:
                   2950:        default:
                   2951:                error = ENOTTY;
                   2952:                break;
                   2953:        }
                   2954:        DPRINTF(("mixer_ioctl(%d,'%c',%d) result %d\n",
                   2955:                 IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
                   2956:        return (error);
                   2957: }
                   2958: #endif
                   2959:
                   2960: int
                   2961: audiokqfilter(dev_t dev, struct knote *kn)
                   2962: {
                   2963:        int unit = AUDIOUNIT(dev);
                   2964:        struct audio_softc *sc = audio_cd.cd_devs[unit];
                   2965:        struct klist *klist;
                   2966:        int s;
                   2967:
                   2968:        switch (kn->kn_filter) {
                   2969:        case EVFILT_READ:
                   2970:                klist = &sc->sc_rsel.si_note;
                   2971:                kn->kn_fop = &audioread_filtops;
                   2972:                break;
                   2973:        case EVFILT_WRITE:
                   2974:                klist = &sc->sc_wsel.si_note;
                   2975:                kn->kn_fop = &audiowrite_filtops;
                   2976:                break;
                   2977:        default:
                   2978:                return (1);
                   2979:        }
                   2980:        kn->kn_hook = (void *)sc;
                   2981:
                   2982:        s = splaudio();
                   2983:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
                   2984:        splx(s);
                   2985:
                   2986:        return (0);
                   2987: }
                   2988:
                   2989: void
                   2990: filt_audiordetach(struct knote *kn)
                   2991: {
                   2992:        struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
                   2993:        int s = splaudio();
                   2994:
                   2995:        SLIST_REMOVE(&sc->sc_rsel.si_note, kn, knote, kn_selnext);
                   2996:        splx(s);
                   2997: }
                   2998:
                   2999: int
                   3000: filt_audioread(struct knote *kn, long hint)
                   3001: {
                   3002:        struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
                   3003:
                   3004:        return AUDIO_FILTREAD(sc);
                   3005: }
                   3006:
                   3007: void
                   3008: filt_audiowdetach(struct knote *kn)
                   3009: {
                   3010:        struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
                   3011:        int s = splaudio();
                   3012:
                   3013:        SLIST_REMOVE(&sc->sc_wsel.si_note, kn, knote, kn_selnext);
                   3014:        splx(s);
                   3015: }
                   3016:
                   3017: int
                   3018: filt_audiowrite(struct knote *kn, long hint)
                   3019: {
                   3020:        struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
                   3021:
                   3022:        return AUDIO_FILTWRITE(sc);
                   3023: }
                   3024:
                   3025: #if NAUDIO > 0 && NWSKBD > 0
                   3026: int
                   3027: wskbd_get_mixerdev(struct audio_softc *sc, int dir, int *index)
                   3028: {
                   3029:        mixer_devinfo_t mi;
                   3030:        int mixer_class;
                   3031:        int error;
                   3032:
                   3033:        /* looking for ``outputs'' */
                   3034:        for (mi.index = 0; ; mi.index++) {
                   3035:                error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi);
                   3036:                if (error != 0)
                   3037:                        return (-1);
                   3038:
                   3039:                if (mi.type == AUDIO_MIXER_CLASS &&
                   3040:                    strcmp(mi.label.name, AudioCoutputs) == 0) {
                   3041:                        mixer_class = mi.mixer_class;
                   3042:                        break;
                   3043:                }
                   3044:        }
                   3045:
                   3046:        /*
                   3047:         * looking for ``outputs.master''
                   3048:         * start mi.index from 0 because ''outputs.master'' can precede
                   3049:         * ''outputs''.
                   3050:         */
                   3051:        for (mi.index = 0; ; mi.index++) {
                   3052:                error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi);
                   3053:                if (error != 0)
                   3054:                        return (-1);
                   3055:
                   3056:                if (mi.type == AUDIO_MIXER_VALUE &&
                   3057:                    mi.mixer_class == mixer_class &&
                   3058:                    strcmp(mi.label.name, AudioNmaster) == 0) {
                   3059:                        if (dir == 0) {
                   3060:                                /* looking for ``outputs.master.mute'' */
                   3061:                                if (mi.next < 0)
                   3062:                                        return (-1);
                   3063:
                   3064:                                mi.index = mi.next;
                   3065:                                error = sc->hw_if->query_devinfo(sc->hw_hdl,
                   3066:                                    &mi);
                   3067:                                if (error != 0)
                   3068:                                        return (-1);
                   3069:
                   3070:                                if (mi.type != AUDIO_MIXER_ENUM ||
                   3071:                                    strcmp(mi.label.name, AudioNmute) != 0)
                   3072:                                        return (-1);
                   3073:                        }
                   3074:
                   3075:                        *index = mi.index;
                   3076:                        return (0);
                   3077:                }
                   3078:        }
                   3079:
                   3080:        return (-1);
                   3081: }
                   3082:
                   3083: int
                   3084: wskbd_set_mixervolume(long dir)
                   3085: {
                   3086:        struct audio_softc *sc;
                   3087:        mixer_devinfo_t mi;
                   3088:        mixer_ctrl_t ct;
                   3089:        int l, r;
                   3090:        int error;
                   3091:
                   3092:        if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) {
                   3093:                DPRINTF(("wskbd_set_mixervolume: audio_cd\n"));
                   3094:                return (ENXIO);
                   3095:        }
                   3096:
                   3097:        error = wskbd_get_mixerdev(sc, dir, &ct.dev);
                   3098:        if (error == -1) {
                   3099:                DPRINTF(("wskbd_set_mixervolume: wskbd_get_mixerdev\n"));
                   3100:                return (ENXIO);
                   3101:        }
                   3102:
                   3103:        if (dir == 0) {
                   3104:                /*
                   3105:                 * Mute.
                   3106:                 * Use mixer_ioctl() for writing. It does many things for us.
                   3107:                 */
                   3108:                ct.type = AUDIO_MIXER_ENUM;
                   3109:                error = sc->hw_if->get_port(sc->hw_hdl, &ct);
                   3110:                if (error != 0) {
                   3111:                        DPRINTF(("wskbd_set_mixervolume:"
                   3112:                            " get_port: %d\n", error));
                   3113:                        return (error);
                   3114:                }
                   3115:
                   3116:                ct.un.ord = !ct.un.ord; /* toggle */
                   3117:
                   3118:                error = mixer_ioctl(MIXER_DEVICE,
                   3119:                    AUDIO_MIXER_WRITE, (caddr_t)&ct, FWRITE, curproc);
                   3120:                if (error != 0) {
                   3121:                        DPRINTF(("wskbd_set_mixervolume:"
                   3122:                            " mixer_ioctl: %d\n", error));
                   3123:                        return (error);
                   3124:                }
                   3125:        } else {
                   3126:                mi.index = ct.dev;
                   3127:                error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi);
                   3128:                if (error != 0) {
                   3129:                        DPRINTF(("wskbd_set_mixervolume:"
                   3130:                            " query_devinfo: %d\n", error));
                   3131:                        return (error);
                   3132:                }
                   3133:
                   3134:                ct.type = AUDIO_MIXER_VALUE;
                   3135:
                   3136:                error = au_get_lr_value(sc, &ct, &l, &r);
                   3137:                if (error != 0) {
                   3138:                        DPRINTF(("wskbd_set_mixervolume:"
                   3139:                            " au_get_lr_value: %d\n", error));
                   3140:                        return (error);
                   3141:                }
                   3142:
                   3143:                if (dir > 0) {
                   3144:                        /*
                   3145:                         * Raise volume
                   3146:                         */
                   3147:                        if (l > AUDIO_MAX_GAIN - mi.un.v.delta)
                   3148:                                l = AUDIO_MAX_GAIN;
                   3149:                        else
                   3150:                                l += mi.un.v.delta;
                   3151:
                   3152:                        if (r > AUDIO_MAX_GAIN - mi.un.v.delta)
                   3153:                                r = AUDIO_MAX_GAIN;
                   3154:                        else
                   3155:                                r += mi.un.v.delta;
                   3156:
                   3157:                } else {
                   3158:                        /*
                   3159:                         * Lower volume
                   3160:                         */
                   3161:                        if (l < AUDIO_MIN_GAIN + mi.un.v.delta)
                   3162:                                l = AUDIO_MIN_GAIN;
                   3163:                        else
                   3164:                                l -= mi.un.v.delta;
                   3165:
                   3166:                        if (r < AUDIO_MIN_GAIN + mi.un.v.delta)
                   3167:                                r = AUDIO_MIN_GAIN;
                   3168:                        else
                   3169:                                r -= mi.un.v.delta;
                   3170:                }
                   3171:
                   3172:                error = au_set_lr_value(sc, &ct, l, r);
                   3173:                if (error != 0) {
                   3174:                        DPRINTF(("wskbd_set_mixervolume:"
                   3175:                            " au_set_lr_value: %d\n", error));
                   3176:                        return (error);
                   3177:                }
                   3178:        }
                   3179:
                   3180:        return (0);
                   3181: }
                   3182: #endif /* NAUDIO > 0 && NWSKBD > 0 */

CVSweb