xref: /openbsd-src/sys/dev/isa/sbdsp.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: sbdsp.c,v 1.33 2013/05/15 08:29:24 ratchov 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 
416 	mtx_enter(&audio_lock);
417 	bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
418 	delay(20);
419 	bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
420 	delay(30);
421 	mtx_leave(&audio_lock);
422 }
423 
424 int
425 sbdsp_mix_read(sc, mixerport)
426 	struct sbdsp_softc *sc;
427 	int mixerport;
428 {
429 	bus_space_tag_t iot = sc->sc_iot;
430 	bus_space_handle_t ioh = sc->sc_ioh;
431 	int val;
432 
433 	mtx_enter(&audio_lock);
434 	bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
435 	delay(20);
436 	val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
437 	delay(30);
438 	mtx_leave(&audio_lock);
439 	return val;
440 }
441 
442 /*
443  * Various routines to interface to higher level audio driver
444  */
445 
446 int
447 sbdsp_query_encoding(addr, fp)
448 	void *addr;
449 	struct audio_encoding *fp;
450 {
451 	struct sbdsp_softc *sc = addr;
452 	int emul, found = 0;
453 
454 	emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
455 
456 	switch (fp->index) {
457 	case 0:
458 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
459 		fp->encoding = AUDIO_ENCODING_ULINEAR;
460 		fp->precision = 8;
461 		fp->flags = 0;
462 		found = 1;
463 		break;
464 	case 1:
465 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
466 		fp->encoding = AUDIO_ENCODING_ULAW;
467 		fp->precision = 8;
468 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
469 		found = 1;
470 		break;
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 		found = 1;
477 		break;
478 	case 3:
479 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
480 		fp->encoding = AUDIO_ENCODING_SLINEAR;
481 		fp->precision = 8;
482 		fp->flags = emul;
483 		found = 1;
484 		break;
485         }
486 	if (found) {
487 		fp->bps = 1;
488 		fp->msb = 1;
489 		return 0;
490 	} else if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
491 		return EINVAL;
492 
493         switch(fp->index) {
494         case 4:
495 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
496 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
497 		fp->precision = 16;
498 		fp->flags = 0;
499 		break;
500 	case 5:
501 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
502 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
503 		fp->precision = 16;
504 		fp->flags = emul;
505 		break;
506 	case 6:
507 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
508 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
509 		fp->precision = 16;
510 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
511 		break;
512 	case 7:
513 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
514 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
515 		fp->precision = 16;
516 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
517 		break;
518 	default:
519 		return EINVAL;
520 	}
521 	fp->bps = 2;
522 	fp->msb = 1;
523 	return 0;
524 }
525 
526 int
527 sbdsp_set_params(addr, setmode, usemode, play, rec)
528 	void *addr;
529 	int setmode, usemode;
530 	struct audio_params *play, *rec;
531 {
532 	struct sbdsp_softc *sc = addr;
533 	struct sbmode *m;
534 	u_int rate, tc, bmode;
535 	void (*swcode)(void *, u_char *buf, int cnt);
536 	int factor;
537 	int model;
538 	int chan;
539 	struct audio_params *p;
540 	int mode;
541 
542 	if (sc->sc_open == SB_OPEN_MIDI)
543 		return EBUSY;
544 
545 	model = sc->sc_model;
546 	if (model > SB_16)
547 		model = SB_16;	/* later models work like SB16 */
548 
549 	/*
550 	 * Prior to the SB16, we have only one clock, so make the sample
551 	 * rates match.
552 	 */
553 	if (!ISSB16CLASS(sc) &&
554 	    play->sample_rate != rec->sample_rate &&
555 	    usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
556 		if (setmode == AUMODE_PLAY) {
557 			rec->sample_rate = play->sample_rate;
558 			setmode |= AUMODE_RECORD;
559 		} else if (setmode == AUMODE_RECORD) {
560 			play->sample_rate = rec->sample_rate;
561 			setmode |= AUMODE_PLAY;
562 		} else
563 			return (EINVAL);
564 	}
565 
566 	/* Set first record info, then play info */
567 	for (mode = AUMODE_RECORD; mode != -1;
568 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
569 		if ((setmode & mode) == 0)
570 			continue;
571 
572 		p = mode == AUMODE_PLAY ? play : rec;
573 
574 		switch (model) {
575 		case SB_1:
576 		case SB_20:
577 			if (mode == AUMODE_PLAY) {
578 				if (p->sample_rate < 4000)
579 					p->sample_rate = 4000;
580 				else if (p->sample_rate > 22727)
581 					p->sample_rate = 22727; /* 22050 ? */
582 			} else {
583 				if (p->sample_rate < 4000)
584 					p->sample_rate = 4000;
585 				else if (p->sample_rate > 12987)
586 					p->sample_rate = 12987;
587 			}
588 			break;
589 		case SB_2x:
590 			if (mode == AUMODE_PLAY) {
591 				if (p->sample_rate < 4000)
592 					p->sample_rate = 4000;
593 				else if (p->sample_rate > 45454)
594 					p->sample_rate = 45454; /* 44100 ? */
595 			} else {
596 				if (p->sample_rate < 4000)
597 					p->sample_rate = 4000;
598 				else if (p->sample_rate > 14925)
599 					p->sample_rate = 14925; /* ??? */
600 			}
601 			break;
602 		case SB_PRO:
603 		case SB_JAZZ:
604 			if (p->channels == 2) {
605 				if (p->sample_rate < 11025)
606 					p->sample_rate = 11025;
607 				else if (p->sample_rate > 22727)
608 					p->sample_rate = 22727; /* 22050 ? */
609 			} else {
610 				if (p->sample_rate < 4000)
611 					p->sample_rate = 4000;
612 				else if (p->sample_rate > 45454)
613 					p->sample_rate = 45454; /* 44100 ? */
614 			}
615 			break;
616 		case SB_16:
617 			if (p->sample_rate < 5000)
618 				p->sample_rate = 5000;
619 			else if (p->sample_rate > 45000)
620 				p->sample_rate = 45000; /* 44100 ? */
621 			break;
622 		}
623 
624 		/* Locate proper commands */
625 		for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
626 		    m->model != -1; m++) {
627 			if (model == m->model &&
628 			    p->channels == m->channels &&
629 			    p->precision == m->precision &&
630 			    p->sample_rate >= m->lowrate &&
631 			    p->sample_rate <= m->highrate)
632 				break;
633 		}
634 		if (m->model == -1)
635 			return EINVAL;
636 		rate = p->sample_rate;
637 		swcode = 0;
638 		factor = 1;
639 		tc = 1;
640 		bmode = -1;
641 		if (model == SB_16) {
642 			switch (p->encoding) {
643 			case AUDIO_ENCODING_SLINEAR_BE:
644 				if (p->precision == 16)
645 					swcode = swap_bytes;
646 				/* fall into */
647 			case AUDIO_ENCODING_SLINEAR_LE:
648 				bmode = SB_BMODE_SIGNED;
649 				break;
650 			case AUDIO_ENCODING_ULINEAR_BE:
651 				if (p->precision == 16)
652 					swcode = swap_bytes;
653 				/* fall into */
654 			case AUDIO_ENCODING_ULINEAR_LE:
655 				bmode = SB_BMODE_UNSIGNED;
656 				break;
657 			case AUDIO_ENCODING_ULAW:
658 				if (mode == AUMODE_PLAY) {
659 					swcode = mulaw_to_ulinear16_le;
660 					factor = 2;
661 					m = &sbpmodes[PLAY16];
662 				} else
663 					swcode = ulinear8_to_mulaw;
664 				bmode = SB_BMODE_UNSIGNED;
665 				break;
666 			case AUDIO_ENCODING_ALAW:
667 				if (mode == AUMODE_PLAY) {
668 					swcode = alaw_to_ulinear16_le;
669 					factor = 2;
670 					m = &sbpmodes[PLAY16];
671 				} else
672 					swcode = ulinear8_to_alaw;
673 				bmode = SB_BMODE_UNSIGNED;
674 				break;
675 			default:
676 				return EINVAL;
677 			}
678 			if (p->channels == 2)
679 				bmode |= SB_BMODE_STEREO;
680 		} else if (m->model == SB_JAZZ && m->precision == 16) {
681 			switch (p->encoding) {
682 			case AUDIO_ENCODING_SLINEAR_LE:
683 				break;
684 			case AUDIO_ENCODING_ULINEAR_LE:
685 				swcode = change_sign16_le;
686 				break;
687 			case AUDIO_ENCODING_SLINEAR_BE:
688 				swcode = swap_bytes;
689 				break;
690 			case AUDIO_ENCODING_ULINEAR_BE:
691 				swcode = mode == AUMODE_PLAY ?
692 					swap_bytes_change_sign16_le : change_sign16_swap_bytes_le;
693 				break;
694 			case AUDIO_ENCODING_ULAW:
695 				swcode = mode == AUMODE_PLAY ?
696 					mulaw_to_ulinear8 : ulinear8_to_mulaw;
697 				break;
698 			case AUDIO_ENCODING_ALAW:
699 				swcode = mode == AUMODE_PLAY ?
700 					alaw_to_ulinear8 : ulinear8_to_alaw;
701 				break;
702 			default:
703 				return EINVAL;
704 			}
705 			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
706 			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
707 		} else {
708 			switch (p->encoding) {
709 			case AUDIO_ENCODING_SLINEAR_BE:
710 			case AUDIO_ENCODING_SLINEAR_LE:
711 				swcode = change_sign8;
712 				break;
713 			case AUDIO_ENCODING_ULINEAR_BE:
714 			case AUDIO_ENCODING_ULINEAR_LE:
715 				break;
716 			case AUDIO_ENCODING_ULAW:
717 				swcode = mode == AUMODE_PLAY ?
718 					mulaw_to_ulinear8 : ulinear8_to_mulaw;
719 				break;
720 			case AUDIO_ENCODING_ALAW:
721 				swcode = mode == AUMODE_PLAY ?
722 					alaw_to_ulinear8 : ulinear8_to_alaw;
723 				break;
724 			default:
725 				return EINVAL;
726 			}
727 			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
728 			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
729 		}
730 
731 		chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
732 		if (mode == AUMODE_PLAY) {
733 			sc->sc_o.rate = rate;
734 			sc->sc_o.tc = tc;
735 			sc->sc_o.modep = m;
736 			sc->sc_o.bmode = bmode;
737 			sc->sc_o.dmachan = chan;
738 		} else {
739 			sc->sc_i.rate = rate;
740 			sc->sc_i.tc = tc;
741 			sc->sc_i.modep = m;
742 			sc->sc_i.bmode = bmode;
743 			sc->sc_i.dmachan = chan;
744 		}
745 
746 		p->sw_code = swcode;
747 		p->factor = factor;
748 		p->bps = AUDIO_BPS(p->precision);
749 		p->msb = 1;
750 		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",
751 			 sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
752 			 p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
753 
754 	}
755 
756 	/*
757 	 * XXX
758 	 * Should wait for chip to be idle.
759 	 */
760 	sc->sc_i.run = SB_NOTRUNNING;
761 	sc->sc_o.run = SB_NOTRUNNING;
762 
763 	if (sc->sc_fullduplex &&
764 	    usemode == (AUMODE_PLAY | AUMODE_RECORD) &&
765 	    sc->sc_i.dmachan == sc->sc_o.dmachan) {
766 		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));
767 		if (sc->sc_o.dmachan == sc->sc_drq8) {
768 			/* Use 16 bit DMA for playing by expanding the samples. */
769 			play->sw_code = linear8_to_linear16_le;
770 			play->factor = 2;
771 			sc->sc_o.modep = &sbpmodes[PLAY16];
772 			sc->sc_o.dmachan = sc->sc_drq16;
773 		} else {
774 			return EINVAL;
775 		}
776 	}
777 	DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
778 		 sc->sc_i.dmachan, sc->sc_o.dmachan));
779 
780 	return 0;
781 }
782 
783 void
784 sbdsp_set_ifilter(addr, which)
785 	void *addr;
786 	int which;
787 {
788 	struct sbdsp_softc *sc = addr;
789 	int mixval;
790 
791 	mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
792 	switch (which) {
793 	case 0:
794 		mixval |= SBP_FILTER_OFF;
795 		break;
796 	case SB_TREBLE:
797 		mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
798 		break;
799 	case SB_BASS:
800 		mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
801 		break;
802 	default:
803 		return;
804 	}
805 	sc->in_filter = mixval & SBP_IFILTER_MASK;
806 	sbdsp_mix_write(sc, SBP_INFILTER, mixval);
807 }
808 
809 int
810 sbdsp_get_ifilter(addr)
811 	void *addr;
812 {
813 	struct sbdsp_softc *sc = addr;
814 
815 	sc->in_filter =
816 		sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
817 	switch (sc->in_filter) {
818 	case SBP_FILTER_ON|SBP_IFILTER_HIGH:
819 		return SB_TREBLE;
820 	case SBP_FILTER_ON|SBP_IFILTER_LOW:
821 		return SB_BASS;
822 	default:
823 		return 0;
824 	}
825 }
826 
827 int
828 sbdsp_set_in_ports(sc, mask)
829 	struct sbdsp_softc *sc;
830 	int mask;
831 {
832 	int bitsl, bitsr;
833 	int sbport;
834 
835 	if (sc->sc_open == SB_OPEN_MIDI)
836 		return EBUSY;
837 
838 	DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
839 		 sc->sc_mixer_model, mask));
840 
841 	switch(sc->sc_mixer_model) {
842 	case SBM_NONE:
843 		return EINVAL;
844 	case SBM_CT1335:
845 		if (mask != (1 << SB_MIC_VOL))
846 			return EINVAL;
847 		break;
848 	case SBM_CT1345:
849 		switch (mask) {
850 		case 1 << SB_MIC_VOL:
851 			sbport = SBP_FROM_MIC;
852 			break;
853 		case 1 << SB_LINE_IN_VOL:
854 			sbport = SBP_FROM_LINE;
855 			break;
856 		case 1 << SB_CD_VOL:
857 			sbport = SBP_FROM_CD;
858 			break;
859 		default:
860 			return (EINVAL);
861 		}
862 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
863 		break;
864 	case SBM_CT1XX5:
865 	case SBM_CT1745:
866 		if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
867 			     (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
868 			return EINVAL;
869 		bitsr = 0;
870 		if (mask & (1<<SB_MIDI_VOL))    bitsr |= SBP_MIDI_SRC_R;
871 		if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
872 		if (mask & (1<<SB_CD_VOL))      bitsr |= SBP_CD_SRC_R;
873 		bitsl = SB_SRC_R_TO_L(bitsr);
874 		if (mask & (1<<SB_MIC_VOL)) {
875 			bitsl |= SBP_MIC_SRC;
876 			bitsr |= SBP_MIC_SRC;
877 		}
878 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
879 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
880 		break;
881 	}
882 	sc->in_mask = mask;
883 
884 	return 0;
885 }
886 
887 int
888 sbdsp_speaker_ctl(addr, newstate)
889 	void *addr;
890 	int newstate;
891 {
892 	struct sbdsp_softc *sc = addr;
893 
894 	if (sc->sc_open == SB_OPEN_MIDI)
895 		return EBUSY;
896 
897 	if ((newstate == SPKR_ON) &&
898 	    (sc->spkr_state == SPKR_OFF)) {
899 		sbdsp_spkron(sc);
900 		sc->spkr_state = SPKR_ON;
901 	}
902 	if ((newstate == SPKR_OFF) &&
903 	    (sc->spkr_state == SPKR_ON)) {
904 		sbdsp_spkroff(sc);
905 		sc->spkr_state = SPKR_OFF;
906 	}
907 	return 0;
908 }
909 
910 int
911 sbdsp_round_blocksize(addr, blk)
912 	void *addr;
913 	int blk;
914 {
915 	return (blk + 3) & -4;	/* round to biggest sample size */
916 }
917 
918 int
919 sbdsp_open(addr, flags)
920 	void *addr;
921 	int flags;
922 {
923 	struct sbdsp_softc *sc = addr;
924 
925         DPRINTF(("sbdsp_open: sc=%p\n", sc));
926 
927 	if (sc->sc_open != SB_CLOSED)
928 		return EBUSY;
929 	if (sbdsp_reset(sc) != 0)
930 		return EIO;
931 
932 	sc->sc_open = SB_OPEN_AUDIO;
933 	sc->sc_openflags = flags;
934 	sc->sc_intrm = 0;
935 	if (ISSBPRO(sc) &&
936 	    sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
937 		DPRINTF(("sbdsp_open: can't set mono mode\n"));
938 		/* we'll readjust when it's time for DMA. */
939 	}
940 
941 	/*
942 	 * Leave most things as they were; users must change things if
943 	 * the previous process didn't leave it they way they wanted.
944 	 * Looked at another way, it's easy to set up a configuration
945 	 * in one program and leave it for another to inherit.
946 	 */
947 	DPRINTF(("sbdsp_open: opened\n"));
948 
949 	return 0;
950 }
951 
952 void
953 sbdsp_close(addr)
954 	void *addr;
955 {
956 	struct sbdsp_softc *sc = addr;
957 
958         DPRINTF(("sbdsp_close: sc=%p\n", sc));
959 
960 	sc->sc_open = SB_CLOSED;
961 	sbdsp_spkroff(sc);
962 	sc->spkr_state = SPKR_OFF;
963 	sc->sc_intr8 = 0;
964 	sc->sc_intr16 = 0;
965 	sc->sc_intrm = 0;
966 	sbdsp_haltdma(sc);
967 
968 	DPRINTF(("sbdsp_close: closed\n"));
969 }
970 
971 /*
972  * Lower-level routines
973  */
974 
975 /*
976  * Reset the card.
977  * Return non-zero if the card isn't detected.
978  */
979 int
980 sbdsp_reset(sc)
981 	struct sbdsp_softc *sc;
982 {
983 	bus_space_tag_t iot = sc->sc_iot;
984 	bus_space_handle_t ioh = sc->sc_ioh;
985 
986 	sc->sc_intr8 = 0;
987 	sc->sc_intr16 = 0;
988 	if (sc->sc_i.run != SB_NOTRUNNING) {
989 		isa_dmaabort(sc->sc_isa, sc->sc_i.dmachan);
990 		sc->sc_i.run = SB_NOTRUNNING;
991 	}
992 	if (sc->sc_o.run != SB_NOTRUNNING) {
993 		isa_dmaabort(sc->sc_isa, sc->sc_o.dmachan);
994 		sc->sc_o.run = SB_NOTRUNNING;
995 	}
996 
997 	/*
998 	 * See SBK, section 11.3.
999 	 * We pulse a reset signal into the card.
1000 	 * Gee, what a brilliant hardware design.
1001 	 */
1002 	bus_space_write_1(iot, ioh, SBP_DSP_RESET, 1);
1003 	delay(10);
1004 	bus_space_write_1(iot, ioh, SBP_DSP_RESET, 0);
1005 	delay(30);
1006 	if (sbdsp_rdsp(sc) != SB_MAGIC)
1007 		return -1;
1008 
1009 	return 0;
1010 }
1011 
1012 /*
1013  * Write a byte to the dsp.
1014  * We are at the mercy of the card as we use a
1015  * polling loop and wait until it can take the byte.
1016  */
1017 int
1018 sbdsp_wdsp(sc, v)
1019 	struct sbdsp_softc *sc;
1020 	int v;
1021 {
1022 	bus_space_tag_t iot = sc->sc_iot;
1023 	bus_space_handle_t ioh = sc->sc_ioh;
1024 	int i;
1025 	u_char x;
1026 
1027 	for (i = SBDSP_NPOLL; --i >= 0; ) {
1028 		x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
1029 		delay(10);
1030 		if ((x & SB_DSP_BUSY) == 0) {
1031 			bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
1032 			delay(10);
1033 			return 0;
1034 		}
1035 	}
1036 	++sberr.wdsp;
1037 	return -1;
1038 }
1039 
1040 /*
1041  * Read a byte from the DSP, using polling.
1042  */
1043 int
1044 sbdsp_rdsp(sc)
1045 	struct sbdsp_softc *sc;
1046 {
1047 	bus_space_tag_t iot = sc->sc_iot;
1048 	bus_space_handle_t ioh = sc->sc_ioh;
1049 	int i;
1050 	u_char x;
1051 
1052 	for (i = SBDSP_NPOLL; --i >= 0; ) {
1053 		x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
1054 		delay(10);
1055 		if (x & SB_DSP_READY) {
1056 			x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
1057 			delay(10);
1058 			return x;
1059 		}
1060 	}
1061 	++sberr.rdsp;
1062 	return -1;
1063 }
1064 
1065 /*
1066  * Doing certain things (like toggling the speaker) make
1067  * the SB hardware go away for a while, so pause a little.
1068  */
1069 void
1070 sbdsp_to(arg)
1071 	void *arg;
1072 {
1073 	wakeup(arg);
1074 }
1075 
1076 void
1077 sbdsp_pause(sc)
1078 	struct sbdsp_softc *sc;
1079 {
1080 	timeout_add_msec(&sc->sc_tmo, 125);	/* 8x per second */
1081 	(void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
1082 }
1083 
1084 /*
1085  * Turn on the speaker.  The SBK documention says this operation
1086  * can take up to 1/10 of a second.  Higher level layers should
1087  * probably let the task sleep for this amount of time after
1088  * calling here.  Otherwise, things might not work (because
1089  * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
1090  *
1091  * These engineers had their heads up their ass when
1092  * they designed this card.
1093  */
1094 void
1095 sbdsp_spkron(sc)
1096 	struct sbdsp_softc *sc;
1097 {
1098 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
1099 	sbdsp_pause(sc);
1100 }
1101 
1102 /*
1103  * Turn off the speaker; see comment above.
1104  */
1105 void
1106 sbdsp_spkroff(sc)
1107 	struct sbdsp_softc *sc;
1108 {
1109 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
1110 	sbdsp_pause(sc);
1111 }
1112 
1113 /*
1114  * Read the version number out of the card.
1115  * Store version information in the softc.
1116  */
1117 void
1118 sbversion(sc)
1119 	struct sbdsp_softc *sc;
1120 {
1121 	int v;
1122 
1123 	sc->sc_model = SB_UNK;
1124 	sc->sc_version = 0;
1125 	if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
1126 		return;
1127 	v = sbdsp_rdsp(sc) << 8;
1128 	v |= sbdsp_rdsp(sc);
1129 	if (v < 0)
1130 		return;
1131 	sc->sc_version = v;
1132 	switch(SBVER_MAJOR(v)) {
1133 	case 1:
1134 		sc->sc_mixer_model = SBM_NONE;
1135 		sc->sc_model = SB_1;
1136 		break;
1137 	case 2:
1138 		/* Some SB2 have a mixer, some don't. */
1139 		sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
1140 		sbdsp_mix_write(sc, SBP_1335_MIDI_VOL,   0x06);
1141 		/* Check if we can read back the mixer values. */
1142 		if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
1143 		    (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL)   & 0x0e) == 0x06)
1144 			sc->sc_mixer_model = SBM_CT1335;
1145 		else
1146 			sc->sc_mixer_model = SBM_NONE;
1147 		if (SBVER_MINOR(v) == 0)
1148 			sc->sc_model = SB_20;
1149 		else
1150 			sc->sc_model = SB_2x;
1151 		break;
1152 	case 3:
1153 		sc->sc_mixer_model = SBM_CT1345;
1154 		sc->sc_model = SB_PRO;
1155 		break;
1156 	case 4:
1157 #if 0
1158 /* XXX This does not work */
1159 		/* Most SB16 have a tone controls, but some don't. */
1160 		sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
1161 		/* Check if we can read back the mixer value. */
1162 		if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
1163 			sc->sc_mixer_model = SBM_CT1745;
1164 		else
1165 			sc->sc_mixer_model = SBM_CT1XX5;
1166 #else
1167 		sc->sc_mixer_model = SBM_CT1745;
1168 #endif
1169 #if 0
1170 /* XXX figure out a good way of determining the model */
1171 		/* XXX what about SB_32 */
1172 		if (SBVER_MINOR(v) == 16)
1173 			sc->sc_model = SB_64;
1174 		else
1175 #endif
1176 			sc->sc_model = SB_16;
1177 		break;
1178 	}
1179 }
1180 
1181 /*
1182  * Halt a DMA in progress.
1183  */
1184 int
1185 sbdsp_haltdma(addr)
1186 	void *addr;
1187 {
1188 	struct sbdsp_softc *sc = addr;
1189 
1190 	DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
1191 
1192 	mtx_enter(&audio_lock);
1193 	sbdsp_reset(sc);
1194 	mtx_leave(&audio_lock);
1195 	return 0;
1196 }
1197 
1198 int
1199 sbdsp_set_timeconst(sc, tc)
1200 	struct sbdsp_softc *sc;
1201 	int tc;
1202 {
1203 	DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
1204 
1205 	if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
1206 	    sbdsp_wdsp(sc, tc) < 0)
1207 		return EIO;
1208 
1209 	return 0;
1210 }
1211 
1212 int
1213 sbdsp16_set_rate(sc, cmd, rate)
1214 	struct sbdsp_softc *sc;
1215 	int cmd, rate;
1216 {
1217 	DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
1218 
1219 	if (sbdsp_wdsp(sc, cmd) < 0 ||
1220 	    sbdsp_wdsp(sc, rate >> 8) < 0 ||
1221 	    sbdsp_wdsp(sc, rate) < 0)
1222 		return EIO;
1223 	return 0;
1224 }
1225 
1226 int
1227 sbdsp_trigger_input(addr, start, end, blksize, intr, arg, param)
1228 	void *addr;
1229 	void *start, *end;
1230 	int blksize;
1231 	void (*intr)(void *);
1232 	void *arg;
1233 	struct audio_params *param;
1234 {
1235 	struct sbdsp_softc *sc = addr;
1236 	int stereo = param->channels == 2;
1237 	int width = param->precision * param->factor;
1238 	int filter;
1239 	int rc;
1240 
1241 #ifdef DIAGNOSTIC
1242 	if (stereo && (blksize & 1)) {
1243 		DPRINTF(("stereo record odd bytes (%d)\n", blksize));
1244 		return (EIO);
1245 	}
1246 #endif
1247 
1248 	sc->sc_intrr = intr;
1249 	sc->sc_argr = arg;
1250 
1251 	if (width == 8) {
1252 #ifdef DIAGNOSTIC
1253 		if (sc->sc_i.dmachan != sc->sc_drq8) {
1254 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1255 			    width, sc->sc_i.dmachan);
1256 			return (EIO);
1257 		}
1258 #endif
1259 		sc->sc_intr8 = sbdsp_block_input;
1260 		sc->sc_arg8 = addr;
1261 	} else {
1262 #ifdef DIAGNOSTIC
1263 		if (sc->sc_i.dmachan != sc->sc_drq16) {
1264 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1265 			    width, sc->sc_i.dmachan);
1266 			return (EIO);
1267 		}
1268 #endif
1269 		sc->sc_intr16 = sbdsp_block_input;
1270 		sc->sc_arg16 = addr;
1271 	}
1272 
1273 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
1274 		blksize >>= 1;
1275 	--blksize;
1276 	sc->sc_i.blksize = blksize;
1277 
1278 	if (ISSBPRO(sc)) {
1279 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
1280 			return (EIO);
1281 		filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
1282 		sbdsp_mix_write(sc, SBP_INFILTER,
1283 		    (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
1284 		    filter);
1285 	}
1286 
1287 	if (ISSB16CLASS(sc)) {
1288 		if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
1289 			DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
1290 				 sc->sc_i.rate));
1291 			return (EIO);
1292 		}
1293 	} else {
1294 		if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
1295 			DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
1296 				 sc->sc_i.rate));
1297 			return (EIO);
1298 		}
1299 	}
1300 
1301 	DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
1302 	    start, end, sc->sc_i.dmachan));
1303 	mtx_enter(&audio_lock);
1304 	isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, start, (char *)end -
1305 	    (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1306 	rc = sbdsp_block_input(addr);
1307 	mtx_leave(&audio_lock);
1308 	return rc;
1309 }
1310 
1311 int
1312 sbdsp_block_input(addr)
1313 	void *addr;
1314 {
1315 	struct sbdsp_softc *sc = addr;
1316 	int cc = sc->sc_i.blksize;
1317 
1318 	DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
1319 
1320 	if (sc->sc_i.run != SB_NOTRUNNING)
1321 		sc->sc_intrr(sc->sc_argr);
1322 
1323 	if (sc->sc_model == SB_1) {
1324 		/* Non-looping mode, start DMA */
1325 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1326 		    sbdsp_wdsp(sc, cc) < 0 ||
1327 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1328 			DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
1329 			return (EIO);
1330 		}
1331 		sc->sc_i.run = SB_RUNNING;
1332 	} else if (sc->sc_i.run == SB_NOTRUNNING) {
1333 		/* Initialize looping PCM */
1334 		if (ISSB16CLASS(sc)) {
1335 			DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
1336 			    sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
1337 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1338 			    sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
1339 			    sbdsp_wdsp(sc, cc) < 0 ||
1340 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1341 				DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
1342 				return (EIO);
1343 			}
1344 		} else {
1345 			DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc));
1346 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1347 			    sbdsp_wdsp(sc, cc) < 0 ||
1348 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1349 				DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
1350 				return (EIO);
1351 			}
1352 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
1353 				DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
1354 				return (EIO);
1355 			}
1356 		}
1357 		sc->sc_i.run = SB_LOOPING;
1358 	}
1359 
1360 	return (0);
1361 }
1362 
1363 int
1364 sbdsp_trigger_output(addr, start, end, blksize, intr, arg, param)
1365 	void *addr;
1366 	void *start, *end;
1367 	int blksize;
1368 	void (*intr)(void *);
1369 	void *arg;
1370 	struct audio_params *param;
1371 {
1372 	struct sbdsp_softc *sc = addr;
1373 	int stereo = param->channels == 2;
1374 	int width = param->precision * param->factor;
1375 	int cmd;
1376 	int rc;
1377 
1378 #ifdef DIAGNOSTIC
1379 	if (stereo && (blksize & 1)) {
1380 		DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
1381 		return (EIO);
1382 	}
1383 #endif
1384 
1385 	sc->sc_intrp = intr;
1386 	sc->sc_argp = arg;
1387 
1388 	if (width == 8) {
1389 #ifdef DIAGNOSTIC
1390 		if (sc->sc_o.dmachan != sc->sc_drq8) {
1391 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1392 			    width, sc->sc_o.dmachan);
1393 			return (EIO);
1394 		}
1395 #endif
1396 		sc->sc_intr8 = sbdsp_block_output;
1397 		sc->sc_arg8 = addr;
1398 	} else {
1399 #ifdef DIAGNOSTIC
1400 		if (sc->sc_o.dmachan != sc->sc_drq16) {
1401 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1402 			    width, sc->sc_o.dmachan);
1403 			return (EIO);
1404 		}
1405 #endif
1406 		sc->sc_intr16 = sbdsp_block_output;
1407 		sc->sc_arg16 = addr;
1408 	}
1409 
1410 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
1411 		blksize >>= 1;
1412 	--blksize;
1413 	sc->sc_o.blksize = blksize;
1414 
1415 	if (ISSBPRO(sc)) {
1416 		/* make sure we re-set stereo mixer bit when we start output. */
1417 		sbdsp_mix_write(sc, SBP_STEREO,
1418 		    (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1419 		    (stereo ?  SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1420 		cmd = sc->sc_o.modep->cmdchan;
1421 		if (cmd && sbdsp_wdsp(sc, cmd) < 0)
1422 			return (EIO);
1423 	}
1424 
1425 	if (ISSB16CLASS(sc)) {
1426 		if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
1427 			DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
1428 				 sc->sc_o.rate));
1429 			return (EIO);
1430 		}
1431 	} else {
1432 		if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
1433 			DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
1434 				 sc->sc_o.rate));
1435 			return (EIO);
1436 		}
1437 	}
1438 
1439 	DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
1440 	    start, end, sc->sc_o.dmachan));
1441 	mtx_enter(&audio_lock);
1442 	isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, start, (char *)end -
1443 	    (char *)start, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1444 	rc = sbdsp_block_output(addr);
1445 	mtx_leave(&audio_lock);
1446 	return rc;
1447 }
1448 
1449 int
1450 sbdsp_block_output(addr)
1451 	void *addr;
1452 {
1453 	struct sbdsp_softc *sc = addr;
1454 	int cc = sc->sc_o.blksize;
1455 
1456 	DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
1457 
1458 	if (sc->sc_o.run != SB_NOTRUNNING)
1459 		sc->sc_intrp(sc->sc_argp);
1460 
1461 	if (sc->sc_model == SB_1) {
1462 		/* Non-looping mode, initialized. Start DMA and PCM */
1463 		if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1464 		    sbdsp_wdsp(sc, cc) < 0 ||
1465 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1466 			DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
1467 			return (EIO);
1468 		}
1469 		sc->sc_o.run = SB_RUNNING;
1470 	} else if (sc->sc_o.run == SB_NOTRUNNING) {
1471 		/* Initialize looping PCM */
1472 		if (ISSB16CLASS(sc)) {
1473 			DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
1474 			    sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
1475 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1476 			    sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
1477 			    sbdsp_wdsp(sc, cc) < 0 ||
1478 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1479 				DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
1480 				return (EIO);
1481 			}
1482 		} else {
1483 			DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc));
1484 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1485 			    sbdsp_wdsp(sc, cc) < 0 ||
1486 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1487 				DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
1488 				return (EIO);
1489 			}
1490 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
1491 				DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
1492 				return (EIO);
1493 			}
1494 		}
1495 		sc->sc_o.run = SB_LOOPING;
1496 	}
1497 
1498 	return (0);
1499 }
1500 
1501 /*
1502  * Only the DSP unit on the sound blaster generates interrupts.
1503  * There are three cases of interrupt: reception of a midi byte
1504  * (when mode is enabled), completion of dma transmission, or
1505  * completion of a dma reception.
1506  *
1507  * If there is interrupt sharing or a spurious interrupt occurs
1508  * there is no way to distinguish this on an SB2.  So if you have
1509  * an SB2 and experience problems, buy an SB16 (it's only $40).
1510  */
1511 int
1512 sbdsp_intr(arg)
1513 	void *arg;
1514 {
1515 	struct sbdsp_softc *sc = arg;
1516 	u_char irq;
1517 
1518 	mtx_enter(&audio_lock);
1519 	DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
1520 		   sc->sc_intr8, sc->sc_intr16));
1521 	if (ISSB16CLASS(sc)) {
1522 		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1523 		    SBP_MIXER_ADDR, SBP_IRQ_STATUS);
1524 		delay(20);
1525 		irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1526 		    SBP_MIXER_DATA);
1527 		delay(30);
1528 		if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 0) {
1529 			DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
1530 			mtx_leave(&audio_lock);
1531 			return 0;
1532 		}
1533 	} else {
1534 		/* XXXX CHECK FOR INTERRUPT */
1535 		irq = SBP_IRQ_DMA8;
1536 	}
1537 
1538 	sc->sc_interrupts++;
1539 	delay(10);		/* XXX why? */
1540 
1541 	/* clear interrupt */
1542 	if (irq & SBP_IRQ_DMA8) {
1543 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
1544 		if (sc->sc_intr8)
1545 			sc->sc_intr8(sc->sc_arg8);
1546 	}
1547 	if (irq & SBP_IRQ_DMA16) {
1548 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
1549 		if (sc->sc_intr16)
1550 			sc->sc_intr16(sc->sc_arg16);
1551 	}
1552 #if NMIDI > 0
1553 	if ((irq & SBP_IRQ_MPU401) && sc->sc_hasmpu) {
1554 		mpu_intr(&sc->sc_mpu_sc);
1555 	}
1556 #endif
1557 	mtx_leave(&audio_lock);
1558 	return 1;
1559 }
1560 
1561 /* Like val & mask, but make sure the result is correctly rounded. */
1562 #define MAXVAL 256
1563 static int
1564 sbdsp_adjust(val, mask)
1565 	int val, mask;
1566 {
1567 	val += (MAXVAL - mask) >> 1;
1568 	if (val >= MAXVAL)
1569 		val = MAXVAL-1;
1570 	return val & mask;
1571 }
1572 
1573 void
1574 sbdsp_set_mixer_gain(sc, port)
1575 	struct sbdsp_softc *sc;
1576 	int port;
1577 {
1578 	int src, gain;
1579 
1580 	switch(sc->sc_mixer_model) {
1581 	case SBM_NONE:
1582 		return;
1583 	case SBM_CT1335:
1584 		gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
1585 		switch(port) {
1586 		case SB_MASTER_VOL:
1587 			src = SBP_1335_MASTER_VOL;
1588 			break;
1589 		case SB_MIDI_VOL:
1590 			src = SBP_1335_MIDI_VOL;
1591 			break;
1592 		case SB_CD_VOL:
1593 			src = SBP_1335_CD_VOL;
1594 			break;
1595 		case SB_VOICE_VOL:
1596 			src = SBP_1335_VOICE_VOL;
1597 			gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
1598 			break;
1599 		default:
1600 			return;
1601 		}
1602 		sbdsp_mix_write(sc, src, gain);
1603 		break;
1604 	case SBM_CT1345:
1605 		gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
1606 				      sc->gain[port][SB_RIGHT]);
1607 		switch (port) {
1608 		case SB_MIC_VOL:
1609 			src = SBP_MIC_VOL;
1610 			gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
1611 			break;
1612 		case SB_MASTER_VOL:
1613 			src = SBP_MASTER_VOL;
1614 			break;
1615 		case SB_LINE_IN_VOL:
1616 			src = SBP_LINE_VOL;
1617 			break;
1618 		case SB_VOICE_VOL:
1619 			src = SBP_VOICE_VOL;
1620 			break;
1621 		case SB_MIDI_VOL:
1622 			src = SBP_MIDI_VOL;
1623 			break;
1624 		case SB_CD_VOL:
1625 			src = SBP_CD_VOL;
1626 			break;
1627 		default:
1628 			return;
1629 		}
1630 		sbdsp_mix_write(sc, src, gain);
1631 		break;
1632 	case SBM_CT1XX5:
1633 	case SBM_CT1745:
1634 		switch (port) {
1635 		case SB_MIC_VOL:
1636 			src = SB16P_MIC_L;
1637 			break;
1638 		case SB_MASTER_VOL:
1639 			src = SB16P_MASTER_L;
1640 			break;
1641 		case SB_LINE_IN_VOL:
1642 			src = SB16P_LINE_L;
1643 			break;
1644 		case SB_VOICE_VOL:
1645 			src = SB16P_VOICE_L;
1646 			break;
1647 		case SB_MIDI_VOL:
1648 			src = SB16P_MIDI_L;
1649 			break;
1650 		case SB_CD_VOL:
1651 			src = SB16P_CD_L;
1652 			break;
1653 		case SB_INPUT_GAIN:
1654 			src = SB16P_INPUT_GAIN_L;
1655 			break;
1656 		case SB_OUTPUT_GAIN:
1657 			src = SB16P_OUTPUT_GAIN_L;
1658 			break;
1659 		case SB_TREBLE:
1660 			src = SB16P_TREBLE_L;
1661 			break;
1662 		case SB_BASS:
1663 			src = SB16P_BASS_L;
1664 			break;
1665 		case SB_PCSPEAKER:
1666 			sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
1667 			return;
1668 		default:
1669 			return;
1670 		}
1671 		sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
1672 		sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
1673 		break;
1674 	}
1675 }
1676 
1677 int
1678 sbdsp_mixer_set_port(addr, cp)
1679 	void *addr;
1680 	mixer_ctrl_t *cp;
1681 {
1682 	struct sbdsp_softc *sc = addr;
1683 	int lgain, rgain;
1684 	int mask, bits;
1685 	int lmask, rmask, lbits, rbits;
1686 	int mute, swap;
1687 
1688 	if (sc->sc_open == SB_OPEN_MIDI)
1689 		return EBUSY;
1690 
1691 	DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
1692 	    cp->un.value.num_channels));
1693 
1694 	if (sc->sc_mixer_model == SBM_NONE)
1695 		return EINVAL;
1696 
1697 	switch (cp->dev) {
1698 	case SB_TREBLE:
1699 	case SB_BASS:
1700 		if (sc->sc_mixer_model == SBM_CT1345 ||
1701                     sc->sc_mixer_model == SBM_CT1XX5) {
1702 			if (cp->type != AUDIO_MIXER_ENUM)
1703 				return EINVAL;
1704 			switch (cp->dev) {
1705 			case SB_TREBLE:
1706 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
1707 				return 0;
1708 			case SB_BASS:
1709 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
1710 				return 0;
1711 			}
1712 		}
1713 	case SB_PCSPEAKER:
1714 	case SB_INPUT_GAIN:
1715 	case SB_OUTPUT_GAIN:
1716 		if (!ISSBM1745(sc))
1717 			return EINVAL;
1718 	case SB_MIC_VOL:
1719 	case SB_LINE_IN_VOL:
1720 		if (sc->sc_mixer_model == SBM_CT1335)
1721 			return EINVAL;
1722 	case SB_VOICE_VOL:
1723 	case SB_MIDI_VOL:
1724 	case SB_CD_VOL:
1725 	case SB_MASTER_VOL:
1726 		if (cp->type != AUDIO_MIXER_VALUE)
1727 			return EINVAL;
1728 
1729 		/*
1730 		 * All the mixer ports are stereo except for the microphone.
1731 		 * If we get a single-channel gain value passed in, then we
1732 		 * duplicate it to both left and right channels.
1733 		 */
1734 
1735 		switch (cp->dev) {
1736 		case SB_MIC_VOL:
1737 			if (cp->un.value.num_channels != 1)
1738 				return EINVAL;
1739 
1740 			lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
1741 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1742 			break;
1743 		case SB_PCSPEAKER:
1744 			if (cp->un.value.num_channels != 1)
1745 				return EINVAL;
1746 			/* fall into */
1747 		case SB_INPUT_GAIN:
1748 		case SB_OUTPUT_GAIN:
1749 			lgain = rgain = SB_ADJUST_2_GAIN(sc,
1750 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1751 			break;
1752 		default:
1753 			switch (cp->un.value.num_channels) {
1754 			case 1:
1755 				lgain = rgain = SB_ADJUST_GAIN(sc,
1756 				  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1757 				break;
1758 			case 2:
1759 				if (sc->sc_mixer_model == SBM_CT1335)
1760 					return EINVAL;
1761 				lgain = SB_ADJUST_GAIN(sc,
1762 				  cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1763 				rgain = SB_ADJUST_GAIN(sc,
1764 				  cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1765 				break;
1766 			default:
1767 				return EINVAL;
1768 			}
1769 			break;
1770 		}
1771 		sc->gain[cp->dev][SB_LEFT]  = lgain;
1772 		sc->gain[cp->dev][SB_RIGHT] = rgain;
1773 
1774 		sbdsp_set_mixer_gain(sc, cp->dev);
1775 		break;
1776 
1777 	case SB_RECORD_SOURCE:
1778 		if (ISSBM1745(sc)) {
1779 			if (cp->type != AUDIO_MIXER_SET)
1780 				return EINVAL;
1781 			return sbdsp_set_in_ports(sc, cp->un.mask);
1782 		} else {
1783 			if (cp->type != AUDIO_MIXER_ENUM)
1784 				return EINVAL;
1785 			sc->in_port = cp->un.ord;
1786 			return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
1787 		}
1788 		break;
1789 
1790 	case SB_AGC:
1791 		if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
1792 			return EINVAL;
1793 		sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
1794 		break;
1795 
1796 	case SB_CD_OUT_MUTE:
1797 		mask = SB16P_SW_CD;
1798 		goto omute;
1799 	case SB_MIC_OUT_MUTE:
1800 		mask = SB16P_SW_MIC;
1801 		goto omute;
1802 	case SB_LINE_OUT_MUTE:
1803 		mask = SB16P_SW_LINE;
1804 	omute:
1805 		if (cp->type != AUDIO_MIXER_ENUM)
1806 			return EINVAL;
1807 		bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
1808 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1809 		if (cp->un.ord)
1810 			bits = bits & ~mask;
1811 		else
1812 			bits = bits | mask;
1813 		sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
1814 		break;
1815 
1816 	case SB_MIC_IN_MUTE:
1817 	case SB_MIC_SWAP:
1818 		lmask = rmask = SB16P_SW_MIC;
1819 		goto imute;
1820 	case SB_CD_IN_MUTE:
1821 	case SB_CD_SWAP:
1822 		lmask = SB16P_SW_CD_L;
1823 		rmask = SB16P_SW_CD_R;
1824 		goto imute;
1825 	case SB_LINE_IN_MUTE:
1826 	case SB_LINE_SWAP:
1827 		lmask = SB16P_SW_LINE_L;
1828 		rmask = SB16P_SW_LINE_R;
1829 		goto imute;
1830 	case SB_MIDI_IN_MUTE:
1831 	case SB_MIDI_SWAP:
1832 		lmask = SB16P_SW_MIDI_L;
1833 		rmask = SB16P_SW_MIDI_R;
1834 	imute:
1835 		if (cp->type != AUDIO_MIXER_ENUM)
1836 			return EINVAL;
1837 		mask = lmask | rmask;
1838 		lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
1839 		rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
1840 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1841 		if (SB_IS_IN_MUTE(cp->dev)) {
1842 			mute = cp->dev;
1843 			swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
1844 		} else {
1845 			swap = cp->dev;
1846 			mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
1847 		}
1848 		if (sc->gain[swap][SB_LR]) {
1849 			mask = lmask;
1850 			lmask = rmask;
1851 			rmask = mask;
1852 		}
1853 		if (!sc->gain[mute][SB_LR]) {
1854 			lbits = lbits | lmask;
1855 			rbits = rbits | rmask;
1856 		}
1857 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
1858 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
1859 		break;
1860 
1861 	default:
1862 		return EINVAL;
1863 	}
1864 
1865 	return 0;
1866 }
1867 
1868 int
1869 sbdsp_mixer_get_port(addr, cp)
1870 	void *addr;
1871 	mixer_ctrl_t *cp;
1872 {
1873 	struct sbdsp_softc *sc = addr;
1874 
1875 	if (sc->sc_open == SB_OPEN_MIDI)
1876 		return EBUSY;
1877 
1878 	DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
1879 
1880 	if (sc->sc_mixer_model == SBM_NONE)
1881 		return EINVAL;
1882 
1883 	switch (cp->dev) {
1884 	case SB_TREBLE:
1885 	case SB_BASS:
1886 		if (sc->sc_mixer_model == SBM_CT1345 ||
1887                     sc->sc_mixer_model == SBM_CT1XX5) {
1888 			switch (cp->dev) {
1889 			case SB_TREBLE:
1890 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
1891 				return 0;
1892 			case SB_BASS:
1893 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
1894 				return 0;
1895 			}
1896 		}
1897 	case SB_PCSPEAKER:
1898 	case SB_INPUT_GAIN:
1899 	case SB_OUTPUT_GAIN:
1900 		if (!ISSBM1745(sc))
1901 			return EINVAL;
1902 	case SB_MIC_VOL:
1903 	case SB_LINE_IN_VOL:
1904 		if (sc->sc_mixer_model == SBM_CT1335)
1905 			return EINVAL;
1906 	case SB_VOICE_VOL:
1907 	case SB_MIDI_VOL:
1908 	case SB_CD_VOL:
1909 	case SB_MASTER_VOL:
1910 		switch (cp->dev) {
1911 		case SB_MIC_VOL:
1912 		case SB_PCSPEAKER:
1913 			if (cp->un.value.num_channels != 1)
1914 				return EINVAL;
1915 			/* fall into */
1916 		default:
1917 			switch (cp->un.value.num_channels) {
1918 			case 1:
1919 				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1920 					sc->gain[cp->dev][SB_LEFT];
1921 				break;
1922 			case 2:
1923 				cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1924 					sc->gain[cp->dev][SB_LEFT];
1925 				cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1926 					sc->gain[cp->dev][SB_RIGHT];
1927 				break;
1928 			default:
1929 				return EINVAL;
1930 			}
1931 			break;
1932 		}
1933 		break;
1934 
1935 	case SB_RECORD_SOURCE:
1936 		if (ISSBM1745(sc))
1937 			cp->un.mask = sc->in_mask;
1938 		else
1939 			cp->un.ord = sc->in_port;
1940 		break;
1941 
1942 	case SB_AGC:
1943 		if (!ISSBM1745(sc))
1944 			return EINVAL;
1945 		cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
1946 		break;
1947 
1948 	case SB_CD_IN_MUTE:
1949 	case SB_MIC_IN_MUTE:
1950 	case SB_LINE_IN_MUTE:
1951 	case SB_MIDI_IN_MUTE:
1952 	case SB_CD_SWAP:
1953 	case SB_MIC_SWAP:
1954 	case SB_LINE_SWAP:
1955 	case SB_MIDI_SWAP:
1956 	case SB_CD_OUT_MUTE:
1957 	case SB_MIC_OUT_MUTE:
1958 	case SB_LINE_OUT_MUTE:
1959 		cp->un.ord = sc->gain[cp->dev][SB_LR];
1960 		break;
1961 
1962 	default:
1963 		return EINVAL;
1964 	}
1965 
1966 	return 0;
1967 }
1968 
1969 int
1970 sbdsp_mixer_query_devinfo(addr, dip)
1971 	void *addr;
1972 	mixer_devinfo_t *dip;
1973 {
1974 	struct sbdsp_softc *sc = addr;
1975 	int chan, class, is1745;
1976 
1977 	DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1978 		 sc->sc_mixer_model, dip->index));
1979 
1980 	if (dip->index < 0)
1981 		return ENXIO;
1982 
1983 	if (sc->sc_mixer_model == SBM_NONE)
1984 		return ENXIO;
1985 
1986 	chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
1987 	is1745 = ISSBM1745(sc);
1988 	class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
1989 
1990 	switch (dip->index) {
1991 	case SB_MASTER_VOL:
1992 		dip->type = AUDIO_MIXER_VALUE;
1993 		dip->mixer_class = SB_OUTPUT_CLASS;
1994 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1995 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1996 		dip->un.v.num_channels = chan;
1997 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1998 		return 0;
1999 	case SB_MIDI_VOL:
2000 		dip->type = AUDIO_MIXER_VALUE;
2001 		dip->mixer_class = class;
2002 		dip->prev = AUDIO_MIXER_LAST;
2003 		dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
2004 		strlcpy(dip->label.name, AudioNfmsynth, sizeof dip->label.name);
2005 		dip->un.v.num_channels = chan;
2006 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2007 		return 0;
2008 	case SB_CD_VOL:
2009 		dip->type = AUDIO_MIXER_VALUE;
2010 		dip->mixer_class = class;
2011 		dip->prev = AUDIO_MIXER_LAST;
2012 		dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
2013 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
2014 		dip->un.v.num_channels = chan;
2015 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2016 		return 0;
2017 	case SB_VOICE_VOL:
2018 		dip->type = AUDIO_MIXER_VALUE;
2019 		dip->mixer_class = class;
2020 		dip->prev = AUDIO_MIXER_LAST;
2021 		dip->next = AUDIO_MIXER_LAST;
2022 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
2023 		dip->un.v.num_channels = chan;
2024 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2025 		return 0;
2026 	case SB_OUTPUT_CLASS:
2027 		dip->type = AUDIO_MIXER_CLASS;
2028 		dip->mixer_class = SB_OUTPUT_CLASS;
2029 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2030 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
2031 		return 0;
2032 	}
2033 
2034 	if (sc->sc_mixer_model == SBM_CT1335)
2035 		return ENXIO;
2036 
2037 	switch (dip->index) {
2038 	case SB_MIC_VOL:
2039 		dip->type = AUDIO_MIXER_VALUE;
2040 		dip->mixer_class = class;
2041 		dip->prev = AUDIO_MIXER_LAST;
2042 		dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
2043 		strlcpy(dip->label.name, AudioNmicrophone,
2044 		    sizeof dip->label.name);
2045 		dip->un.v.num_channels = 1;
2046 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2047 		return 0;
2048 
2049 	case SB_LINE_IN_VOL:
2050 		dip->type = AUDIO_MIXER_VALUE;
2051 		dip->mixer_class = class;
2052 		dip->prev = AUDIO_MIXER_LAST;
2053 		dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
2054 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
2055 		dip->un.v.num_channels = 2;
2056 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2057 		return 0;
2058 
2059 	case SB_RECORD_SOURCE:
2060 		dip->mixer_class = SB_RECORD_CLASS;
2061 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2062 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
2063 		if (ISSBM1745(sc)) {
2064 			dip->type = AUDIO_MIXER_SET;
2065 			dip->un.s.num_mem = 4;
2066 			strlcpy(dip->un.s.member[0].label.name,
2067 			    AudioNmicrophone,
2068 			    sizeof dip->un.s.member[0].label.name);
2069 			dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
2070 			strlcpy(dip->un.s.member[1].label.name,
2071 			    AudioNcd, sizeof dip->un.s.member[1].label.name);
2072 			dip->un.s.member[1].mask = 1 << SB_CD_VOL;
2073 			strlcpy(dip->un.s.member[2].label.name,
2074 			    AudioNline, sizeof dip->un.s.member[2].label.name);
2075 			dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
2076 			strlcpy(dip->un.s.member[3].label.name,
2077 			    AudioNfmsynth,
2078 			    sizeof dip->un.s.member[3].label.name);
2079 			dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
2080 		} else {
2081 			dip->type = AUDIO_MIXER_ENUM;
2082 			dip->un.e.num_mem = 3;
2083 			strlcpy(dip->un.e.member[0].label.name,
2084 			    AudioNmicrophone,
2085 			    sizeof dip->un.e.member[0].label.name);
2086 			dip->un.e.member[0].ord = SB_MIC_VOL;
2087 			strlcpy(dip->un.e.member[1].label.name, AudioNcd,
2088 			    sizeof dip->un.e.member[1].label.name);
2089 			dip->un.e.member[1].ord = SB_CD_VOL;
2090 			strlcpy(dip->un.e.member[2].label.name, AudioNline,
2091 			    sizeof dip->un.e.member[2].label.name);
2092 			dip->un.e.member[2].ord = SB_LINE_IN_VOL;
2093 		}
2094 		return 0;
2095 
2096 	case SB_BASS:
2097 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2098 		strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
2099 		if (sc->sc_mixer_model == SBM_CT1745) {
2100 			dip->type = AUDIO_MIXER_VALUE;
2101 			dip->mixer_class = SB_EQUALIZATION_CLASS;
2102 			dip->un.v.num_channels = 2;
2103 			strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
2104 		} else {
2105 			dip->type = AUDIO_MIXER_ENUM;
2106 			dip->mixer_class = SB_INPUT_CLASS;
2107 			dip->un.e.num_mem = 2;
2108 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2109 			    sizeof dip->un.e.member[0].label.name);
2110 			dip->un.e.member[0].ord = 0;
2111 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
2112 			    sizeof dip->un.e.member[1].label.name);
2113 			dip->un.e.member[1].ord = 1;
2114 		}
2115 		return 0;
2116 
2117 	case SB_TREBLE:
2118 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2119 		strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
2120 		if (sc->sc_mixer_model == SBM_CT1745) {
2121 			dip->type = AUDIO_MIXER_VALUE;
2122 			dip->mixer_class = SB_EQUALIZATION_CLASS;
2123 			dip->un.v.num_channels = 2;
2124 			strlcpy(dip->un.v.units.name, AudioNtreble, sizeof dip->un.v.units.name);
2125 		} else {
2126 			dip->type = AUDIO_MIXER_ENUM;
2127 			dip->mixer_class = SB_INPUT_CLASS;
2128 			dip->un.e.num_mem = 2;
2129 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2130 			    sizeof dip->un.e.member[0].label.name);
2131 			dip->un.e.member[0].ord = 0;
2132 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
2133 			    sizeof dip->un.e.member[1].label.name);
2134 			dip->un.e.member[1].ord = 1;
2135 		}
2136 		return 0;
2137 
2138 	case SB_RECORD_CLASS:			/* record source class */
2139 		dip->type = AUDIO_MIXER_CLASS;
2140 		dip->mixer_class = SB_RECORD_CLASS;
2141 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2142 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
2143 		return 0;
2144 
2145 	case SB_INPUT_CLASS:
2146 		dip->type = AUDIO_MIXER_CLASS;
2147 		dip->mixer_class = SB_INPUT_CLASS;
2148 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2149 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
2150 		return 0;
2151 
2152 	}
2153 
2154 	if (sc->sc_mixer_model == SBM_CT1345)
2155 		return ENXIO;
2156 
2157 	switch(dip->index) {
2158 	case SB_PCSPEAKER:
2159 		dip->type = AUDIO_MIXER_VALUE;
2160 		dip->mixer_class = SB_INPUT_CLASS;
2161 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2162 		strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
2163 		dip->un.v.num_channels = 1;
2164 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2165 		return 0;
2166 
2167 	case SB_INPUT_GAIN:
2168 		dip->type = AUDIO_MIXER_VALUE;
2169 		dip->mixer_class = SB_INPUT_CLASS;
2170 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2171 		strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
2172 		dip->un.v.num_channels = 2;
2173 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2174 		return 0;
2175 
2176 	case SB_OUTPUT_GAIN:
2177 		dip->type = AUDIO_MIXER_VALUE;
2178 		dip->mixer_class = SB_OUTPUT_CLASS;
2179 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2180 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
2181 		dip->un.v.num_channels = 2;
2182 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2183 		return 0;
2184 
2185 	case SB_AGC:
2186 		dip->type = AUDIO_MIXER_ENUM;
2187 		dip->mixer_class = SB_INPUT_CLASS;
2188 		dip->prev = dip->next = AUDIO_MIXER_LAST;
2189 		strlcpy(dip->label.name, "agc", sizeof dip->label.name);
2190 		dip->un.e.num_mem = 2;
2191 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2192 		    sizeof dip->un.e.member[0].label.name);
2193 		dip->un.e.member[0].ord = 0;
2194 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2195 		    sizeof dip->un.e.member[1].label.name);
2196 		dip->un.e.member[1].ord = 1;
2197 		return 0;
2198 
2199 	case SB_EQUALIZATION_CLASS:
2200 		dip->type = AUDIO_MIXER_CLASS;
2201 		dip->mixer_class = SB_EQUALIZATION_CLASS;
2202 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2203 		strlcpy(dip->label.name, AudioCequalization, sizeof dip->label.name);
2204 		return 0;
2205 
2206 	case SB_CD_IN_MUTE:
2207 		dip->prev = SB_CD_VOL;
2208 		dip->next = SB_CD_SWAP;
2209 		dip->mixer_class = SB_INPUT_CLASS;
2210 		goto mute;
2211 
2212 	case SB_MIC_IN_MUTE:
2213 		dip->prev = SB_MIC_VOL;
2214 		dip->next = SB_MIC_SWAP;
2215 		dip->mixer_class = SB_INPUT_CLASS;
2216 		goto mute;
2217 
2218 	case SB_LINE_IN_MUTE:
2219 		dip->prev = SB_LINE_IN_VOL;
2220 		dip->next = SB_LINE_SWAP;
2221 		dip->mixer_class = SB_INPUT_CLASS;
2222 		goto mute;
2223 
2224 	case SB_MIDI_IN_MUTE:
2225 		dip->prev = SB_MIDI_VOL;
2226 		dip->next = SB_MIDI_SWAP;
2227 		dip->mixer_class = SB_INPUT_CLASS;
2228 		goto mute;
2229 
2230 	case SB_CD_SWAP:
2231 		dip->prev = SB_CD_IN_MUTE;
2232 		dip->next = SB_CD_OUT_MUTE;
2233 		goto swap;
2234 
2235 	case SB_MIC_SWAP:
2236 		dip->prev = SB_MIC_IN_MUTE;
2237 		dip->next = SB_MIC_OUT_MUTE;
2238 		goto swap;
2239 
2240 	case SB_LINE_SWAP:
2241 		dip->prev = SB_LINE_IN_MUTE;
2242 		dip->next = SB_LINE_OUT_MUTE;
2243 		goto swap;
2244 
2245 	case SB_MIDI_SWAP:
2246 		dip->prev = SB_MIDI_IN_MUTE;
2247 		dip->next = AUDIO_MIXER_LAST;
2248 	swap:
2249 		dip->mixer_class = SB_INPUT_CLASS;
2250 		strlcpy(dip->label.name, AudioNswap, sizeof dip->label.name);
2251 		goto mute1;
2252 
2253 	case SB_CD_OUT_MUTE:
2254 		dip->prev = SB_CD_SWAP;
2255 		dip->next = AUDIO_MIXER_LAST;
2256 		dip->mixer_class = SB_OUTPUT_CLASS;
2257 		goto mute;
2258 
2259 	case SB_MIC_OUT_MUTE:
2260 		dip->prev = SB_MIC_SWAP;
2261 		dip->next = AUDIO_MIXER_LAST;
2262 		dip->mixer_class = SB_OUTPUT_CLASS;
2263 		goto mute;
2264 
2265 	case SB_LINE_OUT_MUTE:
2266 		dip->prev = SB_LINE_SWAP;
2267 		dip->next = AUDIO_MIXER_LAST;
2268 		dip->mixer_class = SB_OUTPUT_CLASS;
2269 	mute:
2270 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
2271 	mute1:
2272 		dip->type = AUDIO_MIXER_ENUM;
2273 		dip->un.e.num_mem = 2;
2274 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2275 		    sizeof dip->un.e.member[0].label.name);
2276 		dip->un.e.member[0].ord = 0;
2277 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2278 		    sizeof dip->un.e.member[1].label.name);
2279 		dip->un.e.member[1].ord = 1;
2280 		return 0;
2281 
2282 	}
2283 
2284 	return ENXIO;
2285 }
2286 
2287 void *
2288 sb_malloc(addr, direction, size, pool, flags)
2289 	void *addr;
2290 	int direction;
2291 	size_t size;
2292 	int pool;
2293 	int flags;
2294 {
2295 	struct sbdsp_softc *sc = addr;
2296 	int drq;
2297 
2298 	/* 8-bit has more restrictive alignment */
2299 	if (sc->sc_drq8 != -1)
2300 		drq = sc->sc_drq8;
2301 	else
2302 		drq = sc->sc_drq16;
2303 
2304 	return isa_malloc(sc->sc_isa, drq, size, pool, flags);
2305 }
2306 
2307 void
2308 sb_free(addr, ptr, pool)
2309 	void *addr;
2310 	void *ptr;
2311 	int pool;
2312 {
2313 	isa_free(ptr, pool);
2314 }
2315 
2316 size_t
2317 sb_round(addr, direction, size)
2318 	void *addr;
2319 	int direction;
2320 	size_t size;
2321 {
2322 	if (size > MAX_ISADMA)
2323 		size = MAX_ISADMA;
2324 	return size;
2325 }
2326 
2327 paddr_t
2328 sb_mappage(addr, mem, off, prot)
2329 	void *addr;
2330         void *mem;
2331         off_t off;
2332 	int prot;
2333 {
2334 	return isa_mappage(mem, off, prot);
2335 }
2336 
2337 int
2338 sbdsp_get_props(addr)
2339 	void *addr;
2340 {
2341 	struct sbdsp_softc *sc = addr;
2342 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
2343 	       (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
2344 }
2345 
2346 #if NMIDI > 0
2347 /*
2348  * MIDI related routines.
2349  */
2350 
2351 int
2352 sbdsp_midi_open(addr, flags, iintr, ointr, arg)
2353 	void *addr;
2354 	int flags;
2355 	void (*iintr)(void *, int);
2356 	void (*ointr)(void *);
2357 	void *arg;
2358 {
2359 	struct sbdsp_softc *sc = addr;
2360 
2361         DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
2362 
2363 	if (sc->sc_open != SB_CLOSED)
2364 		return EBUSY;
2365 	if (sbdsp_reset(sc) != 0)
2366 		return EIO;
2367 
2368 	if (sc->sc_model >= SB_20)
2369 		if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
2370 			return EIO;
2371 	sc->sc_open = SB_OPEN_MIDI;
2372 	sc->sc_openflags = flags;
2373 	sc->sc_intr8 = sbdsp_midi_intr;
2374 	sc->sc_arg8 = addr;
2375 	sc->sc_intrm = iintr;
2376 	sc->sc_argm = arg;
2377 	return 0;
2378 }
2379 
2380 void
2381 sbdsp_midi_close(addr)
2382 	void *addr;
2383 {
2384 	struct sbdsp_softc *sc = addr;
2385 
2386         DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
2387 
2388 	if (sc->sc_model >= SB_20)
2389 		sbdsp_reset(sc); /* exit UART mode */
2390 	sc->sc_open = SB_CLOSED;
2391 	sc->sc_intrm = 0;
2392 }
2393 
2394 int
2395 sbdsp_midi_output(addr, d)
2396 	void *addr;
2397 	int d;
2398 {
2399 	struct sbdsp_softc *sc = addr;
2400 
2401 	if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
2402 		return 1;
2403 	(void)sbdsp_wdsp(sc, d);
2404 	return 1;
2405 }
2406 
2407 void
2408 sbdsp_midi_getinfo(addr, mi)
2409 	void *addr;
2410 	struct midi_info *mi;
2411 {
2412 	struct sbdsp_softc *sc = addr;
2413 
2414 	mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
2415 	mi->props = MIDI_PROP_CAN_INPUT;
2416 }
2417 
2418 int
2419 sbdsp_midi_intr(addr)
2420 	void *addr;
2421 {
2422 	struct sbdsp_softc *sc = addr;
2423 
2424 	sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
2425 	return (0);
2426 }
2427 
2428 #endif
2429