root/dev/isa/sb.c

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

DEFINITIONS

This source file includes following definitions.
  1. sbmatch
  2. sbattach
  3. sb_getdev
  4. sb_mpu401_open
  5. sb_mpu401_output
  6. sb_mpu401_close
  7. sb_mpu401_getinfo

    1 /*      $OpenBSD: sb.c,v 1.24 2006/04/07 22:41:33 jsg Exp $     */
    2 /*      $NetBSD: sb.c,v 1.57 1998/01/12 09:43:46 thorpej Exp $  */
    3 
    4 /*
    5  * Copyright (c) 1991-1993 Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the Computer Systems
   19  *      Engineering Group at Lawrence Berkeley Laboratory.
   20  * 4. Neither the name of the University nor of the Laboratory may be used
   21  *    to endorse or promote products derived from this software without
   22  *    specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  */
   37 
   38 #include "midi.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/errno.h>
   43 #include <sys/ioctl.h>
   44 #include <sys/syslog.h>
   45 #include <sys/device.h>
   46 #include <sys/proc.h>
   47 
   48 #include <machine/cpu.h>
   49 #include <machine/intr.h>
   50 #include <machine/bus.h>
   51 
   52 #include <sys/audioio.h>
   53 #include <dev/audio_if.h>
   54 #include <dev/midi_if.h>
   55 
   56 #include <dev/isa/isavar.h>
   57 #include <dev/isa/isadmavar.h>
   58 
   59 #include <dev/isa/sbreg.h>
   60 #include <dev/isa/sbvar.h>
   61 #include <dev/isa/sbdspvar.h>
   62 
   63 struct cfdriver sb_cd = {
   64         NULL, "sb", DV_DULL
   65 };
   66 
   67 #if NMIDI > 0
   68 int     sb_mpu401_open(void *, int, void (*iintr)(void *, int),
   69                        void (*ointr)(void *), void *arg);
   70 void    sb_mpu401_close(void *);
   71 int     sb_mpu401_output(void *, int);
   72 void    sb_mpu401_getinfo(void *, struct midi_info *);
   73 
   74 struct midi_hw_if sb_midi_hw_if = {
   75         sbdsp_midi_open,
   76         sbdsp_midi_close,
   77         sbdsp_midi_output,
   78         0,                      /* flush */
   79         sbdsp_midi_getinfo,
   80         0,                      /* ioctl */
   81 };
   82 
   83 struct midi_hw_if sb_mpu401_hw_if = {
   84         sb_mpu401_open,
   85         sb_mpu401_close,
   86         sb_mpu401_output,
   87         0,                      /* flush */
   88         sb_mpu401_getinfo,
   89         0,                      /* ioctl */
   90 };
   91 #endif
   92 
   93 struct audio_device sb_device = {
   94         "SoundBlaster",
   95         "x",
   96         "sb"
   97 };
   98 
   99 int     sb_getdev(void *, struct audio_device *);
  100 
  101 /*
  102  * Define our interface to the higher level audio driver.
  103  */
  104 
  105 struct audio_hw_if sb_hw_if = {
  106         sbdsp_open,
  107         sbdsp_close,
  108         0,
  109         sbdsp_query_encoding,
  110         sbdsp_set_params,
  111         sbdsp_round_blocksize,
  112         0,
  113         0,
  114         0,
  115         0,
  116         0,
  117         sbdsp_haltdma,
  118         sbdsp_haltdma,
  119         sbdsp_speaker_ctl,
  120         sb_getdev,
  121         0,
  122         sbdsp_mixer_set_port,
  123         sbdsp_mixer_get_port,
  124         sbdsp_mixer_query_devinfo,
  125         sb_malloc,
  126         sb_free,
  127         sb_round,
  128         sb_mappage,
  129         sbdsp_get_props,
  130         sbdsp_trigger_output,
  131         sbdsp_trigger_input
  132 };
  133 
  134 #ifdef AUDIO_DEBUG
  135 #define DPRINTF(x)      if (sbdebug) printf x
  136 int     sbdebug = 0;
  137 #else
  138 #define DPRINTF(x)
  139 #endif
  140 
  141 /*
  142  * Probe / attach routines.
  143  */
  144 
  145 
  146 int
  147 sbmatch(sc)
  148         struct sbdsp_softc *sc;
  149 {
  150         static u_char drq_conf[8] = {
  151                 0x01, 0x02, -1, 0x08, -1, 0x20, 0x40, 0x80
  152         };
  153 
  154         static u_char irq_conf[11] = {
  155                 -1, -1, 0x01, -1, -1, 0x02, -1, 0x04, -1, 0x01, 0x08
  156         };
  157 
  158         if (sbdsp_probe(sc) == 0)
  159                 return 0;
  160 
  161         /*
  162          * Cannot auto-discover DMA channel.
  163          */
  164         if (ISSBPROCLASS(sc)) {
  165                 if (!SBP_DRQ_VALID(sc->sc_drq8)) {
  166                         DPRINTF(("%s: configured dma chan %d invalid\n",
  167                             sc->sc_dev.dv_xname, sc->sc_drq8));
  168                         return 0;
  169                 }
  170         } else {
  171                 if (!SB_DRQ_VALID(sc->sc_drq8)) {
  172                         DPRINTF(("%s: configured dma chan %d invalid\n",
  173                             sc->sc_dev.dv_xname, sc->sc_drq8));
  174                         return 0;
  175                 }
  176         }
  177 
  178         if (0 <= sc->sc_drq16 && sc->sc_drq16 <= 3)
  179                 /* 
  180                  * XXX Some ViBRA16 cards seem to have two 8 bit DMA 
  181                  * channels.  I've no clue how to use them, so ignore
  182                  * one of them for now.  -- augustss@netbsd.org
  183                  */
  184                 sc->sc_drq16 = -1;
  185 
  186         if (ISSB16CLASS(sc)) {
  187                 if (sc->sc_drq16 == -1)
  188                         sc->sc_drq16 = sc->sc_drq8;
  189                 if (!SB16_DRQ_VALID(sc->sc_drq16)) {
  190                         DPRINTF(("%s: configured dma chan %d invalid\n",
  191                             sc->sc_dev.dv_xname, sc->sc_drq16));
  192                         return 0;
  193                 }
  194         } else
  195                 sc->sc_drq16 = sc->sc_drq8;
  196         
  197         if (ISSBPROCLASS(sc)) {
  198                 if (!SBP_IRQ_VALID(sc->sc_irq)) {
  199                         DPRINTF(("%s: configured irq %d invalid\n",
  200                             sc->sc_dev.dv_xname, sc->sc_irq));
  201                         return 0;
  202                 }
  203         } else {
  204                 if (!SB_IRQ_VALID(sc->sc_irq)) {
  205                         DPRINTF(("%s: configured irq %d invalid\n",
  206                             sc->sc_dev.dv_xname, sc->sc_irq));
  207                         return 0;
  208                 }
  209         }
  210 
  211         if (ISSB16CLASS(sc)) {
  212                 int w, r;
  213 #if 0
  214                 DPRINTF(("%s: old drq conf %02x\n", sc->sc_dev.dv_xname,
  215                     sbdsp_mix_read(sc, SBP_SET_DRQ)));
  216                 DPRINTF(("%s: try drq conf %02x\n", sc->sc_dev.dv_xname,
  217                     drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8]));
  218 #endif
  219                 w = drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8];
  220                 sbdsp_mix_write(sc, SBP_SET_DRQ, w);
  221                 r = sbdsp_mix_read(sc, SBP_SET_DRQ) & 0xeb;
  222                 if (r != w) {
  223                         DPRINTF(("%s: setting drq mask %02x failed, got %02x\n", sc->sc_dev.dv_xname, w, r));
  224                         return 0;
  225                 }
  226 #if 0
  227                 DPRINTF(("%s: new drq conf %02x\n", sc->sc_dev.dv_xname,
  228                     sbdsp_mix_read(sc, SBP_SET_DRQ)));
  229 #endif
  230 
  231 #if 0
  232                 DPRINTF(("%s: old irq conf %02x\n", sc->sc_dev.dv_xname,
  233                     sbdsp_mix_read(sc, SBP_SET_IRQ)));
  234                 DPRINTF(("%s: try irq conf %02x\n", sc->sc_dev.dv_xname,
  235                     irq_conf[sc->sc_irq]));
  236 #endif
  237                 w = irq_conf[sc->sc_irq];
  238                 sbdsp_mix_write(sc, SBP_SET_IRQ, w);
  239                 r = sbdsp_mix_read(sc, SBP_SET_IRQ) & 0x0f;
  240                 if (r != w) {
  241                         DPRINTF(("%s: setting irq mask %02x failed, got %02x\n",
  242                             sc->sc_dev.dv_xname, w, r));
  243                         return 0;
  244                 }
  245 #if 0
  246                 DPRINTF(("%s: new irq conf %02x\n", sc->sc_dev.dv_xname,
  247                     sbdsp_mix_read(sc, SBP_SET_IRQ)));
  248 #endif
  249         }
  250 
  251         return 1;
  252 }
  253 
  254 
  255 void
  256 sbattach(sc)
  257         struct sbdsp_softc *sc;
  258 {
  259         struct audio_attach_args arg;
  260 #if NMIDI > 0
  261         struct midi_hw_if *mhw = &sb_midi_hw_if;
  262 #endif
  263 
  264         sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->sc_irq, IST_EDGE,
  265             IPL_AUDIO, sbdsp_intr, sc, sc->sc_dev.dv_xname);
  266 
  267         sbdsp_attach(sc);
  268 
  269 #if NMIDI > 0
  270         sc->sc_hasmpu = 0;
  271         if (ISSB16CLASS(sc) && sc->sc_mpu_sc.iobase != 0) {
  272                 sc->sc_mpu_sc.iot = sc->sc_iot;
  273                 if (mpu_find(&sc->sc_mpu_sc)) {
  274                         sc->sc_hasmpu = 1;
  275                         mhw = &sb_mpu401_hw_if;
  276                 }
  277         }
  278         midi_attach_mi(mhw, sc, &sc->sc_dev);
  279 #endif
  280 
  281         audio_attach_mi(&sb_hw_if, sc, &sc->sc_dev);
  282 
  283         arg.type = AUDIODEV_TYPE_OPL;
  284         arg.hwif = 0;
  285         arg.hdl = 0;
  286         (void)config_found(&sc->sc_dev, &arg, audioprint);
  287 }
  288 
  289 /*
  290  * Various routines to interface to higher level audio driver
  291  */
  292 
  293 int
  294 sb_getdev(addr, retp)
  295         void *addr;
  296         struct audio_device *retp;
  297 {
  298         struct sbdsp_softc *sc = addr;
  299         static char *names[] = SB_NAMES;
  300         char *config;
  301 
  302         if (sc->sc_model == SB_JAZZ)
  303                 strlcpy(retp->name, "MV Jazz16", sizeof retp->name);
  304         else
  305                 strlcpy(retp->name, "SoundBlaster", sizeof retp->name);
  306         snprintf(retp->version, sizeof retp->version, "%d.%02d", 
  307                  SBVER_MAJOR(sc->sc_version),
  308                  SBVER_MINOR(sc->sc_version));
  309         if (0 <= sc->sc_model && sc->sc_model < sizeof names / sizeof names[0])
  310                 config = names[sc->sc_model];
  311         else
  312                 config = "??";
  313         strlcpy(retp->config, config, sizeof retp->config);
  314                 
  315         return 0;
  316 }
  317 
  318 #if NMIDI > 0
  319 
  320 #define SBMPU(a) (&((struct sbdsp_softc *)addr)->sc_mpu_sc)
  321 
  322 int
  323 sb_mpu401_open(addr, flags, iintr, ointr, arg)
  324         void *addr;
  325         int flags;
  326         void (*iintr)(void *, int);
  327         void (*ointr)(void *);
  328         void *arg;
  329 {
  330         return mpu_open(SBMPU(addr), flags, iintr, ointr, arg);
  331 }
  332 
  333 int
  334 sb_mpu401_output(addr, d)
  335         void *addr;
  336         int d;
  337 {
  338         return mpu_output(SBMPU(addr), d);
  339 }
  340 
  341 void
  342 sb_mpu401_close(addr)
  343         void *addr;
  344 {
  345         mpu_close(SBMPU(addr));
  346 }
  347 
  348 void
  349 sb_mpu401_getinfo(addr, mi)
  350         void *addr;
  351         struct midi_info *mi;
  352 {
  353         mi->name = "SB MPU-401 UART";
  354         mi->props = 0;
  355 }
  356 #endif

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