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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/sbdsp.c

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

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

Cache object: bb4398b51773851319ce376bda7b0c5a


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


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