[BACK]Return to wss_isa.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/wss_isa.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb