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