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