[BACK]Return to wss_isa.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Annotation of src/sys/dev/isa/wss_isa.c, Revision 1.17

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

CVSweb <webmaster@jp.NetBSD.org>