1351377Scy/* $NetBSD: sb_isa.c,v 1.39 2019/05/08 13:40:18 isaki Exp $ */ 2351377Scy 3351377Scy/* 4351377Scy * Copyright (c) 1991-1993 Regents of the University of California. 5351377Scy * All rights reserved. 6351377Scy * 7351377Scy * Redistribution and use in source and binary forms, with or without 8351377Scy * modification, are permitted provided that the following conditions 9351377Scy * are met: 10351377Scy * 1. Redistributions of source code must retain the above copyright 11351377Scy * notice, this list of conditions and the following disclaimer. 12351377Scy * 2. Redistributions in binary form must reproduce the above copyright 13351377Scy * notice, this list of conditions and the following disclaimer in the 14351377Scy * documentation and/or other materials provided with the distribution. 15351377Scy * 3. All advertising materials mentioning features or use of this software 16351377Scy * must display the following acknowledgement: 17351377Scy * This product includes software developed by the Computer Systems 18351377Scy * Engineering Group at Lawrence Berkeley Laboratory. 19351377Scy * 4. Neither the name of the University nor of the Laboratory may be used 20351377Scy * to endorse or promote products derived from this software without 21351377Scy * specific prior written permission. 22351377Scy * 23351377Scy * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24351377Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25351377Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26351377Scy * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27351377Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28351377Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29351377Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30351377Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31351377Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32351377Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33351377Scy * SUCH DAMAGE. 34351377Scy * 35351377Scy */ 36351377Scy 37351377Scy#include <sys/cdefs.h> 38351377Scy__KERNEL_RCSID(0, "$NetBSD: sb_isa.c,v 1.39 2019/05/08 13:40:18 isaki Exp $"); 39351377Scy 40351377Scy#include <sys/param.h> 41351377Scy#include <sys/systm.h> 42351377Scy#include <sys/errno.h> 43351377Scy#include <sys/ioctl.h> 44351377Scy#include <sys/syslog.h> 45351377Scy#include <sys/device.h> 46351377Scy#include <sys/proc.h> 47351377Scy 48351377Scy#include <sys/bus.h> 49351377Scy 50351377Scy#include <sys/audioio.h> 51351377Scy#include <dev/audio/audio_if.h> 52351377Scy#include <dev/midi_if.h> 53351377Scy 54351377Scy#include <dev/isa/isavar.h> 55351377Scy#include <dev/isa/isadmavar.h> 56351377Scy 57351377Scy#include <dev/isa/sbreg.h> 58351377Scy#include <dev/isa/sbvar.h> 59351377Scy 60351377Scy#include <dev/isa/sbdspvar.h> 61351377Scy 62351377Scystatic int sbfind(device_t, struct sbdsp_softc *, int, 63351377Scy struct isa_attach_args *, cfdata_t); 64351377Scy 65351377Scyint sb_isa_match(device_t, cfdata_t, void *); 66351377Scyvoid sb_isa_attach(device_t, device_t, void *); 67351377Scy 68351377ScyCFATTACH_DECL_NEW(sb_isa, sizeof(struct sbdsp_softc), 69351377Scy sb_isa_match, sb_isa_attach, NULL, NULL); 70351377Scy 71351377Scy/* 72351377Scy * Probe / attach routines. 73351377Scy */ 74351377Scy 75351377Scy/* 76351377Scy * Probe for the soundblaster hardware. 77351377Scy */ 78351377Scyint 79351377Scysb_isa_match(device_t parent, cfdata_t match, void *aux) 80351377Scy{ 81351377Scy struct isa_attach_args *ia = aux; 82351377Scy struct sbdsp_softc probesc, *sc = &probesc; 83351377Scy 84351377Scy if (ia->ia_nio < 1) 85351377Scy return (0); 86351377Scy if (ia->ia_nirq < 1) 87351377Scy return (0); 88351377Scy if (ia->ia_ndrq < 1) 89351377Scy return (0); 90351377Scy 91351377Scy if (ISA_DIRECT_CONFIG(ia)) 92351377Scy return (0); 93351377Scy 94351377Scy memset(sc, 0, sizeof *sc); 95351377Scy return sbfind(parent, sc, 1, aux, match); 96351377Scy} 97351377Scy 98351377Scystatic int 99351377Scysbfind(device_t parent, struct sbdsp_softc *sc, int probing, 100351377Scy struct isa_attach_args *ia, cfdata_t match) 101351377Scy{ 102351377Scy int rc = 0; 103351377Scy 104351377Scy if (!SB_BASE_VALID(ia->ia_io[0].ir_addr)) { 105351377Scy printf("sb: configured iobase 0x%x invalid\n", 106351377Scy ia->ia_io[0].ir_addr); 107351377Scy return 0; 108351377Scy } 109351377Scy 110351377Scy sc->sc_ic = ia->ia_ic; 111351377Scy 112351377Scy sc->sc_iot = ia->ia_iot; 113351377Scy /* Map i/o space [we map 24 ports which is the max of the sb and pro */ 114351377Scy if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, SBP_NPORT, 0, 115351377Scy &sc->sc_ioh)) 116351377Scy return 0; 117351377Scy 118351377Scy /* XXX These are only for setting chip configuration registers. */ 119351377Scy sc->sc_iobase = ia->ia_io[0].ir_addr; 120351377Scy sc->sc_irq = ia->ia_irq[0].ir_irq; 121351377Scy 122351377Scy sc->sc_drq8 = ia->ia_drq[0].ir_drq; 123351377Scy sc->sc_drq16 = ia->ia_drq[1].ir_drq; 124351377Scy 125351377Scy if (!sbmatch(sc, probing, match)) 126351377Scy goto bad; 127351377Scy 128351377Scy rc = 1; 129351377Scy 130351377Scy if (probing) { 131351377Scy ia->ia_nio = 1; 132351377Scy if (ISSBPROCLASS(sc)) 133351377Scy ia->ia_io[0].ir_size = SBP_NPORT; 134351377Scy else 135351377Scy ia->ia_io[0].ir_size = SB_NPORT; 136351377Scy 137351377Scy if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ) 138351377Scy ia->ia_ndrq = 1; 139351377Scy else 140351377Scy ia->ia_ndrq = 2; 141351377Scy 142351377Scy ia->ia_nirq = 1; 143351377Scy ia->ia_irq[0].ir_irq = sc->sc_irq; 144351377Scy 145351377Scy ia->ia_niomem = 0; 146351377Scy } 147351377Scy 148351377Scybad: 149351377Scy bus_space_unmap(sc->sc_iot, sc->sc_ioh, SBP_NPORT); 150351377Scy return rc; 151351377Scy} 152351377Scy 153351377Scy 154351377Scy/* 155351377Scy * Attach hardware to driver, attach hardware driver to audio 156351377Scy * pseudo-device driver . 157351377Scy */ 158351377Scyvoid 159351377Scysb_isa_attach(device_t parent, device_t self, void *aux) 160351377Scy{ 161351377Scy struct sbdsp_softc *sc = device_private(self); 162351377Scy struct isa_attach_args *ia = aux; 163351377Scy 164351377Scy sc->sc_dev = self; 165351377Scy 166351377Scy if (!sbfind(parent, sc, 0, ia, device_cfdata(self)) || 167351377Scy bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 168351377Scy ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) { 169351377Scy aprint_error_dev(self, "sbfind failed\n"); 170351377Scy return; 171351377Scy } 172351377Scy 173351377Scy mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 174351377Scy mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 175351377Scy 176351377Scy sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 177351377Scy IST_EDGE, IPL_AUDIO, sbdsp_intr, sc); 178351377Scy 179351377Scy sbattach(sc); 180351377Scy} 181351377Scy