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

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