This source file includes following definitions.
- wss_isa_probe
- wssfind
- wss_isa_attach
- detect_mad16
- madprobe
- madunmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/errno.h>
46 #include <sys/ioctl.h>
47 #include <sys/syslog.h>
48 #include <sys/device.h>
49 #include <sys/proc.h>
50 #include <sys/buf.h>
51
52 #include <machine/cpu.h>
53 #include <machine/intr.h>
54 #include <machine/bus.h>
55
56 #include <sys/audioio.h>
57 #include <dev/audio_if.h>
58
59 #include <dev/isa/isavar.h>
60 #include <dev/isa/isadmavar.h>
61
62 #include <dev/ic/ad1848reg.h>
63 #include <dev/isa/ad1848var.h>
64 #include <dev/isa/wssreg.h>
65 #include <dev/isa/wssvar.h>
66 #include <dev/isa/madreg.h>
67
68 #ifdef AUDIO_DEBUG
69 #define DPRINTF(x) if (wssdebug) printf x
70 extern int wssdebug;
71 #else
72 #define DPRINTF(x)
73 #endif
74
75 static int wssfind(struct device *, struct wss_softc *, struct isa_attach_args *);
76
77 static void madprobe(struct wss_softc *, int);
78 static void madunmap(struct wss_softc *);
79 static int detect_mad16(struct wss_softc *, int);
80
81 int wss_isa_probe(struct device *, void *, void *);
82 void wss_isa_attach(struct device *, struct device *, void *);
83
84 struct cfattach wss_isa_ca = {
85 sizeof(struct wss_softc), wss_isa_probe, wss_isa_attach
86 };
87
88 struct cfdriver wss_cd = {
89 NULL, "wss", DV_DULL
90 };
91
92
93
94
95 int
96 wss_isa_probe(parent, match, aux)
97 struct device *parent;
98 void *match;
99 void *aux;
100 {
101 struct wss_softc probesc, *sc = &probesc;
102
103 bzero(sc, sizeof *sc);
104 sc->sc_dev.dv_cfdata = ((struct device *)match)->dv_cfdata;
105 if (wssfind(parent, sc, aux)) {
106 bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
107 ad1848_unmap(&sc->sc_ad1848);
108 madunmap(sc);
109 return 1;
110 } else
111
112 return 0;
113 }
114
115 static int
116 wssfind(parent, sc, ia)
117 struct device *parent;
118 struct wss_softc *sc;
119 struct isa_attach_args *ia;
120 {
121 static u_char interrupt_bits[12] = {
122 -1, -1, -1, -1, -1, 0x0, -1, 0x08, -1, 0x10, 0x18, 0x20
123 };
124 static u_char dma_bits[4] = {1, 2, 0, 3};
125
126 sc->sc_iot = ia->ia_iot;
127 if (sc->sc_dev.dv_cfdata->cf_flags & 1)
128 madprobe(sc, ia->ia_iobase);
129 else
130 sc->mad_chip_type = MAD_NONE;
131
132 if (!WSS_BASE_VALID(ia->ia_iobase)) {
133 DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
134 goto bad1;
135 }
136
137
138 if (bus_space_map(sc->sc_iot, ia->ia_iobase, WSS_CODEC, 0, &sc->sc_ioh))
139 goto bad1;
140
141 sc->sc_ad1848.sc_iot = sc->sc_iot;
142
143
144 if (ad1848_mapprobe(&sc->sc_ad1848, ia->ia_iobase + WSS_CODEC) == 0)
145 goto bad;
146
147 ia->ia_iosize = WSS_NPORT;
148
149
150 if (!WSS_DRQ_VALID(ia->ia_drq)) {
151 DPRINTF(("wss: configured dma chan %d invalid\n", ia->ia_drq));
152 goto bad;
153 }
154 sc->wss_drq = ia->ia_drq;
155
156 if (sc->wss_drq != DRQUNK && !isa_drq_isfree(parent, sc->wss_drq))
157 goto bad;
158
159 if (!WSS_IRQ_VALID(ia->ia_irq)) {
160 DPRINTF(("wss: configured interrupt %d invalid\n", ia->ia_irq));
161 goto bad;
162 }
163
164 sc->wss_irq = ia->ia_irq;
165
166 if (sc->sc_ad1848.mode <= 1)
167 ia->ia_drq2 = DRQUNK;
168 sc->wss_recdrq =
169 sc->sc_ad1848.mode > 1 && ia->ia_drq2 != DRQUNK ?
170 ia->ia_drq2 : ia->ia_drq;
171 if (sc->wss_recdrq != sc->wss_drq && !isa_drq_isfree(parent, sc->wss_recdrq))
172 goto bad;
173
174
175 bus_space_write_1(sc->sc_iot, sc->sc_ioh, WSS_CONFIG,
176 (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_drq]));
177
178 return 1;
179
180 bad:
181 bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
182 bad1:
183 madunmap(sc);
184 return 0;
185 }
186
187
188
189
190
191 void
192 wss_isa_attach(parent, self, aux)
193 struct device *parent, *self;
194 void *aux;
195 {
196 struct wss_softc *sc = (struct wss_softc *)self;
197 struct isa_attach_args *ia = (struct isa_attach_args *)aux;
198
199 if (!wssfind(parent, sc, ia)) {
200 printf("%s: wssfind failed\n", sc->sc_dev.dv_xname);
201 return;
202 }
203
204 sc->sc_ic = ia->ia_ic;
205 sc->sc_ad1848.sc_isa = parent;
206
207 wssattach(sc);
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 static int
245 detect_mad16(sc, chip_type)
246 struct wss_softc *sc;
247 int chip_type;
248 {
249 unsigned char tmp, tmp2;
250
251 sc->mad_chip_type = chip_type;
252
253
254
255
256
257
258 if ((tmp = mad_read(sc, MC1_PORT)) == 0xff) {
259 DPRINTF(("MC1_PORT returned 0xff\n"));
260 return 0;
261 }
262
263
264
265
266
267 if ((tmp2 = bus_space_read_1(sc->sc_iot, sc->mad_ioh, MC1_PORT)) == tmp) {
268 DPRINTF(("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
269 return 0;
270 }
271
272 mad_write(sc, MC1_PORT, tmp ^ 0x80);
273
274
275 if ((tmp2 = mad_read(sc, MC1_PORT)) != (tmp ^ 0x80)) {
276 mad_write(sc, MC1_PORT, tmp);
277 DPRINTF(("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
278 return 0;
279 }
280
281 mad_write(sc, MC1_PORT, tmp);
282 return 1;
283 }
284
285 static void
286 madprobe(sc, iobase)
287 struct wss_softc *sc;
288 int iobase;
289 {
290 static int valid_ports[M_WSS_NPORTS] =
291 { M_WSS_PORT0, M_WSS_PORT1, M_WSS_PORT2, M_WSS_PORT3 };
292 int i;
293
294
295 if (bus_space_map(sc->sc_iot, MAD_BASE, MAD_NPORT, 0, &sc->mad_ioh))
296 goto bad0;
297 if (bus_space_map(sc->sc_iot, MAD_REG1, MAD_LEN1, 0, &sc->mad_ioh1))
298 goto bad1;
299 if (bus_space_map(sc->sc_iot, MAD_REG2, MAD_LEN2, 0, &sc->mad_ioh2))
300 goto bad2;
301 if (bus_space_map(sc->sc_iot, MAD_REG3, MAD_LEN3, 0, &sc->mad_ioh3))
302 goto bad3;
303
304 DPRINTF(("mad: Detect using password = 0xE2\n"));
305 if (!detect_mad16(sc, MAD_82C928)) {
306
307 DPRINTF(("mad: Detect using password = 0xE3\n"));
308 if (!detect_mad16(sc, MAD_82C929))
309 goto bad;
310 sc->mad_chip_type = MAD_82C929;
311 DPRINTF(("mad: 82C929 detected\n"));
312 } else {
313 sc->mad_chip_type = MAD_82C928;
314 if ((mad_read(sc, MC3_PORT) & 0x03) == 0x03) {
315 DPRINTF(("mad: Mozart detected\n"));
316 sc->mad_chip_type = MAD_OTI601D;
317 } else {
318 DPRINTF(("mad: 82C928 detected?\n"));
319 sc->mad_chip_type = MAD_82C928;
320 }
321 }
322
323 #ifdef AUDIO_DEBUG
324 if (wssdebug)
325 for (i = MC1_PORT; i <= MC7_PORT; i++)
326 printf("mad: port %03x = %02x\n", i, mad_read(sc, i));
327 #endif
328
329
330 for (i = 0; i < M_WSS_NPORTS; i++)
331 if (valid_ports[i] == iobase)
332 break;
333 if (i >= M_WSS_NPORTS) {
334 printf("mad: Bad WSS base address 0x%x\n", iobase);
335 goto bad;
336 }
337 sc->mad_ioindex = i;
338
339 mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(i) | MC1_JOYDISABLE);
340 mad_write(sc, MC2_PORT, 0x03);
341 mad_write(sc, MC3_PORT, 0xf0);
342 return;
343
344 bad:
345 bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
346 bad3:
347 bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
348 bad2:
349 bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
350 bad1:
351 bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
352 bad0:
353 sc->mad_chip_type = MAD_NONE;
354 }
355
356 static void
357 madunmap(sc)
358 struct wss_softc *sc;
359 {
360 if (sc->mad_chip_type == MAD_NONE)
361 return;
362 bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
363 bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
364 bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
365 bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
366 }