[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

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