Annotation of src/sys/dev/isa/wss_isa.c, Revision 1.17
1.17 ! drochner 1: /* $NetBSD: wss_isa.c,v 1.16 2003/05/03 18:11:29 wiz Exp $ */
1.1 augustss 2:
3: /*
4: * Copyright (c) 1994 John Brezak
5: * Copyright (c) 1991-1993 Regents of the University of California.
6: * All rights reserved.
7: *
8: * MAD support:
9: * Copyright (c) 1996 Lennart Augustsson
10: * Based on code which is
11: * Copyright (c) 1994 Hannu Savolainen
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the Computer Systems
24: * Engineering Group at Lawrence Berkeley Laboratory.
25: * 4. Neither the name of the University nor of the Laboratory may be used
26: * to endorse or promote products derived from this software without
27: * specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: *
41: */
1.11 lukem 42:
43: #include <sys/cdefs.h>
1.17 ! drochner 44: __KERNEL_RCSID(0, "$NetBSD: wss_isa.c,v 1.16 2003/05/03 18:11:29 wiz Exp $");
1.11 lukem 45:
1.1 augustss 46: #include <sys/param.h>
47: #include <sys/systm.h>
1.5 pk 48: #include <sys/device.h>
1.1 augustss 49: #include <sys/errno.h>
50:
51: #include <machine/cpu.h>
52: #include <machine/intr.h>
53: #include <machine/bus.h>
54:
55: #include <sys/audioio.h>
56: #include <dev/audio_if.h>
57:
58: #include <dev/isa/isavar.h>
59: #include <dev/isa/isadmavar.h>
60:
61: #include <dev/ic/ad1848reg.h>
62: #include <dev/isa/ad1848var.h>
63: #include <dev/isa/wssreg.h>
64: #include <dev/isa/wssvar.h>
65: #include <dev/isa/madreg.h>
66:
67: #ifdef AUDIO_DEBUG
68: #define DPRINTF(x) if (wssdebug) printf x
69: extern int wssdebug;
70: #else
71: #define DPRINTF(x)
72: #endif
73:
1.12 thorpej 74: static int wssfind __P((struct device *, struct wss_softc *, int,
75: struct isa_attach_args *));
1.1 augustss 76:
77: static void madprobe __P((struct wss_softc *, int));
78: static void madunmap __P((struct wss_softc *));
79: static int detect_mad16 __P((struct wss_softc *, int));
80:
1.2 drochner 81: int wss_isa_probe __P((struct device *, struct cfdata *, void *));
1.1 augustss 82: void wss_isa_attach __P((struct device *, struct device *, void *));
83:
1.15 thorpej 84: CFATTACH_DECL(wss_isa, sizeof(struct wss_softc),
85: wss_isa_probe, wss_isa_attach, NULL, NULL);
1.1 augustss 86:
87: /*
88: * Probe for the Microsoft Sound System hardware.
89: */
90: int
91: wss_isa_probe(parent, match, aux)
92: struct device *parent;
93: struct cfdata *match;
94: void *aux;
95: {
1.12 thorpej 96: struct isa_attach_args *ia = aux;
1.1 augustss 97: struct wss_softc probesc, *sc = &probesc;
1.5 pk 98: struct ad1848_softc *ac = (struct ad1848_softc *)&sc->sc_ad1848;
1.1 augustss 99:
1.12 thorpej 100: if (ia->ia_nio < 1)
101: return 0;
102: if (ia->ia_nirq < 1)
103: return 0;
104: if (ia->ia_ndrq < 1)
105: return 0;
106:
107: if (ISA_DIRECT_CONFIG(ia))
108: return 0;
109:
1.10 thorpej 110: memset(sc, 0, sizeof *sc);
1.5 pk 111: ac->sc_dev.dv_cfdata = match;
1.12 thorpej 112: if (wssfind(parent, sc, 1, aux)) {
1.1 augustss 113: bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
1.5 pk 114: ad1848_isa_unmap(&sc->sc_ad1848);
1.1 augustss 115: madunmap(sc);
116: return 1;
117: } else
118: /* Everything is already unmapped */
119: return 0;
120: }
121:
122: static int
1.12 thorpej 123: wssfind(parent, sc, probing, ia)
1.1 augustss 124: struct device *parent;
125: struct wss_softc *sc;
1.12 thorpej 126: int probing;
1.1 augustss 127: struct isa_attach_args *ia;
128: {
1.9 drochner 129: struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
1.1 augustss 130: static u_char interrupt_bits[12] = {
131: -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
132: };
133: static u_char dma_bits[4] = {1, 2, 0, 3};
1.12 thorpej 134: int ndrq, playdrq, recdrq;
135:
1.1 augustss 136: sc->sc_iot = ia->ia_iot;
1.5 pk 137: if (ac->sc_dev.dv_cfdata->cf_flags & 1)
1.12 thorpej 138: madprobe(sc, ia->ia_io[0].ir_addr);
1.1 augustss 139: else
140: sc->mad_chip_type = MAD_NONE;
141:
1.6 mycroft 142: #if 0
1.12 thorpej 143: if (!WSS_BASE_VALID(ia->ia_io[0].ir_addr)) {
1.1 augustss 144: DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
145: goto bad1;
146: }
1.6 mycroft 147: #endif
1.1 augustss 148:
149: /* Map the ports upto the AD1848 port */
1.12 thorpej 150: if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, WSS_CODEC,
151: 0, &sc->sc_ioh))
1.1 augustss 152: goto bad1;
153:
1.5 pk 154: ac->sc_iot = sc->sc_iot;
1.1 augustss 155:
156: /* Is there an ad1848 chip at (WSS iobase + WSS_CODEC)? */
1.12 thorpej 157: if (ad1848_isa_mapprobe(&sc->sc_ad1848,
158: ia->ia_io[0].ir_addr + WSS_CODEC) == 0)
1.1 augustss 159: goto bad;
160:
1.6 mycroft 161: #if 0
1.1 augustss 162: /* Setup WSS interrupt and DMA */
1.12 thorpej 163: if (!WSS_DRQ_VALID(ia->ia_drq[0].ir_drq)) {
1.16 wiz 164: DPRINTF(("wss: configured DMA chan %d invalid\n",
1.12 thorpej 165: ia->ia_drq[0].ir_drq));
1.1 augustss 166: goto bad;
167: }
1.6 mycroft 168: #endif
1.12 thorpej 169: sc->wss_playdrq = ia->ia_drq[0].ir_drq;
1.7 mycroft 170: sc->wss_ic = ia->ia_ic;
1.1 augustss 171:
1.17 ! drochner 172: if (sc->wss_playdrq != ISA_UNKNOWN_DRQ &&
1.12 thorpej 173: !isa_drq_isfree(sc->wss_ic, sc->wss_playdrq))
1.1 augustss 174: goto bad;
175:
1.6 mycroft 176: #if 0
1.12 thorpej 177: if (!WSS_IRQ_VALID(ia->ia_irq[0].ir_irq)) {
178: DPRINTF(("wss: configured interrupt %d invalid\n",
179: ia->ia_irq[0].ir_irq));
1.1 augustss 180: goto bad;
181: }
1.6 mycroft 182: #endif
1.1 augustss 183:
1.12 thorpej 184: sc->wss_irq = ia->ia_irq[0].ir_irq;
185:
186: playdrq = ia->ia_drq[0].ir_drq;
187: if (ia->ia_ndrq > 1) {
188: ndrq = 2;
189: recdrq = ia->ia_drq[1].ir_drq;
190: } else {
191: ndrq = 1;
1.17 ! drochner 192: recdrq = ISA_UNKNOWN_DRQ;
1.12 thorpej 193: }
1.1 augustss 194:
1.5 pk 195: if (ac->mode <= 1)
1.12 thorpej 196: ndrq = 1;
1.1 augustss 197: sc->wss_recdrq =
1.12 thorpej 198: ac->mode > 1 && ndrq > 1 &&
1.17 ! drochner 199: recdrq != ISA_UNKNOWN_DRQ ? recdrq : playdrq;
1.7 mycroft 200: if (sc->wss_recdrq != sc->wss_playdrq && !isa_drq_isfree(sc->wss_ic,
1.3 thorpej 201: sc->wss_recdrq))
1.1 augustss 202: goto bad;
203:
1.12 thorpej 204: if (probing) {
205: ia->ia_nio = 1;
206: ia->ia_io[0].ir_size = WSS_NPORT;
207:
208: ia->ia_nirq = 1;
209:
210: ia->ia_ndrq = ndrq;
211: ia->ia_drq[0].ir_drq = playdrq;
212: if (ndrq > 1)
213: ia->ia_drq[1].ir_drq = recdrq;
214:
215: ia->ia_niomem = 0;
216: }
217:
1.1 augustss 218: /* XXX recdrq */
219: bus_space_write_1(sc->sc_iot, sc->sc_ioh, WSS_CONFIG,
1.12 thorpej 220: (interrupt_bits[ia->ia_irq[0].ir_irq] |
221: dma_bits[ia->ia_drq[0].ir_drq]));
1.1 augustss 222:
223: return 1;
224:
225: bad:
226: bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
227: bad1:
228: madunmap(sc);
229: return 0;
230: }
231:
232: /*
233: * Attach hardware to driver, attach hardware driver to audio
234: * pseudo-device driver .
235: */
236: void
237: wss_isa_attach(parent, self, aux)
238: struct device *parent, *self;
239: void *aux;
240: {
241: struct wss_softc *sc = (struct wss_softc *)self;
1.5 pk 242: struct ad1848_softc *ac = (struct ad1848_softc *)&sc->sc_ad1848;
1.1 augustss 243: struct isa_attach_args *ia = (struct isa_attach_args *)aux;
244:
1.12 thorpej 245: if (!wssfind(parent, sc, 0, ia)) {
1.5 pk 246: printf("%s: wssfind failed\n", ac->sc_dev.dv_xname);
1.1 augustss 247: return;
248: }
249:
1.3 thorpej 250: sc->wss_ic = ia->ia_ic;
1.1 augustss 251:
252: wssattach(sc);
253: }
254:
255: /*
256: * Copyright by Hannu Savolainen 1994
257: *
258: * Redistribution and use in source and binary forms, with or without
259: * modification, are permitted provided that the following conditions are
260: * met: 1. Redistributions of source code must retain the above copyright
261: * notice, this list of conditions and the following disclaimer. 2.
262: * Redistributions in binary form must reproduce the above copyright notice,
263: * this list of conditions and the following disclaimer in the documentation
264: * and/or other materials provided with the distribution.
265: *
266: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
267: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
268: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
269: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
270: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
272: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
273: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
274: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
275: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
276: * SUCH DAMAGE.
277: *
278: */
279:
280: /*
281: * Initialization code for OPTi MAD16 compatible audio chips. Including
282: *
283: * OPTi 82C928 MAD16 (replaced by C929)
284: * OAK OTI-601D Mozart
285: * OPTi 82C929 MAD16 Pro
286: * OPTi 82C931
287: */
288:
289: static int
290: detect_mad16(sc, chip_type)
291: struct wss_softc *sc;
292: int chip_type;
293: {
294: unsigned char tmp, tmp2;
295:
296: sc->mad_chip_type = chip_type;
297: /*
298: * Check that reading a register doesn't return bus float (0xff)
299: * when the card is accessed using password. This may fail in case
300: * the card is in low power mode. Normally at least the power saving mode
301: * bit should be 0.
302: */
303: if ((tmp = mad_read(sc, MC1_PORT)) == 0xff) {
304: DPRINTF(("MC1_PORT returned 0xff\n"));
305: return 0;
306: }
307:
308: /*
309: * Now check that the gate is closed on first I/O after writing
310: * the password. (This is how a MAD16 compatible card works).
311: */
312: if ((tmp2 = bus_space_read_1(sc->sc_iot, sc->mad_ioh, MC1_PORT)) == tmp) {
313: DPRINTF(("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
314: return 0;
315: }
316:
317: mad_write(sc, MC1_PORT, tmp ^ 0x80); /* Toggle a bit */
318:
319: /* Compare the bit */
320: if ((tmp2 = mad_read(sc, MC1_PORT)) != (tmp ^ 0x80)) {
321: mad_write(sc, MC1_PORT, tmp); /* Restore */
322: DPRINTF(("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
323: return 0;
324: }
325:
326: mad_write(sc, MC1_PORT, tmp); /* Restore */
327: return 1;
328: }
329:
330: static void
331: madprobe(sc, iobase)
332: struct wss_softc *sc;
333: int iobase;
334: {
335: static int valid_ports[M_WSS_NPORTS] =
336: { M_WSS_PORT0, M_WSS_PORT1, M_WSS_PORT2, M_WSS_PORT3 };
337: int i;
338:
339: /* Allocate bus space that the MAD chip wants */
340: if (bus_space_map(sc->sc_iot, MAD_BASE, MAD_NPORT, 0, &sc->mad_ioh))
341: goto bad0;
342: if (bus_space_map(sc->sc_iot, MAD_REG1, MAD_LEN1, 0, &sc->mad_ioh1))
343: goto bad1;
344: if (bus_space_map(sc->sc_iot, MAD_REG2, MAD_LEN2, 0, &sc->mad_ioh2))
345: goto bad2;
1.8 augustss 346: if (bus_space_map(sc->sc_iot, MAD_REG3, MAD_LEN3, 0, &sc->sc_opl_ioh))
1.1 augustss 347: goto bad3;
348:
349: DPRINTF(("mad: Detect using password = 0xE2\n"));
350: if (!detect_mad16(sc, MAD_82C928)) {
351: /* No luck. Try different model */
352: DPRINTF(("mad: Detect using password = 0xE3\n"));
353: if (!detect_mad16(sc, MAD_82C929))
354: goto bad;
355: sc->mad_chip_type = MAD_82C929;
356: DPRINTF(("mad: 82C929 detected\n"));
357: } else {
358: sc->mad_chip_type = MAD_82C928;
359: if ((mad_read(sc, MC3_PORT) & 0x03) == 0x03) {
360: DPRINTF(("mad: Mozart detected\n"));
361: sc->mad_chip_type = MAD_OTI601D;
362: } else {
363: DPRINTF(("mad: 82C928 detected?\n"));
364: sc->mad_chip_type = MAD_82C928;
365: }
366: }
367:
368: #ifdef AUDIO_DEBUG
369: if (wssdebug)
370: for (i = MC1_PORT; i <= MC7_PORT; i++)
371: printf("mad: port %03x = %02x\n", i, mad_read(sc, i));
372: #endif
373:
374: /* Set the WSS address. */
375: for (i = 0; i < M_WSS_NPORTS; i++)
376: if (valid_ports[i] == iobase)
377: break;
378: if (i >= M_WSS_NPORTS) { /* Not a valid port */
379: printf("mad: Bad WSS base address 0x%x\n", iobase);
380: goto bad;
381: }
382: sc->mad_ioindex = i;
383: /* enable WSS emulation at the I/O port, no joystick */
384: mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(i) | MC1_JOYDISABLE);
385: mad_write(sc, MC2_PORT, 0x03); /* ? */
386: mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
387: return;
388:
389: bad:
1.8 augustss 390: bus_space_unmap(sc->sc_iot, sc->sc_opl_ioh, MAD_LEN3);
1.1 augustss 391: bad3:
392: bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
393: bad2:
394: bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
395: bad1:
396: bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
397: bad0:
398: sc->mad_chip_type = MAD_NONE;
399: }
400:
401: static void
402: madunmap(sc)
403: struct wss_softc *sc;
404: {
405: if (sc->mad_chip_type == MAD_NONE)
406: return;
407: bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
408: bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
409: bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
1.8 augustss 410: bus_space_unmap(sc->sc_iot, sc->sc_opl_ioh, MAD_LEN3);
1.1 augustss 411: }
CVSweb <webmaster@jp.NetBSD.org>