1 1.41 isaki /* $NetBSD: gus_isapnp.c,v 1.41 2020/02/29 05:51:11 isaki Exp $ */ 2 1.1 augustss 3 1.1 augustss /* 4 1.36 jmcneill * Copyright (c) 1997, 1999, 2008 The NetBSD Foundation, Inc. 5 1.1 augustss * All rights reserved. 6 1.1 augustss * 7 1.1 augustss * Author: Kari Mettinen 8 1.1 augustss * 9 1.1 augustss * Redistribution and use in source and binary forms, with or without 10 1.1 augustss * modification, are permitted provided that the following conditions 11 1.1 augustss * are met: 12 1.1 augustss * 1. Redistributions of source code must retain the above copyright 13 1.1 augustss * notice, this list of conditions and the following disclaimer. 14 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 augustss * notice, this list of conditions and the following disclaimer in the 16 1.1 augustss * documentation and/or other materials provided with the distribution. 17 1.1 augustss * 18 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 1.2 jtc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 1.2 jtc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 1.1 augustss * POSSIBILITY OF SUCH DAMAGE. 29 1.1 augustss */ 30 1.17 lukem 31 1.17 lukem #include <sys/cdefs.h> 32 1.41 isaki __KERNEL_RCSID(0, "$NetBSD: gus_isapnp.c,v 1.41 2020/02/29 05:51:11 isaki Exp $"); 33 1.11 mycroft 34 1.11 mycroft #include "guspnp.h" 35 1.11 mycroft #if NGUSPNP > 0 36 1.1 augustss 37 1.1 augustss #include <sys/param.h> 38 1.1 augustss #include <sys/systm.h> 39 1.1 augustss #include <sys/errno.h> 40 1.1 augustss #include <sys/ioctl.h> 41 1.1 augustss #include <sys/syslog.h> 42 1.1 augustss #include <sys/device.h> 43 1.1 augustss #include <sys/proc.h> 44 1.31 ad #include <sys/bus.h> 45 1.36 jmcneill #include <sys/audioio.h> 46 1.1 augustss 47 1.40 isaki #include <dev/audio/audio_if.h> 48 1.1 augustss 49 1.1 augustss #include <dev/isa/isavar.h> 50 1.1 augustss #include <dev/isa/isadmavar.h> 51 1.1 augustss 52 1.1 augustss #include <dev/isapnp/isapnpreg.h> 53 1.1 augustss #include <dev/isapnp/isapnpvar.h> 54 1.9 christos #include <dev/isapnp/isapnpdevs.h> 55 1.1 augustss 56 1.1 augustss #include <dev/ic/interwavevar.h> 57 1.1 augustss #include <dev/ic/interwavereg.h> 58 1.1 augustss 59 1.1 augustss 60 1.35 cegger int gus_isapnp_match(device_t, cfdata_t, void *); 61 1.35 cegger void gus_isapnp_attach(device_t, device_t, void *); 62 1.24 kent static int gus_isapnp_open(void *, int); 63 1.1 augustss 64 1.23 yamt static const struct audio_hw_if guspnp_hw_if = { 65 1.39 isaki .open = gus_isapnp_open, 66 1.39 isaki .close = iwclose, 67 1.40 isaki .query_format = iw_query_format, 68 1.40 isaki .set_format = iw_audio_set_format, 69 1.39 isaki .commit_settings = iw_commit_settings, 70 1.39 isaki .init_output = iw_init_output, 71 1.39 isaki .init_input = iw_init_input, 72 1.39 isaki .start_output = iw_start_output, 73 1.39 isaki .start_input = iw_start_input, 74 1.39 isaki .halt_output = iw_halt_output, 75 1.39 isaki .halt_input = iw_halt_input, 76 1.39 isaki .speaker_ctl = iw_speaker_ctl, 77 1.39 isaki .getdev = iw_getdev, 78 1.39 isaki .set_port = iw_set_port, 79 1.39 isaki .get_port = iw_get_port, 80 1.39 isaki .query_devinfo = iw_query_devinfo, 81 1.39 isaki .allocm = iw_malloc, 82 1.39 isaki .freem = iw_free, 83 1.39 isaki .round_buffersize = iw_round_buffersize, 84 1.39 isaki .get_props = iw_get_props, 85 1.39 isaki .get_locks = iw_get_locks, 86 1.1 augustss }; 87 1.1 augustss 88 1.37 chs CFATTACH_DECL_NEW(guspnp, sizeof(struct iw_softc), 89 1.20 thorpej gus_isapnp_match, gus_isapnp_attach, NULL, NULL); 90 1.1 augustss 91 1.6 thorpej extern struct cfdriver guspnp_cd; 92 1.1 augustss 93 1.1 augustss /* 94 1.1 augustss * Probe / attach routines. 95 1.1 augustss */ 96 1.1 augustss 97 1.1 augustss /* 98 1.1 augustss * Probe for the guspnp hardware. 99 1.1 augustss * 100 1.1 augustss * The thing has 5 separate devices on the card 101 1.1 augustss */ 102 1.1 augustss 103 1.14 augustss static int gus_0 = 1; /* XXX what's this */ 104 1.1 augustss 105 1.1 augustss int 106 1.35 cegger gus_isapnp_match(device_t parent, cfdata_t match, void *aux) 107 1.1 augustss { 108 1.13 mycroft int pri, variant; 109 1.12 mycroft 110 1.13 mycroft pri = isapnp_devmatch(aux, &isapnp_gus_devinfo, &variant); 111 1.13 mycroft if (pri && variant > 0) 112 1.13 mycroft pri = 0; 113 1.24 kent return pri; 114 1.1 augustss } 115 1.1 augustss 116 1.1 augustss /* 117 1.1 augustss * Attach hardware to driver, attach hardware driver to audio 118 1.1 augustss * pseudo-device driver. 119 1.1 augustss */ 120 1.1 augustss void 121 1.35 cegger gus_isapnp_attach(device_t parent, device_t self, void *aux) 122 1.1 augustss { 123 1.24 kent struct iw_softc *sc; 124 1.24 kent struct isapnp_attach_args *ipa; 125 1.1 augustss 126 1.26 thorpej sc = device_private(self); 127 1.24 kent ipa = aux; 128 1.38 msaitoh aprint_naive("\n"); 129 1.38 msaitoh aprint_normal("\n"); 130 1.1 augustss 131 1.1 augustss if (!gus_0) 132 1.1 augustss return; 133 1.13 mycroft gus_0 = 0; 134 1.1 augustss 135 1.4 augustss if (isapnp_config(ipa->ipa_iot, ipa->ipa_memt, ipa)) { 136 1.37 chs aprint_error_dev(self, "error in region allocation\n"); 137 1.4 augustss return; 138 1.4 augustss } 139 1.1 augustss 140 1.37 chs sc->sc_dev = self; 141 1.1 augustss sc->sc_iot = ipa->ipa_iot; 142 1.1 augustss 143 1.1 augustss /* handle is the region base */ 144 1.1 augustss 145 1.1 augustss sc->dir_h = 0; /* XXXXX */ 146 1.1 augustss sc->p2xr = 0; 147 1.1 augustss sc->p2xr_h = ipa->ipa_io[0].h; 148 1.1 augustss sc->sc_p2xr_ic = ipa->ipa_ic; 149 1.1 augustss sc->p3xr = 0; 150 1.1 augustss sc->p3xr_h = ipa->ipa_io[1].h; 151 1.1 augustss sc->sc_p3xr_ic = ipa->ipa_ic; 152 1.1 augustss sc->codec_index = 0; 153 1.1 augustss sc->codec_index_h = ipa->ipa_io[2].h; 154 1.1 augustss sc->sc_irq = ipa->ipa_irq[0].num; 155 1.1 augustss sc->sc_recdrq = ipa->ipa_drq[0].num; 156 1.1 augustss sc->sc_playdrq = ipa->ipa_drq[1].num; 157 1.1 augustss 158 1.7 thorpej sc->sc_ic = ipa->ipa_ic; 159 1.1 augustss 160 1.24 kent /* 161 1.1 augustss * Create our DMA maps. 162 1.1 augustss */ 163 1.24 kent if (sc->sc_playdrq != -1) { 164 1.15 thorpej sc->sc_play_maxsize = isa_dmamaxsize(sc->sc_ic, 165 1.15 thorpej sc->sc_playdrq); 166 1.28 jmcneill if (isa_drq_alloc(sc->sc_ic, sc->sc_playdrq) != 0) { 167 1.37 chs aprint_error_dev(self, "can't reserve drq %d\n", 168 1.32 cegger sc->sc_playdrq); 169 1.28 jmcneill return; 170 1.28 jmcneill } 171 1.24 kent if (isa_dmamap_create(sc->sc_ic, sc->sc_playdrq, 172 1.24 kent sc->sc_play_maxsize, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { 173 1.37 chs aprint_error_dev(self, "can't create map for drq %d\n", 174 1.32 cegger sc->sc_playdrq); 175 1.24 kent return; 176 1.24 kent } 177 1.24 kent } 178 1.24 kent if (sc->sc_recdrq != -1) { 179 1.15 thorpej sc->sc_rec_maxsize = isa_dmamaxsize(sc->sc_ic, 180 1.15 thorpej sc->sc_recdrq); 181 1.28 jmcneill if (isa_drq_alloc(sc->sc_ic, sc->sc_recdrq) != 0) { 182 1.37 chs aprint_error_dev(self, "can't reserve drq %d\n", 183 1.32 cegger sc->sc_recdrq); 184 1.28 jmcneill return; 185 1.28 jmcneill } 186 1.24 kent if (isa_dmamap_create(sc->sc_ic, sc->sc_recdrq, 187 1.24 kent sc->sc_rec_maxsize, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { 188 1.37 chs aprint_error_dev(self, "can't create map for drq %d\n", 189 1.32 cegger sc->sc_recdrq); 190 1.24 kent return; 191 1.24 kent } 192 1.24 kent } 193 1.1 augustss 194 1.24 kent /* 195 1.22 wiz * isapnp is a child if isa, and we need isa for the DMA 196 1.1 augustss * routines. 197 1.1 augustss */ 198 1.1 augustss sc->iw_cd = &guspnp_cd; 199 1.1 augustss sc->iw_hw_if = &guspnp_hw_if; 200 1.1 augustss 201 1.38 msaitoh aprint_normal_dev(self, "%s %s", ipa->ipa_devident, ipa->ipa_devclass); 202 1.1 augustss 203 1.1 augustss iwattach(sc); 204 1.1 augustss } 205 1.1 augustss 206 1.24 kent static int 207 1.24 kent gus_isapnp_open(void *addr, int flags) 208 1.1 augustss { 209 1.1 augustss /* open hardware */ 210 1.24 kent struct iw_softc *sc; 211 1.1 augustss 212 1.24 kent sc = (struct iw_softc *)addr; 213 1.1 augustss if (!sc) 214 1.1 augustss return ENXIO; 215 1.1 augustss 216 1.1 augustss return iwopen(sc,flags); 217 1.1 augustss } 218 1.1 augustss 219 1.1 augustss #endif /* NGUSPNP */ 220