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