Annotation of sys/dev/isa/sb.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sb.c,v 1.24 2006/04/07 22:41:33 jsg Exp $ */
! 2: /* $NetBSD: sb.c,v 1.57 1998/01/12 09:43:46 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1991-1993 Regents of the University of California.
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed by the Computer Systems
! 19: * Engineering Group at Lawrence Berkeley Laboratory.
! 20: * 4. Neither the name of the University nor of the Laboratory may be used
! 21: * to endorse or promote products derived from this software without
! 22: * specific prior written permission.
! 23: *
! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 34: * SUCH DAMAGE.
! 35: *
! 36: */
! 37:
! 38: #include "midi.h"
! 39:
! 40: #include <sys/param.h>
! 41: #include <sys/systm.h>
! 42: #include <sys/errno.h>
! 43: #include <sys/ioctl.h>
! 44: #include <sys/syslog.h>
! 45: #include <sys/device.h>
! 46: #include <sys/proc.h>
! 47:
! 48: #include <machine/cpu.h>
! 49: #include <machine/intr.h>
! 50: #include <machine/bus.h>
! 51:
! 52: #include <sys/audioio.h>
! 53: #include <dev/audio_if.h>
! 54: #include <dev/midi_if.h>
! 55:
! 56: #include <dev/isa/isavar.h>
! 57: #include <dev/isa/isadmavar.h>
! 58:
! 59: #include <dev/isa/sbreg.h>
! 60: #include <dev/isa/sbvar.h>
! 61: #include <dev/isa/sbdspvar.h>
! 62:
! 63: struct cfdriver sb_cd = {
! 64: NULL, "sb", DV_DULL
! 65: };
! 66:
! 67: #if NMIDI > 0
! 68: int sb_mpu401_open(void *, int, void (*iintr)(void *, int),
! 69: void (*ointr)(void *), void *arg);
! 70: void sb_mpu401_close(void *);
! 71: int sb_mpu401_output(void *, int);
! 72: void sb_mpu401_getinfo(void *, struct midi_info *);
! 73:
! 74: struct midi_hw_if sb_midi_hw_if = {
! 75: sbdsp_midi_open,
! 76: sbdsp_midi_close,
! 77: sbdsp_midi_output,
! 78: 0, /* flush */
! 79: sbdsp_midi_getinfo,
! 80: 0, /* ioctl */
! 81: };
! 82:
! 83: struct midi_hw_if sb_mpu401_hw_if = {
! 84: sb_mpu401_open,
! 85: sb_mpu401_close,
! 86: sb_mpu401_output,
! 87: 0, /* flush */
! 88: sb_mpu401_getinfo,
! 89: 0, /* ioctl */
! 90: };
! 91: #endif
! 92:
! 93: struct audio_device sb_device = {
! 94: "SoundBlaster",
! 95: "x",
! 96: "sb"
! 97: };
! 98:
! 99: int sb_getdev(void *, struct audio_device *);
! 100:
! 101: /*
! 102: * Define our interface to the higher level audio driver.
! 103: */
! 104:
! 105: struct audio_hw_if sb_hw_if = {
! 106: sbdsp_open,
! 107: sbdsp_close,
! 108: 0,
! 109: sbdsp_query_encoding,
! 110: sbdsp_set_params,
! 111: sbdsp_round_blocksize,
! 112: 0,
! 113: 0,
! 114: 0,
! 115: 0,
! 116: 0,
! 117: sbdsp_haltdma,
! 118: sbdsp_haltdma,
! 119: sbdsp_speaker_ctl,
! 120: sb_getdev,
! 121: 0,
! 122: sbdsp_mixer_set_port,
! 123: sbdsp_mixer_get_port,
! 124: sbdsp_mixer_query_devinfo,
! 125: sb_malloc,
! 126: sb_free,
! 127: sb_round,
! 128: sb_mappage,
! 129: sbdsp_get_props,
! 130: sbdsp_trigger_output,
! 131: sbdsp_trigger_input
! 132: };
! 133:
! 134: #ifdef AUDIO_DEBUG
! 135: #define DPRINTF(x) if (sbdebug) printf x
! 136: int sbdebug = 0;
! 137: #else
! 138: #define DPRINTF(x)
! 139: #endif
! 140:
! 141: /*
! 142: * Probe / attach routines.
! 143: */
! 144:
! 145:
! 146: int
! 147: sbmatch(sc)
! 148: struct sbdsp_softc *sc;
! 149: {
! 150: static u_char drq_conf[8] = {
! 151: 0x01, 0x02, -1, 0x08, -1, 0x20, 0x40, 0x80
! 152: };
! 153:
! 154: static u_char irq_conf[11] = {
! 155: -1, -1, 0x01, -1, -1, 0x02, -1, 0x04, -1, 0x01, 0x08
! 156: };
! 157:
! 158: if (sbdsp_probe(sc) == 0)
! 159: return 0;
! 160:
! 161: /*
! 162: * Cannot auto-discover DMA channel.
! 163: */
! 164: if (ISSBPROCLASS(sc)) {
! 165: if (!SBP_DRQ_VALID(sc->sc_drq8)) {
! 166: DPRINTF(("%s: configured dma chan %d invalid\n",
! 167: sc->sc_dev.dv_xname, sc->sc_drq8));
! 168: return 0;
! 169: }
! 170: } else {
! 171: if (!SB_DRQ_VALID(sc->sc_drq8)) {
! 172: DPRINTF(("%s: configured dma chan %d invalid\n",
! 173: sc->sc_dev.dv_xname, sc->sc_drq8));
! 174: return 0;
! 175: }
! 176: }
! 177:
! 178: if (0 <= sc->sc_drq16 && sc->sc_drq16 <= 3)
! 179: /*
! 180: * XXX Some ViBRA16 cards seem to have two 8 bit DMA
! 181: * channels. I've no clue how to use them, so ignore
! 182: * one of them for now. -- augustss@netbsd.org
! 183: */
! 184: sc->sc_drq16 = -1;
! 185:
! 186: if (ISSB16CLASS(sc)) {
! 187: if (sc->sc_drq16 == -1)
! 188: sc->sc_drq16 = sc->sc_drq8;
! 189: if (!SB16_DRQ_VALID(sc->sc_drq16)) {
! 190: DPRINTF(("%s: configured dma chan %d invalid\n",
! 191: sc->sc_dev.dv_xname, sc->sc_drq16));
! 192: return 0;
! 193: }
! 194: } else
! 195: sc->sc_drq16 = sc->sc_drq8;
! 196:
! 197: if (ISSBPROCLASS(sc)) {
! 198: if (!SBP_IRQ_VALID(sc->sc_irq)) {
! 199: DPRINTF(("%s: configured irq %d invalid\n",
! 200: sc->sc_dev.dv_xname, sc->sc_irq));
! 201: return 0;
! 202: }
! 203: } else {
! 204: if (!SB_IRQ_VALID(sc->sc_irq)) {
! 205: DPRINTF(("%s: configured irq %d invalid\n",
! 206: sc->sc_dev.dv_xname, sc->sc_irq));
! 207: return 0;
! 208: }
! 209: }
! 210:
! 211: if (ISSB16CLASS(sc)) {
! 212: int w, r;
! 213: #if 0
! 214: DPRINTF(("%s: old drq conf %02x\n", sc->sc_dev.dv_xname,
! 215: sbdsp_mix_read(sc, SBP_SET_DRQ)));
! 216: DPRINTF(("%s: try drq conf %02x\n", sc->sc_dev.dv_xname,
! 217: drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8]));
! 218: #endif
! 219: w = drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8];
! 220: sbdsp_mix_write(sc, SBP_SET_DRQ, w);
! 221: r = sbdsp_mix_read(sc, SBP_SET_DRQ) & 0xeb;
! 222: if (r != w) {
! 223: DPRINTF(("%s: setting drq mask %02x failed, got %02x\n", sc->sc_dev.dv_xname, w, r));
! 224: return 0;
! 225: }
! 226: #if 0
! 227: DPRINTF(("%s: new drq conf %02x\n", sc->sc_dev.dv_xname,
! 228: sbdsp_mix_read(sc, SBP_SET_DRQ)));
! 229: #endif
! 230:
! 231: #if 0
! 232: DPRINTF(("%s: old irq conf %02x\n", sc->sc_dev.dv_xname,
! 233: sbdsp_mix_read(sc, SBP_SET_IRQ)));
! 234: DPRINTF(("%s: try irq conf %02x\n", sc->sc_dev.dv_xname,
! 235: irq_conf[sc->sc_irq]));
! 236: #endif
! 237: w = irq_conf[sc->sc_irq];
! 238: sbdsp_mix_write(sc, SBP_SET_IRQ, w);
! 239: r = sbdsp_mix_read(sc, SBP_SET_IRQ) & 0x0f;
! 240: if (r != w) {
! 241: DPRINTF(("%s: setting irq mask %02x failed, got %02x\n",
! 242: sc->sc_dev.dv_xname, w, r));
! 243: return 0;
! 244: }
! 245: #if 0
! 246: DPRINTF(("%s: new irq conf %02x\n", sc->sc_dev.dv_xname,
! 247: sbdsp_mix_read(sc, SBP_SET_IRQ)));
! 248: #endif
! 249: }
! 250:
! 251: return 1;
! 252: }
! 253:
! 254:
! 255: void
! 256: sbattach(sc)
! 257: struct sbdsp_softc *sc;
! 258: {
! 259: struct audio_attach_args arg;
! 260: #if NMIDI > 0
! 261: struct midi_hw_if *mhw = &sb_midi_hw_if;
! 262: #endif
! 263:
! 264: sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->sc_irq, IST_EDGE,
! 265: IPL_AUDIO, sbdsp_intr, sc, sc->sc_dev.dv_xname);
! 266:
! 267: sbdsp_attach(sc);
! 268:
! 269: #if NMIDI > 0
! 270: sc->sc_hasmpu = 0;
! 271: if (ISSB16CLASS(sc) && sc->sc_mpu_sc.iobase != 0) {
! 272: sc->sc_mpu_sc.iot = sc->sc_iot;
! 273: if (mpu_find(&sc->sc_mpu_sc)) {
! 274: sc->sc_hasmpu = 1;
! 275: mhw = &sb_mpu401_hw_if;
! 276: }
! 277: }
! 278: midi_attach_mi(mhw, sc, &sc->sc_dev);
! 279: #endif
! 280:
! 281: audio_attach_mi(&sb_hw_if, sc, &sc->sc_dev);
! 282:
! 283: arg.type = AUDIODEV_TYPE_OPL;
! 284: arg.hwif = 0;
! 285: arg.hdl = 0;
! 286: (void)config_found(&sc->sc_dev, &arg, audioprint);
! 287: }
! 288:
! 289: /*
! 290: * Various routines to interface to higher level audio driver
! 291: */
! 292:
! 293: int
! 294: sb_getdev(addr, retp)
! 295: void *addr;
! 296: struct audio_device *retp;
! 297: {
! 298: struct sbdsp_softc *sc = addr;
! 299: static char *names[] = SB_NAMES;
! 300: char *config;
! 301:
! 302: if (sc->sc_model == SB_JAZZ)
! 303: strlcpy(retp->name, "MV Jazz16", sizeof retp->name);
! 304: else
! 305: strlcpy(retp->name, "SoundBlaster", sizeof retp->name);
! 306: snprintf(retp->version, sizeof retp->version, "%d.%02d",
! 307: SBVER_MAJOR(sc->sc_version),
! 308: SBVER_MINOR(sc->sc_version));
! 309: if (0 <= sc->sc_model && sc->sc_model < sizeof names / sizeof names[0])
! 310: config = names[sc->sc_model];
! 311: else
! 312: config = "??";
! 313: strlcpy(retp->config, config, sizeof retp->config);
! 314:
! 315: return 0;
! 316: }
! 317:
! 318: #if NMIDI > 0
! 319:
! 320: #define SBMPU(a) (&((struct sbdsp_softc *)addr)->sc_mpu_sc)
! 321:
! 322: int
! 323: sb_mpu401_open(addr, flags, iintr, ointr, arg)
! 324: void *addr;
! 325: int flags;
! 326: void (*iintr)(void *, int);
! 327: void (*ointr)(void *);
! 328: void *arg;
! 329: {
! 330: return mpu_open(SBMPU(addr), flags, iintr, ointr, arg);
! 331: }
! 332:
! 333: int
! 334: sb_mpu401_output(addr, d)
! 335: void *addr;
! 336: int d;
! 337: {
! 338: return mpu_output(SBMPU(addr), d);
! 339: }
! 340:
! 341: void
! 342: sb_mpu401_close(addr)
! 343: void *addr;
! 344: {
! 345: mpu_close(SBMPU(addr));
! 346: }
! 347:
! 348: void
! 349: sb_mpu401_getinfo(addr, mi)
! 350: void *addr;
! 351: struct midi_info *mi;
! 352: {
! 353: mi->name = "SB MPU-401 UART";
! 354: mi->props = 0;
! 355: }
! 356: #endif
CVSweb