root/dev/isa/sbdsp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sb_printsc
  2. sbdsp_probe
  3. sbdsp_jazz16_probe
  4. sbdsp_attach
  5. sbdsp_mix_write
  6. sbdsp_mix_read
  7. sbdsp_query_encoding
  8. sbdsp_set_params
  9. sbdsp_set_ifilter
  10. sbdsp_get_ifilter
  11. sbdsp_set_in_ports
  12. sbdsp_speaker_ctl
  13. sbdsp_round_blocksize
  14. sbdsp_open
  15. sbdsp_close
  16. sbdsp_reset
  17. sbdsp_wdsp
  18. sbdsp_rdsp
  19. sbdsp_to
  20. sbdsp_pause
  21. sbdsp_spkron
  22. sbdsp_spkroff
  23. sbversion
  24. sbdsp_haltdma
  25. sbdsp_set_timeconst
  26. sbdsp16_set_rate
  27. sbdsp_trigger_input
  28. sbdsp_block_input
  29. sbdsp_trigger_output
  30. sbdsp_block_output
  31. sbdsp_intr
  32. sbdsp_adjust
  33. sbdsp_set_mixer_gain
  34. sbdsp_mixer_set_port
  35. sbdsp_mixer_get_port
  36. sbdsp_mixer_query_devinfo
  37. sb_malloc
  38. sb_free
  39. sb_round
  40. sb_mappage
  41. sbdsp_get_props
  42. sbdsp_midi_open
  43. sbdsp_midi_close
  44. sbdsp_midi_output
  45. sbdsp_midi_getinfo
  46. sbdsp_midi_intr

    1 /*      $OpenBSD: sbdsp.c,v 1.25 2006/12/29 13:04:37 pedro 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 /*
   38  * SoundBlaster Pro code provided by John Kohl, based on lots of
   39  * information he gleaned from Steve Haehnichen <steve@vigra.com>'s
   40  * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
   41  * <sachs@meibm15.cen.uiuc.edu>.
   42  * Lots of rewrites by Lennart Augustsson <augustss@cs.chalmers.se>
   43  * with information from SB "Hardware Programming Guide" and the
   44  * Linux drivers.
   45  */
   46 
   47 #include "midi.h"
   48 
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/errno.h>
   52 #include <sys/ioctl.h>
   53 #include <sys/syslog.h>
   54 #include <sys/device.h>
   55 #include <sys/proc.h>
   56 #include <sys/buf.h>
   57 
   58 #include <machine/cpu.h>
   59 #include <machine/intr.h>
   60 #include <machine/bus.h>
   61 
   62 #include <sys/audioio.h>
   63 #include <dev/audio_if.h>
   64 #include <dev/midi_if.h>
   65 #include <dev/mulaw.h>
   66 #include <dev/auconv.h>
   67 
   68 #include <dev/isa/isavar.h>
   69 #include <dev/isa/isadmavar.h>
   70 
   71 #include <dev/isa/sbreg.h>
   72 #include <dev/isa/sbdspvar.h>
   73 
   74 
   75 #ifdef AUDIO_DEBUG
   76 #define DPRINTF(x)      if (sbdspdebug) printf x
   77 #define DPRINTFN(n,x)   if (sbdspdebug >= (n)) printf x
   78 int     sbdspdebug = 0;
   79 #else
   80 #define DPRINTF(x)
   81 #define DPRINTFN(n,x)
   82 #endif
   83 
   84 #ifndef SBDSP_NPOLL
   85 #define SBDSP_NPOLL 3000
   86 #endif
   87 
   88 struct {
   89         int wdsp;
   90         int rdsp;
   91         int wmidi;
   92 } sberr;
   93 
   94 /*
   95  * Time constant routines follow.  See SBK, section 12.
   96  * Although they don't come out and say it (in the docs),
   97  * the card clearly uses a 1MHz countdown timer, as the
   98  * low-speed formula (p. 12-4) is:
   99  *      tc = 256 - 10^6 / sr
  100  * In high-speed mode, the constant is the upper byte of a 16-bit counter,
  101  * and a 256MHz clock is used:
  102  *      tc = 65536 - 256 * 10^ 6 / sr
  103  * Since we can only use the upper byte of the HS TC, the two formulae
  104  * are equivalent.  (Why didn't they say so?)  E.g.,
  105  *      (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
  106  *
  107  * The crossover point (from low- to high-speed modes) is different
  108  * for the SBPRO and SB20.  The table on p. 12-5 gives the following data:
  109  *
  110  *                              SBPRO                   SB20
  111  *                              -----                   --------
  112  * input ls min                 4       KHz             4       KHz
  113  * input ls max                 23      KHz             13      KHz
  114  * input hs max                 44.1    KHz             15      KHz
  115  * output ls min                4       KHz             4       KHz
  116  * output ls max                23      KHz             23      KHz
  117  * output hs max                44.1    KHz             44.1    KHz
  118  */
  119 /* XXX Should we round the tc?
  120 #define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
  121 */
  122 #define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
  123 #define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
  124 
  125 struct sbmode {
  126         short   model;
  127         u_char  channels;
  128         u_char  precision;
  129         u_short lowrate, highrate;
  130         u_char  cmd;
  131         u_char  cmdchan;
  132 };
  133 static struct sbmode sbpmodes[] = {
  134  { SB_1,    1,  8,  4000, 22727, SB_DSP_WDMA      },
  135  { SB_20,   1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
  136  { SB_2x,   1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
  137  { SB_2x,   1,  8, 22727, 45454, SB_DSP_HS_OUTPUT },
  138  { SB_PRO,  1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
  139  { SB_PRO,  1,  8, 22727, 45454, SB_DSP_HS_OUTPUT },
  140  { SB_PRO,  2,  8, 11025, 22727, SB_DSP_HS_OUTPUT },
  141  /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
  142  { SB_JAZZ, 1,  8,  4000, 22727, SB_DSP_WDMA_LOOP, SB_DSP_RECORD_MONO },
  143  { SB_JAZZ, 1,  8, 22727, 45454, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_MONO },
  144  { SB_JAZZ, 2,  8, 11025, 22727, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_STEREO },
  145  { SB_JAZZ, 1, 16,  4000, 22727, SB_DSP_WDMA_LOOP, JAZZ16_RECORD_MONO },
  146  { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_MONO },
  147  { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_STEREO },
  148  { SB_16,   1,  8,  5000, 45000, SB_DSP16_WDMA_8  },
  149  { SB_16,   2,  8,  5000, 45000, SB_DSP16_WDMA_8  },
  150 #define PLAY16 15 /* must be the index of the next entry in the table */
  151  { SB_16,   1, 16,  5000, 45000, SB_DSP16_WDMA_16 },
  152  { SB_16,   2, 16,  5000, 45000, SB_DSP16_WDMA_16 },
  153  { -1 }
  154 };
  155 static struct sbmode sbrmodes[] = {
  156  { SB_1,    1,  8,  4000, 12987, SB_DSP_RDMA      },
  157  { SB_20,   1,  8,  4000, 12987, SB_DSP_RDMA_LOOP },
  158  { SB_2x,   1,  8,  4000, 12987, SB_DSP_RDMA_LOOP },
  159  { SB_2x,   1,  8, 12987, 14925, SB_DSP_HS_INPUT  },
  160  { SB_PRO,  1,  8,  4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
  161  { SB_PRO,  1,  8, 22727, 45454, SB_DSP_HS_INPUT,  SB_DSP_RECORD_MONO },
  162  { SB_PRO,  2,  8, 11025, 22727, SB_DSP_HS_INPUT,  SB_DSP_RECORD_STEREO },
  163  { SB_JAZZ, 1,  8,  4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
  164  { SB_JAZZ, 1,  8, 22727, 45454, SB_DSP_HS_INPUT,  SB_DSP_RECORD_MONO },
  165  { SB_JAZZ, 2,  8, 11025, 22727, SB_DSP_HS_INPUT,  SB_DSP_RECORD_STEREO },
  166  { SB_JAZZ, 1, 16,  4000, 22727, SB_DSP_RDMA_LOOP, JAZZ16_RECORD_MONO },
  167  { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_INPUT,  JAZZ16_RECORD_MONO },
  168  { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_INPUT,  JAZZ16_RECORD_STEREO },
  169  { SB_16,   1,  8,  5000, 45000, SB_DSP16_RDMA_8  },
  170  { SB_16,   2,  8,  5000, 45000, SB_DSP16_RDMA_8  },
  171  { SB_16,   1, 16,  5000, 45000, SB_DSP16_RDMA_16 },
  172  { SB_16,   2, 16,  5000, 45000, SB_DSP16_RDMA_16 },
  173  { -1 }
  174 };
  175 
  176 void    sbversion(struct sbdsp_softc *);
  177 void    sbdsp_jazz16_probe(struct sbdsp_softc *);
  178 void    sbdsp_set_mixer_gain(struct sbdsp_softc *sc, int port);
  179 void    sbdsp_to(void *);
  180 void    sbdsp_pause(struct sbdsp_softc *);
  181 int     sbdsp_set_timeconst(struct sbdsp_softc *, int);
  182 int     sbdsp16_set_rate(struct sbdsp_softc *, int, int);
  183 int     sbdsp_set_in_ports(struct sbdsp_softc *, int);
  184 void    sbdsp_set_ifilter(void *, int);
  185 int     sbdsp_get_ifilter(void *);
  186 
  187 int     sbdsp_block_output(void *);
  188 int     sbdsp_block_input(void *);
  189 static  int sbdsp_adjust(int, int);
  190 
  191 int     sbdsp_midi_intr(void *);
  192 
  193 #ifdef AUDIO_DEBUG
  194 void    sb_printsc(struct sbdsp_softc *);
  195 
  196 void
  197 sb_printsc(sc)
  198         struct sbdsp_softc *sc;
  199 {
  200         int i;
  201 
  202         printf("open %d dmachan %d/%d %d/%d iobase 0x%x irq %d\n",
  203             (int)sc->sc_open, sc->sc_i.run, sc->sc_o.run,
  204             sc->sc_drq8, sc->sc_drq16,
  205             sc->sc_iobase, sc->sc_irq);
  206         printf("irate %d itc %x orate %d otc %x\n",
  207             sc->sc_i.rate, sc->sc_i.tc,
  208             sc->sc_o.rate, sc->sc_o.tc);
  209         printf("spkron %u nintr %lu\n",
  210             sc->spkr_state, sc->sc_interrupts);
  211         printf("intr8 %p arg8 %p\n",
  212             sc->sc_intr8, sc->sc_arg16);
  213         printf("intr16 %p arg16 %p\n",
  214             sc->sc_intr8, sc->sc_arg16);
  215         printf("gain:");
  216         for (i = 0; i < SB_NDEVS; i++)
  217                 printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
  218         printf("\n");
  219 }
  220 #endif /* AUDIO_DEBUG */
  221 
  222 /*
  223  * Probe / attach routines.
  224  */
  225 
  226 /*
  227  * Probe for the soundblaster hardware.
  228  */
  229 int
  230 sbdsp_probe(sc)
  231         struct sbdsp_softc *sc;
  232 {
  233 
  234         if (sbdsp_reset(sc) < 0) {
  235                 DPRINTF(("sbdsp: couldn't reset card\n"));
  236                 return 0;
  237         }
  238         /* if flags set, go and probe the jazz16 stuff */
  239         if (sc->sc_dev.dv_cfdata->cf_flags & 1)
  240                 sbdsp_jazz16_probe(sc);
  241         else
  242                 sbversion(sc);
  243         if (sc->sc_model == SB_UNK) {
  244                 /* Unknown SB model found. */
  245                 DPRINTF(("sbdsp: unknown SB model found\n"));
  246                 return 0;
  247         }
  248         return 1;
  249 }
  250 
  251 /*
  252  * Try add-on stuff for Jazz16.
  253  */
  254 void
  255 sbdsp_jazz16_probe(sc)
  256         struct sbdsp_softc *sc;
  257 {
  258         static u_char jazz16_irq_conf[16] = {
  259             -1, -1, 0x02, 0x03,
  260             -1, 0x01, -1, 0x04,
  261             -1, 0x02, 0x05, -1,
  262             -1, -1, -1, 0x06};
  263         static u_char jazz16_drq_conf[8] = {
  264             -1, 0x01, -1, 0x02,
  265             -1, 0x03, -1, 0x04};
  266 
  267         bus_space_tag_t iot = sc->sc_iot;
  268         bus_space_handle_t ioh;
  269 
  270         sbversion(sc);
  271 
  272         DPRINTF(("jazz16 probe\n"));
  273 
  274         if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
  275                 DPRINTF(("bus map failed\n"));
  276                 return;
  277         }
  278 
  279         if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
  280             jazz16_irq_conf[sc->sc_irq] == (u_char)-1) {
  281                 DPRINTF(("drq/irq check failed\n"));
  282                 goto done;              /* give up, we can't do it. */
  283         }
  284 
  285         bus_space_write_1(iot, ioh, 0, JAZZ16_WAKEUP);
  286         delay(10000);                   /* delay 10 ms */
  287         bus_space_write_1(iot, ioh, 0, JAZZ16_SETBASE);
  288         bus_space_write_1(iot, ioh, 0, sc->sc_iobase & 0x70);
  289 
  290         if (sbdsp_reset(sc) < 0) {
  291                 DPRINTF(("sbdsp_reset check failed\n"));
  292                 goto done;              /* XXX? what else could we do? */
  293         }
  294 
  295         if (sbdsp_wdsp(sc, JAZZ16_READ_VER)) {
  296                 DPRINTF(("read16 setup failed\n"));
  297                 goto done;
  298         }
  299 
  300         if (sbdsp_rdsp(sc) != JAZZ16_VER_JAZZ) {
  301                 DPRINTF(("read16 failed\n"));
  302                 goto done;
  303         }
  304 
  305         /* XXX set both 8 & 16-bit drq to same channel, it works fine. */
  306         sc->sc_drq16 = sc->sc_drq8;
  307         if (sbdsp_wdsp(sc, JAZZ16_SET_DMAINTR) ||
  308             sbdsp_wdsp(sc, (jazz16_drq_conf[sc->sc_drq16] << 4) |
  309                 jazz16_drq_conf[sc->sc_drq8]) ||
  310             sbdsp_wdsp(sc, jazz16_irq_conf[sc->sc_irq])) {
  311                 DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
  312         } else {
  313                 DPRINTF(("jazz16 detected!\n"));
  314                 sc->sc_model = SB_JAZZ;
  315                 sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
  316         }
  317 
  318 done:
  319         bus_space_unmap(iot, ioh, 1);
  320 }
  321 
  322 /*
  323  * Attach hardware to driver, attach hardware driver to audio
  324  * pseudo-device driver .
  325  */
  326 void
  327 sbdsp_attach(sc)
  328         struct sbdsp_softc *sc;
  329 {
  330         struct audio_params pparams, rparams;
  331         int i;
  332         u_int v;
  333 
  334         /*
  335          * Create our DMA maps.
  336          */
  337         if (sc->sc_drq8 != -1) {
  338                 if (isa_dmamap_create(sc->sc_isa, sc->sc_drq8,
  339                     MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
  340                         printf("%s: can't create map for drq %d\n",
  341                             sc->sc_dev.dv_xname, sc->sc_drq8);
  342                         return;
  343                 }
  344         }
  345         if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8) {
  346                 if (isa_dmamap_create(sc->sc_isa, sc->sc_drq16,
  347                     MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
  348                         printf("%s: can't create map for drq %d\n",
  349                             sc->sc_dev.dv_xname, sc->sc_drq16);
  350                         return;
  351                 }
  352         }
  353 
  354         pparams = audio_default;
  355         rparams = audio_default;
  356         sbdsp_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
  357 
  358         sbdsp_set_in_ports(sc, 1 << SB_MIC_VOL);
  359 
  360         if (sc->sc_mixer_model != SBM_NONE) {
  361                 /* Reset the mixer.*/
  362                 sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
  363                 /* And set our own default values */
  364                 for (i = 0; i < SB_NDEVS; i++) {
  365                         switch(i) {
  366                         case SB_MIC_VOL:
  367                         case SB_LINE_IN_VOL:
  368                                 v = 0;
  369                                 break;
  370                         case SB_BASS:
  371                         case SB_TREBLE:
  372                                 v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN/2);
  373                                 break;
  374                         case SB_CD_IN_MUTE:
  375                         case SB_MIC_IN_MUTE:
  376                         case SB_LINE_IN_MUTE:
  377                         case SB_MIDI_IN_MUTE:
  378                         case SB_CD_SWAP:
  379                         case SB_MIC_SWAP:
  380                         case SB_LINE_SWAP:
  381                         case SB_MIDI_SWAP:
  382                         case SB_CD_OUT_MUTE:
  383                         case SB_MIC_OUT_MUTE:
  384                         case SB_LINE_OUT_MUTE:
  385                                 v = 0;
  386                                 break;
  387                         default:
  388                                 v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
  389                                 break;
  390                         }
  391                         sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
  392                         sbdsp_set_mixer_gain(sc, i);
  393                 }
  394                 sc->in_filter = 0;      /* no filters turned on, please */
  395         }
  396 
  397         printf(": dsp v%d.%02d%s\n",
  398                SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
  399                sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
  400 
  401         timeout_set(&sc->sc_tmo, sbdsp_to, sbdsp_to);
  402         sc->sc_fullduplex = ISSB16CLASS(sc) &&
  403                 sc->sc_drq8 != -1 && sc->sc_drq16 != -1 &&
  404                 sc->sc_drq8 != sc->sc_drq16;
  405 }
  406 
  407 void
  408 sbdsp_mix_write(sc, mixerport, val)
  409         struct sbdsp_softc *sc;
  410         int mixerport;
  411         int val;
  412 {
  413         bus_space_tag_t iot = sc->sc_iot;
  414         bus_space_handle_t ioh = sc->sc_ioh;
  415         int s;
  416 
  417         s = splaudio();
  418         bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
  419         delay(20);
  420         bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
  421         delay(30);
  422         splx(s);
  423 }
  424 
  425 int
  426 sbdsp_mix_read(sc, mixerport)
  427         struct sbdsp_softc *sc;
  428         int mixerport;
  429 {
  430         bus_space_tag_t iot = sc->sc_iot;
  431         bus_space_handle_t ioh = sc->sc_ioh;
  432         int val;
  433         int s;
  434 
  435         s = splaudio();
  436         bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
  437         delay(20);
  438         val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
  439         delay(30);
  440         splx(s);
  441         return val;
  442 }
  443 
  444 /*
  445  * Various routines to interface to higher level audio driver
  446  */
  447 
  448 int
  449 sbdsp_query_encoding(addr, fp)
  450         void *addr;
  451         struct audio_encoding *fp;
  452 {
  453         struct sbdsp_softc *sc = addr;
  454         int emul;
  455 
  456         emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
  457 
  458         switch (fp->index) {
  459         case 0:
  460                 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
  461                 fp->encoding = AUDIO_ENCODING_ULINEAR;
  462                 fp->precision = 8;
  463                 fp->flags = 0;
  464                 return 0;
  465         case 1:
  466                 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
  467                 fp->encoding = AUDIO_ENCODING_ULAW;
  468                 fp->precision = 8;
  469                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  470                 return 0;
  471         case 2:
  472                 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
  473                 fp->encoding = AUDIO_ENCODING_ALAW;
  474                 fp->precision = 8;
  475                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  476                 return 0;
  477         case 3:
  478                 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
  479                 fp->encoding = AUDIO_ENCODING_SLINEAR;
  480                 fp->precision = 8;
  481                 fp->flags = emul;
  482                 return 0;
  483         }
  484         if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
  485                 return EINVAL;
  486 
  487         switch(fp->index) {
  488         case 4:
  489                 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
  490                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  491                 fp->precision = 16;
  492                 fp->flags = 0;
  493                 return 0;
  494         case 5:
  495                 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
  496                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  497                 fp->precision = 16;
  498                 fp->flags = emul;
  499                 return 0;
  500         case 6:
  501                 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
  502                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  503                 fp->precision = 16;
  504                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  505                 return 0;
  506         case 7:
  507                 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
  508                 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
  509                 fp->precision = 16;
  510                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  511                 return 0;
  512         default:
  513                 return EINVAL;
  514         }
  515         return 0;
  516 }
  517 
  518 int
  519 sbdsp_set_params(addr, setmode, usemode, play, rec)
  520         void *addr;
  521         int setmode, usemode;
  522         struct audio_params *play, *rec;
  523 {
  524         struct sbdsp_softc *sc = addr;
  525         struct sbmode *m;
  526         u_int rate, tc, bmode;
  527         void (*swcode)(void *, u_char *buf, int cnt);
  528         int factor;
  529         int model;
  530         int chan;
  531         struct audio_params *p;
  532         int mode;
  533 
  534         if (sc->sc_open == SB_OPEN_MIDI)
  535                 return EBUSY;
  536 
  537         model = sc->sc_model;
  538         if (model > SB_16)
  539                 model = SB_16;  /* later models work like SB16 */
  540 
  541         /*
  542          * Prior to the SB16, we have only one clock, so make the sample
  543          * rates match.
  544          */
  545         if (!ISSB16CLASS(sc) &&
  546             play->sample_rate != rec->sample_rate &&
  547             usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
  548                 if (setmode == AUMODE_PLAY) {
  549                         rec->sample_rate = play->sample_rate;
  550                         setmode |= AUMODE_RECORD;
  551                 } else if (setmode == AUMODE_RECORD) {
  552                         play->sample_rate = rec->sample_rate;
  553                         setmode |= AUMODE_PLAY;
  554                 } else
  555                         return (EINVAL);
  556         }
  557 
  558         /* Set first record info, then play info */
  559         for (mode = AUMODE_RECORD; mode != -1;
  560              mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
  561                 if ((setmode & mode) == 0)
  562                         continue;
  563 
  564                 p = mode == AUMODE_PLAY ? play : rec;
  565                 /* Locate proper commands */
  566                 for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
  567                     m->model != -1; m++) {
  568                         if (model == m->model &&
  569                             p->channels == m->channels &&
  570                             p->precision == m->precision &&
  571                             p->sample_rate >= m->lowrate &&
  572                             p->sample_rate <= m->highrate)
  573                                 break;
  574                 }
  575                 if (m->model == -1)
  576                         return EINVAL;
  577                 rate = p->sample_rate;
  578                 swcode = 0;
  579                 factor = 1;
  580                 tc = 1;
  581                 bmode = -1;
  582                 if (model == SB_16) {
  583                         switch (p->encoding) {
  584                         case AUDIO_ENCODING_SLINEAR_BE:
  585                                 if (p->precision == 16)
  586                                         swcode = swap_bytes;
  587                                 /* fall into */
  588                         case AUDIO_ENCODING_SLINEAR_LE:
  589                                 bmode = SB_BMODE_SIGNED;
  590                                 break;
  591                         case AUDIO_ENCODING_ULINEAR_BE:
  592                                 if (p->precision == 16)
  593                                         swcode = swap_bytes;
  594                                 /* fall into */
  595                         case AUDIO_ENCODING_ULINEAR_LE:
  596                                 bmode = SB_BMODE_UNSIGNED;
  597                                 break;
  598                         case AUDIO_ENCODING_ULAW:
  599                                 if (mode == AUMODE_PLAY) {
  600                                         swcode = mulaw_to_ulinear16;
  601                                         factor = 2;
  602                                         m = &sbpmodes[PLAY16];
  603                                 } else
  604                                         swcode = ulinear8_to_mulaw;
  605                                 bmode = SB_BMODE_UNSIGNED;
  606                                 break;
  607                         case AUDIO_ENCODING_ALAW:
  608                                 if (mode == AUMODE_PLAY) {
  609                                         swcode = alaw_to_ulinear16;
  610                                         factor = 2;
  611                                         m = &sbpmodes[PLAY16];
  612                                 } else
  613                                         swcode = ulinear8_to_alaw;
  614                                 bmode = SB_BMODE_UNSIGNED;
  615                                 break;
  616                         default:
  617                                 return EINVAL;
  618                         }
  619                         if (p->channels == 2)
  620                                 bmode |= SB_BMODE_STEREO;
  621                 } else if (m->model == SB_JAZZ && m->precision == 16) {
  622                         switch (p->encoding) {
  623                         case AUDIO_ENCODING_SLINEAR_LE:
  624                                 break;
  625                         case AUDIO_ENCODING_ULINEAR_LE:
  626                                 swcode = change_sign16;
  627                                 break;
  628                         case AUDIO_ENCODING_SLINEAR_BE:
  629                                 swcode = swap_bytes;
  630                                 break;
  631                         case AUDIO_ENCODING_ULINEAR_BE:
  632                                 swcode = mode == AUMODE_PLAY ?
  633                                         swap_bytes_change_sign16 : change_sign16_swap_bytes;
  634                                 break;
  635                         case AUDIO_ENCODING_ULAW:
  636                                 swcode = mode == AUMODE_PLAY ?
  637                                         mulaw_to_ulinear8 : ulinear8_to_mulaw;
  638                                 break;
  639                         case AUDIO_ENCODING_ALAW:
  640                                 swcode = mode == AUMODE_PLAY ?
  641                                         alaw_to_ulinear8 : ulinear8_to_alaw;
  642                                 break;
  643                         default:
  644                                 return EINVAL;
  645                         }
  646                         tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
  647                         p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
  648                 } else {
  649                         switch (p->encoding) {
  650                         case AUDIO_ENCODING_SLINEAR_BE:
  651                         case AUDIO_ENCODING_SLINEAR_LE:
  652                                 swcode = change_sign8;
  653                                 break;
  654                         case AUDIO_ENCODING_ULINEAR_BE:
  655                         case AUDIO_ENCODING_ULINEAR_LE:
  656                                 break;
  657                         case AUDIO_ENCODING_ULAW:
  658                                 swcode = mode == AUMODE_PLAY ?
  659                                         mulaw_to_ulinear8 : ulinear8_to_mulaw;
  660                                 break;
  661                         case AUDIO_ENCODING_ALAW:
  662                                 swcode = mode == AUMODE_PLAY ?
  663                                         alaw_to_ulinear8 : ulinear8_to_alaw;
  664                                 break;
  665                         default:
  666                                 return EINVAL;
  667                         }
  668                         tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
  669                         p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
  670                 }
  671 
  672                 chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
  673                 if (mode == AUMODE_PLAY) {
  674                         sc->sc_o.rate = rate;
  675                         sc->sc_o.tc = tc;
  676                         sc->sc_o.modep = m;
  677                         sc->sc_o.bmode = bmode;
  678                         sc->sc_o.dmachan = chan;
  679                 } else {
  680                         sc->sc_i.rate = rate;
  681                         sc->sc_i.tc = tc;
  682                         sc->sc_i.modep = m;
  683                         sc->sc_i.bmode = bmode;
  684                         sc->sc_i.dmachan = chan;
  685                 }
  686 
  687                 p->sw_code = swcode;
  688                 p->factor = factor;
  689                 DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x, swcode=%p, factor=%d\n",
  690                          sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
  691                          p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
  692 
  693         }
  694 
  695         /*
  696          * XXX
  697          * Should wait for chip to be idle.
  698          */
  699         sc->sc_i.run = SB_NOTRUNNING;
  700         sc->sc_o.run = SB_NOTRUNNING;
  701 
  702         if (sc->sc_fullduplex &&
  703             usemode == (AUMODE_PLAY | AUMODE_RECORD) &&
  704             sc->sc_i.dmachan == sc->sc_o.dmachan) {
  705                 DPRINTF(("sbdsp_set_params: fd=%d, usemode=%d, idma=%d, odma=%d\n", sc->sc_fullduplex, usemode, sc->sc_i.dmachan, sc->sc_o.dmachan));
  706                 if (sc->sc_o.dmachan == sc->sc_drq8) {
  707                         /* Use 16 bit DMA for playing by expanding the samples. */
  708                         play->sw_code = linear8_to_linear16;
  709                         play->factor = 2;
  710                         sc->sc_o.modep = &sbpmodes[PLAY16];
  711                         sc->sc_o.dmachan = sc->sc_drq16;
  712                 } else {
  713                         return EINVAL;
  714                 }
  715         }
  716         DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
  717                  sc->sc_i.dmachan, sc->sc_o.dmachan));
  718 
  719         return 0;
  720 }
  721 
  722 void
  723 sbdsp_set_ifilter(addr, which)
  724         void *addr;
  725         int which;
  726 {
  727         struct sbdsp_softc *sc = addr;
  728         int mixval;
  729 
  730         mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
  731         switch (which) {
  732         case 0:
  733                 mixval |= SBP_FILTER_OFF;
  734                 break;
  735         case SB_TREBLE:
  736                 mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
  737                 break;
  738         case SB_BASS:
  739                 mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
  740                 break;
  741         default:
  742                 return;
  743         }
  744         sc->in_filter = mixval & SBP_IFILTER_MASK;
  745         sbdsp_mix_write(sc, SBP_INFILTER, mixval);
  746 }
  747 
  748 int
  749 sbdsp_get_ifilter(addr)
  750         void *addr;
  751 {
  752         struct sbdsp_softc *sc = addr;
  753 
  754         sc->in_filter =
  755                 sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
  756         switch (sc->in_filter) {
  757         case SBP_FILTER_ON|SBP_IFILTER_HIGH:
  758                 return SB_TREBLE;
  759         case SBP_FILTER_ON|SBP_IFILTER_LOW:
  760                 return SB_BASS;
  761         default:
  762                 return 0;
  763         }
  764 }
  765 
  766 int
  767 sbdsp_set_in_ports(sc, mask)
  768         struct sbdsp_softc *sc;
  769         int mask;
  770 {
  771         int bitsl, bitsr;
  772         int sbport;
  773 
  774         if (sc->sc_open == SB_OPEN_MIDI)
  775                 return EBUSY;
  776 
  777         DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
  778                  sc->sc_mixer_model, mask));
  779 
  780         switch(sc->sc_mixer_model) {
  781         case SBM_NONE:
  782                 return EINVAL;
  783         case SBM_CT1335:
  784                 if (mask != (1 << SB_MIC_VOL))
  785                         return EINVAL;
  786                 break;
  787         case SBM_CT1345:
  788                 switch (mask) {
  789                 case 1 << SB_MIC_VOL:
  790                         sbport = SBP_FROM_MIC;
  791                         break;
  792                 case 1 << SB_LINE_IN_VOL:
  793                         sbport = SBP_FROM_LINE;
  794                         break;
  795                 case 1 << SB_CD_VOL:
  796                         sbport = SBP_FROM_CD;
  797                         break;
  798                 default:
  799                         return (EINVAL);
  800                 }
  801                 sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
  802                 break;
  803         case SBM_CT1XX5:
  804         case SBM_CT1745:
  805                 if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
  806                              (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
  807                         return EINVAL;
  808                 bitsr = 0;
  809                 if (mask & (1<<SB_MIDI_VOL))    bitsr |= SBP_MIDI_SRC_R;
  810                 if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
  811                 if (mask & (1<<SB_CD_VOL))      bitsr |= SBP_CD_SRC_R;
  812                 bitsl = SB_SRC_R_TO_L(bitsr);
  813                 if (mask & (1<<SB_MIC_VOL)) {
  814                         bitsl |= SBP_MIC_SRC;
  815                         bitsr |= SBP_MIC_SRC;
  816                 }
  817                 sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
  818                 sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
  819                 break;
  820         }
  821         sc->in_mask = mask;
  822 
  823         return 0;
  824 }
  825 
  826 int
  827 sbdsp_speaker_ctl(addr, newstate)
  828         void *addr;
  829         int newstate;
  830 {
  831         struct sbdsp_softc *sc = addr;
  832 
  833         if (sc->sc_open == SB_OPEN_MIDI)
  834                 return EBUSY;
  835 
  836         if ((newstate == SPKR_ON) &&
  837             (sc->spkr_state == SPKR_OFF)) {
  838                 sbdsp_spkron(sc);
  839                 sc->spkr_state = SPKR_ON;
  840         }
  841         if ((newstate == SPKR_OFF) &&
  842             (sc->spkr_state == SPKR_ON)) {
  843                 sbdsp_spkroff(sc);
  844                 sc->spkr_state = SPKR_OFF;
  845         }
  846         return 0;
  847 }
  848 
  849 int
  850 sbdsp_round_blocksize(addr, blk)
  851         void *addr;
  852         int blk;
  853 {
  854         return (blk + 3) & -4;  /* round to biggest sample size */
  855 }
  856 
  857 int
  858 sbdsp_open(addr, flags)
  859         void *addr;
  860         int flags;
  861 {
  862         struct sbdsp_softc *sc = addr;
  863 
  864         DPRINTF(("sbdsp_open: sc=%p\n", sc));
  865 
  866         if (sc->sc_open != SB_CLOSED)
  867                 return EBUSY;
  868         if (sbdsp_reset(sc) != 0)
  869                 return EIO;
  870 
  871         sc->sc_open = SB_OPEN_AUDIO;
  872         sc->sc_openflags = flags;
  873         sc->sc_intrm = 0;
  874         if (ISSBPRO(sc) &&
  875             sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
  876                 DPRINTF(("sbdsp_open: can't set mono mode\n"));
  877                 /* we'll readjust when it's time for DMA. */
  878         }
  879 
  880         /*
  881          * Leave most things as they were; users must change things if
  882          * the previous process didn't leave it they way they wanted.
  883          * Looked at another way, it's easy to set up a configuration
  884          * in one program and leave it for another to inherit.
  885          */
  886         DPRINTF(("sbdsp_open: opened\n"));
  887 
  888         return 0;
  889 }
  890 
  891 void
  892 sbdsp_close(addr)
  893         void *addr;
  894 {
  895         struct sbdsp_softc *sc = addr;
  896 
  897         DPRINTF(("sbdsp_close: sc=%p\n", sc));
  898 
  899         sc->sc_open = SB_CLOSED;
  900         sbdsp_spkroff(sc);
  901         sc->spkr_state = SPKR_OFF;
  902         sc->sc_intr8 = 0;
  903         sc->sc_intr16 = 0;
  904         sc->sc_intrm = 0;
  905         sbdsp_haltdma(sc);
  906 
  907         DPRINTF(("sbdsp_close: closed\n"));
  908 }
  909 
  910 /*
  911  * Lower-level routines
  912  */
  913 
  914 /*
  915  * Reset the card.
  916  * Return non-zero if the card isn't detected.
  917  */
  918 int
  919 sbdsp_reset(sc)
  920         struct sbdsp_softc *sc;
  921 {
  922         bus_space_tag_t iot = sc->sc_iot;
  923         bus_space_handle_t ioh = sc->sc_ioh;
  924 
  925         sc->sc_intr8 = 0;
  926         sc->sc_intr16 = 0;
  927         if (sc->sc_i.run != SB_NOTRUNNING) {
  928                 isa_dmaabort(sc->sc_isa, sc->sc_i.dmachan);
  929                 sc->sc_i.run = SB_NOTRUNNING;
  930         }
  931         if (sc->sc_o.run != SB_NOTRUNNING) {
  932                 isa_dmaabort(sc->sc_isa, sc->sc_o.dmachan);
  933                 sc->sc_o.run = SB_NOTRUNNING;
  934         }
  935 
  936         /*
  937          * See SBK, section 11.3.
  938          * We pulse a reset signal into the card.
  939          * Gee, what a brilliant hardware design.
  940          */
  941         bus_space_write_1(iot, ioh, SBP_DSP_RESET, 1);
  942         delay(10);
  943         bus_space_write_1(iot, ioh, SBP_DSP_RESET, 0);
  944         delay(30);
  945         if (sbdsp_rdsp(sc) != SB_MAGIC)
  946                 return -1;
  947 
  948         return 0;
  949 }
  950 
  951 /*
  952  * Write a byte to the dsp.
  953  * We are at the mercy of the card as we use a
  954  * polling loop and wait until it can take the byte.
  955  */
  956 int
  957 sbdsp_wdsp(sc, v)
  958         struct sbdsp_softc *sc;
  959         int v;
  960 {
  961         bus_space_tag_t iot = sc->sc_iot;
  962         bus_space_handle_t ioh = sc->sc_ioh;
  963         int i;
  964         u_char x;
  965 
  966         for (i = SBDSP_NPOLL; --i >= 0; ) {
  967                 x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
  968                 delay(10);
  969                 if ((x & SB_DSP_BUSY) == 0) {
  970                         bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
  971                         delay(10);
  972                         return 0;
  973                 }
  974         }
  975         ++sberr.wdsp;
  976         return -1;
  977 }
  978 
  979 /*
  980  * Read a byte from the DSP, using polling.
  981  */
  982 int
  983 sbdsp_rdsp(sc)
  984         struct sbdsp_softc *sc;
  985 {
  986         bus_space_tag_t iot = sc->sc_iot;
  987         bus_space_handle_t ioh = sc->sc_ioh;
  988         int i;
  989         u_char x;
  990 
  991         for (i = SBDSP_NPOLL; --i >= 0; ) {
  992                 x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
  993                 delay(10);
  994                 if (x & SB_DSP_READY) {
  995                         x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
  996                         delay(10);
  997                         return x;
  998                 }
  999         }
 1000         ++sberr.rdsp;
 1001         return -1;
 1002 }
 1003 
 1004 /*
 1005  * Doing certain things (like toggling the speaker) make
 1006  * the SB hardware go away for a while, so pause a little.
 1007  */
 1008 void
 1009 sbdsp_to(arg)
 1010         void *arg;
 1011 {
 1012         wakeup(arg);
 1013 }
 1014 
 1015 void
 1016 sbdsp_pause(sc)
 1017         struct sbdsp_softc *sc;
 1018 {
 1019         extern int hz;
 1020 
 1021         timeout_add(&sc->sc_tmo, hz/8);
 1022         (void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
 1023 }
 1024 
 1025 /*
 1026  * Turn on the speaker.  The SBK documention says this operation
 1027  * can take up to 1/10 of a second.  Higher level layers should
 1028  * probably let the task sleep for this amount of time after
 1029  * calling here.  Otherwise, things might not work (because
 1030  * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
 1031  *
 1032  * These engineers had their heads up their ass when
 1033  * they designed this card.
 1034  */
 1035 void
 1036 sbdsp_spkron(sc)
 1037         struct sbdsp_softc *sc;
 1038 {
 1039         (void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
 1040         sbdsp_pause(sc);
 1041 }
 1042 
 1043 /*
 1044  * Turn off the speaker; see comment above.
 1045  */
 1046 void
 1047 sbdsp_spkroff(sc)
 1048         struct sbdsp_softc *sc;
 1049 {
 1050         (void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
 1051         sbdsp_pause(sc);
 1052 }
 1053 
 1054 /*
 1055  * Read the version number out of the card.
 1056  * Store version information in the softc.
 1057  */
 1058 void
 1059 sbversion(sc)
 1060         struct sbdsp_softc *sc;
 1061 {
 1062         int v;
 1063 
 1064         sc->sc_model = SB_UNK;
 1065         sc->sc_version = 0;
 1066         if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
 1067                 return;
 1068         v = sbdsp_rdsp(sc) << 8;
 1069         v |= sbdsp_rdsp(sc);
 1070         if (v < 0)
 1071                 return;
 1072         sc->sc_version = v;
 1073         switch(SBVER_MAJOR(v)) {
 1074         case 1:
 1075                 sc->sc_mixer_model = SBM_NONE;
 1076                 sc->sc_model = SB_1;
 1077                 break;
 1078         case 2:
 1079                 /* Some SB2 have a mixer, some don't. */
 1080                 sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
 1081                 sbdsp_mix_write(sc, SBP_1335_MIDI_VOL,   0x06);
 1082                 /* Check if we can read back the mixer values. */
 1083                 if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
 1084                     (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL)   & 0x0e) == 0x06)
 1085                         sc->sc_mixer_model = SBM_CT1335;
 1086                 else
 1087                         sc->sc_mixer_model = SBM_NONE;
 1088                 if (SBVER_MINOR(v) == 0)
 1089                         sc->sc_model = SB_20;
 1090                 else
 1091                         sc->sc_model = SB_2x;
 1092                 break;
 1093         case 3:
 1094                 sc->sc_mixer_model = SBM_CT1345;
 1095                 sc->sc_model = SB_PRO;
 1096                 break;
 1097         case 4:
 1098 #if 0
 1099 /* XXX This does not work */
 1100                 /* Most SB16 have a tone controls, but some don't. */
 1101                 sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
 1102                 /* Check if we can read back the mixer value. */
 1103                 if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
 1104                         sc->sc_mixer_model = SBM_CT1745;
 1105                 else
 1106                         sc->sc_mixer_model = SBM_CT1XX5;
 1107 #else
 1108                 sc->sc_mixer_model = SBM_CT1745;
 1109 #endif
 1110 #if 0
 1111 /* XXX figure out a good way of determining the model */
 1112                 /* XXX what about SB_32 */
 1113                 if (SBVER_MINOR(v) == 16)
 1114                         sc->sc_model = SB_64;
 1115                 else
 1116 #endif
 1117                         sc->sc_model = SB_16;
 1118                 break;
 1119         }
 1120 }
 1121 
 1122 /*
 1123  * Halt a DMA in progress.
 1124  */
 1125 int
 1126 sbdsp_haltdma(addr)
 1127         void *addr;
 1128 {
 1129         struct sbdsp_softc *sc = addr;
 1130 
 1131         DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
 1132 
 1133         sbdsp_reset(sc);
 1134         return 0;
 1135 }
 1136 
 1137 int
 1138 sbdsp_set_timeconst(sc, tc)
 1139         struct sbdsp_softc *sc;
 1140         int tc;
 1141 {
 1142         DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
 1143 
 1144         if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
 1145             sbdsp_wdsp(sc, tc) < 0)
 1146                 return EIO;
 1147 
 1148         return 0;
 1149 }
 1150 
 1151 int
 1152 sbdsp16_set_rate(sc, cmd, rate)
 1153         struct sbdsp_softc *sc;
 1154         int cmd, rate;
 1155 {
 1156         DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
 1157 
 1158         if (sbdsp_wdsp(sc, cmd) < 0 ||
 1159             sbdsp_wdsp(sc, rate >> 8) < 0 ||
 1160             sbdsp_wdsp(sc, rate) < 0)
 1161                 return EIO;
 1162         return 0;
 1163 }
 1164 
 1165 int
 1166 sbdsp_trigger_input(addr, start, end, blksize, intr, arg, param)
 1167         void *addr;
 1168         void *start, *end;
 1169         int blksize;
 1170         void (*intr)(void *);
 1171         void *arg;
 1172         struct audio_params *param;
 1173 {
 1174         struct sbdsp_softc *sc = addr;
 1175         int stereo = param->channels == 2;
 1176         int width = param->precision * param->factor;
 1177         int filter;
 1178 
 1179 #ifdef DIAGNOSTIC
 1180         if (stereo && (blksize & 1)) {
 1181                 DPRINTF(("stereo record odd bytes (%d)\n", blksize));
 1182                 return (EIO);
 1183         }
 1184 #endif
 1185 
 1186         sc->sc_intrr = intr;
 1187         sc->sc_argr = arg;
 1188 
 1189         if (width == 8) {
 1190 #ifdef DIAGNOSTIC
 1191                 if (sc->sc_i.dmachan != sc->sc_drq8) {
 1192                         printf("sbdsp_trigger_input: width=%d bad chan %d\n",
 1193                             width, sc->sc_i.dmachan);
 1194                         return (EIO);
 1195                 }
 1196 #endif
 1197                 sc->sc_intr8 = sbdsp_block_input;
 1198                 sc->sc_arg8 = addr;
 1199         } else {
 1200 #ifdef DIAGNOSTIC
 1201                 if (sc->sc_i.dmachan != sc->sc_drq16) {
 1202                         printf("sbdsp_trigger_input: width=%d bad chan %d\n",
 1203                             width, sc->sc_i.dmachan);
 1204                         return (EIO);
 1205                 }
 1206 #endif
 1207                 sc->sc_intr16 = sbdsp_block_input;
 1208                 sc->sc_arg16 = addr;
 1209         }
 1210 
 1211         if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
 1212                 blksize >>= 1;
 1213         --blksize;
 1214         sc->sc_i.blksize = blksize;
 1215 
 1216         if (ISSBPRO(sc)) {
 1217                 if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
 1218                         return (EIO);
 1219                 filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
 1220                 sbdsp_mix_write(sc, SBP_INFILTER,
 1221                     (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
 1222                     filter);
 1223         }
 1224 
 1225         if (ISSB16CLASS(sc)) {
 1226                 if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
 1227                         DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
 1228                                  sc->sc_i.rate));
 1229                         return (EIO);
 1230                 }
 1231         } else {
 1232                 if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
 1233                         DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
 1234                                  sc->sc_i.rate));
 1235                         return (EIO);
 1236                 }
 1237         }
 1238 
 1239         DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
 1240             start, end, sc->sc_i.dmachan));
 1241         isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, start, (char *)end -
 1242             (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
 1243 
 1244         return sbdsp_block_input(addr);
 1245 }
 1246 
 1247 int
 1248 sbdsp_block_input(addr)
 1249         void *addr;
 1250 {
 1251         struct sbdsp_softc *sc = addr;
 1252         int cc = sc->sc_i.blksize;
 1253 
 1254         DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
 1255 
 1256         if (sc->sc_i.run != SB_NOTRUNNING)
 1257                 sc->sc_intrr(sc->sc_argr);
 1258 
 1259         if (sc->sc_model == SB_1) {
 1260                 /* Non-looping mode, start DMA */
 1261                 if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
 1262                     sbdsp_wdsp(sc, cc) < 0 ||
 1263                     sbdsp_wdsp(sc, cc >> 8) < 0) {
 1264                         DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
 1265                         return (EIO);
 1266                 }
 1267                 sc->sc_i.run = SB_RUNNING;
 1268         } else if (sc->sc_i.run == SB_NOTRUNNING) {
 1269                 /* Initialize looping PCM */
 1270                 if (ISSB16CLASS(sc)) {
 1271                         DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
 1272                             sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
 1273                         if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
 1274                             sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
 1275                             sbdsp_wdsp(sc, cc) < 0 ||
 1276                             sbdsp_wdsp(sc, cc >> 8) < 0) {
 1277                                 DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
 1278                                 return (EIO);
 1279                         }
 1280                 } else {
 1281                         DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc));
 1282                         if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
 1283                             sbdsp_wdsp(sc, cc) < 0 ||
 1284                             sbdsp_wdsp(sc, cc >> 8) < 0) {
 1285                                 DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
 1286                                 return (EIO);
 1287                         }
 1288                         if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
 1289                                 DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
 1290                                 return (EIO);
 1291                         }
 1292                 }
 1293                 sc->sc_i.run = SB_LOOPING;
 1294         }
 1295 
 1296         return (0);
 1297 }
 1298 
 1299 int
 1300 sbdsp_trigger_output(addr, start, end, blksize, intr, arg, param)
 1301         void *addr;
 1302         void *start, *end;
 1303         int blksize;
 1304         void (*intr)(void *);
 1305         void *arg;
 1306         struct audio_params *param;
 1307 {
 1308         struct sbdsp_softc *sc = addr;
 1309         int stereo = param->channels == 2;
 1310         int width = param->precision * param->factor;
 1311         int cmd;
 1312 
 1313 #ifdef DIAGNOSTIC
 1314         if (stereo && (blksize & 1)) {
 1315                 DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
 1316                 return (EIO);
 1317         }
 1318 #endif
 1319 
 1320         sc->sc_intrp = intr;
 1321         sc->sc_argp = arg;
 1322 
 1323         if (width == 8) {
 1324 #ifdef DIAGNOSTIC
 1325                 if (sc->sc_o.dmachan != sc->sc_drq8) {
 1326                         printf("sbdsp_trigger_output: width=%d bad chan %d\n",
 1327                             width, sc->sc_o.dmachan);
 1328                         return (EIO);
 1329                 }
 1330 #endif
 1331                 sc->sc_intr8 = sbdsp_block_output;
 1332                 sc->sc_arg8 = addr;
 1333         } else {
 1334 #ifdef DIAGNOSTIC
 1335                 if (sc->sc_o.dmachan != sc->sc_drq16) {
 1336                         printf("sbdsp_trigger_output: width=%d bad chan %d\n",
 1337                             width, sc->sc_o.dmachan);
 1338                         return (EIO);
 1339                 }
 1340 #endif
 1341                 sc->sc_intr16 = sbdsp_block_output;
 1342                 sc->sc_arg16 = addr;
 1343         }
 1344 
 1345         if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
 1346                 blksize >>= 1;
 1347         --blksize;
 1348         sc->sc_o.blksize = blksize;
 1349 
 1350         if (ISSBPRO(sc)) {
 1351                 /* make sure we re-set stereo mixer bit when we start output. */
 1352                 sbdsp_mix_write(sc, SBP_STEREO,
 1353                     (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
 1354                     (stereo ?  SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
 1355                 cmd = sc->sc_o.modep->cmdchan;
 1356                 if (cmd && sbdsp_wdsp(sc, cmd) < 0)
 1357                         return (EIO);
 1358         }
 1359 
 1360         if (ISSB16CLASS(sc)) {
 1361                 if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
 1362                         DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
 1363                                  sc->sc_o.rate));
 1364                         return (EIO);
 1365                 }
 1366         } else {
 1367                 if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
 1368                         DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
 1369                                  sc->sc_o.rate));
 1370                         return (EIO);
 1371                 }
 1372         }
 1373 
 1374         DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
 1375             start, end, sc->sc_o.dmachan));
 1376         isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, start, (char *)end -
 1377             (char *)start, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
 1378 
 1379         return sbdsp_block_output(addr);
 1380 }
 1381 
 1382 int
 1383 sbdsp_block_output(addr)
 1384         void *addr;
 1385 {
 1386         struct sbdsp_softc *sc = addr;
 1387         int cc = sc->sc_o.blksize;
 1388 
 1389         DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
 1390 
 1391         if (sc->sc_o.run != SB_NOTRUNNING)
 1392                 sc->sc_intrp(sc->sc_argp);
 1393 
 1394         if (sc->sc_model == SB_1) {
 1395                 /* Non-looping mode, initialized. Start DMA and PCM */
 1396                 if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
 1397                     sbdsp_wdsp(sc, cc) < 0 ||
 1398                     sbdsp_wdsp(sc, cc >> 8) < 0) {
 1399                         DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
 1400                         return (EIO);
 1401                 }
 1402                 sc->sc_o.run = SB_RUNNING;
 1403         } else if (sc->sc_o.run == SB_NOTRUNNING) {
 1404                 /* Initialize looping PCM */
 1405                 if (ISSB16CLASS(sc)) {
 1406                         DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
 1407                             sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
 1408                         if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
 1409                             sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
 1410                             sbdsp_wdsp(sc, cc) < 0 ||
 1411                             sbdsp_wdsp(sc, cc >> 8) < 0) {
 1412                                 DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
 1413                                 return (EIO);
 1414                         }
 1415                 } else {
 1416                         DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc));
 1417                         if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
 1418                             sbdsp_wdsp(sc, cc) < 0 ||
 1419                             sbdsp_wdsp(sc, cc >> 8) < 0) {
 1420                                 DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
 1421                                 return (EIO);
 1422                         }
 1423                         if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
 1424                                 DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
 1425                                 return (EIO);
 1426                         }
 1427                 }
 1428                 sc->sc_o.run = SB_LOOPING;
 1429         }
 1430 
 1431         return (0);
 1432 }
 1433 
 1434 /*
 1435  * Only the DSP unit on the sound blaster generates interrupts.
 1436  * There are three cases of interrupt: reception of a midi byte
 1437  * (when mode is enabled), completion of dma transmission, or
 1438  * completion of a dma reception.
 1439  *
 1440  * If there is interrupt sharing or a spurious interrupt occurs
 1441  * there is no way to distinguish this on an SB2.  So if you have
 1442  * an SB2 and experience problems, buy an SB16 (it's only $40).
 1443  */
 1444 int
 1445 sbdsp_intr(arg)
 1446         void *arg;
 1447 {
 1448         struct sbdsp_softc *sc = arg;
 1449         u_char irq;
 1450 
 1451         DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
 1452                    sc->sc_intr8, sc->sc_intr16));
 1453         if (ISSB16CLASS(sc)) {
 1454                 irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
 1455                 if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 0) {
 1456                         DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
 1457                         return 0;
 1458                 }
 1459         } else {
 1460                 /* XXXX CHECK FOR INTERRUPT */
 1461                 irq = SBP_IRQ_DMA8;
 1462         }
 1463 
 1464         sc->sc_interrupts++;
 1465         delay(10);              /* XXX why? */
 1466 
 1467         /* clear interrupt */
 1468         if (irq & SBP_IRQ_DMA8) {
 1469                 bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
 1470                 if (sc->sc_intr8)
 1471                         sc->sc_intr8(sc->sc_arg8);
 1472         }
 1473         if (irq & SBP_IRQ_DMA16) {
 1474                 bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
 1475                 if (sc->sc_intr16)
 1476                         sc->sc_intr16(sc->sc_arg16);
 1477         }
 1478 #if NMIDI > 0
 1479         if ((irq & SBP_IRQ_MPU401) && sc->sc_hasmpu) {
 1480                 mpu_intr(&sc->sc_mpu_sc);
 1481         }
 1482 #endif
 1483         return 1;
 1484 }
 1485 
 1486 /* Like val & mask, but make sure the result is correctly rounded. */
 1487 #define MAXVAL 256
 1488 static int
 1489 sbdsp_adjust(val, mask)
 1490         int val, mask;
 1491 {
 1492         val += (MAXVAL - mask) >> 1;
 1493         if (val >= MAXVAL)
 1494                 val = MAXVAL-1;
 1495         return val & mask;
 1496 }
 1497 
 1498 void
 1499 sbdsp_set_mixer_gain(sc, port)
 1500         struct sbdsp_softc *sc;
 1501         int port;
 1502 {
 1503         int src, gain;
 1504 
 1505         switch(sc->sc_mixer_model) {
 1506         case SBM_NONE:
 1507                 return;
 1508         case SBM_CT1335:
 1509                 gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
 1510                 switch(port) {
 1511                 case SB_MASTER_VOL:
 1512                         src = SBP_1335_MASTER_VOL;
 1513                         break;
 1514                 case SB_MIDI_VOL:
 1515                         src = SBP_1335_MIDI_VOL;
 1516                         break;
 1517                 case SB_CD_VOL:
 1518                         src = SBP_1335_CD_VOL;
 1519                         break;
 1520                 case SB_VOICE_VOL:
 1521                         src = SBP_1335_VOICE_VOL;
 1522                         gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
 1523                         break;
 1524                 default:
 1525                         return;
 1526                 }
 1527                 sbdsp_mix_write(sc, src, gain);
 1528                 break;
 1529         case SBM_CT1345:
 1530                 gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
 1531                                       sc->gain[port][SB_RIGHT]);
 1532                 switch (port) {
 1533                 case SB_MIC_VOL:
 1534                         src = SBP_MIC_VOL;
 1535                         gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
 1536                         break;
 1537                 case SB_MASTER_VOL:
 1538                         src = SBP_MASTER_VOL;
 1539                         break;
 1540                 case SB_LINE_IN_VOL:
 1541                         src = SBP_LINE_VOL;
 1542                         break;
 1543                 case SB_VOICE_VOL:
 1544                         src = SBP_VOICE_VOL;
 1545                         break;
 1546                 case SB_MIDI_VOL:
 1547                         src = SBP_MIDI_VOL;
 1548                         break;
 1549                 case SB_CD_VOL:
 1550                         src = SBP_CD_VOL;
 1551                         break;
 1552                 default:
 1553                         return;
 1554                 }
 1555                 sbdsp_mix_write(sc, src, gain);
 1556                 break;
 1557         case SBM_CT1XX5:
 1558         case SBM_CT1745:
 1559                 switch (port) {
 1560                 case SB_MIC_VOL:
 1561                         src = SB16P_MIC_L;
 1562                         break;
 1563                 case SB_MASTER_VOL:
 1564                         src = SB16P_MASTER_L;
 1565                         break;
 1566                 case SB_LINE_IN_VOL:
 1567                         src = SB16P_LINE_L;
 1568                         break;
 1569                 case SB_VOICE_VOL:
 1570                         src = SB16P_VOICE_L;
 1571                         break;
 1572                 case SB_MIDI_VOL:
 1573                         src = SB16P_MIDI_L;
 1574                         break;
 1575                 case SB_CD_VOL:
 1576                         src = SB16P_CD_L;
 1577                         break;
 1578                 case SB_INPUT_GAIN:
 1579                         src = SB16P_INPUT_GAIN_L;
 1580                         break;
 1581                 case SB_OUTPUT_GAIN:
 1582                         src = SB16P_OUTPUT_GAIN_L;
 1583                         break;
 1584                 case SB_TREBLE:
 1585                         src = SB16P_TREBLE_L;
 1586                         break;
 1587                 case SB_BASS:
 1588                         src = SB16P_BASS_L;
 1589                         break;
 1590                 case SB_PCSPEAKER:
 1591                         sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
 1592                         return;
 1593                 default:
 1594                         return;
 1595                 }
 1596                 sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
 1597                 sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
 1598                 break;
 1599         }
 1600 }
 1601 
 1602 int
 1603 sbdsp_mixer_set_port(addr, cp)
 1604         void *addr;
 1605         mixer_ctrl_t *cp;
 1606 {
 1607         struct sbdsp_softc *sc = addr;
 1608         int lgain, rgain;
 1609         int mask, bits;
 1610         int lmask, rmask, lbits, rbits;
 1611         int mute, swap;
 1612 
 1613         if (sc->sc_open == SB_OPEN_MIDI)
 1614                 return EBUSY;
 1615 
 1616         DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
 1617             cp->un.value.num_channels));
 1618 
 1619         if (sc->sc_mixer_model == SBM_NONE)
 1620                 return EINVAL;
 1621 
 1622         switch (cp->dev) {
 1623         case SB_TREBLE:
 1624         case SB_BASS:
 1625                 if (sc->sc_mixer_model == SBM_CT1345 ||
 1626                     sc->sc_mixer_model == SBM_CT1XX5) {
 1627                         if (cp->type != AUDIO_MIXER_ENUM)
 1628                                 return EINVAL;
 1629                         switch (cp->dev) {
 1630                         case SB_TREBLE:
 1631                                 sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
 1632                                 return 0;
 1633                         case SB_BASS:
 1634                                 sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
 1635                                 return 0;
 1636                         }
 1637                 }
 1638         case SB_PCSPEAKER:
 1639         case SB_INPUT_GAIN:
 1640         case SB_OUTPUT_GAIN:
 1641                 if (!ISSBM1745(sc))
 1642                         return EINVAL;
 1643         case SB_MIC_VOL:
 1644         case SB_LINE_IN_VOL:
 1645                 if (sc->sc_mixer_model == SBM_CT1335)
 1646                         return EINVAL;
 1647         case SB_VOICE_VOL:
 1648         case SB_MIDI_VOL:
 1649         case SB_CD_VOL:
 1650         case SB_MASTER_VOL:
 1651                 if (cp->type != AUDIO_MIXER_VALUE)
 1652                         return EINVAL;
 1653 
 1654                 /*
 1655                  * All the mixer ports are stereo except for the microphone.
 1656                  * If we get a single-channel gain value passed in, then we
 1657                  * duplicate it to both left and right channels.
 1658                  */
 1659 
 1660                 switch (cp->dev) {
 1661                 case SB_MIC_VOL:
 1662                         if (cp->un.value.num_channels != 1)
 1663                                 return EINVAL;
 1664 
 1665                         lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
 1666                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
 1667                         break;
 1668                 case SB_PCSPEAKER:
 1669                         if (cp->un.value.num_channels != 1)
 1670                                 return EINVAL;
 1671                         /* fall into */
 1672                 case SB_INPUT_GAIN:
 1673                 case SB_OUTPUT_GAIN:
 1674                         lgain = rgain = SB_ADJUST_2_GAIN(sc,
 1675                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
 1676                         break;
 1677                 default:
 1678                         switch (cp->un.value.num_channels) {
 1679                         case 1:
 1680                                 lgain = rgain = SB_ADJUST_GAIN(sc,
 1681                                   cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
 1682                                 break;
 1683                         case 2:
 1684                                 if (sc->sc_mixer_model == SBM_CT1335)
 1685                                         return EINVAL;
 1686                                 lgain = SB_ADJUST_GAIN(sc,
 1687                                   cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
 1688                                 rgain = SB_ADJUST_GAIN(sc,
 1689                                   cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
 1690                                 break;
 1691                         default:
 1692                                 return EINVAL;
 1693                         }
 1694                         break;
 1695                 }
 1696                 sc->gain[cp->dev][SB_LEFT]  = lgain;
 1697                 sc->gain[cp->dev][SB_RIGHT] = rgain;
 1698 
 1699                 sbdsp_set_mixer_gain(sc, cp->dev);
 1700                 break;
 1701 
 1702         case SB_RECORD_SOURCE:
 1703                 if (ISSBM1745(sc)) {
 1704                         if (cp->type != AUDIO_MIXER_SET)
 1705                                 return EINVAL;
 1706                         return sbdsp_set_in_ports(sc, cp->un.mask);
 1707                 } else {
 1708                         if (cp->type != AUDIO_MIXER_ENUM)
 1709                                 return EINVAL;
 1710                         sc->in_port = cp->un.ord;
 1711                         return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
 1712                 }
 1713                 break;
 1714 
 1715         case SB_AGC:
 1716                 if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
 1717                         return EINVAL;
 1718                 sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
 1719                 break;
 1720 
 1721         case SB_CD_OUT_MUTE:
 1722                 mask = SB16P_SW_CD;
 1723                 goto omute;
 1724         case SB_MIC_OUT_MUTE:
 1725                 mask = SB16P_SW_MIC;
 1726                 goto omute;
 1727         case SB_LINE_OUT_MUTE:
 1728                 mask = SB16P_SW_LINE;
 1729         omute:
 1730                 if (cp->type != AUDIO_MIXER_ENUM)
 1731                         return EINVAL;
 1732                 bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
 1733                 sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
 1734                 if (cp->un.ord)
 1735                         bits = bits & ~mask;
 1736                 else
 1737                         bits = bits | mask;
 1738                 sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
 1739                 break;
 1740 
 1741         case SB_MIC_IN_MUTE:
 1742         case SB_MIC_SWAP:
 1743                 lmask = rmask = SB16P_SW_MIC;
 1744                 goto imute;
 1745         case SB_CD_IN_MUTE:
 1746         case SB_CD_SWAP:
 1747                 lmask = SB16P_SW_CD_L;
 1748                 rmask = SB16P_SW_CD_R;
 1749                 goto imute;
 1750         case SB_LINE_IN_MUTE:
 1751         case SB_LINE_SWAP:
 1752                 lmask = SB16P_SW_LINE_L;
 1753                 rmask = SB16P_SW_LINE_R;
 1754                 goto imute;
 1755         case SB_MIDI_IN_MUTE:
 1756         case SB_MIDI_SWAP:
 1757                 lmask = SB16P_SW_MIDI_L;
 1758                 rmask = SB16P_SW_MIDI_R;
 1759         imute:
 1760                 if (cp->type != AUDIO_MIXER_ENUM)
 1761                         return EINVAL;
 1762                 mask = lmask | rmask;
 1763                 lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
 1764                 rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
 1765                 sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
 1766                 if (SB_IS_IN_MUTE(cp->dev)) {
 1767                         mute = cp->dev;
 1768                         swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
 1769                 } else {
 1770                         swap = cp->dev;
 1771                         mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
 1772                 }
 1773                 if (sc->gain[swap][SB_LR]) {
 1774                         mask = lmask;
 1775                         lmask = rmask;
 1776                         rmask = mask;
 1777                 }
 1778                 if (!sc->gain[mute][SB_LR]) {
 1779                         lbits = lbits | lmask;
 1780                         rbits = rbits | rmask;
 1781                 }
 1782                 sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
 1783                 sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
 1784                 break;
 1785 
 1786         default:
 1787                 return EINVAL;
 1788         }
 1789 
 1790         return 0;
 1791 }
 1792 
 1793 int
 1794 sbdsp_mixer_get_port(addr, cp)
 1795         void *addr;
 1796         mixer_ctrl_t *cp;
 1797 {
 1798         struct sbdsp_softc *sc = addr;
 1799 
 1800         if (sc->sc_open == SB_OPEN_MIDI)
 1801                 return EBUSY;
 1802 
 1803         DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
 1804 
 1805         if (sc->sc_mixer_model == SBM_NONE)
 1806                 return EINVAL;
 1807 
 1808         switch (cp->dev) {
 1809         case SB_TREBLE:
 1810         case SB_BASS:
 1811                 if (sc->sc_mixer_model == SBM_CT1345 ||
 1812                     sc->sc_mixer_model == SBM_CT1XX5) {
 1813                         switch (cp->dev) {
 1814                         case SB_TREBLE:
 1815                                 cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
 1816                                 return 0;
 1817                         case SB_BASS:
 1818                                 cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
 1819                                 return 0;
 1820                         }
 1821                 }
 1822         case SB_PCSPEAKER:
 1823         case SB_INPUT_GAIN:
 1824         case SB_OUTPUT_GAIN:
 1825                 if (!ISSBM1745(sc))
 1826                         return EINVAL;
 1827         case SB_MIC_VOL:
 1828         case SB_LINE_IN_VOL:
 1829                 if (sc->sc_mixer_model == SBM_CT1335)
 1830                         return EINVAL;
 1831         case SB_VOICE_VOL:
 1832         case SB_MIDI_VOL:
 1833         case SB_CD_VOL:
 1834         case SB_MASTER_VOL:
 1835                 switch (cp->dev) {
 1836                 case SB_MIC_VOL:
 1837                 case SB_PCSPEAKER:
 1838                         if (cp->un.value.num_channels != 1)
 1839                                 return EINVAL;
 1840                         /* fall into */
 1841                 default:
 1842                         switch (cp->un.value.num_channels) {
 1843                         case 1:
 1844                                 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
 1845                                         sc->gain[cp->dev][SB_LEFT];
 1846                                 break;
 1847                         case 2:
 1848                                 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
 1849                                         sc->gain[cp->dev][SB_LEFT];
 1850                                 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
 1851                                         sc->gain[cp->dev][SB_RIGHT];
 1852                                 break;
 1853                         default:
 1854                                 return EINVAL;
 1855                         }
 1856                         break;
 1857                 }
 1858                 break;
 1859 
 1860         case SB_RECORD_SOURCE:
 1861                 if (ISSBM1745(sc))
 1862                         cp->un.mask = sc->in_mask;
 1863                 else
 1864                         cp->un.ord = sc->in_port;
 1865                 break;
 1866 
 1867         case SB_AGC:
 1868                 if (!ISSBM1745(sc))
 1869                         return EINVAL;
 1870                 cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
 1871                 break;
 1872 
 1873         case SB_CD_IN_MUTE:
 1874         case SB_MIC_IN_MUTE:
 1875         case SB_LINE_IN_MUTE:
 1876         case SB_MIDI_IN_MUTE:
 1877         case SB_CD_SWAP:
 1878         case SB_MIC_SWAP:
 1879         case SB_LINE_SWAP:
 1880         case SB_MIDI_SWAP:
 1881         case SB_CD_OUT_MUTE:
 1882         case SB_MIC_OUT_MUTE:
 1883         case SB_LINE_OUT_MUTE:
 1884                 cp->un.ord = sc->gain[cp->dev][SB_LR];
 1885                 break;
 1886 
 1887         default:
 1888                 return EINVAL;
 1889         }
 1890 
 1891         return 0;
 1892 }
 1893 
 1894 int
 1895 sbdsp_mixer_query_devinfo(addr, dip)
 1896         void *addr;
 1897         mixer_devinfo_t *dip;
 1898 {
 1899         struct sbdsp_softc *sc = addr;
 1900         int chan, class, is1745;
 1901 
 1902         DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
 1903                  sc->sc_mixer_model, dip->index));
 1904 
 1905         if (sc->sc_mixer_model == SBM_NONE)
 1906                 return ENXIO;
 1907 
 1908         chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
 1909         is1745 = ISSBM1745(sc);
 1910         class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
 1911 
 1912         switch (dip->index) {
 1913         case SB_MASTER_VOL:
 1914                 dip->type = AUDIO_MIXER_VALUE;
 1915                 dip->mixer_class = SB_OUTPUT_CLASS;
 1916                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 1917                 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
 1918                 dip->un.v.num_channels = chan;
 1919                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 1920                 return 0;
 1921         case SB_MIDI_VOL:
 1922                 dip->type = AUDIO_MIXER_VALUE;
 1923                 dip->mixer_class = class;
 1924                 dip->prev = AUDIO_MIXER_LAST;
 1925                 dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
 1926                 strlcpy(dip->label.name, AudioNfmsynth, sizeof dip->label.name);
 1927                 dip->un.v.num_channels = chan;
 1928                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 1929                 return 0;
 1930         case SB_CD_VOL:
 1931                 dip->type = AUDIO_MIXER_VALUE;
 1932                 dip->mixer_class = class;
 1933                 dip->prev = AUDIO_MIXER_LAST;
 1934                 dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
 1935                 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
 1936                 dip->un.v.num_channels = chan;
 1937                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 1938                 return 0;
 1939         case SB_VOICE_VOL:
 1940                 dip->type = AUDIO_MIXER_VALUE;
 1941                 dip->mixer_class = class;
 1942                 dip->prev = AUDIO_MIXER_LAST;
 1943                 dip->next = AUDIO_MIXER_LAST;
 1944                 strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
 1945                 dip->un.v.num_channels = chan;
 1946                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 1947                 return 0;
 1948         case SB_OUTPUT_CLASS:
 1949                 dip->type = AUDIO_MIXER_CLASS;
 1950                 dip->mixer_class = SB_OUTPUT_CLASS;
 1951                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1952                 strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
 1953                 return 0;
 1954         }
 1955 
 1956         if (sc->sc_mixer_model == SBM_CT1335)
 1957                 return ENXIO;
 1958 
 1959         switch (dip->index) {
 1960         case SB_MIC_VOL:
 1961                 dip->type = AUDIO_MIXER_VALUE;
 1962                 dip->mixer_class = class;
 1963                 dip->prev = AUDIO_MIXER_LAST;
 1964                 dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
 1965                 strlcpy(dip->label.name, AudioNmicrophone,
 1966                     sizeof dip->label.name);
 1967                 dip->un.v.num_channels = 1;
 1968                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 1969                 return 0;
 1970 
 1971         case SB_LINE_IN_VOL:
 1972                 dip->type = AUDIO_MIXER_VALUE;
 1973                 dip->mixer_class = class;
 1974                 dip->prev = AUDIO_MIXER_LAST;
 1975                 dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
 1976                 strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
 1977                 dip->un.v.num_channels = 2;
 1978                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 1979                 return 0;
 1980 
 1981         case SB_RECORD_SOURCE:
 1982                 dip->mixer_class = SB_RECORD_CLASS;
 1983                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 1984                 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
 1985                 if (ISSBM1745(sc)) {
 1986                         dip->type = AUDIO_MIXER_SET;
 1987                         dip->un.s.num_mem = 4;
 1988                         strlcpy(dip->un.s.member[0].label.name,
 1989                             AudioNmicrophone,
 1990                             sizeof dip->un.s.member[0].label.name);
 1991                         dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
 1992                         strlcpy(dip->un.s.member[1].label.name,
 1993                             AudioNcd, sizeof dip->un.s.member[1].label.name);
 1994                         dip->un.s.member[1].mask = 1 << SB_CD_VOL;
 1995                         strlcpy(dip->un.s.member[2].label.name,
 1996                             AudioNline, sizeof dip->un.s.member[2].label.name);
 1997                         dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
 1998                         strlcpy(dip->un.s.member[3].label.name,
 1999                             AudioNfmsynth,
 2000                             sizeof dip->un.s.member[3].label.name);
 2001                         dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
 2002                 } else {
 2003                         dip->type = AUDIO_MIXER_ENUM;
 2004                         dip->un.e.num_mem = 3;
 2005                         strlcpy(dip->un.e.member[0].label.name,
 2006                             AudioNmicrophone,
 2007                             sizeof dip->un.e.member[0].label.name);
 2008                         dip->un.e.member[0].ord = SB_MIC_VOL;
 2009                         strlcpy(dip->un.e.member[1].label.name, AudioNcd,
 2010                             sizeof dip->un.e.member[1].label.name);
 2011                         dip->un.e.member[1].ord = SB_CD_VOL;
 2012                         strlcpy(dip->un.e.member[2].label.name, AudioNline,
 2013                             sizeof dip->un.e.member[2].label.name);
 2014                         dip->un.e.member[2].ord = SB_LINE_IN_VOL;
 2015                 }
 2016                 return 0;
 2017 
 2018         case SB_BASS:
 2019                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 2020                 strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
 2021                 if (sc->sc_mixer_model == SBM_CT1745) {
 2022                         dip->type = AUDIO_MIXER_VALUE;
 2023                         dip->mixer_class = SB_EQUALIZATION_CLASS;
 2024                         dip->un.v.num_channels = 2;
 2025                         strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
 2026                 } else {
 2027                         dip->type = AUDIO_MIXER_ENUM;
 2028                         dip->mixer_class = SB_INPUT_CLASS;
 2029                         dip->un.e.num_mem = 2;
 2030                         strlcpy(dip->un.e.member[0].label.name, AudioNoff,
 2031                             sizeof dip->un.e.member[0].label.name);
 2032                         dip->un.e.member[0].ord = 0;
 2033                         strlcpy(dip->un.e.member[1].label.name, AudioNon,
 2034                             sizeof dip->un.e.member[1].label.name);
 2035                         dip->un.e.member[1].ord = 1;
 2036                 }
 2037                 return 0;
 2038 
 2039         case SB_TREBLE:
 2040                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 2041                 strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
 2042                 if (sc->sc_mixer_model == SBM_CT1745) {
 2043                         dip->type = AUDIO_MIXER_VALUE;
 2044                         dip->mixer_class = SB_EQUALIZATION_CLASS;
 2045                         dip->un.v.num_channels = 2;
 2046                         strlcpy(dip->un.v.units.name, AudioNtreble, sizeof dip->un.v.units.name);
 2047                 } else {
 2048                         dip->type = AUDIO_MIXER_ENUM;
 2049                         dip->mixer_class = SB_INPUT_CLASS;
 2050                         dip->un.e.num_mem = 2;
 2051                         strlcpy(dip->un.e.member[0].label.name, AudioNoff,
 2052                             sizeof dip->un.e.member[0].label.name);
 2053                         dip->un.e.member[0].ord = 0;
 2054                         strlcpy(dip->un.e.member[1].label.name, AudioNon,
 2055                             sizeof dip->un.e.member[1].label.name);
 2056                         dip->un.e.member[1].ord = 1;
 2057                 }
 2058                 return 0;
 2059 
 2060         case SB_RECORD_CLASS:                   /* record source class */
 2061                 dip->type = AUDIO_MIXER_CLASS;
 2062                 dip->mixer_class = SB_RECORD_CLASS;
 2063                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 2064                 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
 2065                 return 0;
 2066 
 2067         case SB_INPUT_CLASS:
 2068                 dip->type = AUDIO_MIXER_CLASS;
 2069                 dip->mixer_class = SB_INPUT_CLASS;
 2070                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 2071                 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
 2072                 return 0;
 2073 
 2074         }
 2075 
 2076         if (sc->sc_mixer_model == SBM_CT1345)
 2077                 return ENXIO;
 2078 
 2079         switch(dip->index) {
 2080         case SB_PCSPEAKER:
 2081                 dip->type = AUDIO_MIXER_VALUE;
 2082                 dip->mixer_class = SB_INPUT_CLASS;
 2083                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 2084                 strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
 2085                 dip->un.v.num_channels = 1;
 2086                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 2087                 return 0;
 2088 
 2089         case SB_INPUT_GAIN:
 2090                 dip->type = AUDIO_MIXER_VALUE;
 2091                 dip->mixer_class = SB_INPUT_CLASS;
 2092                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 2093                 strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
 2094                 dip->un.v.num_channels = 2;
 2095                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 2096                 return 0;
 2097 
 2098         case SB_OUTPUT_GAIN:
 2099                 dip->type = AUDIO_MIXER_VALUE;
 2100                 dip->mixer_class = SB_OUTPUT_CLASS;
 2101                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 2102                 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
 2103                 dip->un.v.num_channels = 2;
 2104                 strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
 2105                 return 0;
 2106 
 2107         case SB_AGC:
 2108                 dip->type = AUDIO_MIXER_ENUM;
 2109                 dip->mixer_class = SB_INPUT_CLASS;
 2110                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 2111                 strlcpy(dip->label.name, "agc", sizeof dip->label.name);
 2112                 dip->un.e.num_mem = 2;
 2113                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
 2114                     sizeof dip->un.e.member[0].label.name);
 2115                 dip->un.e.member[0].ord = 0;
 2116                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
 2117                     sizeof dip->un.e.member[1].label.name);
 2118                 dip->un.e.member[1].ord = 1;
 2119                 return 0;
 2120 
 2121         case SB_EQUALIZATION_CLASS:
 2122                 dip->type = AUDIO_MIXER_CLASS;
 2123                 dip->mixer_class = SB_EQUALIZATION_CLASS;
 2124                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 2125                 strlcpy(dip->label.name, AudioCequalization, sizeof dip->label.name);
 2126                 return 0;
 2127 
 2128         case SB_CD_IN_MUTE:
 2129                 dip->prev = SB_CD_VOL;
 2130                 dip->next = SB_CD_SWAP;
 2131                 dip->mixer_class = SB_INPUT_CLASS;
 2132                 goto mute;
 2133 
 2134         case SB_MIC_IN_MUTE:
 2135                 dip->prev = SB_MIC_VOL;
 2136                 dip->next = SB_MIC_SWAP;
 2137                 dip->mixer_class = SB_INPUT_CLASS;
 2138                 goto mute;
 2139 
 2140         case SB_LINE_IN_MUTE:
 2141                 dip->prev = SB_LINE_IN_VOL;
 2142                 dip->next = SB_LINE_SWAP;
 2143                 dip->mixer_class = SB_INPUT_CLASS;
 2144                 goto mute;
 2145 
 2146         case SB_MIDI_IN_MUTE:
 2147                 dip->prev = SB_MIDI_VOL;
 2148                 dip->next = SB_MIDI_SWAP;
 2149                 dip->mixer_class = SB_INPUT_CLASS;
 2150                 goto mute;
 2151 
 2152         case SB_CD_SWAP:
 2153                 dip->prev = SB_CD_IN_MUTE;
 2154                 dip->next = SB_CD_OUT_MUTE;
 2155                 goto swap;
 2156 
 2157         case SB_MIC_SWAP:
 2158                 dip->prev = SB_MIC_IN_MUTE;
 2159                 dip->next = SB_MIC_OUT_MUTE;
 2160                 goto swap;
 2161 
 2162         case SB_LINE_SWAP:
 2163                 dip->prev = SB_LINE_IN_MUTE;
 2164                 dip->next = SB_LINE_OUT_MUTE;
 2165                 goto swap;
 2166 
 2167         case SB_MIDI_SWAP:
 2168                 dip->prev = SB_MIDI_IN_MUTE;
 2169                 dip->next = AUDIO_MIXER_LAST;
 2170         swap:
 2171                 dip->mixer_class = SB_INPUT_CLASS;
 2172                 strlcpy(dip->label.name, AudioNswap, sizeof dip->label.name);
 2173                 goto mute1;
 2174 
 2175         case SB_CD_OUT_MUTE:
 2176                 dip->prev = SB_CD_SWAP;
 2177                 dip->next = AUDIO_MIXER_LAST;
 2178                 dip->mixer_class = SB_OUTPUT_CLASS;
 2179                 goto mute;
 2180 
 2181         case SB_MIC_OUT_MUTE:
 2182                 dip->prev = SB_MIC_SWAP;
 2183                 dip->next = AUDIO_MIXER_LAST;
 2184                 dip->mixer_class = SB_OUTPUT_CLASS;
 2185                 goto mute;
 2186 
 2187         case SB_LINE_OUT_MUTE:
 2188                 dip->prev = SB_LINE_SWAP;
 2189                 dip->next = AUDIO_MIXER_LAST;
 2190                 dip->mixer_class = SB_OUTPUT_CLASS;
 2191         mute:
 2192                 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
 2193         mute1:
 2194                 dip->type = AUDIO_MIXER_ENUM;
 2195                 dip->un.e.num_mem = 2;
 2196                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
 2197                     sizeof dip->un.e.member[0].label.name);
 2198                 dip->un.e.member[0].ord = 0;
 2199                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
 2200                     sizeof dip->un.e.member[1].label.name);
 2201                 dip->un.e.member[1].ord = 1;
 2202                 return 0;
 2203 
 2204         }
 2205 
 2206         return ENXIO;
 2207 }
 2208 
 2209 void *
 2210 sb_malloc(addr, direction, size, pool, flags)
 2211         void *addr;
 2212         int direction;
 2213         size_t size;
 2214         int pool;
 2215         int flags;
 2216 {
 2217         struct sbdsp_softc *sc = addr;
 2218         int drq;
 2219 
 2220         /* 8-bit has more restrictive alignment */
 2221         if (sc->sc_drq8 != -1)
 2222                 drq = sc->sc_drq8;
 2223         else
 2224                 drq = sc->sc_drq16;
 2225 
 2226         return isa_malloc(sc->sc_isa, drq, size, pool, flags);
 2227 }
 2228 
 2229 void
 2230 sb_free(addr, ptr, pool)
 2231         void *addr;
 2232         void *ptr;
 2233         int pool;
 2234 {
 2235         isa_free(ptr, pool);
 2236 }
 2237 
 2238 size_t
 2239 sb_round(addr, direction, size)
 2240         void *addr;
 2241         int direction;
 2242         size_t size;
 2243 {
 2244         if (size > MAX_ISADMA)
 2245                 size = MAX_ISADMA;
 2246         return size;
 2247 }
 2248 
 2249 paddr_t
 2250 sb_mappage(addr, mem, off, prot)
 2251         void *addr;
 2252         void *mem;
 2253         off_t off;
 2254         int prot;
 2255 {
 2256         return isa_mappage(mem, off, prot);
 2257 }
 2258 
 2259 int
 2260 sbdsp_get_props(addr)
 2261         void *addr;
 2262 {
 2263         struct sbdsp_softc *sc = addr;
 2264         return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
 2265                (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
 2266 }
 2267 
 2268 #if NMIDI > 0
 2269 /*
 2270  * MIDI related routines.
 2271  */
 2272 
 2273 int
 2274 sbdsp_midi_open(addr, flags, iintr, ointr, arg)
 2275         void *addr;
 2276         int flags;
 2277         void (*iintr)(void *, int);
 2278         void (*ointr)(void *);
 2279         void *arg;
 2280 {
 2281         struct sbdsp_softc *sc = addr;
 2282 
 2283         DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
 2284 
 2285         if (sc->sc_open != SB_CLOSED)
 2286                 return EBUSY;
 2287         if (sbdsp_reset(sc) != 0)
 2288                 return EIO;
 2289 
 2290         if (sc->sc_model >= SB_20)
 2291                 if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
 2292                         return EIO;
 2293         sc->sc_open = SB_OPEN_MIDI;
 2294         sc->sc_openflags = flags;
 2295         sc->sc_intr8 = sbdsp_midi_intr;
 2296         sc->sc_arg8 = addr;
 2297         sc->sc_intrm = iintr;
 2298         sc->sc_argm = arg;
 2299         return 0;
 2300 }
 2301 
 2302 void
 2303 sbdsp_midi_close(addr)
 2304         void *addr;
 2305 {
 2306         struct sbdsp_softc *sc = addr;
 2307 
 2308         DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
 2309 
 2310         if (sc->sc_model >= SB_20)
 2311                 sbdsp_reset(sc); /* exit UART mode */
 2312         sc->sc_open = SB_CLOSED;
 2313         sc->sc_intrm = 0;
 2314 }
 2315 
 2316 int
 2317 sbdsp_midi_output(addr, d)
 2318         void *addr;
 2319         int d;
 2320 {
 2321         struct sbdsp_softc *sc = addr;
 2322 
 2323         if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
 2324                 return EIO;
 2325         if (sbdsp_wdsp(sc, d))
 2326                 return EIO;
 2327         return 0;
 2328 }
 2329 
 2330 void
 2331 sbdsp_midi_getinfo(addr, mi)
 2332         void *addr;
 2333         struct midi_info *mi;
 2334 {
 2335         struct sbdsp_softc *sc = addr;
 2336 
 2337         mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
 2338         mi->props = MIDI_PROP_CAN_INPUT;
 2339 }
 2340 
 2341 int
 2342 sbdsp_midi_intr(addr)
 2343         void *addr;
 2344 {
 2345         struct sbdsp_softc *sc = addr;
 2346 
 2347         sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
 2348         return (0);
 2349 }
 2350 
 2351 #endif

/* [<][>][^][v][top][bottom][index][help] */