[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     ! 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