xref: /openbsd/sys/dev/isa/sbdsp.c (revision 404b540a)
1 /*	$OpenBSD: sbdsp.c,v 1.29 2009/07/31 22:53:04 sthen Exp $	*/
2 
3 /*
4  * Copyright (c) 1991-1993 Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the Computer Systems
18  *	Engineering Group at Lawrence Berkeley Laboratory.
19  * 4. Neither the name of the University nor of the Laboratory may be used
20  *    to endorse or promote products derived from this software without
21  *    specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 /*
38  * SoundBlaster Pro code provided by John Kohl, based on lots of
39  * information he gleaned from Steve Haehnichen <steve@vigra.com>'s
40  * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
41  * <sachs@meibm15.cen.uiuc.edu>.
42  * Lots of rewrites by Lennart Augustsson <augustss@cs.chalmers.se>
43  * with information from SB "Hardware Programming Guide" and the
44  * Linux drivers.
45  */
46 
47 #include "midi.h"
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/errno.h>
52 #include <sys/ioctl.h>
53 #include <sys/syslog.h>
54 #include <sys/device.h>
55 #include <sys/proc.h>
56 #include <sys/buf.h>
57 
58 #include <machine/cpu.h>
59 #include <machine/intr.h>
60 #include <machine/bus.h>
61 
62 #include <sys/audioio.h>
63 #include <dev/audio_if.h>
64 #include <dev/midi_if.h>
65 #include <dev/mulaw.h>
66 #include <dev/auconv.h>
67 
68 #include <dev/isa/isavar.h>
69 #include <dev/isa/isadmavar.h>
70 
71 #include <dev/isa/sbreg.h>
72 #include <dev/isa/sbdspvar.h>
73 
74 
75 #ifdef AUDIO_DEBUG
76 #define DPRINTF(x)	if (sbdspdebug) printf x
77 #define DPRINTFN(n,x)	if (sbdspdebug >= (n)) printf x
78 int	sbdspdebug = 0;
79 #else
80 #define DPRINTF(x)
81 #define DPRINTFN(n,x)
82 #endif
83 
84 #ifndef SBDSP_NPOLL
85 #define SBDSP_NPOLL 3000
86 #endif
87 
88 struct {
89 	int wdsp;
90 	int rdsp;
91 	int wmidi;
92 } sberr;
93 
94 /*
95  * Time constant routines follow.  See SBK, section 12.
96  * Although they don't come out and say it (in the docs),
97  * the card clearly uses a 1MHz countdown timer, as the
98  * low-speed formula (p. 12-4) is:
99  *	tc = 256 - 10^6 / sr
100  * In high-speed mode, the constant is the upper byte of a 16-bit counter,
101  * and a 256MHz clock is used:
102  *	tc = 65536 - 256 * 10^ 6 / sr
103  * Since we can only use the upper byte of the HS TC, the two formulae
104  * are equivalent.  (Why didn't they say so?)  E.g.,
105  *	(65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
106  *
107  * The crossover point (from low- to high-speed modes) is different
108  * for the SBPRO and SB20.  The table on p. 12-5 gives the following data:
109  *
110  *				SBPRO			SB20
111  *				-----			--------
112  * input ls min			4	KHz		4	KHz
113  * input ls max			23	KHz		13	KHz
114  * input hs max			44.1	KHz		15	KHz
115  * output ls min		4	KHz		4	KHz
116  * output ls max		23	KHz		23	KHz
117  * output hs max		44.1	KHz		44.1	KHz
118  */
119 /* XXX Should we round the tc?
120 #define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
121 */
122 #define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
123 #define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
124 
125 struct sbmode {
126 	short	model;
127 	u_char	channels;
128 	u_char	precision;
129 	u_short	lowrate, highrate;
130 	u_char	cmd;
131 	u_char	cmdchan;
132 };
133 static struct sbmode sbpmodes[] = {
134  { SB_1,    1,  8,  4000, 22727, SB_DSP_WDMA      },
135  { SB_20,   1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
136  { SB_2x,   1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
137  { SB_2x,   1,  8, 22727, 45454, SB_DSP_HS_OUTPUT },
138  { SB_PRO,  1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
139  { SB_PRO,  1,  8, 22727, 45454, SB_DSP_HS_OUTPUT },
140  { SB_PRO,  2,  8, 11025, 22727, SB_DSP_HS_OUTPUT },
141  /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
142  { SB_JAZZ, 1,  8,  4000, 22727, SB_DSP_WDMA_LOOP, SB_DSP_RECORD_MONO },
143  { SB_JAZZ, 1,  8, 22727, 45454, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_MONO },
144  { SB_JAZZ, 2,  8, 11025, 22727, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_STEREO },
145  { SB_JAZZ, 1, 16,  4000, 22727, SB_DSP_WDMA_LOOP, JAZZ16_RECORD_MONO },
146  { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_MONO },
147  { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_STEREO },
148  { SB_16,   1,  8,  5000, 45000, SB_DSP16_WDMA_8  },
149  { SB_16,   2,  8,  5000, 45000, SB_DSP16_WDMA_8  },
150 #define PLAY16 15 /* must be the index of the next entry in the table */
151  { SB_16,   1, 16,  5000, 45000, SB_DSP16_WDMA_16 },
152  { SB_16,   2, 16,  5000, 45000, SB_DSP16_WDMA_16 },
153  { -1 }
154 };
155 static struct sbmode sbrmodes[] = {
156  { SB_1,    1,  8,  4000, 12987, SB_DSP_RDMA      },
157  { SB_20,   1,  8,  4000, 12987, SB_DSP_RDMA_LOOP },
158  { SB_2x,   1,  8,  4000, 12987, SB_DSP_RDMA_LOOP },
159  { SB_2x,   1,  8, 12987, 14925, SB_DSP_HS_INPUT  },
160  { SB_PRO,  1,  8,  4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
161  { SB_PRO,  1,  8, 22727, 45454, SB_DSP_HS_INPUT,  SB_DSP_RECORD_MONO },
162  { SB_PRO,  2,  8, 11025, 22727, SB_DSP_HS_INPUT,  SB_DSP_RECORD_STEREO },
163  { SB_JAZZ, 1,  8,  4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
164  { SB_JAZZ, 1,  8, 22727, 45454, SB_DSP_HS_INPUT,  SB_DSP_RECORD_MONO },
165  { SB_JAZZ, 2,  8, 11025, 22727, SB_DSP_HS_INPUT,  SB_DSP_RECORD_STEREO },
166  { SB_JAZZ, 1, 16,  4000, 22727, SB_DSP_RDMA_LOOP, JAZZ16_RECORD_MONO },
167  { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_INPUT,  JAZZ16_RECORD_MONO },
168  { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_INPUT,  JAZZ16_RECORD_STEREO },
169  { SB_16,   1,  8,  5000, 45000, SB_DSP16_RDMA_8  },
170  { SB_16,   2,  8,  5000, 45000, SB_DSP16_RDMA_8  },
171  { SB_16,   1, 16,  5000, 45000, SB_DSP16_RDMA_16 },
172  { SB_16,   2, 16,  5000, 45000, SB_DSP16_RDMA_16 },
173  { -1 }
174 };
175 
176 void	sbversion(struct sbdsp_softc *);
177 void	sbdsp_jazz16_probe(struct sbdsp_softc *);
178 void	sbdsp_set_mixer_gain(struct sbdsp_softc *sc, int port);
179 void	sbdsp_to(void *);
180 void	sbdsp_pause(struct sbdsp_softc *);
181 int	sbdsp_set_timeconst(struct sbdsp_softc *, int);
182 int	sbdsp16_set_rate(struct sbdsp_softc *, int, int);
183 int	sbdsp_set_in_ports(struct sbdsp_softc *, int);
184 void	sbdsp_set_ifilter(void *, int);
185 int	sbdsp_get_ifilter(void *);
186 
187 int	sbdsp_block_output(void *);
188 int	sbdsp_block_input(void *);
189 static	int sbdsp_adjust(int, int);
190 
191 int	sbdsp_midi_intr(void *);
192 
193 #ifdef AUDIO_DEBUG
194 void	sb_printsc(struct sbdsp_softc *);
195 
196 void
197 sb_printsc(sc)
198 	struct sbdsp_softc *sc;
199 {
200 	int i;
201 
202 	printf("open %d dmachan %d/%d %d/%d iobase 0x%x irq %d\n",
203 	    (int)sc->sc_open, sc->sc_i.run, sc->sc_o.run,
204 	    sc->sc_drq8, sc->sc_drq16,
205 	    sc->sc_iobase, sc->sc_irq);
206 	printf("irate %d itc %x orate %d otc %x\n",
207 	    sc->sc_i.rate, sc->sc_i.tc,
208 	    sc->sc_o.rate, sc->sc_o.tc);
209 	printf("spkron %u nintr %lu\n",
210 	    sc->spkr_state, sc->sc_interrupts);
211 	printf("intr8 %p arg8 %p\n",
212 	    sc->sc_intr8, sc->sc_arg16);
213 	printf("intr16 %p arg16 %p\n",
214 	    sc->sc_intr8, sc->sc_arg16);
215 	printf("gain:");
216 	for (i = 0; i < SB_NDEVS; i++)
217 		printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
218 	printf("\n");
219 }
220 #endif /* AUDIO_DEBUG */
221 
222 /*
223  * Probe / attach routines.
224  */
225 
226 /*
227  * Probe for the soundblaster hardware.
228  */
229 int
230 sbdsp_probe(sc)
231 	struct sbdsp_softc *sc;
232 {
233 
234 	if (sbdsp_reset(sc) < 0) {
235 		DPRINTF(("sbdsp: couldn't reset card\n"));
236 		return 0;
237 	}
238 	/* if flags set, go and probe the jazz16 stuff */
239 	if (sc->sc_dev.dv_cfdata->cf_flags & 1)
240 		sbdsp_jazz16_probe(sc);
241 	else
242 		sbversion(sc);
243 	if (sc->sc_model == SB_UNK) {
244 		/* Unknown SB model found. */
245 		DPRINTF(("sbdsp: unknown SB model found\n"));
246 		return 0;
247 	}
248 	return 1;
249 }
250 
251 /*
252  * Try add-on stuff for Jazz16.
253  */
254 void
255 sbdsp_jazz16_probe(sc)
256 	struct sbdsp_softc *sc;
257 {
258 	static u_char jazz16_irq_conf[16] = {
259 	    -1, -1, 0x02, 0x03,
260 	    -1, 0x01, -1, 0x04,
261 	    -1, 0x02, 0x05, -1,
262 	    -1, -1, -1, 0x06};
263 	static u_char jazz16_drq_conf[8] = {
264 	    -1, 0x01, -1, 0x02,
265 	    -1, 0x03, -1, 0x04};
266 
267 	bus_space_tag_t iot = sc->sc_iot;
268 	bus_space_handle_t ioh;
269 
270 	sbversion(sc);
271 
272 	DPRINTF(("jazz16 probe\n"));
273 
274 	if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
275 		DPRINTF(("bus map failed\n"));
276 		return;
277 	}
278 
279 	if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
280 	    jazz16_irq_conf[sc->sc_irq] == (u_char)-1) {
281 		DPRINTF(("drq/irq check failed\n"));
282 		goto done;		/* give up, we can't do it. */
283 	}
284 
285 	bus_space_write_1(iot, ioh, 0, JAZZ16_WAKEUP);
286 	delay(10000);			/* delay 10 ms */
287 	bus_space_write_1(iot, ioh, 0, JAZZ16_SETBASE);
288 	bus_space_write_1(iot, ioh, 0, sc->sc_iobase & 0x70);
289 
290 	if (sbdsp_reset(sc) < 0) {
291 		DPRINTF(("sbdsp_reset check failed\n"));
292 		goto done;		/* XXX? what else could we do? */
293 	}
294 
295 	if (sbdsp_wdsp(sc, JAZZ16_READ_VER)) {
296 		DPRINTF(("read16 setup failed\n"));
297 		goto done;
298 	}
299 
300 	if (sbdsp_rdsp(sc) != JAZZ16_VER_JAZZ) {
301 		DPRINTF(("read16 failed\n"));
302 		goto done;
303 	}
304 
305 	/* XXX set both 8 & 16-bit drq to same channel, it works fine. */
306 	sc->sc_drq16 = sc->sc_drq8;
307 	if (sbdsp_wdsp(sc, JAZZ16_SET_DMAINTR) ||
308 	    sbdsp_wdsp(sc, (jazz16_drq_conf[sc->sc_drq16] << 4) |
309 		jazz16_drq_conf[sc->sc_drq8]) ||
310 	    sbdsp_wdsp(sc, jazz16_irq_conf[sc->sc_irq])) {
311 		DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
312 	} else {
313 		DPRINTF(("jazz16 detected!\n"));
314 		sc->sc_model = SB_JAZZ;
315 		sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
316 	}
317 
318 done:
319 	bus_space_unmap(iot, ioh, 1);
320 }
321 
322 /*
323  * Attach hardware to driver, attach hardware driver to audio
324  * pseudo-device driver .
325  */
326 void
327 sbdsp_attach(sc)
328 	struct sbdsp_softc *sc;
329 {
330 	struct audio_params pparams, rparams;
331         int i;
332         u_int v;
333 
334 	/*
335 	 * Create our DMA maps.
336 	 */
337 	if (sc->sc_drq8 != -1) {
338 		if (isa_dmamap_create(sc->sc_isa, sc->sc_drq8,
339 		    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
340 			printf("%s: can't create map for drq %d\n",
341 			    sc->sc_dev.dv_xname, sc->sc_drq8);
342 			return;
343 		}
344 	}
345 	if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8) {
346 		if (isa_dmamap_create(sc->sc_isa, sc->sc_drq16,
347 		    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
348 			printf("%s: can't create map for drq %d\n",
349 			    sc->sc_dev.dv_xname, sc->sc_drq16);
350 			return;
351 		}
352 	}
353 
354 	pparams = audio_default;
355 	rparams = audio_default;
356         sbdsp_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
357 
358 	sbdsp_set_in_ports(sc, 1 << SB_MIC_VOL);
359 
360 	if (sc->sc_mixer_model != SBM_NONE) {
361 		/* Reset the mixer.*/
362 		sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
363                 /* And set our own default values */
364 		for (i = 0; i < SB_NDEVS; i++) {
365 			switch(i) {
366 			case SB_MIC_VOL:
367 			case SB_LINE_IN_VOL:
368 				v = 0;
369 				break;
370 			case SB_BASS:
371 			case SB_TREBLE:
372 				v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN/2);
373 				break;
374 			case SB_CD_IN_MUTE:
375 			case SB_MIC_IN_MUTE:
376 			case SB_LINE_IN_MUTE:
377 			case SB_MIDI_IN_MUTE:
378 			case SB_CD_SWAP:
379 			case SB_MIC_SWAP:
380 			case SB_LINE_SWAP:
381 			case SB_MIDI_SWAP:
382 			case SB_CD_OUT_MUTE:
383 			case SB_MIC_OUT_MUTE:
384 			case SB_LINE_OUT_MUTE:
385 				v = 0;
386 				break;
387 			default:
388 				v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
389 				break;
390 			}
391 			sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
392 			sbdsp_set_mixer_gain(sc, i);
393 		}
394 		sc->in_filter = 0;	/* no filters turned on, please */
395 	}
396 
397 	printf(": dsp v%d.%02d%s\n",
398 	       SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
399 	       sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
400 
401 	timeout_set(&sc->sc_tmo, sbdsp_to, sbdsp_to);
402 	sc->sc_fullduplex = ISSB16CLASS(sc) &&
403 		sc->sc_drq8 != -1 && sc->sc_drq16 != -1 &&
404 		sc->sc_drq8 != sc->sc_drq16;
405 }
406 
407 void
408 sbdsp_mix_write(sc, mixerport, val)
409 	struct sbdsp_softc *sc;
410 	int mixerport;
411 	int val;
412 {
413 	bus_space_tag_t iot = sc->sc_iot;
414 	bus_space_handle_t ioh = sc->sc_ioh;
415 	int s;
416 
417 	s = splaudio();
418 	bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
419 	delay(20);
420 	bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
421 	delay(30);
422 	splx(s);
423 }
424 
425 int
426 sbdsp_mix_read(sc, mixerport)
427 	struct sbdsp_softc *sc;
428 	int mixerport;
429 {
430 	bus_space_tag_t iot = sc->sc_iot;
431 	bus_space_handle_t ioh = sc->sc_ioh;
432 	int val;
433 	int s;
434 
435 	s = splaudio();
436 	bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
437 	delay(20);
438 	val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
439 	delay(30);
440 	splx(s);
441 	return val;
442 }
443 
444 /*
445  * Various routines to interface to higher level audio driver
446  */
447 
448 int
449 sbdsp_query_encoding(addr, fp)
450 	void *addr;
451 	struct audio_encoding *fp;
452 {
453 	struct sbdsp_softc *sc = addr;
454 	int emul;
455 
456 	emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
457 
458 	switch (fp->index) {
459 	case 0:
460 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
461 		fp->encoding = AUDIO_ENCODING_ULINEAR;
462 		fp->precision = 8;
463 		fp->flags = 0;
464 		return 0;
465 	case 1:
466 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
467 		fp->encoding = AUDIO_ENCODING_ULAW;
468 		fp->precision = 8;
469 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
470 		return 0;
471 	case 2:
472 		strlcpy(fp->name, AudioEalaw, sizeof fp->name);
473 		fp->encoding = AUDIO_ENCODING_ALAW;
474 		fp->precision = 8;
475 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
476 		return 0;
477 	case 3:
478 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
479 		fp->encoding = AUDIO_ENCODING_SLINEAR;
480 		fp->precision = 8;
481 		fp->flags = emul;
482 		return 0;
483         }
484         if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
485 		return EINVAL;
486 
487         switch(fp->index) {
488         case 4:
489 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
490 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
491 		fp->precision = 16;
492 		fp->flags = 0;
493 		return 0;
494 	case 5:
495 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
496 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
497 		fp->precision = 16;
498 		fp->flags = emul;
499 		return 0;
500 	case 6:
501 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
502 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
503 		fp->precision = 16;
504 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
505 		return 0;
506 	case 7:
507 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
508 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
509 		fp->precision = 16;
510 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
511 		return 0;
512 	default:
513 		return EINVAL;
514 	}
515 	return 0;
516 }
517 
518 int
519 sbdsp_set_params(addr, setmode, usemode, play, rec)
520 	void *addr;
521 	int setmode, usemode;
522 	struct audio_params *play, *rec;
523 {
524 	struct sbdsp_softc *sc = addr;
525 	struct sbmode *m;
526 	u_int rate, tc, bmode;
527 	void (*swcode)(void *, u_char *buf, int cnt);
528 	int factor;
529 	int model;
530 	int chan;
531 	struct audio_params *p;
532 	int mode;
533 
534 	if (sc->sc_open == SB_OPEN_MIDI)
535 		return EBUSY;
536 
537 	model = sc->sc_model;
538 	if (model > SB_16)
539 		model = SB_16;	/* later models work like SB16 */
540 
541 	/*
542 	 * Prior to the SB16, we have only one clock, so make the sample
543 	 * rates match.
544 	 */
545 	if (!ISSB16CLASS(sc) &&
546 	    play->sample_rate != rec->sample_rate &&
547 	    usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
548 		if (setmode == AUMODE_PLAY) {
549 			rec->sample_rate = play->sample_rate;
550 			setmode |= AUMODE_RECORD;
551 		} else if (setmode == AUMODE_RECORD) {
552 			play->sample_rate = rec->sample_rate;
553 			setmode |= AUMODE_PLAY;
554 		} else
555 			return (EINVAL);
556 	}
557 
558 	/* Set first record info, then play info */
559 	for (mode = AUMODE_RECORD; mode != -1;
560 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
561 		if ((setmode & mode) == 0)
562 			continue;
563 
564 		p = mode == AUMODE_PLAY ? play : rec;
565 		/* Locate proper commands */
566 		for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
567 		    m->model != -1; m++) {
568 			if (model == m->model &&
569 			    p->channels == m->channels &&
570 			    p->precision == m->precision &&
571 			    p->sample_rate >= m->lowrate &&
572 			    p->sample_rate <= m->highrate)
573 				break;
574 		}
575 		if (m->model == -1)
576 			return EINVAL;
577 		rate = p->sample_rate;
578 		swcode = 0;
579 		factor = 1;
580 		tc = 1;
581 		bmode = -1;
582 		if (model == SB_16) {
583 			switch (p->encoding) {
584 			case AUDIO_ENCODING_SLINEAR_BE:
585 				if (p->precision == 16)
586 					swcode = swap_bytes;
587 				/* fall into */
588 			case AUDIO_ENCODING_SLINEAR_LE:
589 				bmode = SB_BMODE_SIGNED;
590 				break;
591 			case AUDIO_ENCODING_ULINEAR_BE:
592 				if (p->precision == 16)
593 					swcode = swap_bytes;
594 				/* fall into */
595 			case AUDIO_ENCODING_ULINEAR_LE:
596 				bmode = SB_BMODE_UNSIGNED;
597 				break;
598 			case AUDIO_ENCODING_ULAW:
599 				if (mode == AUMODE_PLAY) {
600 					swcode = mulaw_to_ulinear16_le;
601 					factor = 2;
602 					m = &sbpmodes[PLAY16];
603 				} else
604 					swcode = ulinear8_to_mulaw;
605 				bmode = SB_BMODE_UNSIGNED;
606 				break;
607 			case AUDIO_ENCODING_ALAW:
608 				if (mode == AUMODE_PLAY) {
609 					swcode = alaw_to_ulinear16_le;
610 					factor = 2;
611 					m = &sbpmodes[PLAY16];
612 				} else
613 					swcode = ulinear8_to_alaw;
614 				bmode = SB_BMODE_UNSIGNED;
615 				break;
616 			default:
617 				return EINVAL;
618 			}
619 			if (p->channels == 2)
620 				bmode |= SB_BMODE_STEREO;
621 		} else if (m->model == SB_JAZZ && m->precision == 16) {
622 			switch (p->encoding) {
623 			case AUDIO_ENCODING_SLINEAR_LE:
624 				break;
625 			case AUDIO_ENCODING_ULINEAR_LE:
626 				swcode = change_sign16_le;
627 				break;
628 			case AUDIO_ENCODING_SLINEAR_BE:
629 				swcode = swap_bytes;
630 				break;
631 			case AUDIO_ENCODING_ULINEAR_BE:
632 				swcode = mode == AUMODE_PLAY ?
633 					swap_bytes_change_sign16_le : change_sign16_swap_bytes_le;
634 				break;
635 			case AUDIO_ENCODING_ULAW:
636 				swcode = mode == AUMODE_PLAY ?
637 					mulaw_to_ulinear8 : ulinear8_to_mulaw;
638 				break;
639 			case AUDIO_ENCODING_ALAW:
640 				swcode = mode == AUMODE_PLAY ?
641 					alaw_to_ulinear8 : ulinear8_to_alaw;
642 				break;
643 			default:
644 				return EINVAL;
645 			}
646 			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
647 			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
648 		} else {
649 			switch (p->encoding) {
650 			case AUDIO_ENCODING_SLINEAR_BE:
651 			case AUDIO_ENCODING_SLINEAR_LE:
652 				swcode = change_sign8;
653 				break;
654 			case AUDIO_ENCODING_ULINEAR_BE:
655 			case AUDIO_ENCODING_ULINEAR_LE:
656 				break;
657 			case AUDIO_ENCODING_ULAW:
658 				swcode = mode == AUMODE_PLAY ?
659 					mulaw_to_ulinear8 : ulinear8_to_mulaw;
660 				break;
661 			case AUDIO_ENCODING_ALAW:
662 				swcode = mode == AUMODE_PLAY ?
663 					alaw_to_ulinear8 : ulinear8_to_alaw;
664 				break;
665 			default:
666 				return EINVAL;
667 			}
668 			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
669 			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
670 		}
671 
672 		chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
673 		if (mode == AUMODE_PLAY) {
674 			sc->sc_o.rate = rate;
675 			sc->sc_o.tc = tc;
676 			sc->sc_o.modep = m;
677 			sc->sc_o.bmode = bmode;
678 			sc->sc_o.dmachan = chan;
679 		} else {
680 			sc->sc_i.rate = rate;
681 			sc->sc_i.tc = tc;
682 			sc->sc_i.modep = m;
683 			sc->sc_i.bmode = bmode;
684 			sc->sc_i.dmachan = chan;
685 		}
686 
687 		p->sw_code = swcode;
688 		p->factor = factor;
689 		DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x, swcode=%p, factor=%d\n",
690 			 sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
691 			 p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
692 
693 	}
694 
695 	/*
696 	 * XXX
697 	 * Should wait for chip to be idle.
698 	 */
699 	sc->sc_i.run = SB_NOTRUNNING;
700 	sc->sc_o.run = SB_NOTRUNNING;
701 
702 	if (sc->sc_fullduplex &&
703 	    usemode == (AUMODE_PLAY | AUMODE_RECORD) &&
704 	    sc->sc_i.dmachan == sc->sc_o.dmachan) {
705 		DPRINTF(("sbdsp_set_params: fd=%d, usemode=%d, idma=%d, odma=%d\n", sc->sc_fullduplex, usemode, sc->sc_i.dmachan, sc->sc_o.dmachan));
706 		if (sc->sc_o.dmachan == sc->sc_drq8) {
707 			/* Use 16 bit DMA for playing by expanding the samples. */
708 			play->sw_code = linear8_to_linear16_le;
709 			play->factor = 2;
710 			sc->sc_o.modep = &sbpmodes[PLAY16];
711 			sc->sc_o.dmachan = sc->sc_drq16;
712 		} else {
713 			return EINVAL;
714 		}
715 	}
716 	DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
717 		 sc->sc_i.dmachan, sc->sc_o.dmachan));
718 
719 	return 0;
720 }
721 
722 void
723 sbdsp_set_ifilter(addr, which)
724 	void *addr;
725 	int which;
726 {
727 	struct sbdsp_softc *sc = addr;
728 	int mixval;
729 
730 	mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
731 	switch (which) {
732 	case 0:
733 		mixval |= SBP_FILTER_OFF;
734 		break;
735 	case SB_TREBLE:
736 		mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
737 		break;
738 	case SB_BASS:
739 		mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
740 		break;
741 	default:
742 		return;
743 	}
744 	sc->in_filter = mixval & SBP_IFILTER_MASK;
745 	sbdsp_mix_write(sc, SBP_INFILTER, mixval);
746 }
747 
748 int
749 sbdsp_get_ifilter(addr)
750 	void *addr;
751 {
752 	struct sbdsp_softc *sc = addr;
753 
754 	sc->in_filter =
755 		sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
756 	switch (sc->in_filter) {
757 	case SBP_FILTER_ON|SBP_IFILTER_HIGH:
758 		return SB_TREBLE;
759 	case SBP_FILTER_ON|SBP_IFILTER_LOW:
760 		return SB_BASS;
761 	default:
762 		return 0;
763 	}
764 }
765 
766 int
767 sbdsp_set_in_ports(sc, mask)
768 	struct sbdsp_softc *sc;
769 	int mask;
770 {
771 	int bitsl, bitsr;
772 	int sbport;
773 
774 	if (sc->sc_open == SB_OPEN_MIDI)
775 		return EBUSY;
776 
777 	DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
778 		 sc->sc_mixer_model, mask));
779 
780 	switch(sc->sc_mixer_model) {
781 	case SBM_NONE:
782 		return EINVAL;
783 	case SBM_CT1335:
784 		if (mask != (1 << SB_MIC_VOL))
785 			return EINVAL;
786 		break;
787 	case SBM_CT1345:
788 		switch (mask) {
789 		case 1 << SB_MIC_VOL:
790 			sbport = SBP_FROM_MIC;
791 			break;
792 		case 1 << SB_LINE_IN_VOL:
793 			sbport = SBP_FROM_LINE;
794 			break;
795 		case 1 << SB_CD_VOL:
796 			sbport = SBP_FROM_CD;
797 			break;
798 		default:
799 			return (EINVAL);
800 		}
801 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
802 		break;
803 	case SBM_CT1XX5:
804 	case SBM_CT1745:
805 		if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
806 			     (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
807 			return EINVAL;
808 		bitsr = 0;
809 		if (mask & (1<<SB_MIDI_VOL))    bitsr |= SBP_MIDI_SRC_R;
810 		if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
811 		if (mask & (1<<SB_CD_VOL))      bitsr |= SBP_CD_SRC_R;
812 		bitsl = SB_SRC_R_TO_L(bitsr);
813 		if (mask & (1<<SB_MIC_VOL)) {
814 			bitsl |= SBP_MIC_SRC;
815 			bitsr |= SBP_MIC_SRC;
816 		}
817 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
818 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
819 		break;
820 	}
821 	sc->in_mask = mask;
822 
823 	return 0;
824 }
825 
826 int
827 sbdsp_speaker_ctl(addr, newstate)
828 	void *addr;
829 	int newstate;
830 {
831 	struct sbdsp_softc *sc = addr;
832 
833 	if (sc->sc_open == SB_OPEN_MIDI)
834 		return EBUSY;
835 
836 	if ((newstate == SPKR_ON) &&
837 	    (sc->spkr_state == SPKR_OFF)) {
838 		sbdsp_spkron(sc);
839 		sc->spkr_state = SPKR_ON;
840 	}
841 	if ((newstate == SPKR_OFF) &&
842 	    (sc->spkr_state == SPKR_ON)) {
843 		sbdsp_spkroff(sc);
844 		sc->spkr_state = SPKR_OFF;
845 	}
846 	return 0;
847 }
848 
849 int
850 sbdsp_round_blocksize(addr, blk)
851 	void *addr;
852 	int blk;
853 {
854 	return (blk + 3) & -4;	/* round to biggest sample size */
855 }
856 
857 int
858 sbdsp_open(addr, flags)
859 	void *addr;
860 	int flags;
861 {
862 	struct sbdsp_softc *sc = addr;
863 
864         DPRINTF(("sbdsp_open: sc=%p\n", sc));
865 
866 	if (sc->sc_open != SB_CLOSED)
867 		return EBUSY;
868 	if (sbdsp_reset(sc) != 0)
869 		return EIO;
870 
871 	sc->sc_open = SB_OPEN_AUDIO;
872 	sc->sc_openflags = flags;
873 	sc->sc_intrm = 0;
874 	if (ISSBPRO(sc) &&
875 	    sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
876 		DPRINTF(("sbdsp_open: can't set mono mode\n"));
877 		/* we'll readjust when it's time for DMA. */
878 	}
879 
880 	/*
881 	 * Leave most things as they were; users must change things if
882 	 * the previous process didn't leave it they way they wanted.
883 	 * Looked at another way, it's easy to set up a configuration
884 	 * in one program and leave it for another to inherit.
885 	 */
886 	DPRINTF(("sbdsp_open: opened\n"));
887 
888 	return 0;
889 }
890 
891 void
892 sbdsp_close(addr)
893 	void *addr;
894 {
895 	struct sbdsp_softc *sc = addr;
896 
897         DPRINTF(("sbdsp_close: sc=%p\n", sc));
898 
899 	sc->sc_open = SB_CLOSED;
900 	sbdsp_spkroff(sc);
901 	sc->spkr_state = SPKR_OFF;
902 	sc->sc_intr8 = 0;
903 	sc->sc_intr16 = 0;
904 	sc->sc_intrm = 0;
905 	sbdsp_haltdma(sc);
906 
907 	DPRINTF(("sbdsp_close: closed\n"));
908 }
909 
910 /*
911  * Lower-level routines
912  */
913 
914 /*
915  * Reset the card.
916  * Return non-zero if the card isn't detected.
917  */
918 int
919 sbdsp_reset(sc)
920 	struct sbdsp_softc *sc;
921 {
922 	bus_space_tag_t iot = sc->sc_iot;
923 	bus_space_handle_t ioh = sc->sc_ioh;
924 
925 	sc->sc_intr8 = 0;
926 	sc->sc_intr16 = 0;
927 	if (sc->sc_i.run != SB_NOTRUNNING) {
928 		isa_dmaabort(sc->sc_isa, sc->sc_i.dmachan);
929 		sc->sc_i.run = SB_NOTRUNNING;
930 	}
931 	if (sc->sc_o.run != SB_NOTRUNNING) {
932 		isa_dmaabort(sc->sc_isa, sc->sc_o.dmachan);
933 		sc->sc_o.run = SB_NOTRUNNING;
934 	}
935 
936 	/*
937 	 * See SBK, section 11.3.
938 	 * We pulse a reset signal into the card.
939 	 * Gee, what a brilliant hardware design.
940 	 */
941 	bus_space_write_1(iot, ioh, SBP_DSP_RESET, 1);
942 	delay(10);
943 	bus_space_write_1(iot, ioh, SBP_DSP_RESET, 0);
944 	delay(30);
945 	if (sbdsp_rdsp(sc) != SB_MAGIC)
946 		return -1;
947 
948 	return 0;
949 }
950 
951 /*
952  * Write a byte to the dsp.
953  * We are at the mercy of the card as we use a
954  * polling loop and wait until it can take the byte.
955  */
956 int
957 sbdsp_wdsp(sc, v)
958 	struct sbdsp_softc *sc;
959 	int v;
960 {
961 	bus_space_tag_t iot = sc->sc_iot;
962 	bus_space_handle_t ioh = sc->sc_ioh;
963 	int i;
964 	u_char x;
965 
966 	for (i = SBDSP_NPOLL; --i >= 0; ) {
967 		x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
968 		delay(10);
969 		if ((x & SB_DSP_BUSY) == 0) {
970 			bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
971 			delay(10);
972 			return 0;
973 		}
974 	}
975 	++sberr.wdsp;
976 	return -1;
977 }
978 
979 /*
980  * Read a byte from the DSP, using polling.
981  */
982 int
983 sbdsp_rdsp(sc)
984 	struct sbdsp_softc *sc;
985 {
986 	bus_space_tag_t iot = sc->sc_iot;
987 	bus_space_handle_t ioh = sc->sc_ioh;
988 	int i;
989 	u_char x;
990 
991 	for (i = SBDSP_NPOLL; --i >= 0; ) {
992 		x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
993 		delay(10);
994 		if (x & SB_DSP_READY) {
995 			x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
996 			delay(10);
997 			return x;
998 		}
999 	}
1000 	++sberr.rdsp;
1001 	return -1;
1002 }
1003 
1004 /*
1005  * Doing certain things (like toggling the speaker) make
1006  * the SB hardware go away for a while, so pause a little.
1007  */
1008 void
1009 sbdsp_to(arg)
1010 	void *arg;
1011 {
1012 	wakeup(arg);
1013 }
1014 
1015 void
1016 sbdsp_pause(sc)
1017 	struct sbdsp_softc *sc;
1018 {
1019 	timeout_add_msec(&sc->sc_tmo, 125);	/* 8x per second */
1020 	(void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
1021 }
1022 
1023 /*
1024  * Turn on the speaker.  The SBK documention says this operation
1025  * can take up to 1/10 of a second.  Higher level layers should
1026  * probably let the task sleep for this amount of time after
1027  * calling here.  Otherwise, things might not work (because
1028  * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
1029  *
1030  * These engineers had their heads up their ass when
1031  * they designed this card.
1032  */
1033 void
1034 sbdsp_spkron(sc)
1035 	struct sbdsp_softc *sc;
1036 {
1037 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
1038 	sbdsp_pause(sc);
1039 }
1040 
1041 /*
1042  * Turn off the speaker; see comment above.
1043  */
1044 void
1045 sbdsp_spkroff(sc)
1046 	struct sbdsp_softc *sc;
1047 {
1048 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
1049 	sbdsp_pause(sc);
1050 }
1051 
1052 /*
1053  * Read the version number out of the card.
1054  * Store version information in the softc.
1055  */
1056 void
1057 sbversion(sc)
1058 	struct sbdsp_softc *sc;
1059 {
1060 	int v;
1061 
1062 	sc->sc_model = SB_UNK;
1063 	sc->sc_version = 0;
1064 	if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
1065 		return;
1066 	v = sbdsp_rdsp(sc) << 8;
1067 	v |= sbdsp_rdsp(sc);
1068 	if (v < 0)
1069 		return;
1070 	sc->sc_version = v;
1071 	switch(SBVER_MAJOR(v)) {
1072 	case 1:
1073 		sc->sc_mixer_model = SBM_NONE;
1074 		sc->sc_model = SB_1;
1075 		break;
1076 	case 2:
1077 		/* Some SB2 have a mixer, some don't. */
1078 		sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
1079 		sbdsp_mix_write(sc, SBP_1335_MIDI_VOL,   0x06);
1080 		/* Check if we can read back the mixer values. */
1081 		if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
1082 		    (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL)   & 0x0e) == 0x06)
1083 			sc->sc_mixer_model = SBM_CT1335;
1084 		else
1085 			sc->sc_mixer_model = SBM_NONE;
1086 		if (SBVER_MINOR(v) == 0)
1087 			sc->sc_model = SB_20;
1088 		else
1089 			sc->sc_model = SB_2x;
1090 		break;
1091 	case 3:
1092 		sc->sc_mixer_model = SBM_CT1345;
1093 		sc->sc_model = SB_PRO;
1094 		break;
1095 	case 4:
1096 #if 0
1097 /* XXX This does not work */
1098 		/* Most SB16 have a tone controls, but some don't. */
1099 		sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
1100 		/* Check if we can read back the mixer value. */
1101 		if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
1102 			sc->sc_mixer_model = SBM_CT1745;
1103 		else
1104 			sc->sc_mixer_model = SBM_CT1XX5;
1105 #else
1106 		sc->sc_mixer_model = SBM_CT1745;
1107 #endif
1108 #if 0
1109 /* XXX figure out a good way of determining the model */
1110 		/* XXX what about SB_32 */
1111 		if (SBVER_MINOR(v) == 16)
1112 			sc->sc_model = SB_64;
1113 		else
1114 #endif
1115 			sc->sc_model = SB_16;
1116 		break;
1117 	}
1118 }
1119 
1120 /*
1121  * Halt a DMA in progress.
1122  */
1123 int
1124 sbdsp_haltdma(addr)
1125 	void *addr;
1126 {
1127 	struct sbdsp_softc *sc = addr;
1128 
1129 	DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
1130 
1131 	sbdsp_reset(sc);
1132 	return 0;
1133 }
1134 
1135 int
1136 sbdsp_set_timeconst(sc, tc)
1137 	struct sbdsp_softc *sc;
1138 	int tc;
1139 {
1140 	DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
1141 
1142 	if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
1143 	    sbdsp_wdsp(sc, tc) < 0)
1144 		return EIO;
1145 
1146 	return 0;
1147 }
1148 
1149 int
1150 sbdsp16_set_rate(sc, cmd, rate)
1151 	struct sbdsp_softc *sc;
1152 	int cmd, rate;
1153 {
1154 	DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
1155 
1156 	if (sbdsp_wdsp(sc, cmd) < 0 ||
1157 	    sbdsp_wdsp(sc, rate >> 8) < 0 ||
1158 	    sbdsp_wdsp(sc, rate) < 0)
1159 		return EIO;
1160 	return 0;
1161 }
1162 
1163 int
1164 sbdsp_trigger_input(addr, start, end, blksize, intr, arg, param)
1165 	void *addr;
1166 	void *start, *end;
1167 	int blksize;
1168 	void (*intr)(void *);
1169 	void *arg;
1170 	struct audio_params *param;
1171 {
1172 	struct sbdsp_softc *sc = addr;
1173 	int stereo = param->channels == 2;
1174 	int width = param->precision * param->factor;
1175 	int filter;
1176 
1177 #ifdef DIAGNOSTIC
1178 	if (stereo && (blksize & 1)) {
1179 		DPRINTF(("stereo record odd bytes (%d)\n", blksize));
1180 		return (EIO);
1181 	}
1182 #endif
1183 
1184 	sc->sc_intrr = intr;
1185 	sc->sc_argr = arg;
1186 
1187 	if (width == 8) {
1188 #ifdef DIAGNOSTIC
1189 		if (sc->sc_i.dmachan != sc->sc_drq8) {
1190 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1191 			    width, sc->sc_i.dmachan);
1192 			return (EIO);
1193 		}
1194 #endif
1195 		sc->sc_intr8 = sbdsp_block_input;
1196 		sc->sc_arg8 = addr;
1197 	} else {
1198 #ifdef DIAGNOSTIC
1199 		if (sc->sc_i.dmachan != sc->sc_drq16) {
1200 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1201 			    width, sc->sc_i.dmachan);
1202 			return (EIO);
1203 		}
1204 #endif
1205 		sc->sc_intr16 = sbdsp_block_input;
1206 		sc->sc_arg16 = addr;
1207 	}
1208 
1209 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
1210 		blksize >>= 1;
1211 	--blksize;
1212 	sc->sc_i.blksize = blksize;
1213 
1214 	if (ISSBPRO(sc)) {
1215 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
1216 			return (EIO);
1217 		filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
1218 		sbdsp_mix_write(sc, SBP_INFILTER,
1219 		    (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
1220 		    filter);
1221 	}
1222 
1223 	if (ISSB16CLASS(sc)) {
1224 		if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
1225 			DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
1226 				 sc->sc_i.rate));
1227 			return (EIO);
1228 		}
1229 	} else {
1230 		if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
1231 			DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
1232 				 sc->sc_i.rate));
1233 			return (EIO);
1234 		}
1235 	}
1236 
1237 	DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
1238 	    start, end, sc->sc_i.dmachan));
1239 	isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, start, (char *)end -
1240 	    (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1241 
1242 	return sbdsp_block_input(addr);
1243 }
1244 
1245 int
1246 sbdsp_block_input(addr)
1247 	void *addr;
1248 {
1249 	struct sbdsp_softc *sc = addr;
1250 	int cc = sc->sc_i.blksize;
1251 
1252 	DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
1253 
1254 	if (sc->sc_i.run != SB_NOTRUNNING)
1255 		sc->sc_intrr(sc->sc_argr);
1256 
1257 	if (sc->sc_model == SB_1) {
1258 		/* Non-looping mode, start DMA */
1259 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1260 		    sbdsp_wdsp(sc, cc) < 0 ||
1261 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1262 			DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
1263 			return (EIO);
1264 		}
1265 		sc->sc_i.run = SB_RUNNING;
1266 	} else if (sc->sc_i.run == SB_NOTRUNNING) {
1267 		/* Initialize looping PCM */
1268 		if (ISSB16CLASS(sc)) {
1269 			DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
1270 			    sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
1271 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1272 			    sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
1273 			    sbdsp_wdsp(sc, cc) < 0 ||
1274 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1275 				DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
1276 				return (EIO);
1277 			}
1278 		} else {
1279 			DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc));
1280 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1281 			    sbdsp_wdsp(sc, cc) < 0 ||
1282 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1283 				DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
1284 				return (EIO);
1285 			}
1286 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
1287 				DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
1288 				return (EIO);
1289 			}
1290 		}
1291 		sc->sc_i.run = SB_LOOPING;
1292 	}
1293 
1294 	return (0);
1295 }
1296 
1297 int
1298 sbdsp_trigger_output(addr, start, end, blksize, intr, arg, param)
1299 	void *addr;
1300 	void *start, *end;
1301 	int blksize;
1302 	void (*intr)(void *);
1303 	void *arg;
1304 	struct audio_params *param;
1305 {
1306 	struct sbdsp_softc *sc = addr;
1307 	int stereo = param->channels == 2;
1308 	int width = param->precision * param->factor;
1309 	int cmd;
1310 
1311 #ifdef DIAGNOSTIC
1312 	if (stereo && (blksize & 1)) {
1313 		DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
1314 		return (EIO);
1315 	}
1316 #endif
1317 
1318 	sc->sc_intrp = intr;
1319 	sc->sc_argp = arg;
1320 
1321 	if (width == 8) {
1322 #ifdef DIAGNOSTIC
1323 		if (sc->sc_o.dmachan != sc->sc_drq8) {
1324 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1325 			    width, sc->sc_o.dmachan);
1326 			return (EIO);
1327 		}
1328 #endif
1329 		sc->sc_intr8 = sbdsp_block_output;
1330 		sc->sc_arg8 = addr;
1331 	} else {
1332 #ifdef DIAGNOSTIC
1333 		if (sc->sc_o.dmachan != sc->sc_drq16) {
1334 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1335 			    width, sc->sc_o.dmachan);
1336 			return (EIO);
1337 		}
1338 #endif
1339 		sc->sc_intr16 = sbdsp_block_output;
1340 		sc->sc_arg16 = addr;
1341 	}
1342 
1343 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
1344 		blksize >>= 1;
1345 	--blksize;
1346 	sc->sc_o.blksize = blksize;
1347 
1348 	if (ISSBPRO(sc)) {
1349 		/* make sure we re-set stereo mixer bit when we start output. */
1350 		sbdsp_mix_write(sc, SBP_STEREO,
1351 		    (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1352 		    (stereo ?  SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1353 		cmd = sc->sc_o.modep->cmdchan;
1354 		if (cmd && sbdsp_wdsp(sc, cmd) < 0)
1355 			return (EIO);
1356 	}
1357 
1358 	if (ISSB16CLASS(sc)) {
1359 		if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
1360 			DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
1361 				 sc->sc_o.rate));
1362 			return (EIO);
1363 		}
1364 	} else {
1365 		if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
1366 			DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
1367 				 sc->sc_o.rate));
1368 			return (EIO);
1369 		}
1370 	}
1371 
1372 	DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
1373 	    start, end, sc->sc_o.dmachan));
1374 	isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, start, (char *)end -
1375 	    (char *)start, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1376 
1377 	return sbdsp_block_output(addr);
1378 }
1379 
1380 int
1381 sbdsp_block_output(addr)
1382 	void *addr;
1383 {
1384 	struct sbdsp_softc *sc = addr;
1385 	int cc = sc->sc_o.blksize;
1386 
1387 	DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
1388 
1389 	if (sc->sc_o.run != SB_NOTRUNNING)
1390 		sc->sc_intrp(sc->sc_argp);
1391 
1392 	if (sc->sc_model == SB_1) {
1393 		/* Non-looping mode, initialized. Start DMA and PCM */
1394 		if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1395 		    sbdsp_wdsp(sc, cc) < 0 ||
1396 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1397 			DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
1398 			return (EIO);
1399 		}
1400 		sc->sc_o.run = SB_RUNNING;
1401 	} else if (sc->sc_o.run == SB_NOTRUNNING) {
1402 		/* Initialize looping PCM */
1403 		if (ISSB16CLASS(sc)) {
1404 			DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
1405 			    sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
1406 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1407 			    sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
1408 			    sbdsp_wdsp(sc, cc) < 0 ||
1409 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1410 				DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
1411 				return (EIO);
1412 			}
1413 		} else {
1414 			DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc));
1415 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1416 			    sbdsp_wdsp(sc, cc) < 0 ||
1417 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1418 				DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
1419 				return (EIO);
1420 			}
1421 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
1422 				DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
1423 				return (EIO);
1424 			}
1425 		}
1426 		sc->sc_o.run = SB_LOOPING;
1427 	}
1428 
1429 	return (0);
1430 }
1431 
1432 /*
1433  * Only the DSP unit on the sound blaster generates interrupts.
1434  * There are three cases of interrupt: reception of a midi byte
1435  * (when mode is enabled), completion of dma transmission, or
1436  * completion of a dma reception.
1437  *
1438  * If there is interrupt sharing or a spurious interrupt occurs
1439  * there is no way to distinguish this on an SB2.  So if you have
1440  * an SB2 and experience problems, buy an SB16 (it's only $40).
1441  */
1442 int
1443 sbdsp_intr(arg)
1444 	void *arg;
1445 {
1446 	struct sbdsp_softc *sc = arg;
1447 	u_char irq;
1448 
1449 	DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
1450 		   sc->sc_intr8, sc->sc_intr16));
1451 	if (ISSB16CLASS(sc)) {
1452 		irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
1453 		if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 0) {
1454 			DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
1455 			return 0;
1456 		}
1457 	} else {
1458 		/* XXXX CHECK FOR INTERRUPT */
1459 		irq = SBP_IRQ_DMA8;
1460 	}
1461 
1462 	sc->sc_interrupts++;
1463 	delay(10);		/* XXX why? */
1464 
1465 	/* clear interrupt */
1466 	if (irq & SBP_IRQ_DMA8) {
1467 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
1468 		if (sc->sc_intr8)
1469 			sc->sc_intr8(sc->sc_arg8);
1470 	}
1471 	if (irq & SBP_IRQ_DMA16) {
1472 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
1473 		if (sc->sc_intr16)
1474 			sc->sc_intr16(sc->sc_arg16);
1475 	}
1476 #if NMIDI > 0
1477 	if ((irq & SBP_IRQ_MPU401) && sc->sc_hasmpu) {
1478 		mpu_intr(&sc->sc_mpu_sc);
1479 	}
1480 #endif
1481 	return 1;
1482 }
1483 
1484 /* Like val & mask, but make sure the result is correctly rounded. */
1485 #define MAXVAL 256
1486 static int
1487 sbdsp_adjust(val, mask)
1488 	int val, mask;
1489 {
1490 	val += (MAXVAL - mask) >> 1;
1491 	if (val >= MAXVAL)
1492 		val = MAXVAL-1;
1493 	return val & mask;
1494 }
1495 
1496 void
1497 sbdsp_set_mixer_gain(sc, port)
1498 	struct sbdsp_softc *sc;
1499 	int port;
1500 {
1501 	int src, gain;
1502 
1503 	switch(sc->sc_mixer_model) {
1504 	case SBM_NONE:
1505 		return;
1506 	case SBM_CT1335:
1507 		gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
1508 		switch(port) {
1509 		case SB_MASTER_VOL:
1510 			src = SBP_1335_MASTER_VOL;
1511 			break;
1512 		case SB_MIDI_VOL:
1513 			src = SBP_1335_MIDI_VOL;
1514 			break;
1515 		case SB_CD_VOL:
1516 			src = SBP_1335_CD_VOL;
1517 			break;
1518 		case SB_VOICE_VOL:
1519 			src = SBP_1335_VOICE_VOL;
1520 			gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
1521 			break;
1522 		default:
1523 			return;
1524 		}
1525 		sbdsp_mix_write(sc, src, gain);
1526 		break;
1527 	case SBM_CT1345:
1528 		gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
1529 				      sc->gain[port][SB_RIGHT]);
1530 		switch (port) {
1531 		case SB_MIC_VOL:
1532 			src = SBP_MIC_VOL;
1533 			gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
1534 			break;
1535 		case SB_MASTER_VOL:
1536 			src = SBP_MASTER_VOL;
1537 			break;
1538 		case SB_LINE_IN_VOL:
1539 			src = SBP_LINE_VOL;
1540 			break;
1541 		case SB_VOICE_VOL:
1542 			src = SBP_VOICE_VOL;
1543 			break;
1544 		case SB_MIDI_VOL:
1545 			src = SBP_MIDI_VOL;
1546 			break;
1547 		case SB_CD_VOL:
1548 			src = SBP_CD_VOL;
1549 			break;
1550 		default:
1551 			return;
1552 		}
1553 		sbdsp_mix_write(sc, src, gain);
1554 		break;
1555 	case SBM_CT1XX5:
1556 	case SBM_CT1745:
1557 		switch (port) {
1558 		case SB_MIC_VOL:
1559 			src = SB16P_MIC_L;
1560 			break;
1561 		case SB_MASTER_VOL:
1562 			src = SB16P_MASTER_L;
1563 			break;
1564 		case SB_LINE_IN_VOL:
1565 			src = SB16P_LINE_L;
1566 			break;
1567 		case SB_VOICE_VOL:
1568 			src = SB16P_VOICE_L;
1569 			break;
1570 		case SB_MIDI_VOL:
1571 			src = SB16P_MIDI_L;
1572 			break;
1573 		case SB_CD_VOL:
1574 			src = SB16P_CD_L;
1575 			break;
1576 		case SB_INPUT_GAIN:
1577 			src = SB16P_INPUT_GAIN_L;
1578 			break;
1579 		case SB_OUTPUT_GAIN:
1580 			src = SB16P_OUTPUT_GAIN_L;
1581 			break;
1582 		case SB_TREBLE:
1583 			src = SB16P_TREBLE_L;
1584 			break;
1585 		case SB_BASS:
1586 			src = SB16P_BASS_L;
1587 			break;
1588 		case SB_PCSPEAKER:
1589 			sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
1590 			return;
1591 		default:
1592 			return;
1593 		}
1594 		sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
1595 		sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
1596 		break;
1597 	}
1598 }
1599 
1600 int
1601 sbdsp_mixer_set_port(addr, cp)
1602 	void *addr;
1603 	mixer_ctrl_t *cp;
1604 {
1605 	struct sbdsp_softc *sc = addr;
1606 	int lgain, rgain;
1607 	int mask, bits;
1608 	int lmask, rmask, lbits, rbits;
1609 	int mute, swap;
1610 
1611 	if (sc->sc_open == SB_OPEN_MIDI)
1612 		return EBUSY;
1613 
1614 	DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
1615 	    cp->un.value.num_channels));
1616 
1617 	if (sc->sc_mixer_model == SBM_NONE)
1618 		return EINVAL;
1619 
1620 	switch (cp->dev) {
1621 	case SB_TREBLE:
1622 	case SB_BASS:
1623 		if (sc->sc_mixer_model == SBM_CT1345 ||
1624                     sc->sc_mixer_model == SBM_CT1XX5) {
1625 			if (cp->type != AUDIO_MIXER_ENUM)
1626 				return EINVAL;
1627 			switch (cp->dev) {
1628 			case SB_TREBLE:
1629 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
1630 				return 0;
1631 			case SB_BASS:
1632 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
1633 				return 0;
1634 			}
1635 		}
1636 	case SB_PCSPEAKER:
1637 	case SB_INPUT_GAIN:
1638 	case SB_OUTPUT_GAIN:
1639 		if (!ISSBM1745(sc))
1640 			return EINVAL;
1641 	case SB_MIC_VOL:
1642 	case SB_LINE_IN_VOL:
1643 		if (sc->sc_mixer_model == SBM_CT1335)
1644 			return EINVAL;
1645 	case SB_VOICE_VOL:
1646 	case SB_MIDI_VOL:
1647 	case SB_CD_VOL:
1648 	case SB_MASTER_VOL:
1649 		if (cp->type != AUDIO_MIXER_VALUE)
1650 			return EINVAL;
1651 
1652 		/*
1653 		 * All the mixer ports are stereo except for the microphone.
1654 		 * If we get a single-channel gain value passed in, then we
1655 		 * duplicate it to both left and right channels.
1656 		 */
1657 
1658 		switch (cp->dev) {
1659 		case SB_MIC_VOL:
1660 			if (cp->un.value.num_channels != 1)
1661 				return EINVAL;
1662 
1663 			lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
1664 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1665 			break;
1666 		case SB_PCSPEAKER:
1667 			if (cp->un.value.num_channels != 1)
1668 				return EINVAL;
1669 			/* fall into */
1670 		case SB_INPUT_GAIN:
1671 		case SB_OUTPUT_GAIN:
1672 			lgain = rgain = SB_ADJUST_2_GAIN(sc,
1673 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1674 			break;
1675 		default:
1676 			switch (cp->un.value.num_channels) {
1677 			case 1:
1678 				lgain = rgain = SB_ADJUST_GAIN(sc,
1679 				  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1680 				break;
1681 			case 2:
1682 				if (sc->sc_mixer_model == SBM_CT1335)
1683 					return EINVAL;
1684 				lgain = SB_ADJUST_GAIN(sc,
1685 				  cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1686 				rgain = SB_ADJUST_GAIN(sc,
1687 				  cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1688 				break;
1689 			default:
1690 				return EINVAL;
1691 			}
1692 			break;
1693 		}
1694 		sc->gain[cp->dev][SB_LEFT]  = lgain;
1695 		sc->gain[cp->dev][SB_RIGHT] = rgain;
1696 
1697 		sbdsp_set_mixer_gain(sc, cp->dev);
1698 		break;
1699 
1700 	case SB_RECORD_SOURCE:
1701 		if (ISSBM1745(sc)) {
1702 			if (cp->type != AUDIO_MIXER_SET)
1703 				return EINVAL;
1704 			return sbdsp_set_in_ports(sc, cp->un.mask);
1705 		} else {
1706 			if (cp->type != AUDIO_MIXER_ENUM)
1707 				return EINVAL;
1708 			sc->in_port = cp->un.ord;
1709 			return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
1710 		}
1711 		break;
1712 
1713 	case SB_AGC:
1714 		if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
1715 			return EINVAL;
1716 		sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
1717 		break;
1718 
1719 	case SB_CD_OUT_MUTE:
1720 		mask = SB16P_SW_CD;
1721 		goto omute;
1722 	case SB_MIC_OUT_MUTE:
1723 		mask = SB16P_SW_MIC;
1724 		goto omute;
1725 	case SB_LINE_OUT_MUTE:
1726 		mask = SB16P_SW_LINE;
1727 	omute:
1728 		if (cp->type != AUDIO_MIXER_ENUM)
1729 			return EINVAL;
1730 		bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
1731 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1732 		if (cp->un.ord)
1733 			bits = bits & ~mask;
1734 		else
1735 			bits = bits | mask;
1736 		sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
1737 		break;
1738 
1739 	case SB_MIC_IN_MUTE:
1740 	case SB_MIC_SWAP:
1741 		lmask = rmask = SB16P_SW_MIC;
1742 		goto imute;
1743 	case SB_CD_IN_MUTE:
1744 	case SB_CD_SWAP:
1745 		lmask = SB16P_SW_CD_L;
1746 		rmask = SB16P_SW_CD_R;
1747 		goto imute;
1748 	case SB_LINE_IN_MUTE:
1749 	case SB_LINE_SWAP:
1750 		lmask = SB16P_SW_LINE_L;
1751 		rmask = SB16P_SW_LINE_R;
1752 		goto imute;
1753 	case SB_MIDI_IN_MUTE:
1754 	case SB_MIDI_SWAP:
1755 		lmask = SB16P_SW_MIDI_L;
1756 		rmask = SB16P_SW_MIDI_R;
1757 	imute:
1758 		if (cp->type != AUDIO_MIXER_ENUM)
1759 			return EINVAL;
1760 		mask = lmask | rmask;
1761 		lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
1762 		rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
1763 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1764 		if (SB_IS_IN_MUTE(cp->dev)) {
1765 			mute = cp->dev;
1766 			swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
1767 		} else {
1768 			swap = cp->dev;
1769 			mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
1770 		}
1771 		if (sc->gain[swap][SB_LR]) {
1772 			mask = lmask;
1773 			lmask = rmask;
1774 			rmask = mask;
1775 		}
1776 		if (!sc->gain[mute][SB_LR]) {
1777 			lbits = lbits | lmask;
1778 			rbits = rbits | rmask;
1779 		}
1780 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
1781 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
1782 		break;
1783 
1784 	default:
1785 		return EINVAL;
1786 	}
1787 
1788 	return 0;
1789 }
1790 
1791 int
1792 sbdsp_mixer_get_port(addr, cp)
1793 	void *addr;
1794 	mixer_ctrl_t *cp;
1795 {
1796 	struct sbdsp_softc *sc = addr;
1797 
1798 	if (sc->sc_open == SB_OPEN_MIDI)
1799 		return EBUSY;
1800 
1801 	DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
1802 
1803 	if (sc->sc_mixer_model == SBM_NONE)
1804 		return EINVAL;
1805 
1806 	switch (cp->dev) {
1807 	case SB_TREBLE:
1808 	case SB_BASS:
1809 		if (sc->sc_mixer_model == SBM_CT1345 ||
1810                     sc->sc_mixer_model == SBM_CT1XX5) {
1811 			switch (cp->dev) {
1812 			case SB_TREBLE:
1813 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
1814 				return 0;
1815 			case SB_BASS:
1816 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
1817 				return 0;
1818 			}
1819 		}
1820 	case SB_PCSPEAKER:
1821 	case SB_INPUT_GAIN:
1822 	case SB_OUTPUT_GAIN:
1823 		if (!ISSBM1745(sc))
1824 			return EINVAL;
1825 	case SB_MIC_VOL:
1826 	case SB_LINE_IN_VOL:
1827 		if (sc->sc_mixer_model == SBM_CT1335)
1828 			return EINVAL;
1829 	case SB_VOICE_VOL:
1830 	case SB_MIDI_VOL:
1831 	case SB_CD_VOL:
1832 	case SB_MASTER_VOL:
1833 		switch (cp->dev) {
1834 		case SB_MIC_VOL:
1835 		case SB_PCSPEAKER:
1836 			if (cp->un.value.num_channels != 1)
1837 				return EINVAL;
1838 			/* fall into */
1839 		default:
1840 			switch (cp->un.value.num_channels) {
1841 			case 1:
1842 				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1843 					sc->gain[cp->dev][SB_LEFT];
1844 				break;
1845 			case 2:
1846 				cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1847 					sc->gain[cp->dev][SB_LEFT];
1848 				cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1849 					sc->gain[cp->dev][SB_RIGHT];
1850 				break;
1851 			default:
1852 				return EINVAL;
1853 			}
1854 			break;
1855 		}
1856 		break;
1857 
1858 	case SB_RECORD_SOURCE:
1859 		if (ISSBM1745(sc))
1860 			cp->un.mask = sc->in_mask;
1861 		else
1862 			cp->un.ord = sc->in_port;
1863 		break;
1864 
1865 	case SB_AGC:
1866 		if (!ISSBM1745(sc))
1867 			return EINVAL;
1868 		cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
1869 		break;
1870 
1871 	case SB_CD_IN_MUTE:
1872 	case SB_MIC_IN_MUTE:
1873 	case SB_LINE_IN_MUTE:
1874 	case SB_MIDI_IN_MUTE:
1875 	case SB_CD_SWAP:
1876 	case SB_MIC_SWAP:
1877 	case SB_LINE_SWAP:
1878 	case SB_MIDI_SWAP:
1879 	case SB_CD_OUT_MUTE:
1880 	case SB_MIC_OUT_MUTE:
1881 	case SB_LINE_OUT_MUTE:
1882 		cp->un.ord = sc->gain[cp->dev][SB_LR];
1883 		break;
1884 
1885 	default:
1886 		return EINVAL;
1887 	}
1888 
1889 	return 0;
1890 }
1891 
1892 int
1893 sbdsp_mixer_query_devinfo(addr, dip)
1894 	void *addr;
1895 	mixer_devinfo_t *dip;
1896 {
1897 	struct sbdsp_softc *sc = addr;
1898 	int chan, class, is1745;
1899 
1900 	DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1901 		 sc->sc_mixer_model, dip->index));
1902 
1903 	if (dip->index < 0)
1904 		return ENXIO;
1905 
1906 	if (sc->sc_mixer_model == SBM_NONE)
1907 		return ENXIO;
1908 
1909 	chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
1910 	is1745 = ISSBM1745(sc);
1911 	class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
1912 
1913 	switch (dip->index) {
1914 	case SB_MASTER_VOL:
1915 		dip->type = AUDIO_MIXER_VALUE;
1916 		dip->mixer_class = SB_OUTPUT_CLASS;
1917 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1918 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1919 		dip->un.v.num_channels = chan;
1920 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1921 		return 0;
1922 	case SB_MIDI_VOL:
1923 		dip->type = AUDIO_MIXER_VALUE;
1924 		dip->mixer_class = class;
1925 		dip->prev = AUDIO_MIXER_LAST;
1926 		dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
1927 		strlcpy(dip->label.name, AudioNfmsynth, sizeof dip->label.name);
1928 		dip->un.v.num_channels = chan;
1929 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1930 		return 0;
1931 	case SB_CD_VOL:
1932 		dip->type = AUDIO_MIXER_VALUE;
1933 		dip->mixer_class = class;
1934 		dip->prev = AUDIO_MIXER_LAST;
1935 		dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
1936 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1937 		dip->un.v.num_channels = chan;
1938 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1939 		return 0;
1940 	case SB_VOICE_VOL:
1941 		dip->type = AUDIO_MIXER_VALUE;
1942 		dip->mixer_class = class;
1943 		dip->prev = AUDIO_MIXER_LAST;
1944 		dip->next = AUDIO_MIXER_LAST;
1945 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
1946 		dip->un.v.num_channels = chan;
1947 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1948 		return 0;
1949 	case SB_OUTPUT_CLASS:
1950 		dip->type = AUDIO_MIXER_CLASS;
1951 		dip->mixer_class = SB_OUTPUT_CLASS;
1952 		dip->next = dip->prev = AUDIO_MIXER_LAST;
1953 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
1954 		return 0;
1955 	}
1956 
1957 	if (sc->sc_mixer_model == SBM_CT1335)
1958 		return ENXIO;
1959 
1960 	switch (dip->index) {
1961 	case SB_MIC_VOL:
1962 		dip->type = AUDIO_MIXER_VALUE;
1963 		dip->mixer_class = class;
1964 		dip->prev = AUDIO_MIXER_LAST;
1965 		dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
1966 		strlcpy(dip->label.name, AudioNmicrophone,
1967 		    sizeof dip->label.name);
1968 		dip->un.v.num_channels = 1;
1969 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1970 		return 0;
1971 
1972 	case SB_LINE_IN_VOL:
1973 		dip->type = AUDIO_MIXER_VALUE;
1974 		dip->mixer_class = class;
1975 		dip->prev = AUDIO_MIXER_LAST;
1976 		dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
1977 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
1978 		dip->un.v.num_channels = 2;
1979 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1980 		return 0;
1981 
1982 	case SB_RECORD_SOURCE:
1983 		dip->mixer_class = SB_RECORD_CLASS;
1984 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1985 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1986 		if (ISSBM1745(sc)) {
1987 			dip->type = AUDIO_MIXER_SET;
1988 			dip->un.s.num_mem = 4;
1989 			strlcpy(dip->un.s.member[0].label.name,
1990 			    AudioNmicrophone,
1991 			    sizeof dip->un.s.member[0].label.name);
1992 			dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
1993 			strlcpy(dip->un.s.member[1].label.name,
1994 			    AudioNcd, sizeof dip->un.s.member[1].label.name);
1995 			dip->un.s.member[1].mask = 1 << SB_CD_VOL;
1996 			strlcpy(dip->un.s.member[2].label.name,
1997 			    AudioNline, sizeof dip->un.s.member[2].label.name);
1998 			dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
1999 			strlcpy(dip->un.s.member[3].label.name,
2000 			    AudioNfmsynth,
2001 			    sizeof dip->un.s.member[3].label.name);
2002 			dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
2003 		} else {
2004 			dip->type = AUDIO_MIXER_ENUM;
2005 			dip->un.e.num_mem = 3;
2006 			strlcpy(dip->un.e.member[0].label.name,
2007 			    AudioNmicrophone,
2008 			    sizeof dip->un.e.member[0].label.name);
2009 			dip->un.e.member[0].ord = SB_MIC_VOL;
2010 			strlcpy(dip->un.e.member[1].label.name, AudioNcd,
2011 			    sizeof dip->un.e.member[1].label.name);
2012 			dip->un.e.member[1].ord = SB_CD_VOL;
2013 			strlcpy(dip->un.e.member[2].label.name, AudioNline,
2014 			    sizeof dip->un.e.member[2].label.name);
2015 			dip->un.e.member[2].ord = SB_LINE_IN_VOL;
2016 		}
2017 		return 0;
2018 
2019 	case SB_BASS:
2020 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2021 		strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
2022 		if (sc->sc_mixer_model == SBM_CT1745) {
2023 			dip->type = AUDIO_MIXER_VALUE;
2024 			dip->mixer_class = SB_EQUALIZATION_CLASS;
2025 			dip->un.v.num_channels = 2;
2026 			strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
2027 		} else {
2028 			dip->type = AUDIO_MIXER_ENUM;
2029 			dip->mixer_class = SB_INPUT_CLASS;
2030 			dip->un.e.num_mem = 2;
2031 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2032 			    sizeof dip->un.e.member[0].label.name);
2033 			dip->un.e.member[0].ord = 0;
2034 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
2035 			    sizeof dip->un.e.member[1].label.name);
2036 			dip->un.e.member[1].ord = 1;
2037 		}
2038 		return 0;
2039 
2040 	case SB_TREBLE:
2041 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2042 		strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
2043 		if (sc->sc_mixer_model == SBM_CT1745) {
2044 			dip->type = AUDIO_MIXER_VALUE;
2045 			dip->mixer_class = SB_EQUALIZATION_CLASS;
2046 			dip->un.v.num_channels = 2;
2047 			strlcpy(dip->un.v.units.name, AudioNtreble, sizeof dip->un.v.units.name);
2048 		} else {
2049 			dip->type = AUDIO_MIXER_ENUM;
2050 			dip->mixer_class = SB_INPUT_CLASS;
2051 			dip->un.e.num_mem = 2;
2052 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2053 			    sizeof dip->un.e.member[0].label.name);
2054 			dip->un.e.member[0].ord = 0;
2055 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
2056 			    sizeof dip->un.e.member[1].label.name);
2057 			dip->un.e.member[1].ord = 1;
2058 		}
2059 		return 0;
2060 
2061 	case SB_RECORD_CLASS:			/* record source class */
2062 		dip->type = AUDIO_MIXER_CLASS;
2063 		dip->mixer_class = SB_RECORD_CLASS;
2064 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2065 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
2066 		return 0;
2067 
2068 	case SB_INPUT_CLASS:
2069 		dip->type = AUDIO_MIXER_CLASS;
2070 		dip->mixer_class = SB_INPUT_CLASS;
2071 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2072 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
2073 		return 0;
2074 
2075 	}
2076 
2077 	if (sc->sc_mixer_model == SBM_CT1345)
2078 		return ENXIO;
2079 
2080 	switch(dip->index) {
2081 	case SB_PCSPEAKER:
2082 		dip->type = AUDIO_MIXER_VALUE;
2083 		dip->mixer_class = SB_INPUT_CLASS;
2084 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2085 		strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
2086 		dip->un.v.num_channels = 1;
2087 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2088 		return 0;
2089 
2090 	case SB_INPUT_GAIN:
2091 		dip->type = AUDIO_MIXER_VALUE;
2092 		dip->mixer_class = SB_INPUT_CLASS;
2093 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2094 		strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
2095 		dip->un.v.num_channels = 2;
2096 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2097 		return 0;
2098 
2099 	case SB_OUTPUT_GAIN:
2100 		dip->type = AUDIO_MIXER_VALUE;
2101 		dip->mixer_class = SB_OUTPUT_CLASS;
2102 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2103 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
2104 		dip->un.v.num_channels = 2;
2105 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2106 		return 0;
2107 
2108 	case SB_AGC:
2109 		dip->type = AUDIO_MIXER_ENUM;
2110 		dip->mixer_class = SB_INPUT_CLASS;
2111 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2112 		strlcpy(dip->label.name, "agc", sizeof dip->label.name);
2113 		dip->un.e.num_mem = 2;
2114 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2115 		    sizeof dip->un.e.member[0].label.name);
2116 		dip->un.e.member[0].ord = 0;
2117 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2118 		    sizeof dip->un.e.member[1].label.name);
2119 		dip->un.e.member[1].ord = 1;
2120 		return 0;
2121 
2122 	case SB_EQUALIZATION_CLASS:
2123 		dip->type = AUDIO_MIXER_CLASS;
2124 		dip->mixer_class = SB_EQUALIZATION_CLASS;
2125 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2126 		strlcpy(dip->label.name, AudioCequalization, sizeof dip->label.name);
2127 		return 0;
2128 
2129 	case SB_CD_IN_MUTE:
2130 		dip->prev = SB_CD_VOL;
2131 		dip->next = SB_CD_SWAP;
2132 		dip->mixer_class = SB_INPUT_CLASS;
2133 		goto mute;
2134 
2135 	case SB_MIC_IN_MUTE:
2136 		dip->prev = SB_MIC_VOL;
2137 		dip->next = SB_MIC_SWAP;
2138 		dip->mixer_class = SB_INPUT_CLASS;
2139 		goto mute;
2140 
2141 	case SB_LINE_IN_MUTE:
2142 		dip->prev = SB_LINE_IN_VOL;
2143 		dip->next = SB_LINE_SWAP;
2144 		dip->mixer_class = SB_INPUT_CLASS;
2145 		goto mute;
2146 
2147 	case SB_MIDI_IN_MUTE:
2148 		dip->prev = SB_MIDI_VOL;
2149 		dip->next = SB_MIDI_SWAP;
2150 		dip->mixer_class = SB_INPUT_CLASS;
2151 		goto mute;
2152 
2153 	case SB_CD_SWAP:
2154 		dip->prev = SB_CD_IN_MUTE;
2155 		dip->next = SB_CD_OUT_MUTE;
2156 		goto swap;
2157 
2158 	case SB_MIC_SWAP:
2159 		dip->prev = SB_MIC_IN_MUTE;
2160 		dip->next = SB_MIC_OUT_MUTE;
2161 		goto swap;
2162 
2163 	case SB_LINE_SWAP:
2164 		dip->prev = SB_LINE_IN_MUTE;
2165 		dip->next = SB_LINE_OUT_MUTE;
2166 		goto swap;
2167 
2168 	case SB_MIDI_SWAP:
2169 		dip->prev = SB_MIDI_IN_MUTE;
2170 		dip->next = AUDIO_MIXER_LAST;
2171 	swap:
2172 		dip->mixer_class = SB_INPUT_CLASS;
2173 		strlcpy(dip->label.name, AudioNswap, sizeof dip->label.name);
2174 		goto mute1;
2175 
2176 	case SB_CD_OUT_MUTE:
2177 		dip->prev = SB_CD_SWAP;
2178 		dip->next = AUDIO_MIXER_LAST;
2179 		dip->mixer_class = SB_OUTPUT_CLASS;
2180 		goto mute;
2181 
2182 	case SB_MIC_OUT_MUTE:
2183 		dip->prev = SB_MIC_SWAP;
2184 		dip->next = AUDIO_MIXER_LAST;
2185 		dip->mixer_class = SB_OUTPUT_CLASS;
2186 		goto mute;
2187 
2188 	case SB_LINE_OUT_MUTE:
2189 		dip->prev = SB_LINE_SWAP;
2190 		dip->next = AUDIO_MIXER_LAST;
2191 		dip->mixer_class = SB_OUTPUT_CLASS;
2192 	mute:
2193 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
2194 	mute1:
2195 		dip->type = AUDIO_MIXER_ENUM;
2196 		dip->un.e.num_mem = 2;
2197 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2198 		    sizeof dip->un.e.member[0].label.name);
2199 		dip->un.e.member[0].ord = 0;
2200 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2201 		    sizeof dip->un.e.member[1].label.name);
2202 		dip->un.e.member[1].ord = 1;
2203 		return 0;
2204 
2205 	}
2206 
2207 	return ENXIO;
2208 }
2209 
2210 void *
2211 sb_malloc(addr, direction, size, pool, flags)
2212 	void *addr;
2213 	int direction;
2214 	size_t size;
2215 	int pool;
2216 	int flags;
2217 {
2218 	struct sbdsp_softc *sc = addr;
2219 	int drq;
2220 
2221 	/* 8-bit has more restrictive alignment */
2222 	if (sc->sc_drq8 != -1)
2223 		drq = sc->sc_drq8;
2224 	else
2225 		drq = sc->sc_drq16;
2226 
2227 	return isa_malloc(sc->sc_isa, drq, size, pool, flags);
2228 }
2229 
2230 void
2231 sb_free(addr, ptr, pool)
2232 	void *addr;
2233 	void *ptr;
2234 	int pool;
2235 {
2236 	isa_free(ptr, pool);
2237 }
2238 
2239 size_t
2240 sb_round(addr, direction, size)
2241 	void *addr;
2242 	int direction;
2243 	size_t size;
2244 {
2245 	if (size > MAX_ISADMA)
2246 		size = MAX_ISADMA;
2247 	return size;
2248 }
2249 
2250 paddr_t
2251 sb_mappage(addr, mem, off, prot)
2252 	void *addr;
2253         void *mem;
2254         off_t off;
2255 	int prot;
2256 {
2257 	return isa_mappage(mem, off, prot);
2258 }
2259 
2260 int
2261 sbdsp_get_props(addr)
2262 	void *addr;
2263 {
2264 	struct sbdsp_softc *sc = addr;
2265 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
2266 	       (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
2267 }
2268 
2269 #if NMIDI > 0
2270 /*
2271  * MIDI related routines.
2272  */
2273 
2274 int
2275 sbdsp_midi_open(addr, flags, iintr, ointr, arg)
2276 	void *addr;
2277 	int flags;
2278 	void (*iintr)(void *, int);
2279 	void (*ointr)(void *);
2280 	void *arg;
2281 {
2282 	struct sbdsp_softc *sc = addr;
2283 
2284         DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
2285 
2286 	if (sc->sc_open != SB_CLOSED)
2287 		return EBUSY;
2288 	if (sbdsp_reset(sc) != 0)
2289 		return EIO;
2290 
2291 	if (sc->sc_model >= SB_20)
2292 		if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
2293 			return EIO;
2294 	sc->sc_open = SB_OPEN_MIDI;
2295 	sc->sc_openflags = flags;
2296 	sc->sc_intr8 = sbdsp_midi_intr;
2297 	sc->sc_arg8 = addr;
2298 	sc->sc_intrm = iintr;
2299 	sc->sc_argm = arg;
2300 	return 0;
2301 }
2302 
2303 void
2304 sbdsp_midi_close(addr)
2305 	void *addr;
2306 {
2307 	struct sbdsp_softc *sc = addr;
2308 
2309         DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
2310 
2311 	if (sc->sc_model >= SB_20)
2312 		sbdsp_reset(sc); /* exit UART mode */
2313 	sc->sc_open = SB_CLOSED;
2314 	sc->sc_intrm = 0;
2315 }
2316 
2317 int
2318 sbdsp_midi_output(addr, d)
2319 	void *addr;
2320 	int d;
2321 {
2322 	struct sbdsp_softc *sc = addr;
2323 
2324 	if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
2325 		return EIO;
2326 	if (sbdsp_wdsp(sc, d))
2327 		return EIO;
2328 	return 0;
2329 }
2330 
2331 void
2332 sbdsp_midi_getinfo(addr, mi)
2333 	void *addr;
2334 	struct midi_info *mi;
2335 {
2336 	struct sbdsp_softc *sc = addr;
2337 
2338 	mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
2339 	mi->props = MIDI_PROP_CAN_INPUT;
2340 }
2341 
2342 int
2343 sbdsp_midi_intr(addr)
2344 	void *addr;
2345 {
2346 	struct sbdsp_softc *sc = addr;
2347 
2348 	sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
2349 	return (0);
2350 }
2351 
2352 #endif
2353