The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/audio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: d83aa3ba40832d8b6bf5321161dc666d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.