xref: /openbsd-src/sys/dev/isa/sbdsp.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: sbdsp.c,v 1.27 2008/01/14 01:25:50 jakemsr 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 	extern int hz;
1020 
1021 	timeout_add(&sc->sc_tmo, hz/8);
1022 	(void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
1023 }
1024 
1025 /*
1026  * Turn on the speaker.  The SBK documention says this operation
1027  * can take up to 1/10 of a second.  Higher level layers should
1028  * probably let the task sleep for this amount of time after
1029  * calling here.  Otherwise, things might not work (because
1030  * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
1031  *
1032  * These engineers had their heads up their ass when
1033  * they designed this card.
1034  */
1035 void
1036 sbdsp_spkron(sc)
1037 	struct sbdsp_softc *sc;
1038 {
1039 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
1040 	sbdsp_pause(sc);
1041 }
1042 
1043 /*
1044  * Turn off the speaker; see comment above.
1045  */
1046 void
1047 sbdsp_spkroff(sc)
1048 	struct sbdsp_softc *sc;
1049 {
1050 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
1051 	sbdsp_pause(sc);
1052 }
1053 
1054 /*
1055  * Read the version number out of the card.
1056  * Store version information in the softc.
1057  */
1058 void
1059 sbversion(sc)
1060 	struct sbdsp_softc *sc;
1061 {
1062 	int v;
1063 
1064 	sc->sc_model = SB_UNK;
1065 	sc->sc_version = 0;
1066 	if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
1067 		return;
1068 	v = sbdsp_rdsp(sc) << 8;
1069 	v |= sbdsp_rdsp(sc);
1070 	if (v < 0)
1071 		return;
1072 	sc->sc_version = v;
1073 	switch(SBVER_MAJOR(v)) {
1074 	case 1:
1075 		sc->sc_mixer_model = SBM_NONE;
1076 		sc->sc_model = SB_1;
1077 		break;
1078 	case 2:
1079 		/* Some SB2 have a mixer, some don't. */
1080 		sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
1081 		sbdsp_mix_write(sc, SBP_1335_MIDI_VOL,   0x06);
1082 		/* Check if we can read back the mixer values. */
1083 		if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
1084 		    (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL)   & 0x0e) == 0x06)
1085 			sc->sc_mixer_model = SBM_CT1335;
1086 		else
1087 			sc->sc_mixer_model = SBM_NONE;
1088 		if (SBVER_MINOR(v) == 0)
1089 			sc->sc_model = SB_20;
1090 		else
1091 			sc->sc_model = SB_2x;
1092 		break;
1093 	case 3:
1094 		sc->sc_mixer_model = SBM_CT1345;
1095 		sc->sc_model = SB_PRO;
1096 		break;
1097 	case 4:
1098 #if 0
1099 /* XXX This does not work */
1100 		/* Most SB16 have a tone controls, but some don't. */
1101 		sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
1102 		/* Check if we can read back the mixer value. */
1103 		if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
1104 			sc->sc_mixer_model = SBM_CT1745;
1105 		else
1106 			sc->sc_mixer_model = SBM_CT1XX5;
1107 #else
1108 		sc->sc_mixer_model = SBM_CT1745;
1109 #endif
1110 #if 0
1111 /* XXX figure out a good way of determining the model */
1112 		/* XXX what about SB_32 */
1113 		if (SBVER_MINOR(v) == 16)
1114 			sc->sc_model = SB_64;
1115 		else
1116 #endif
1117 			sc->sc_model = SB_16;
1118 		break;
1119 	}
1120 }
1121 
1122 /*
1123  * Halt a DMA in progress.
1124  */
1125 int
1126 sbdsp_haltdma(addr)
1127 	void *addr;
1128 {
1129 	struct sbdsp_softc *sc = addr;
1130 
1131 	DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
1132 
1133 	sbdsp_reset(sc);
1134 	return 0;
1135 }
1136 
1137 int
1138 sbdsp_set_timeconst(sc, tc)
1139 	struct sbdsp_softc *sc;
1140 	int tc;
1141 {
1142 	DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
1143 
1144 	if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
1145 	    sbdsp_wdsp(sc, tc) < 0)
1146 		return EIO;
1147 
1148 	return 0;
1149 }
1150 
1151 int
1152 sbdsp16_set_rate(sc, cmd, rate)
1153 	struct sbdsp_softc *sc;
1154 	int cmd, rate;
1155 {
1156 	DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
1157 
1158 	if (sbdsp_wdsp(sc, cmd) < 0 ||
1159 	    sbdsp_wdsp(sc, rate >> 8) < 0 ||
1160 	    sbdsp_wdsp(sc, rate) < 0)
1161 		return EIO;
1162 	return 0;
1163 }
1164 
1165 int
1166 sbdsp_trigger_input(addr, start, end, blksize, intr, arg, param)
1167 	void *addr;
1168 	void *start, *end;
1169 	int blksize;
1170 	void (*intr)(void *);
1171 	void *arg;
1172 	struct audio_params *param;
1173 {
1174 	struct sbdsp_softc *sc = addr;
1175 	int stereo = param->channels == 2;
1176 	int width = param->precision * param->factor;
1177 	int filter;
1178 
1179 #ifdef DIAGNOSTIC
1180 	if (stereo && (blksize & 1)) {
1181 		DPRINTF(("stereo record odd bytes (%d)\n", blksize));
1182 		return (EIO);
1183 	}
1184 #endif
1185 
1186 	sc->sc_intrr = intr;
1187 	sc->sc_argr = arg;
1188 
1189 	if (width == 8) {
1190 #ifdef DIAGNOSTIC
1191 		if (sc->sc_i.dmachan != sc->sc_drq8) {
1192 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1193 			    width, sc->sc_i.dmachan);
1194 			return (EIO);
1195 		}
1196 #endif
1197 		sc->sc_intr8 = sbdsp_block_input;
1198 		sc->sc_arg8 = addr;
1199 	} else {
1200 #ifdef DIAGNOSTIC
1201 		if (sc->sc_i.dmachan != sc->sc_drq16) {
1202 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1203 			    width, sc->sc_i.dmachan);
1204 			return (EIO);
1205 		}
1206 #endif
1207 		sc->sc_intr16 = sbdsp_block_input;
1208 		sc->sc_arg16 = addr;
1209 	}
1210 
1211 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
1212 		blksize >>= 1;
1213 	--blksize;
1214 	sc->sc_i.blksize = blksize;
1215 
1216 	if (ISSBPRO(sc)) {
1217 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
1218 			return (EIO);
1219 		filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
1220 		sbdsp_mix_write(sc, SBP_INFILTER,
1221 		    (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
1222 		    filter);
1223 	}
1224 
1225 	if (ISSB16CLASS(sc)) {
1226 		if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
1227 			DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
1228 				 sc->sc_i.rate));
1229 			return (EIO);
1230 		}
1231 	} else {
1232 		if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
1233 			DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
1234 				 sc->sc_i.rate));
1235 			return (EIO);
1236 		}
1237 	}
1238 
1239 	DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
1240 	    start, end, sc->sc_i.dmachan));
1241 	isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, start, (char *)end -
1242 	    (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1243 
1244 	return sbdsp_block_input(addr);
1245 }
1246 
1247 int
1248 sbdsp_block_input(addr)
1249 	void *addr;
1250 {
1251 	struct sbdsp_softc *sc = addr;
1252 	int cc = sc->sc_i.blksize;
1253 
1254 	DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
1255 
1256 	if (sc->sc_i.run != SB_NOTRUNNING)
1257 		sc->sc_intrr(sc->sc_argr);
1258 
1259 	if (sc->sc_model == SB_1) {
1260 		/* Non-looping mode, start DMA */
1261 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1262 		    sbdsp_wdsp(sc, cc) < 0 ||
1263 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1264 			DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
1265 			return (EIO);
1266 		}
1267 		sc->sc_i.run = SB_RUNNING;
1268 	} else if (sc->sc_i.run == SB_NOTRUNNING) {
1269 		/* Initialize looping PCM */
1270 		if (ISSB16CLASS(sc)) {
1271 			DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
1272 			    sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
1273 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1274 			    sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
1275 			    sbdsp_wdsp(sc, cc) < 0 ||
1276 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1277 				DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
1278 				return (EIO);
1279 			}
1280 		} else {
1281 			DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc));
1282 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1283 			    sbdsp_wdsp(sc, cc) < 0 ||
1284 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1285 				DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
1286 				return (EIO);
1287 			}
1288 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
1289 				DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
1290 				return (EIO);
1291 			}
1292 		}
1293 		sc->sc_i.run = SB_LOOPING;
1294 	}
1295 
1296 	return (0);
1297 }
1298 
1299 int
1300 sbdsp_trigger_output(addr, start, end, blksize, intr, arg, param)
1301 	void *addr;
1302 	void *start, *end;
1303 	int blksize;
1304 	void (*intr)(void *);
1305 	void *arg;
1306 	struct audio_params *param;
1307 {
1308 	struct sbdsp_softc *sc = addr;
1309 	int stereo = param->channels == 2;
1310 	int width = param->precision * param->factor;
1311 	int cmd;
1312 
1313 #ifdef DIAGNOSTIC
1314 	if (stereo && (blksize & 1)) {
1315 		DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
1316 		return (EIO);
1317 	}
1318 #endif
1319 
1320 	sc->sc_intrp = intr;
1321 	sc->sc_argp = arg;
1322 
1323 	if (width == 8) {
1324 #ifdef DIAGNOSTIC
1325 		if (sc->sc_o.dmachan != sc->sc_drq8) {
1326 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1327 			    width, sc->sc_o.dmachan);
1328 			return (EIO);
1329 		}
1330 #endif
1331 		sc->sc_intr8 = sbdsp_block_output;
1332 		sc->sc_arg8 = addr;
1333 	} else {
1334 #ifdef DIAGNOSTIC
1335 		if (sc->sc_o.dmachan != sc->sc_drq16) {
1336 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1337 			    width, sc->sc_o.dmachan);
1338 			return (EIO);
1339 		}
1340 #endif
1341 		sc->sc_intr16 = sbdsp_block_output;
1342 		sc->sc_arg16 = addr;
1343 	}
1344 
1345 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
1346 		blksize >>= 1;
1347 	--blksize;
1348 	sc->sc_o.blksize = blksize;
1349 
1350 	if (ISSBPRO(sc)) {
1351 		/* make sure we re-set stereo mixer bit when we start output. */
1352 		sbdsp_mix_write(sc, SBP_STEREO,
1353 		    (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1354 		    (stereo ?  SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1355 		cmd = sc->sc_o.modep->cmdchan;
1356 		if (cmd && sbdsp_wdsp(sc, cmd) < 0)
1357 			return (EIO);
1358 	}
1359 
1360 	if (ISSB16CLASS(sc)) {
1361 		if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
1362 			DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
1363 				 sc->sc_o.rate));
1364 			return (EIO);
1365 		}
1366 	} else {
1367 		if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
1368 			DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
1369 				 sc->sc_o.rate));
1370 			return (EIO);
1371 		}
1372 	}
1373 
1374 	DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
1375 	    start, end, sc->sc_o.dmachan));
1376 	isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, start, (char *)end -
1377 	    (char *)start, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1378 
1379 	return sbdsp_block_output(addr);
1380 }
1381 
1382 int
1383 sbdsp_block_output(addr)
1384 	void *addr;
1385 {
1386 	struct sbdsp_softc *sc = addr;
1387 	int cc = sc->sc_o.blksize;
1388 
1389 	DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
1390 
1391 	if (sc->sc_o.run != SB_NOTRUNNING)
1392 		sc->sc_intrp(sc->sc_argp);
1393 
1394 	if (sc->sc_model == SB_1) {
1395 		/* Non-looping mode, initialized. Start DMA and PCM */
1396 		if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1397 		    sbdsp_wdsp(sc, cc) < 0 ||
1398 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1399 			DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
1400 			return (EIO);
1401 		}
1402 		sc->sc_o.run = SB_RUNNING;
1403 	} else if (sc->sc_o.run == SB_NOTRUNNING) {
1404 		/* Initialize looping PCM */
1405 		if (ISSB16CLASS(sc)) {
1406 			DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
1407 			    sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
1408 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1409 			    sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
1410 			    sbdsp_wdsp(sc, cc) < 0 ||
1411 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1412 				DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
1413 				return (EIO);
1414 			}
1415 		} else {
1416 			DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc));
1417 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1418 			    sbdsp_wdsp(sc, cc) < 0 ||
1419 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1420 				DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
1421 				return (EIO);
1422 			}
1423 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
1424 				DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
1425 				return (EIO);
1426 			}
1427 		}
1428 		sc->sc_o.run = SB_LOOPING;
1429 	}
1430 
1431 	return (0);
1432 }
1433 
1434 /*
1435  * Only the DSP unit on the sound blaster generates interrupts.
1436  * There are three cases of interrupt: reception of a midi byte
1437  * (when mode is enabled), completion of dma transmission, or
1438  * completion of a dma reception.
1439  *
1440  * If there is interrupt sharing or a spurious interrupt occurs
1441  * there is no way to distinguish this on an SB2.  So if you have
1442  * an SB2 and experience problems, buy an SB16 (it's only $40).
1443  */
1444 int
1445 sbdsp_intr(arg)
1446 	void *arg;
1447 {
1448 	struct sbdsp_softc *sc = arg;
1449 	u_char irq;
1450 
1451 	DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
1452 		   sc->sc_intr8, sc->sc_intr16));
1453 	if (ISSB16CLASS(sc)) {
1454 		irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
1455 		if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 0) {
1456 			DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
1457 			return 0;
1458 		}
1459 	} else {
1460 		/* XXXX CHECK FOR INTERRUPT */
1461 		irq = SBP_IRQ_DMA8;
1462 	}
1463 
1464 	sc->sc_interrupts++;
1465 	delay(10);		/* XXX why? */
1466 
1467 	/* clear interrupt */
1468 	if (irq & SBP_IRQ_DMA8) {
1469 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
1470 		if (sc->sc_intr8)
1471 			sc->sc_intr8(sc->sc_arg8);
1472 	}
1473 	if (irq & SBP_IRQ_DMA16) {
1474 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
1475 		if (sc->sc_intr16)
1476 			sc->sc_intr16(sc->sc_arg16);
1477 	}
1478 #if NMIDI > 0
1479 	if ((irq & SBP_IRQ_MPU401) && sc->sc_hasmpu) {
1480 		mpu_intr(&sc->sc_mpu_sc);
1481 	}
1482 #endif
1483 	return 1;
1484 }
1485 
1486 /* Like val & mask, but make sure the result is correctly rounded. */
1487 #define MAXVAL 256
1488 static int
1489 sbdsp_adjust(val, mask)
1490 	int val, mask;
1491 {
1492 	val += (MAXVAL - mask) >> 1;
1493 	if (val >= MAXVAL)
1494 		val = MAXVAL-1;
1495 	return val & mask;
1496 }
1497 
1498 void
1499 sbdsp_set_mixer_gain(sc, port)
1500 	struct sbdsp_softc *sc;
1501 	int port;
1502 {
1503 	int src, gain;
1504 
1505 	switch(sc->sc_mixer_model) {
1506 	case SBM_NONE:
1507 		return;
1508 	case SBM_CT1335:
1509 		gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
1510 		switch(port) {
1511 		case SB_MASTER_VOL:
1512 			src = SBP_1335_MASTER_VOL;
1513 			break;
1514 		case SB_MIDI_VOL:
1515 			src = SBP_1335_MIDI_VOL;
1516 			break;
1517 		case SB_CD_VOL:
1518 			src = SBP_1335_CD_VOL;
1519 			break;
1520 		case SB_VOICE_VOL:
1521 			src = SBP_1335_VOICE_VOL;
1522 			gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
1523 			break;
1524 		default:
1525 			return;
1526 		}
1527 		sbdsp_mix_write(sc, src, gain);
1528 		break;
1529 	case SBM_CT1345:
1530 		gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
1531 				      sc->gain[port][SB_RIGHT]);
1532 		switch (port) {
1533 		case SB_MIC_VOL:
1534 			src = SBP_MIC_VOL;
1535 			gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
1536 			break;
1537 		case SB_MASTER_VOL:
1538 			src = SBP_MASTER_VOL;
1539 			break;
1540 		case SB_LINE_IN_VOL:
1541 			src = SBP_LINE_VOL;
1542 			break;
1543 		case SB_VOICE_VOL:
1544 			src = SBP_VOICE_VOL;
1545 			break;
1546 		case SB_MIDI_VOL:
1547 			src = SBP_MIDI_VOL;
1548 			break;
1549 		case SB_CD_VOL:
1550 			src = SBP_CD_VOL;
1551 			break;
1552 		default:
1553 			return;
1554 		}
1555 		sbdsp_mix_write(sc, src, gain);
1556 		break;
1557 	case SBM_CT1XX5:
1558 	case SBM_CT1745:
1559 		switch (port) {
1560 		case SB_MIC_VOL:
1561 			src = SB16P_MIC_L;
1562 			break;
1563 		case SB_MASTER_VOL:
1564 			src = SB16P_MASTER_L;
1565 			break;
1566 		case SB_LINE_IN_VOL:
1567 			src = SB16P_LINE_L;
1568 			break;
1569 		case SB_VOICE_VOL:
1570 			src = SB16P_VOICE_L;
1571 			break;
1572 		case SB_MIDI_VOL:
1573 			src = SB16P_MIDI_L;
1574 			break;
1575 		case SB_CD_VOL:
1576 			src = SB16P_CD_L;
1577 			break;
1578 		case SB_INPUT_GAIN:
1579 			src = SB16P_INPUT_GAIN_L;
1580 			break;
1581 		case SB_OUTPUT_GAIN:
1582 			src = SB16P_OUTPUT_GAIN_L;
1583 			break;
1584 		case SB_TREBLE:
1585 			src = SB16P_TREBLE_L;
1586 			break;
1587 		case SB_BASS:
1588 			src = SB16P_BASS_L;
1589 			break;
1590 		case SB_PCSPEAKER:
1591 			sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
1592 			return;
1593 		default:
1594 			return;
1595 		}
1596 		sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
1597 		sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
1598 		break;
1599 	}
1600 }
1601 
1602 int
1603 sbdsp_mixer_set_port(addr, cp)
1604 	void *addr;
1605 	mixer_ctrl_t *cp;
1606 {
1607 	struct sbdsp_softc *sc = addr;
1608 	int lgain, rgain;
1609 	int mask, bits;
1610 	int lmask, rmask, lbits, rbits;
1611 	int mute, swap;
1612 
1613 	if (sc->sc_open == SB_OPEN_MIDI)
1614 		return EBUSY;
1615 
1616 	DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
1617 	    cp->un.value.num_channels));
1618 
1619 	if (sc->sc_mixer_model == SBM_NONE)
1620 		return EINVAL;
1621 
1622 	switch (cp->dev) {
1623 	case SB_TREBLE:
1624 	case SB_BASS:
1625 		if (sc->sc_mixer_model == SBM_CT1345 ||
1626                     sc->sc_mixer_model == SBM_CT1XX5) {
1627 			if (cp->type != AUDIO_MIXER_ENUM)
1628 				return EINVAL;
1629 			switch (cp->dev) {
1630 			case SB_TREBLE:
1631 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
1632 				return 0;
1633 			case SB_BASS:
1634 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
1635 				return 0;
1636 			}
1637 		}
1638 	case SB_PCSPEAKER:
1639 	case SB_INPUT_GAIN:
1640 	case SB_OUTPUT_GAIN:
1641 		if (!ISSBM1745(sc))
1642 			return EINVAL;
1643 	case SB_MIC_VOL:
1644 	case SB_LINE_IN_VOL:
1645 		if (sc->sc_mixer_model == SBM_CT1335)
1646 			return EINVAL;
1647 	case SB_VOICE_VOL:
1648 	case SB_MIDI_VOL:
1649 	case SB_CD_VOL:
1650 	case SB_MASTER_VOL:
1651 		if (cp->type != AUDIO_MIXER_VALUE)
1652 			return EINVAL;
1653 
1654 		/*
1655 		 * All the mixer ports are stereo except for the microphone.
1656 		 * If we get a single-channel gain value passed in, then we
1657 		 * duplicate it to both left and right channels.
1658 		 */
1659 
1660 		switch (cp->dev) {
1661 		case SB_MIC_VOL:
1662 			if (cp->un.value.num_channels != 1)
1663 				return EINVAL;
1664 
1665 			lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
1666 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1667 			break;
1668 		case SB_PCSPEAKER:
1669 			if (cp->un.value.num_channels != 1)
1670 				return EINVAL;
1671 			/* fall into */
1672 		case SB_INPUT_GAIN:
1673 		case SB_OUTPUT_GAIN:
1674 			lgain = rgain = SB_ADJUST_2_GAIN(sc,
1675 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1676 			break;
1677 		default:
1678 			switch (cp->un.value.num_channels) {
1679 			case 1:
1680 				lgain = rgain = SB_ADJUST_GAIN(sc,
1681 				  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1682 				break;
1683 			case 2:
1684 				if (sc->sc_mixer_model == SBM_CT1335)
1685 					return EINVAL;
1686 				lgain = SB_ADJUST_GAIN(sc,
1687 				  cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1688 				rgain = SB_ADJUST_GAIN(sc,
1689 				  cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1690 				break;
1691 			default:
1692 				return EINVAL;
1693 			}
1694 			break;
1695 		}
1696 		sc->gain[cp->dev][SB_LEFT]  = lgain;
1697 		sc->gain[cp->dev][SB_RIGHT] = rgain;
1698 
1699 		sbdsp_set_mixer_gain(sc, cp->dev);
1700 		break;
1701 
1702 	case SB_RECORD_SOURCE:
1703 		if (ISSBM1745(sc)) {
1704 			if (cp->type != AUDIO_MIXER_SET)
1705 				return EINVAL;
1706 			return sbdsp_set_in_ports(sc, cp->un.mask);
1707 		} else {
1708 			if (cp->type != AUDIO_MIXER_ENUM)
1709 				return EINVAL;
1710 			sc->in_port = cp->un.ord;
1711 			return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
1712 		}
1713 		break;
1714 
1715 	case SB_AGC:
1716 		if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
1717 			return EINVAL;
1718 		sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
1719 		break;
1720 
1721 	case SB_CD_OUT_MUTE:
1722 		mask = SB16P_SW_CD;
1723 		goto omute;
1724 	case SB_MIC_OUT_MUTE:
1725 		mask = SB16P_SW_MIC;
1726 		goto omute;
1727 	case SB_LINE_OUT_MUTE:
1728 		mask = SB16P_SW_LINE;
1729 	omute:
1730 		if (cp->type != AUDIO_MIXER_ENUM)
1731 			return EINVAL;
1732 		bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
1733 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1734 		if (cp->un.ord)
1735 			bits = bits & ~mask;
1736 		else
1737 			bits = bits | mask;
1738 		sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
1739 		break;
1740 
1741 	case SB_MIC_IN_MUTE:
1742 	case SB_MIC_SWAP:
1743 		lmask = rmask = SB16P_SW_MIC;
1744 		goto imute;
1745 	case SB_CD_IN_MUTE:
1746 	case SB_CD_SWAP:
1747 		lmask = SB16P_SW_CD_L;
1748 		rmask = SB16P_SW_CD_R;
1749 		goto imute;
1750 	case SB_LINE_IN_MUTE:
1751 	case SB_LINE_SWAP:
1752 		lmask = SB16P_SW_LINE_L;
1753 		rmask = SB16P_SW_LINE_R;
1754 		goto imute;
1755 	case SB_MIDI_IN_MUTE:
1756 	case SB_MIDI_SWAP:
1757 		lmask = SB16P_SW_MIDI_L;
1758 		rmask = SB16P_SW_MIDI_R;
1759 	imute:
1760 		if (cp->type != AUDIO_MIXER_ENUM)
1761 			return EINVAL;
1762 		mask = lmask | rmask;
1763 		lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
1764 		rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
1765 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1766 		if (SB_IS_IN_MUTE(cp->dev)) {
1767 			mute = cp->dev;
1768 			swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
1769 		} else {
1770 			swap = cp->dev;
1771 			mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
1772 		}
1773 		if (sc->gain[swap][SB_LR]) {
1774 			mask = lmask;
1775 			lmask = rmask;
1776 			rmask = mask;
1777 		}
1778 		if (!sc->gain[mute][SB_LR]) {
1779 			lbits = lbits | lmask;
1780 			rbits = rbits | rmask;
1781 		}
1782 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
1783 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
1784 		break;
1785 
1786 	default:
1787 		return EINVAL;
1788 	}
1789 
1790 	return 0;
1791 }
1792 
1793 int
1794 sbdsp_mixer_get_port(addr, cp)
1795 	void *addr;
1796 	mixer_ctrl_t *cp;
1797 {
1798 	struct sbdsp_softc *sc = addr;
1799 
1800 	if (sc->sc_open == SB_OPEN_MIDI)
1801 		return EBUSY;
1802 
1803 	DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
1804 
1805 	if (sc->sc_mixer_model == SBM_NONE)
1806 		return EINVAL;
1807 
1808 	switch (cp->dev) {
1809 	case SB_TREBLE:
1810 	case SB_BASS:
1811 		if (sc->sc_mixer_model == SBM_CT1345 ||
1812                     sc->sc_mixer_model == SBM_CT1XX5) {
1813 			switch (cp->dev) {
1814 			case SB_TREBLE:
1815 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
1816 				return 0;
1817 			case SB_BASS:
1818 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
1819 				return 0;
1820 			}
1821 		}
1822 	case SB_PCSPEAKER:
1823 	case SB_INPUT_GAIN:
1824 	case SB_OUTPUT_GAIN:
1825 		if (!ISSBM1745(sc))
1826 			return EINVAL;
1827 	case SB_MIC_VOL:
1828 	case SB_LINE_IN_VOL:
1829 		if (sc->sc_mixer_model == SBM_CT1335)
1830 			return EINVAL;
1831 	case SB_VOICE_VOL:
1832 	case SB_MIDI_VOL:
1833 	case SB_CD_VOL:
1834 	case SB_MASTER_VOL:
1835 		switch (cp->dev) {
1836 		case SB_MIC_VOL:
1837 		case SB_PCSPEAKER:
1838 			if (cp->un.value.num_channels != 1)
1839 				return EINVAL;
1840 			/* fall into */
1841 		default:
1842 			switch (cp->un.value.num_channels) {
1843 			case 1:
1844 				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1845 					sc->gain[cp->dev][SB_LEFT];
1846 				break;
1847 			case 2:
1848 				cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1849 					sc->gain[cp->dev][SB_LEFT];
1850 				cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1851 					sc->gain[cp->dev][SB_RIGHT];
1852 				break;
1853 			default:
1854 				return EINVAL;
1855 			}
1856 			break;
1857 		}
1858 		break;
1859 
1860 	case SB_RECORD_SOURCE:
1861 		if (ISSBM1745(sc))
1862 			cp->un.mask = sc->in_mask;
1863 		else
1864 			cp->un.ord = sc->in_port;
1865 		break;
1866 
1867 	case SB_AGC:
1868 		if (!ISSBM1745(sc))
1869 			return EINVAL;
1870 		cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
1871 		break;
1872 
1873 	case SB_CD_IN_MUTE:
1874 	case SB_MIC_IN_MUTE:
1875 	case SB_LINE_IN_MUTE:
1876 	case SB_MIDI_IN_MUTE:
1877 	case SB_CD_SWAP:
1878 	case SB_MIC_SWAP:
1879 	case SB_LINE_SWAP:
1880 	case SB_MIDI_SWAP:
1881 	case SB_CD_OUT_MUTE:
1882 	case SB_MIC_OUT_MUTE:
1883 	case SB_LINE_OUT_MUTE:
1884 		cp->un.ord = sc->gain[cp->dev][SB_LR];
1885 		break;
1886 
1887 	default:
1888 		return EINVAL;
1889 	}
1890 
1891 	return 0;
1892 }
1893 
1894 int
1895 sbdsp_mixer_query_devinfo(addr, dip)
1896 	void *addr;
1897 	mixer_devinfo_t *dip;
1898 {
1899 	struct sbdsp_softc *sc = addr;
1900 	int chan, class, is1745;
1901 
1902 	DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1903 		 sc->sc_mixer_model, dip->index));
1904 
1905 	if (dip->index < 0)
1906 		return ENXIO;
1907 
1908 	if (sc->sc_mixer_model == SBM_NONE)
1909 		return ENXIO;
1910 
1911 	chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
1912 	is1745 = ISSBM1745(sc);
1913 	class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
1914 
1915 	switch (dip->index) {
1916 	case SB_MASTER_VOL:
1917 		dip->type = AUDIO_MIXER_VALUE;
1918 		dip->mixer_class = SB_OUTPUT_CLASS;
1919 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1920 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1921 		dip->un.v.num_channels = chan;
1922 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1923 		return 0;
1924 	case SB_MIDI_VOL:
1925 		dip->type = AUDIO_MIXER_VALUE;
1926 		dip->mixer_class = class;
1927 		dip->prev = AUDIO_MIXER_LAST;
1928 		dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
1929 		strlcpy(dip->label.name, AudioNfmsynth, sizeof dip->label.name);
1930 		dip->un.v.num_channels = chan;
1931 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1932 		return 0;
1933 	case SB_CD_VOL:
1934 		dip->type = AUDIO_MIXER_VALUE;
1935 		dip->mixer_class = class;
1936 		dip->prev = AUDIO_MIXER_LAST;
1937 		dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
1938 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1939 		dip->un.v.num_channels = chan;
1940 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1941 		return 0;
1942 	case SB_VOICE_VOL:
1943 		dip->type = AUDIO_MIXER_VALUE;
1944 		dip->mixer_class = class;
1945 		dip->prev = AUDIO_MIXER_LAST;
1946 		dip->next = AUDIO_MIXER_LAST;
1947 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
1948 		dip->un.v.num_channels = chan;
1949 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1950 		return 0;
1951 	case SB_OUTPUT_CLASS:
1952 		dip->type = AUDIO_MIXER_CLASS;
1953 		dip->mixer_class = SB_OUTPUT_CLASS;
1954 		dip->next = dip->prev = AUDIO_MIXER_LAST;
1955 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
1956 		return 0;
1957 	}
1958 
1959 	if (sc->sc_mixer_model == SBM_CT1335)
1960 		return ENXIO;
1961 
1962 	switch (dip->index) {
1963 	case SB_MIC_VOL:
1964 		dip->type = AUDIO_MIXER_VALUE;
1965 		dip->mixer_class = class;
1966 		dip->prev = AUDIO_MIXER_LAST;
1967 		dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
1968 		strlcpy(dip->label.name, AudioNmicrophone,
1969 		    sizeof dip->label.name);
1970 		dip->un.v.num_channels = 1;
1971 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1972 		return 0;
1973 
1974 	case SB_LINE_IN_VOL:
1975 		dip->type = AUDIO_MIXER_VALUE;
1976 		dip->mixer_class = class;
1977 		dip->prev = AUDIO_MIXER_LAST;
1978 		dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
1979 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
1980 		dip->un.v.num_channels = 2;
1981 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1982 		return 0;
1983 
1984 	case SB_RECORD_SOURCE:
1985 		dip->mixer_class = SB_RECORD_CLASS;
1986 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1987 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1988 		if (ISSBM1745(sc)) {
1989 			dip->type = AUDIO_MIXER_SET;
1990 			dip->un.s.num_mem = 4;
1991 			strlcpy(dip->un.s.member[0].label.name,
1992 			    AudioNmicrophone,
1993 			    sizeof dip->un.s.member[0].label.name);
1994 			dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
1995 			strlcpy(dip->un.s.member[1].label.name,
1996 			    AudioNcd, sizeof dip->un.s.member[1].label.name);
1997 			dip->un.s.member[1].mask = 1 << SB_CD_VOL;
1998 			strlcpy(dip->un.s.member[2].label.name,
1999 			    AudioNline, sizeof dip->un.s.member[2].label.name);
2000 			dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
2001 			strlcpy(dip->un.s.member[3].label.name,
2002 			    AudioNfmsynth,
2003 			    sizeof dip->un.s.member[3].label.name);
2004 			dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
2005 		} else {
2006 			dip->type = AUDIO_MIXER_ENUM;
2007 			dip->un.e.num_mem = 3;
2008 			strlcpy(dip->un.e.member[0].label.name,
2009 			    AudioNmicrophone,
2010 			    sizeof dip->un.e.member[0].label.name);
2011 			dip->un.e.member[0].ord = SB_MIC_VOL;
2012 			strlcpy(dip->un.e.member[1].label.name, AudioNcd,
2013 			    sizeof dip->un.e.member[1].label.name);
2014 			dip->un.e.member[1].ord = SB_CD_VOL;
2015 			strlcpy(dip->un.e.member[2].label.name, AudioNline,
2016 			    sizeof dip->un.e.member[2].label.name);
2017 			dip->un.e.member[2].ord = SB_LINE_IN_VOL;
2018 		}
2019 		return 0;
2020 
2021 	case SB_BASS:
2022 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2023 		strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
2024 		if (sc->sc_mixer_model == SBM_CT1745) {
2025 			dip->type = AUDIO_MIXER_VALUE;
2026 			dip->mixer_class = SB_EQUALIZATION_CLASS;
2027 			dip->un.v.num_channels = 2;
2028 			strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
2029 		} else {
2030 			dip->type = AUDIO_MIXER_ENUM;
2031 			dip->mixer_class = SB_INPUT_CLASS;
2032 			dip->un.e.num_mem = 2;
2033 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2034 			    sizeof dip->un.e.member[0].label.name);
2035 			dip->un.e.member[0].ord = 0;
2036 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
2037 			    sizeof dip->un.e.member[1].label.name);
2038 			dip->un.e.member[1].ord = 1;
2039 		}
2040 		return 0;
2041 
2042 	case SB_TREBLE:
2043 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2044 		strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
2045 		if (sc->sc_mixer_model == SBM_CT1745) {
2046 			dip->type = AUDIO_MIXER_VALUE;
2047 			dip->mixer_class = SB_EQUALIZATION_CLASS;
2048 			dip->un.v.num_channels = 2;
2049 			strlcpy(dip->un.v.units.name, AudioNtreble, sizeof dip->un.v.units.name);
2050 		} else {
2051 			dip->type = AUDIO_MIXER_ENUM;
2052 			dip->mixer_class = SB_INPUT_CLASS;
2053 			dip->un.e.num_mem = 2;
2054 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2055 			    sizeof dip->un.e.member[0].label.name);
2056 			dip->un.e.member[0].ord = 0;
2057 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
2058 			    sizeof dip->un.e.member[1].label.name);
2059 			dip->un.e.member[1].ord = 1;
2060 		}
2061 		return 0;
2062 
2063 	case SB_RECORD_CLASS:			/* record source class */
2064 		dip->type = AUDIO_MIXER_CLASS;
2065 		dip->mixer_class = SB_RECORD_CLASS;
2066 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2067 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
2068 		return 0;
2069 
2070 	case SB_INPUT_CLASS:
2071 		dip->type = AUDIO_MIXER_CLASS;
2072 		dip->mixer_class = SB_INPUT_CLASS;
2073 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2074 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
2075 		return 0;
2076 
2077 	}
2078 
2079 	if (sc->sc_mixer_model == SBM_CT1345)
2080 		return ENXIO;
2081 
2082 	switch(dip->index) {
2083 	case SB_PCSPEAKER:
2084 		dip->type = AUDIO_MIXER_VALUE;
2085 		dip->mixer_class = SB_INPUT_CLASS;
2086 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2087 		strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
2088 		dip->un.v.num_channels = 1;
2089 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2090 		return 0;
2091 
2092 	case SB_INPUT_GAIN:
2093 		dip->type = AUDIO_MIXER_VALUE;
2094 		dip->mixer_class = SB_INPUT_CLASS;
2095 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2096 		strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
2097 		dip->un.v.num_channels = 2;
2098 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2099 		return 0;
2100 
2101 	case SB_OUTPUT_GAIN:
2102 		dip->type = AUDIO_MIXER_VALUE;
2103 		dip->mixer_class = SB_OUTPUT_CLASS;
2104 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2105 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
2106 		dip->un.v.num_channels = 2;
2107 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2108 		return 0;
2109 
2110 	case SB_AGC:
2111 		dip->type = AUDIO_MIXER_ENUM;
2112 		dip->mixer_class = SB_INPUT_CLASS;
2113 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2114 		strlcpy(dip->label.name, "agc", sizeof dip->label.name);
2115 		dip->un.e.num_mem = 2;
2116 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2117 		    sizeof dip->un.e.member[0].label.name);
2118 		dip->un.e.member[0].ord = 0;
2119 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2120 		    sizeof dip->un.e.member[1].label.name);
2121 		dip->un.e.member[1].ord = 1;
2122 		return 0;
2123 
2124 	case SB_EQUALIZATION_CLASS:
2125 		dip->type = AUDIO_MIXER_CLASS;
2126 		dip->mixer_class = SB_EQUALIZATION_CLASS;
2127 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2128 		strlcpy(dip->label.name, AudioCequalization, sizeof dip->label.name);
2129 		return 0;
2130 
2131 	case SB_CD_IN_MUTE:
2132 		dip->prev = SB_CD_VOL;
2133 		dip->next = SB_CD_SWAP;
2134 		dip->mixer_class = SB_INPUT_CLASS;
2135 		goto mute;
2136 
2137 	case SB_MIC_IN_MUTE:
2138 		dip->prev = SB_MIC_VOL;
2139 		dip->next = SB_MIC_SWAP;
2140 		dip->mixer_class = SB_INPUT_CLASS;
2141 		goto mute;
2142 
2143 	case SB_LINE_IN_MUTE:
2144 		dip->prev = SB_LINE_IN_VOL;
2145 		dip->next = SB_LINE_SWAP;
2146 		dip->mixer_class = SB_INPUT_CLASS;
2147 		goto mute;
2148 
2149 	case SB_MIDI_IN_MUTE:
2150 		dip->prev = SB_MIDI_VOL;
2151 		dip->next = SB_MIDI_SWAP;
2152 		dip->mixer_class = SB_INPUT_CLASS;
2153 		goto mute;
2154 
2155 	case SB_CD_SWAP:
2156 		dip->prev = SB_CD_IN_MUTE;
2157 		dip->next = SB_CD_OUT_MUTE;
2158 		goto swap;
2159 
2160 	case SB_MIC_SWAP:
2161 		dip->prev = SB_MIC_IN_MUTE;
2162 		dip->next = SB_MIC_OUT_MUTE;
2163 		goto swap;
2164 
2165 	case SB_LINE_SWAP:
2166 		dip->prev = SB_LINE_IN_MUTE;
2167 		dip->next = SB_LINE_OUT_MUTE;
2168 		goto swap;
2169 
2170 	case SB_MIDI_SWAP:
2171 		dip->prev = SB_MIDI_IN_MUTE;
2172 		dip->next = AUDIO_MIXER_LAST;
2173 	swap:
2174 		dip->mixer_class = SB_INPUT_CLASS;
2175 		strlcpy(dip->label.name, AudioNswap, sizeof dip->label.name);
2176 		goto mute1;
2177 
2178 	case SB_CD_OUT_MUTE:
2179 		dip->prev = SB_CD_SWAP;
2180 		dip->next = AUDIO_MIXER_LAST;
2181 		dip->mixer_class = SB_OUTPUT_CLASS;
2182 		goto mute;
2183 
2184 	case SB_MIC_OUT_MUTE:
2185 		dip->prev = SB_MIC_SWAP;
2186 		dip->next = AUDIO_MIXER_LAST;
2187 		dip->mixer_class = SB_OUTPUT_CLASS;
2188 		goto mute;
2189 
2190 	case SB_LINE_OUT_MUTE:
2191 		dip->prev = SB_LINE_SWAP;
2192 		dip->next = AUDIO_MIXER_LAST;
2193 		dip->mixer_class = SB_OUTPUT_CLASS;
2194 	mute:
2195 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
2196 	mute1:
2197 		dip->type = AUDIO_MIXER_ENUM;
2198 		dip->un.e.num_mem = 2;
2199 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2200 		    sizeof dip->un.e.member[0].label.name);
2201 		dip->un.e.member[0].ord = 0;
2202 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2203 		    sizeof dip->un.e.member[1].label.name);
2204 		dip->un.e.member[1].ord = 1;
2205 		return 0;
2206 
2207 	}
2208 
2209 	return ENXIO;
2210 }
2211 
2212 void *
2213 sb_malloc(addr, direction, size, pool, flags)
2214 	void *addr;
2215 	int direction;
2216 	size_t size;
2217 	int pool;
2218 	int flags;
2219 {
2220 	struct sbdsp_softc *sc = addr;
2221 	int drq;
2222 
2223 	/* 8-bit has more restrictive alignment */
2224 	if (sc->sc_drq8 != -1)
2225 		drq = sc->sc_drq8;
2226 	else
2227 		drq = sc->sc_drq16;
2228 
2229 	return isa_malloc(sc->sc_isa, drq, size, pool, flags);
2230 }
2231 
2232 void
2233 sb_free(addr, ptr, pool)
2234 	void *addr;
2235 	void *ptr;
2236 	int pool;
2237 {
2238 	isa_free(ptr, pool);
2239 }
2240 
2241 size_t
2242 sb_round(addr, direction, size)
2243 	void *addr;
2244 	int direction;
2245 	size_t size;
2246 {
2247 	if (size > MAX_ISADMA)
2248 		size = MAX_ISADMA;
2249 	return size;
2250 }
2251 
2252 paddr_t
2253 sb_mappage(addr, mem, off, prot)
2254 	void *addr;
2255         void *mem;
2256         off_t off;
2257 	int prot;
2258 {
2259 	return isa_mappage(mem, off, prot);
2260 }
2261 
2262 int
2263 sbdsp_get_props(addr)
2264 	void *addr;
2265 {
2266 	struct sbdsp_softc *sc = addr;
2267 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
2268 	       (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
2269 }
2270 
2271 #if NMIDI > 0
2272 /*
2273  * MIDI related routines.
2274  */
2275 
2276 int
2277 sbdsp_midi_open(addr, flags, iintr, ointr, arg)
2278 	void *addr;
2279 	int flags;
2280 	void (*iintr)(void *, int);
2281 	void (*ointr)(void *);
2282 	void *arg;
2283 {
2284 	struct sbdsp_softc *sc = addr;
2285 
2286         DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
2287 
2288 	if (sc->sc_open != SB_CLOSED)
2289 		return EBUSY;
2290 	if (sbdsp_reset(sc) != 0)
2291 		return EIO;
2292 
2293 	if (sc->sc_model >= SB_20)
2294 		if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
2295 			return EIO;
2296 	sc->sc_open = SB_OPEN_MIDI;
2297 	sc->sc_openflags = flags;
2298 	sc->sc_intr8 = sbdsp_midi_intr;
2299 	sc->sc_arg8 = addr;
2300 	sc->sc_intrm = iintr;
2301 	sc->sc_argm = arg;
2302 	return 0;
2303 }
2304 
2305 void
2306 sbdsp_midi_close(addr)
2307 	void *addr;
2308 {
2309 	struct sbdsp_softc *sc = addr;
2310 
2311         DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
2312 
2313 	if (sc->sc_model >= SB_20)
2314 		sbdsp_reset(sc); /* exit UART mode */
2315 	sc->sc_open = SB_CLOSED;
2316 	sc->sc_intrm = 0;
2317 }
2318 
2319 int
2320 sbdsp_midi_output(addr, d)
2321 	void *addr;
2322 	int d;
2323 {
2324 	struct sbdsp_softc *sc = addr;
2325 
2326 	if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
2327 		return EIO;
2328 	if (sbdsp_wdsp(sc, d))
2329 		return EIO;
2330 	return 0;
2331 }
2332 
2333 void
2334 sbdsp_midi_getinfo(addr, mi)
2335 	void *addr;
2336 	struct midi_info *mi;
2337 {
2338 	struct sbdsp_softc *sc = addr;
2339 
2340 	mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
2341 	mi->props = MIDI_PROP_CAN_INPUT;
2342 }
2343 
2344 int
2345 sbdsp_midi_intr(addr)
2346 	void *addr;
2347 {
2348 	struct sbdsp_softc *sc = addr;
2349 
2350 	sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
2351 	return (0);
2352 }
2353 
2354 #endif
2355