root/dev/isa/wss_isa.c

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

DEFINITIONS

This source file includes following definitions.
  1. wss_isa_probe
  2. wssfind
  3. wss_isa_attach
  4. detect_mad16
  5. madprobe
  6. madunmap

    1 /*      $OpenBSD: wss_isa.c,v 1.5 2006/01/02 05:21:40 brad Exp $        */
    2 /*      $NetBSD: wss_isa.c,v 1.1 1998/01/19 22:18:24 augustss Exp $     */
    3 
    4 /*
    5  * Copyright (c) 1994 John Brezak
    6  * Copyright (c) 1991-1993 Regents of the University of California.
    7  * All rights reserved.
    8  *
    9  * MAD support:
   10  * Copyright (c) 1996 Lennart Augustsson
   11  * Based on code which is
   12  * Copyright (c) 1994 Hannu Savolainen
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. All advertising materials mentioning features or use of this software
   23  *    must display the following acknowledgement:
   24  *      This product includes software developed by the Computer Systems
   25  *      Engineering Group at Lawrence Berkeley Laboratory.
   26  * 4. Neither the name of the University nor of the Laboratory may be used
   27  *    to endorse or promote products derived from this software without
   28  *    specific prior written permission.
   29  *
   30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   40  * SUCH DAMAGE.
   41  *
   42  */
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/errno.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/syslog.h>
   48 #include <sys/device.h>
   49 #include <sys/proc.h>
   50 #include <sys/buf.h>
   51 
   52 #include <machine/cpu.h>
   53 #include <machine/intr.h>
   54 #include <machine/bus.h>
   55 
   56 #include <sys/audioio.h>
   57 #include <dev/audio_if.h>
   58 
   59 #include <dev/isa/isavar.h>
   60 #include <dev/isa/isadmavar.h>
   61 
   62 #include <dev/ic/ad1848reg.h>
   63 #include <dev/isa/ad1848var.h>
   64 #include <dev/isa/wssreg.h>
   65 #include <dev/isa/wssvar.h>
   66 #include <dev/isa/madreg.h>
   67 
   68 #ifdef AUDIO_DEBUG
   69 #define DPRINTF(x)      if (wssdebug) printf x
   70 extern int      wssdebug;
   71 #else
   72 #define DPRINTF(x)
   73 #endif
   74 
   75 static int      wssfind(struct device *, struct wss_softc *, struct isa_attach_args *);
   76 
   77 static void     madprobe(struct wss_softc *, int);
   78 static void     madunmap(struct wss_softc *);
   79 static int      detect_mad16(struct wss_softc *, int);
   80 
   81 int             wss_isa_probe(struct device *, void *, void *);
   82 void            wss_isa_attach(struct device *, struct device *, void *);
   83 
   84 struct cfattach wss_isa_ca = {
   85         sizeof(struct wss_softc), wss_isa_probe, wss_isa_attach
   86 };
   87 
   88 struct cfdriver wss_cd = {
   89         NULL, "wss", DV_DULL
   90 };
   91 
   92 /*
   93  * Probe for the Microsoft Sound System hardware.
   94  */
   95 int
   96 wss_isa_probe(parent, match, aux)
   97     struct device *parent;
   98     void *match;
   99     void *aux;
  100 {
  101     struct wss_softc probesc, *sc = &probesc;
  102 
  103     bzero(sc, sizeof *sc);
  104     sc->sc_dev.dv_cfdata = ((struct device *)match)->dv_cfdata;
  105     if (wssfind(parent, sc, aux)) {
  106         bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
  107         ad1848_unmap(&sc->sc_ad1848);
  108         madunmap(sc);
  109         return 1;
  110     } else
  111         /* Everything is already unmapped */
  112         return 0;
  113 }
  114 
  115 static int
  116 wssfind(parent, sc, ia)
  117     struct device *parent;
  118     struct wss_softc *sc;
  119     struct isa_attach_args *ia;
  120 {
  121     static u_char interrupt_bits[12] = {
  122         -1, -1, -1, -1, -1, 0x0, -1, 0x08, -1, 0x10, 0x18, 0x20
  123     };
  124     static u_char dma_bits[4] = {1, 2, 0, 3};
  125     
  126     sc->sc_iot = ia->ia_iot;
  127     if (sc->sc_dev.dv_cfdata->cf_flags & 1)
  128         madprobe(sc, ia->ia_iobase);
  129     else
  130         sc->mad_chip_type = MAD_NONE;
  131 
  132     if (!WSS_BASE_VALID(ia->ia_iobase)) {
  133         DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
  134         goto bad1;
  135     }
  136 
  137     /* Map the ports upto the AD1848 port */
  138     if (bus_space_map(sc->sc_iot, ia->ia_iobase, WSS_CODEC, 0, &sc->sc_ioh))
  139         goto bad1;
  140 
  141     sc->sc_ad1848.sc_iot = sc->sc_iot;
  142 
  143     /* Is there an ad1848 chip at (WSS iobase + WSS_CODEC)? */
  144     if (ad1848_mapprobe(&sc->sc_ad1848, ia->ia_iobase + WSS_CODEC) == 0)
  145         goto bad;
  146         
  147     ia->ia_iosize = WSS_NPORT;
  148 
  149     /* Setup WSS interrupt and DMA */
  150     if (!WSS_DRQ_VALID(ia->ia_drq)) {
  151         DPRINTF(("wss: configured dma chan %d invalid\n", ia->ia_drq));
  152         goto bad;
  153     }
  154     sc->wss_drq = ia->ia_drq;
  155 
  156     if (sc->wss_drq != DRQUNK && !isa_drq_isfree(parent, sc->wss_drq))
  157             goto bad;
  158 
  159     if (!WSS_IRQ_VALID(ia->ia_irq)) {
  160         DPRINTF(("wss: configured interrupt %d invalid\n", ia->ia_irq));
  161         goto bad;
  162     }
  163 
  164     sc->wss_irq = ia->ia_irq;
  165 
  166     if (sc->sc_ad1848.mode <= 1)
  167         ia->ia_drq2 = DRQUNK;
  168     sc->wss_recdrq = 
  169         sc->sc_ad1848.mode > 1 && ia->ia_drq2 != DRQUNK ? 
  170         ia->ia_drq2 : ia->ia_drq;
  171     if (sc->wss_recdrq != sc->wss_drq && !isa_drq_isfree(parent, sc->wss_recdrq))
  172         goto bad;
  173 
  174     /* XXX recdrq */
  175     bus_space_write_1(sc->sc_iot, sc->sc_ioh, WSS_CONFIG,
  176                       (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_drq]));
  177 
  178     return 1;
  179 
  180 bad:
  181     bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
  182 bad1:
  183     madunmap(sc);
  184     return 0;
  185 }
  186 
  187 /*
  188  * Attach hardware to driver, attach hardware driver to audio
  189  * pseudo-device driver .
  190  */
  191 void
  192 wss_isa_attach(parent, self, aux)
  193     struct device *parent, *self;
  194     void *aux;
  195 {
  196     struct wss_softc *sc = (struct wss_softc *)self;
  197     struct isa_attach_args *ia = (struct isa_attach_args *)aux;
  198     
  199     if (!wssfind(parent, sc, ia)) {
  200         printf("%s: wssfind failed\n", sc->sc_dev.dv_xname);
  201         return;
  202     }
  203 
  204     sc->sc_ic = ia->ia_ic;
  205     sc->sc_ad1848.sc_isa = parent;
  206 
  207     wssattach(sc);
  208 }
  209 
  210 /*
  211  * Copyright by Hannu Savolainen 1994
  212  *
  213  * Redistribution and use in source and binary forms, with or without
  214  * modification, are permitted provided that the following conditions are
  215  * met: 1. Redistributions of source code must retain the above copyright
  216  * notice, this list of conditions and the following disclaimer. 2.
  217  * Redistributions in binary form must reproduce the above copyright notice,
  218  * this list of conditions and the following disclaimer in the documentation
  219  * and/or other materials provided with the distribution.
  220  *
  221  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  222  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  223  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  224  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  225  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  226  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  227  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  228  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  229  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  230  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  231  * SUCH DAMAGE.
  232  *
  233  */
  234 
  235 /*
  236  * Initialization code for OPTi MAD16 compatible audio chips. Including
  237  *
  238  *      OPTi 82C928     MAD16           (replaced by C929)
  239  *      OAK OTI-601D    Mozart
  240  *      OPTi 82C929     MAD16 Pro
  241  *      OPTi 82C931
  242  */
  243 
  244 static int
  245 detect_mad16(sc, chip_type)
  246     struct wss_softc *sc;
  247     int chip_type;
  248 {
  249     unsigned char tmp, tmp2;
  250 
  251     sc->mad_chip_type = chip_type;
  252     /*
  253      * Check that reading a register doesn't return bus float (0xff)
  254      * when the card is accessed using password. This may fail in case
  255      * the card is in low power mode. Normally at least the power saving mode
  256      * bit should be 0.
  257      */
  258     if ((tmp = mad_read(sc, MC1_PORT)) == 0xff) {
  259         DPRINTF(("MC1_PORT returned 0xff\n"));
  260         return 0;
  261     }
  262 
  263     /*
  264      * Now check that the gate is closed on first I/O after writing
  265      * the password. (This is how a MAD16 compatible card works).
  266      */
  267     if ((tmp2 = bus_space_read_1(sc->sc_iot, sc->mad_ioh, MC1_PORT)) == tmp)    {
  268         DPRINTF(("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
  269         return 0;
  270     }
  271 
  272     mad_write(sc, MC1_PORT, tmp ^ 0x80);        /* Toggle a bit */
  273 
  274     /* Compare the bit */
  275     if ((tmp2 = mad_read(sc, MC1_PORT)) != (tmp ^ 0x80)) {
  276         mad_write(sc, MC1_PORT, tmp);   /* Restore */
  277         DPRINTF(("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
  278         return 0;
  279     }
  280 
  281     mad_write(sc, MC1_PORT, tmp);       /* Restore */
  282     return 1;
  283 }
  284 
  285 static void
  286 madprobe(sc, iobase)
  287     struct wss_softc *sc;
  288     int iobase;
  289 {
  290     static int valid_ports[M_WSS_NPORTS] = 
  291         { M_WSS_PORT0, M_WSS_PORT1, M_WSS_PORT2, M_WSS_PORT3 };
  292     int i;
  293 
  294     /* Allocate bus space that the MAD chip wants */
  295     if (bus_space_map(sc->sc_iot, MAD_BASE, MAD_NPORT, 0, &sc->mad_ioh))
  296         goto bad0;
  297     if (bus_space_map(sc->sc_iot, MAD_REG1, MAD_LEN1, 0, &sc->mad_ioh1))
  298         goto bad1;
  299     if (bus_space_map(sc->sc_iot, MAD_REG2, MAD_LEN2, 0, &sc->mad_ioh2))
  300         goto bad2;
  301     if (bus_space_map(sc->sc_iot, MAD_REG3, MAD_LEN3, 0, &sc->mad_ioh3))
  302         goto bad3;
  303 
  304     DPRINTF(("mad: Detect using password = 0xE2\n"));
  305     if (!detect_mad16(sc, MAD_82C928)) {
  306         /* No luck. Try different model */
  307         DPRINTF(("mad: Detect using password = 0xE3\n"));
  308         if (!detect_mad16(sc, MAD_82C929))
  309             goto bad;
  310         sc->mad_chip_type = MAD_82C929;
  311         DPRINTF(("mad: 82C929 detected\n"));
  312     } else {
  313         sc->mad_chip_type = MAD_82C928;
  314         if ((mad_read(sc, MC3_PORT) & 0x03) == 0x03) {
  315             DPRINTF(("mad: Mozart detected\n"));
  316             sc->mad_chip_type = MAD_OTI601D;
  317         } else {
  318             DPRINTF(("mad: 82C928 detected?\n"));
  319             sc->mad_chip_type = MAD_82C928;
  320         }
  321     }
  322 
  323 #ifdef AUDIO_DEBUG
  324     if (wssdebug)
  325         for (i = MC1_PORT; i <= MC7_PORT; i++)
  326             printf("mad: port %03x = %02x\n", i, mad_read(sc, i));
  327 #endif
  328 
  329     /* Set the WSS address. */
  330     for (i = 0; i < M_WSS_NPORTS; i++)
  331         if (valid_ports[i] == iobase)
  332             break;
  333     if (i >= M_WSS_NPORTS) {            /* Not a valid port */
  334         printf("mad: Bad WSS base address 0x%x\n", iobase);
  335         goto bad;
  336     }
  337     sc->mad_ioindex = i;
  338     /* enable WSS emulation at the I/O port, no joystick */
  339     mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(i) | MC1_JOYDISABLE);
  340     mad_write(sc, MC2_PORT, 0x03); /* ? */
  341     mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
  342     return;
  343 
  344 bad:
  345     bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
  346 bad3:
  347     bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
  348 bad2:
  349     bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
  350 bad1:
  351     bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
  352 bad0:
  353     sc->mad_chip_type = MAD_NONE;
  354 }
  355 
  356 static void
  357 madunmap(sc)
  358     struct wss_softc *sc;
  359 {
  360     if (sc->mad_chip_type == MAD_NONE)
  361         return;
  362     bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
  363     bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
  364     bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
  365     bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
  366 }

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