xref: /netbsd-src/sys/dev/isa/gus.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: gus.c,v 1.48 1997/10/19 07:42:26 augustss Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Ken Hornstein and John Kohl.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *	  Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  *
41  * TODO:
42  *	. figure out why mixer activity while sound is playing causes problems
43  *	  (phantom interrupts?)
44  *  	. figure out a better deinterleave strategy that avoids sucking up
45  *	  CPU, memory and cache bandwidth.  (Maybe a special encoding?
46  *	  Maybe use the double-speed sampling/hardware deinterleave trick
47  *	  from the GUS SDK?)  A 486/33 isn't quite fast enough to keep
48  *	  up with 44.1kHz 16-bit stereo output without some drop-outs.
49  *	. use CS4231 for 16-bit sampling, for a-law and mu-law playback.
50  *	. actually test full-duplex sampling(recording) and playback.
51  */
52 
53 /*
54  * Gravis UltraSound driver
55  *
56  * For more detailed information, see the GUS developers' kit
57  * available on the net at:
58  *
59  * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
60  * 	gusdkXXX.zip (developers' kit--get rev 2.22 or later)
61  *		See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
62  *
63  */
64 
65 /*
66  * The GUS Max has a slightly strange set of connections between the CS4231
67  * and the GF1 and the DMA interconnects.  It's set up so that the CS4231 can
68  * be playing while the GF1 is loading patches from the system.
69  *
70  * Here's a recreation of the DMA interconnect diagram:
71  *
72  *       GF1
73  *   +---------+				 digital
74  *   |         |  record			 ASIC
75  *   |         |--------------+
76  *   |         |              |		       +--------+
77  *   |         | play (dram)  |      +----+    |	|
78  *   |         |--------------(------|-\  |    |   +-+  |
79  *   +---------+              |      |  >-|----|---|C|--|------  dma chan 1
80  *                            |  +---|-/  |    |   +-+ 	|
81  *                            |  |   +----+    |    |   |
82  *                            |	 |   +----+    |    |   |
83  *   +---------+        +-+   +--(---|-\  |    |    |   |
84  *   |         | play   |8|      |   |  >-|----|----+---|------  dma chan 2
85  *   | ---C----|--------|/|------(---|-/  |    |        |
86  *   |    ^    |record  |1|      |   +----+    |	|
87  *   |    |    |   /----|6|------+   	       +--------+
88  *   | ---+----|--/     +-+
89  *   +---------+
90  *     CS4231   	8-to-16 bit bus conversion, if needed
91  *
92  *
93  * "C" is an optional combiner.
94  *
95  */
96 
97 #include "gus.h"
98 #if NGUS > 0
99 
100 #include <sys/param.h>
101 #include <sys/systm.h>
102 #include <sys/errno.h>
103 #include <sys/ioctl.h>
104 #include <sys/syslog.h>
105 #include <sys/device.h>
106 #include <sys/proc.h>
107 #include <sys/buf.h>
108 #include <sys/fcntl.h>
109 #include <sys/malloc.h>
110 #include <sys/kernel.h>
111 
112 #include <machine/cpu.h>
113 #include <machine/intr.h>
114 #include <machine/bus.h>
115 #include <machine/pio.h>
116 #include <machine/cpufunc.h>
117 #include <sys/audioio.h>
118 #include <dev/audio_if.h>
119 #include <dev/mulaw.h>
120 #include <dev/auconv.h>
121 
122 #include <dev/isa/isavar.h>
123 #include <dev/isa/isadmavar.h>
124 #include <i386/isa/icu.h>
125 
126 #include <dev/ic/ics2101reg.h>
127 #include <dev/ic/cs4231reg.h>
128 #include <dev/ic/ad1848reg.h>
129 #include <dev/isa/ics2101var.h>
130 #include <dev/isa/ad1848var.h>
131 #include <dev/isa/cs4231var.h>
132 #include "gusreg.h"
133 
134 #ifdef AUDIO_DEBUG
135 #define STATIC /* empty; for debugging symbols */
136 #else
137 #define STATIC static
138 #endif
139 
140 /*
141  * Software state of a single "voice" on the GUS
142  */
143 
144 struct gus_voice {
145 
146 	/*
147 	 * Various control bits
148 	 */
149 
150 	unsigned char voccntl;	/* State of voice control register */
151 	unsigned char volcntl;	/* State of volume control register */
152 	unsigned char pan_pos;	/* Position of volume panning (4 bits) */
153 	int rate;		/* Sample rate of voice being played back */
154 
155 	/*
156 	 * Address of the voice data into the GUS's DRAM.  20 bits each
157 	 */
158 
159 	u_long start_addr;	/* Starting address of voice data loop area */
160 	u_long end_addr;	/* Ending address of voice data loop */
161 	u_long current_addr;	/* Beginning address of voice data
162 				   (start playing here) */
163 
164 	/*
165 	 * linear volume values for the GUS's volume ramp.  0-511 (9 bits).
166 	 * These values must be translated into the logarithmic values using
167 	 * gus_log_volumes[]
168 	 */
169 
170 	int start_volume;	/* Starting position of volume ramp */
171 	int current_volume;	/* Current position of volume on volume ramp */
172 	int end_volume;		/* Ending position of volume on volume ramp */
173 };
174 
175 /*
176  * Software state of GUS
177  */
178 
179 struct gus_softc {
180 	struct device sc_dev;		/* base device */
181 	struct device *sc_isa;		/* pointer to ISA parent */
182 	void *sc_ih;			/* interrupt vector */
183 	bus_space_tag_t sc_iot;		/* tag */
184 	bus_space_handle_t sc_ioh1;	/* handle */
185 	bus_space_handle_t sc_ioh2;	/* handle */
186 	bus_space_handle_t sc_ioh3;	/* ICS2101 handle */
187 	bus_space_handle_t sc_ioh4;	/* MIDI handle */
188 
189 	int sc_iobase;			/* I/O base address */
190 	int sc_irq;			/* IRQ used */
191 	int sc_drq;			/* DMA channel for play */
192 	int sc_recdrq;			/* DMA channel for recording */
193 
194 	int sc_flags;			/* Various flags about the GUS */
195 #define GUS_MIXER_INSTALLED	0x01	/* An ICS mixer is installed */
196 #define GUS_LOCKED		0x02	/* GUS is busy doing multi-phase DMA */
197 #define GUS_CODEC_INSTALLED	0x04	/* CS4231 installed/MAX */
198 #define GUS_PLAYING		0x08	/* GUS is playing a voice */
199 #define GUS_DMAOUT_ACTIVE	0x10	/* GUS is busy doing audio DMA */
200 #define GUS_DMAIN_ACTIVE	0x20	/* GUS is busy sampling  */
201 #define GUS_OPEN		0x100	/* GUS is open */
202 	int sc_dsize;			/* Size of GUS DRAM */
203 	int sc_voices;			/* Number of active voices */
204 	u_char sc_revision;		/* Board revision of GUS */
205 	u_char sc_mixcontrol;		/* Value of GUS_MIX_CONTROL register */
206 
207 	u_long sc_orate;		/* Output sampling rate */
208 	u_long sc_irate;		/* Input sampling rate */
209 
210 	int sc_encoding;		/* Current data encoding type */
211 	int sc_precision;		/* # of bits of precision */
212 	int sc_channels;		/* Number of active channels */
213 	int sc_blocksize;		/* Current blocksize */
214 	int sc_chanblocksize;		/* Current blocksize for each in-use
215 					   channel */
216 	short sc_nbufs;			/* how many on-GUS bufs per-channel */
217 	short sc_bufcnt;		/* how many need to be played */
218 	void *sc_deintr_buf;		/* deinterleave buffer for stereo */
219 
220 	int sc_ogain;			/* Output gain control */
221 	u_char sc_out_port;		/* Current out port (generic only) */
222 	u_char sc_in_port;		/* keep track of it when no codec */
223 
224 	void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */
225 	void *sc_outarg;		/* argument for sc_dmaoutintr() */
226 	u_char *sc_dmaoutaddr;		/* for isa_dmadone */
227 	u_long sc_gusaddr;		/* where did we just put it? */
228 	int sc_dmaoutcnt;		/* for isa_dmadone */
229 
230 	void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */
231 	void *sc_inarg;			/* argument for sc_dmaoutintr() */
232 	u_char *sc_dmainaddr;		/* for isa_dmadone */
233 	int sc_dmaincnt;		/* for isa_dmadone */
234 
235 	struct stereo_dma_intr {
236 		void (*intr)__P((void *));
237 		void *arg;
238 		u_char *buffer;
239 		u_long dmabuf;
240 		int size;
241 		int flags;
242 	} sc_stereo;
243 
244 	/*
245 	 * State information for linear audio layer
246 	 */
247 
248 	int sc_dmabuf;			/* Which ring buffer we're DMA'ing to */
249 	int sc_playbuf;			/* Which ring buffer we're playing */
250 
251 	/*
252 	 * Voice information array.  All voice-specific information is stored
253 	 * here
254 	 */
255 
256 	struct gus_voice sc_voc[32];	/* Voice data for each voice */
257 	union {
258 		struct ics2101_softc sc_mixer_u;
259 		struct ad1848_softc sc_codec_u;
260 	} u;
261 #define sc_mixer u.sc_mixer_u
262 #define sc_codec u.sc_codec_u
263 };
264 
265 struct ics2101_volume {
266 	u_char left;
267 	u_char right;
268 };
269 
270 #define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
271 #define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
272 
273 /*
274  * Mixer devices for ICS2101
275  */
276 /* MIC IN mute, line in mute, line out mute are first since they can be done
277    even if no ICS mixer. */
278 #define GUSICS_MIC_IN_MUTE		0
279 #define GUSICS_LINE_IN_MUTE		1
280 #define GUSICS_MASTER_MUTE		2
281 #define GUSICS_CD_MUTE			3
282 #define GUSICS_DAC_MUTE			4
283 #define GUSICS_MIC_IN_LVL		5
284 #define GUSICS_LINE_IN_LVL		6
285 #define GUSICS_CD_LVL			7
286 #define GUSICS_DAC_LVL			8
287 #define GUSICS_MASTER_LVL		9
288 
289 #define GUSICS_RECORD_SOURCE		10
290 
291 /* Classes */
292 #define GUSICS_INPUT_CLASS		11
293 #define GUSICS_OUTPUT_CLASS		12
294 #define GUSICS_RECORD_CLASS		13
295 
296 /*
297  * Mixer & MUX devices for CS4231
298  */
299 #define GUSMAX_MONO_LVL			0 /* mic input to MUX;
300 					     also mono mixer input */
301 #define GUSMAX_DAC_LVL			1 /* input to MUX; also mixer input */
302 #define GUSMAX_LINE_IN_LVL		2 /* input to MUX; also mixer input */
303 #define GUSMAX_CD_LVL			3 /* mixer input only */
304 #define GUSMAX_MONITOR_LVL		4 /* digital mix (?) */
305 #define GUSMAX_OUT_LVL			5 /* output level. (?) */
306 #define GUSMAX_SPEAKER_LVL		6 /* pseudo-device for mute */
307 #define GUSMAX_LINE_IN_MUTE		7 /* pre-mixer */
308 #define GUSMAX_DAC_MUTE			8 /* pre-mixer */
309 #define GUSMAX_CD_MUTE			9 /* pre-mixer */
310 #define GUSMAX_MONO_MUTE		10 /* pre-mixer--microphone/mono */
311 #define GUSMAX_MONITOR_MUTE		11 /* post-mixer level/mute */
312 #define GUSMAX_SPEAKER_MUTE		12 /* speaker mute */
313 
314 #define GUSMAX_REC_LVL			13 /* post-MUX gain */
315 
316 #define GUSMAX_RECORD_SOURCE		14
317 
318 /* Classes */
319 #define GUSMAX_INPUT_CLASS		15
320 #define GUSMAX_RECORD_CLASS		16
321 #define GUSMAX_MONITOR_CLASS		17
322 #define GUSMAX_OUTPUT_CLASS		18
323 
324 #ifdef AUDIO_DEBUG
325 #define GUSPLAYDEBUG	/*XXX*/
326 #define DPRINTF(x)	if (gusdebug) printf x
327 #define DMAPRINTF(x)	if (gusdmadebug) printf x
328 int	gusdebug = 0;
329 int	gusdmadebug = 0;
330 #else
331 #define DPRINTF(x)
332 #define DMAPRINTF(x)
333 #endif
334 int	gus_dostereo = 1;
335 
336 #define NDMARECS 2048
337 #ifdef GUSPLAYDEBUG
338 int	gusstats = 0;
339 struct dma_record {
340     struct timeval tv;
341     u_long gusaddr;
342     caddr_t bsdaddr;
343     u_short count;
344     u_char channel;
345     u_char direction;
346 } dmarecords[NDMARECS];
347 
348 int dmarecord_index = 0;
349 #endif
350 
351 /*
352  * local routines
353  */
354 
355 int	gusopen __P((void *, int));
356 void	gusclose __P((void *));
357 void	gusmax_close __P((void *));
358 int	gusintr __P((void *));
359 int	gus_set_in_gain __P((caddr_t, u_int, u_char));
360 int	gus_get_in_gain __P((caddr_t));
361 int	gus_set_out_gain __P((caddr_t, u_int, u_char));
362 int	gus_get_out_gain __P((caddr_t));
363 int 	gus_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
364 int 	gusmax_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
365 int	gus_round_blocksize __P((void *, int));
366 int	gus_commit_settings __P((void *));
367 int	gus_dma_output __P((void *, void *, int, void (*)(void *), void *));
368 int	gus_dma_input __P((void *, void *, int, void (*)(void *), void *));
369 int	gus_halt_out_dma __P((void *));
370 int	gus_halt_in_dma __P((void *));
371 int	gus_speaker_ctl __P((void *, int));
372 int	gusmaxopen __P((void *, int));
373 int	gusmax_round_blocksize __P((void *, int));
374 int	gusmax_commit_settings __P((void *));
375 int	gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *));
376 int	gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *));
377 int	gusmax_halt_out_dma __P((void *));
378 int	gusmax_halt_in_dma __P((void *));
379 int	gusmax_speaker_ctl __P((void *, int));
380 int	gus_getdev __P((void *, struct audio_device *));
381 
382 STATIC void	gus_deinterleave __P((struct gus_softc *, void *, int));
383 
384 STATIC int	gus_mic_ctl __P((void *, int));
385 STATIC int	gus_linein_ctl __P((void *, int));
386 STATIC int	gus_test_iobase __P((struct gus_softc *, int));
387 STATIC void	guspoke __P((bus_space_tag_t, bus_space_handle_t, long, u_char));
388 STATIC void	gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int));
389 STATIC void	gus_init_cs4231 __P((struct gus_softc *));
390 STATIC void	gus_init_ics2101 __P((struct gus_softc *));
391 
392 STATIC void	gus_set_chan_addrs __P((struct gus_softc *));
393 STATIC void	gusreset __P((struct gus_softc *, int));
394 STATIC void	gus_set_voices __P((struct gus_softc *, int));
395 STATIC void	gus_set_volume __P((struct gus_softc *, int, int));
396 STATIC void	gus_set_samprate __P((struct gus_softc *, int, int));
397 STATIC void	gus_set_recrate __P((struct gus_softc *, u_long));
398 STATIC void	gus_start_voice __P((struct gus_softc *, int, int));
399 STATIC void	gus_stop_voice __P((struct gus_softc *, int, int));
400 STATIC void	gus_set_endaddr __P((struct gus_softc *, int, u_long));
401 #ifdef GUSPLAYDEBUG
402 STATIC void	gus_set_curaddr __P((struct gus_softc *, int, u_long));
403 STATIC u_long	gus_get_curaddr __P((struct gus_softc *, int));
404 #endif
405 STATIC int	gus_dmaout_intr __P((struct gus_softc *));
406 STATIC void	gus_dmaout_dointr __P((struct gus_softc *));
407 STATIC void	gus_dmaout_timeout __P((void *));
408 STATIC int	gus_dmain_intr __P((struct gus_softc *));
409 STATIC int	gus_voice_intr __P((struct gus_softc *));
410 STATIC void	gus_start_playing __P((struct gus_softc *, int));
411 STATIC int	gus_continue_playing __P((struct gus_softc *, int));
412 STATIC u_char guspeek __P((bus_space_tag_t, bus_space_handle_t, u_long));
413 STATIC u_long convert_to_16bit __P((u_long));
414 STATIC int	gus_mixer_set_port __P((void *, mixer_ctrl_t *));
415 STATIC int	gus_mixer_get_port __P((void *, mixer_ctrl_t *));
416 STATIC int	gusmax_mixer_set_port __P((void *, mixer_ctrl_t *));
417 STATIC int	gusmax_mixer_get_port __P((void *, mixer_ctrl_t *));
418 STATIC int	gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
419 STATIC int	gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
420 STATIC int	gus_query_encoding __P((void *, struct audio_encoding *));
421 STATIC int	gus_get_props __P((void *));
422 STATIC int	gusmax_get_props __P((void *));
423 
424 STATIC void	gusics_master_mute __P((struct ics2101_softc *, int));
425 STATIC void	gusics_dac_mute __P((struct ics2101_softc *, int));
426 STATIC void	gusics_mic_mute __P((struct ics2101_softc *, int));
427 STATIC void	gusics_linein_mute __P((struct ics2101_softc *, int));
428 STATIC void	gusics_cd_mute __P((struct ics2101_softc *, int));
429 
430 STATIC __inline int gus_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
431 STATIC __inline int gus_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
432 
433 void	stereo_dmaintr __P((void *));
434 
435 /*
436  * ISA bus driver routines
437  */
438 
439 int	gusprobe __P((struct device *, void *, void *));
440 void	gusattach __P((struct device *, struct device *, void *));
441 
442 struct cfattach gus_ca = {
443 	sizeof(struct gus_softc), gusprobe, gusattach,
444 };
445 
446 struct cfdriver gus_cd = {
447 	NULL, "gus", DV_DULL
448 };
449 
450 
451 /*
452  * A mapping from IRQ/DRQ values to the values used in the GUS's internal
453  * registers.  A zero means that the referenced IRQ/DRQ is invalid
454  */
455 
456 static int gus_irq_map[] = {
457 	IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6,
458 	IRQUNK, IRQUNK, 7
459 };
460 static int gus_drq_map[] = {
461 	DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5
462 };
463 
464 /*
465  * A list of valid base addresses for the GUS
466  */
467 
468 static int gus_base_addrs[] = {
469 	0x210, 0x220, 0x230, 0x240, 0x250, 0x260
470 };
471 static int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
472 
473 /*
474  * Maximum frequency values of the GUS based on the number of currently active
475  * voices.  Since the GUS samples a voice every 1.6 us, the maximum frequency
476  * is dependent on the number of active voices.  Yes, it is pretty weird.
477  */
478 
479 static int gus_max_frequency[] = {
480 		44100,		/* 14 voices */
481 		41160,		/* 15 voices */
482 		38587,		/* 16 voices */
483 		36317,		/* 17 voices */
484 		34300,		/* 18 voices */
485 		32494,		/* 19 voices */
486 		30870,		/* 20 voices */
487 		29400,		/* 21 voices */
488 		28063,		/* 22 voices */
489 		26843,		/* 23 voices */
490 		25725,		/* 24 voices */
491 		24696,		/* 25 voices */
492 		23746,		/* 26 voices */
493 		22866,		/* 27 voices */
494 		22050,		/* 28 voices */
495 		21289,		/* 29 voices */
496 		20580,		/* 30 voices */
497 		19916,		/* 31 voices */
498 		19293		/* 32 voices */
499 };
500 /*
501  * A mapping of linear volume levels to the logarithmic volume values used
502  * by the GF1 chip on the GUS.  From GUS SDK vol1.c.
503  */
504 
505 static unsigned short gus_log_volumes[512] = {
506  0x0000,
507  0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20,
508  0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20,
509  0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0,
510  0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20,
511  0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68,
512  0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0,
513  0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8,
514  0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20,
515  0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44,
516  0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68,
517  0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c,
518  0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0,
519  0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4,
520  0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8,
521  0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e,
522  0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20,
523  0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32,
524  0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44,
525  0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56,
526  0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68,
527  0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a,
528  0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c,
529  0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e,
530  0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0,
531  0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2,
532  0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4,
533  0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6,
534  0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8,
535  0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05,
536  0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
537  0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
538  0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20,
539  0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29,
540  0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32,
541  0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b,
542  0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44,
543  0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d,
544  0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56,
545  0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
546  0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68,
547  0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71,
548  0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a,
549  0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83,
550  0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c,
551  0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95,
552  0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
553  0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
554  0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0,
555  0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9,
556  0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2,
557  0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb,
558  0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4,
559  0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd,
560  0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6,
561  0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef,
562  0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
563  0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
564 
565 #define SELECT_GUS_REG(iot,ioh1,x) bus_space_write_1(iot,ioh1,GUS_REG_SELECT,x)
566 #define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
567 #define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
568 
569 #define GUS_MIN_VOICES 14	/* Minimum possible number of voices */
570 #define GUS_MAX_VOICES 32	/* Maximum possible number of voices */
571 #define GUS_VOICE_LEFT 0	/* Voice used for left (and mono) playback */
572 #define GUS_VOICE_RIGHT 1	/* Voice used for right playback */
573 #define GUS_MEM_OFFSET 32	/* Offset into GUS memory to begin of buffer */
574 #define GUS_BUFFER_MULTIPLE 1024	/* Audio buffers are multiples of this */
575 #define	GUS_MEM_FOR_BUFFERS	131072	/* use this many bytes on-GUS */
576 #define	GUS_LEFT_RIGHT_OFFSET	(sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
577 
578 #define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
579 
580 /* splgus() must be splaudio() */
581 
582 #define splgus splaudio
583 
584 /*
585  * Interface to higher level audio driver
586  */
587 
588 struct audio_hw_if gus_hw_if = {
589 	gusopen,
590 	gusclose,
591 	NULL,				/* drain */
592 
593 	gus_query_encoding,
594 
595 	gus_set_params,
596 
597 	gus_round_blocksize,
598 
599 	gus_commit_settings,
600 
601 	NULL,
602 	NULL,
603 
604 	gus_dma_output,
605 	gus_dma_input,
606 	gus_halt_out_dma,
607 	gus_halt_in_dma,
608 	gus_speaker_ctl,
609 
610 	gus_getdev,
611 	NULL,
612 	gus_mixer_set_port,
613 	gus_mixer_get_port,
614 	gus_mixer_query_devinfo,
615 	NULL,
616 	NULL,
617 	NULL,
618         NULL,
619 	gus_get_props,
620 };
621 
622 static struct audio_hw_if gusmax_hw_if = {
623 	gusmaxopen,
624 	gusmax_close,
625 	NULL,				/* drain */
626 
627 	gus_query_encoding, /* query encoding */
628 
629 	gusmax_set_params,
630 
631 	gusmax_round_blocksize,
632 
633 	gusmax_commit_settings,
634 
635 	NULL,
636 	NULL,
637 
638 	gusmax_dma_output,
639 	gusmax_dma_input,
640 	gusmax_halt_out_dma,
641 	gusmax_halt_in_dma,
642 
643 	gusmax_speaker_ctl,
644 
645 	gus_getdev,
646 	NULL,
647 	gusmax_mixer_set_port,
648 	gusmax_mixer_get_port,
649 	gusmax_mixer_query_devinfo,
650 	NULL,
651 	NULL,
652 	NULL,
653 	NULL,
654 	gusmax_get_props,
655 };
656 
657 /*
658  * Some info about the current audio device
659  */
660 
661 struct audio_device gus_device = {
662 	"UltraSound",
663 	"",
664 	"gus",
665 };
666 
667 #define FLIP_REV	5		/* This rev has flipped mixer chans */
668 
669 
670 int
671 gusprobe(parent, match, aux)
672 	struct device *parent;
673 	void *match, *aux;
674 {
675 	struct gus_softc *sc = match;
676 	struct isa_attach_args *ia = aux;
677 	int iobase = ia->ia_iobase;
678 	int recdrq = ia->ia_drq2;
679 
680 	sc->sc_iot = ia->ia_iot;
681 	/*
682 	 * Before we do anything else, make sure requested IRQ and DRQ are
683 	 * valid for this card.
684 	 */
685 
686 	/* XXX range check before indexing!! */
687 	if (ia->ia_irq == IRQUNK || gus_irq_map[ia->ia_irq] == IRQUNK) {
688 		printf("gus: invalid irq %d, card not probed\n", ia->ia_irq);
689 		return 0;
690 	}
691 
692 	if (ia->ia_drq == DRQUNK || gus_drq_map[ia->ia_drq] == DRQUNK) {
693 		printf("gus: invalid drq %d, card not probed\n", ia->ia_drq);
694 		return 0;
695 	}
696 
697 	if (recdrq != DRQUNK) {
698 		if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
699 		   printf("gus: invalid second DMA channel (%d), card not probed\n", recdrq);
700 		   return 0;
701 	        }
702 	} else
703 		recdrq = ia->ia_drq;
704 
705 	if (iobase == IOBASEUNK) {
706 		int i;
707 		for(i = 0; i < gus_addrs; i++)
708 			if (gus_test_iobase(sc, gus_base_addrs[i])) {
709 				iobase = gus_base_addrs[i];
710 				goto done;
711 			}
712 		return 0;
713 	} else if (!gus_test_iobase(sc, iobase))
714 			return 0;
715 
716 done:
717 	sc->sc_iobase = iobase;
718 	sc->sc_irq = ia->ia_irq;
719 	sc->sc_drq = ia->ia_drq;
720 	sc->sc_recdrq = recdrq;
721 
722 	if ((sc->sc_drq    != -1 && !isa_drq_isfree(parent, sc->sc_drq)) ||
723 	    (sc->sc_recdrq != -1 && !isa_drq_isfree(parent, sc->sc_recdrq)))
724 		return 0;
725 
726 	ia->ia_iobase = iobase;
727 	ia->ia_iosize = GUS_NPORT1;
728 	return 1;
729 }
730 
731 /*
732  * Test to see if a particular I/O base is valid for the GUS.  Return true
733  * if it is.
734  */
735 
736 STATIC int
737 gus_test_iobase (sc, iobase)
738 	struct gus_softc *sc;
739 	int iobase;
740 {
741 	bus_space_tag_t iot = sc->sc_iot;
742 	bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
743 	u_char s1, s2;
744 	int s;
745 
746 	/* Map i/o space */
747 	if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
748 		return 0;
749 	sc->sc_ioh1 = ioh1;
750 	if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
751 		goto bad1;
752 	sc->sc_ioh2 = ioh2;
753 
754 	/* XXX Maybe we shouldn't fail on mapping this, but just assume
755 	 * the card is of revision 0? */
756 	if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
757 		goto bad2;
758 	sc->sc_ioh3 = ioh3;
759 
760 	if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
761 		goto bad3;
762 	sc->sc_ioh4 = ioh4;
763 
764 	/*
765 	 * Reset GUS to an initial state before we do anything.
766 	 */
767 
768 	s = splgus();
769 	delay(500);
770 
771  	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
772  	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
773 
774  	delay(500);
775 
776 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
777  	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
778 
779  	delay(500);
780 
781 	splx(s);
782 
783 	/*
784 	 * See if we can write to the board's memory
785 	 */
786 
787  	s1 = guspeek(iot, ioh2, 0L);
788  	s2 = guspeek(iot, ioh2, 1L);
789 
790  	guspoke(iot, ioh2, 0L, 0xaa);
791  	guspoke(iot, ioh2, 1L, 0x55);
792 
793  	if (guspeek(iot, ioh2, 0L) != 0xaa)
794 		goto bad;
795 
796 	guspoke(iot, ioh2, 0L, s1);
797 	guspoke(iot, ioh2, 1L, s2);
798 
799 	return 1;
800 
801 bad:
802 	bus_space_unmap(sc->sc_iot, sc->sc_ioh4, GUS_NPORT4);
803 bad3:
804 	bus_space_unmap(sc->sc_iot, sc->sc_ioh3, GUS_NPORT3);
805 bad2:
806 	bus_space_unmap(sc->sc_iot, sc->sc_ioh2, GUS_NPORT2);
807 bad1:
808 	bus_space_unmap(sc->sc_iot, sc->sc_ioh1, GUS_NPORT1);
809 	return 0;
810 }
811 
812 /*
813  * Setup the GUS for use; called shortly after probe
814  */
815 
816 void
817 gusattach(parent, self, aux)
818 	struct device *parent, *self;
819 	void *aux;
820 {
821 	struct gus_softc *sc = (void *) self;
822 	struct isa_attach_args *ia = aux;
823 	bus_space_tag_t iot = sc->sc_iot;
824 	bus_space_handle_t ioh1 = sc->sc_ioh1;
825 	bus_space_handle_t ioh2 = sc->sc_ioh2;
826 	bus_space_handle_t ioh3 = sc->sc_ioh3;
827  	int		i;
828 	unsigned char	c,d,m;
829 
830 	/*
831 	 * Figure out our board rev, and see if we need to initialize the
832 	 * mixer
833 	 */
834 
835 	sc->sc_isa = parent;
836 
837  	delay(500);
838 
839  	c = bus_space_read_1(iot, ioh3, GUS_BOARD_REV);
840 	if (c != 0xff)
841 		sc->sc_revision = c;
842 	else
843 		sc->sc_revision = 0;
844 
845 
846  	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
847  	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
848 
849 	gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
850 	gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
851 
852 	/*
853 	 * Setup the IRQ and DRQ lines in software, using values from
854 	 * config file
855 	 */
856 
857 	m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT;		/* disable all */
858 
859 	c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
860 
861 	if (sc->sc_recdrq == sc->sc_drq)
862 		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
863 				GUSMASK_BOTH_RQ);
864 	else
865 		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
866 				gus_drq_map[sc->sc_recdrq] << 3);
867 
868 	/*
869 	 * Program the IRQ and DMA channels on the GUS.  Note that we hardwire
870 	 * the GUS to only use one IRQ channel, but we give the user the
871 	 * option of using two DMA channels (the other one given by the flags
872 	 * option in the config file).  Two DMA channels are needed for full-
873 	 * duplex operation.
874 	 *
875 	 * The order of these operations is very magical.
876 	 */
877 
878 	disable_intr();		/* XXX needed? */
879 
880 	bus_space_write_1(iot, ioh1, GUS_REG_CONTROL, GUS_REG_IRQCTL);
881 	bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
882 	bus_space_write_1(iot, ioh1, GUS_IRQCTL_CONTROL, 0x00);
883 	bus_space_write_1(iot, ioh1, 0x0f, 0x00);
884 
885 	bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
886 	bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
887 
888 	bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
889 	bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
890 
891 	bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
892 	bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d);
893 
894 	bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
895 	bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
896 
897 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
898 
899 	/* enable line in, line out.  leave mic disabled. */
900 	bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL,
901 	     (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
902 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
903 
904 	enable_intr();
905 
906 	sc->sc_mixcontrol =
907 		(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
908 
909 	/* XXX WILL THIS ALWAYS WORK THE WAY THEY'RE OVERLAYED?! */
910 	sc->sc_codec.sc_isa = sc->sc_dev.dv_parent;
911 
912  	if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
913  		sc->sc_flags |= GUS_MIXER_INSTALLED;
914  		gus_init_ics2101(sc);
915 	}
916 	if (sc->sc_revision >= 0xa) {
917 		gus_init_cs4231(sc);
918 	} else {
919 		/* Not using the CS4231, so create our DMA maps. */
920 		if (sc->sc_drq != -1) {
921 			if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
922 			    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
923 				printf("%s: can't create map for drq %d\n",
924 				       sc->sc_dev.dv_xname, sc->sc_drq);
925 				return;
926 			}
927 		}
928 		if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
929 			if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq,
930 			    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
931 				printf("%s: can't create map for drq %d\n",
932 				       sc->sc_dev.dv_xname, sc->sc_recdrq);
933 				return;
934 			}
935 		}
936 	}
937 
938  	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
939  	/*
940  	 * Check to see how much memory we have on this card; see if any
941  	 * "mirroring" occurs.  We're assuming at least 256K already exists
942  	 * on the card; otherwise the initial probe would have failed
943  	 */
944 
945 	guspoke(iot, ioh2, 0L, 0x00);
946 	for(i = 1; i < 1024; i++) {
947 		u_long loc;
948 
949 		/*
950 		 * See if we've run into mirroring yet
951 		 */
952 
953 		if (guspeek(iot, ioh2, 0L) != 0)
954 			break;
955 
956 		loc = i << 10;
957 
958 		guspoke(iot, ioh2, loc, 0xaa);
959 		if (guspeek(iot, ioh2, loc) != 0xaa)
960 			break;
961 	}
962 
963 	sc->sc_dsize = i;
964 	sprintf(gus_device.version, "3.%d", sc->sc_revision);
965 
966 	printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ",
967 	       sc->sc_revision, sc->sc_dsize);
968 	if (HAS_MIXER(sc))
969 		printf("ICS2101 mixer, ");
970 	if (HAS_CODEC(sc))
971 		printf("%s codec/mixer, ", sc->sc_codec.chip_name);
972 	if (sc->sc_recdrq == sc->sc_drq) {
973 		printf("half-duplex");
974 	} else {
975 		printf("full-duplex, record drq %d", sc->sc_recdrq);
976 	}
977 
978 	printf(">\n");
979 
980 	/*
981 	 * Setup a default interrupt handler
982 	 */
983 
984 	/* XXX we shouldn't have to use splgus == splclock, nor should
985 	 * we use IPL_CLOCK.
986 	 */
987 	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
988 	    IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */);
989 
990 	/*
991 	 * Set some default values
992 	 * XXX others start with 8kHz mono mulaw
993 	 */
994 
995 	sc->sc_irate = sc->sc_orate = 44100;
996 	sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
997 	sc->sc_precision = 16;
998 	sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
999 	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
1000 	sc->sc_channels = 1;
1001 	sc->sc_ogain = 340;
1002 	gus_commit_settings(sc);
1003 
1004 	/*
1005 	 * We always put the left channel full left & right channel
1006 	 * full right.
1007 	 * For mono playback, we set up both voices playing the same buffer.
1008 	 */
1009 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
1010 	SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
1011 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
1012 
1013 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
1014 	SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
1015 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
1016 
1017 	/*
1018 	 * Attach to the generic audio layer
1019 	 */
1020 
1021 	audio_attach_mi(&gus_hw_if, 0, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
1022 }
1023 
1024 int
1025 gusopen(addr, flags)
1026 	void *addr;
1027 	int flags;
1028 {
1029 	struct gus_softc *sc = addr;
1030 
1031 	DPRINTF(("gusopen() called\n"));
1032 
1033 	if (sc->sc_flags & GUS_OPEN)
1034 		return EBUSY;
1035 
1036 	/*
1037 	 * Some initialization
1038 	 */
1039 
1040 	sc->sc_flags |= GUS_OPEN;
1041 	sc->sc_dmabuf = 0;
1042 	sc->sc_playbuf = -1;
1043 	sc->sc_bufcnt = 0;
1044 	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
1045 	sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
1046 
1047 	if (HAS_CODEC(sc)) {
1048 		ad1848_open(&sc->sc_codec, flags);
1049 		sc->sc_codec.aux1_mute = 0;
1050 		ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
1051 		if (flags & FREAD) {
1052 			sc->sc_codec.mono_mute = 0;
1053 			cs4231_mute_mono(&sc->sc_codec, 0);
1054 		}
1055 	} else if (flags & FREAD) {
1056 		/* enable/unmute the microphone */
1057 		if (HAS_MIXER(sc)) {
1058 			gusics_mic_mute(&sc->sc_mixer, 0);
1059 		} else
1060 			gus_mic_ctl(sc, SPKR_ON);
1061 	}
1062 	if (sc->sc_nbufs == 0)
1063 	    gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */
1064 	return 0;
1065 }
1066 
1067 int
1068 gusmaxopen(addr, flags)
1069 	void *addr;
1070 	int flags;
1071 {
1072 	struct ad1848_softc *ac = addr;
1073 	return gusopen(ac->parent, flags);
1074 }
1075 
1076 STATIC void
1077 gus_deinterleave(sc, buf, size)
1078 	struct gus_softc *sc;
1079 	void *buf;
1080 	int size;
1081 {
1082 	/* deinterleave the stereo data.  We can use sc->sc_deintr_buf
1083 	   for scratch space. */
1084 	int i;
1085 
1086 	if (size > sc->sc_blocksize) {
1087 		printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
1088 		return;
1089 	} else if (size < sc->sc_blocksize) {
1090 		DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
1091 	}
1092 
1093 	/*
1094 	 * size is in bytes.
1095 	 */
1096 	if (sc->sc_precision == 16) {
1097 		u_short *dei = sc->sc_deintr_buf;
1098 		u_short *sbuf = buf;
1099 		size >>= 1;		/* bytecnt to shortcnt */
1100 		/* copy 2nd of each pair of samples to the staging area, while
1101 		   compacting the 1st of each pair into the original area. */
1102 		for (i = 0; i < size/2-1; i++)  {
1103 			dei[i] = sbuf[i*2+1];
1104 			sbuf[i+1] = sbuf[i*2+2];
1105 		}
1106 		/*
1107 		 * this has copied one less sample than half of the
1108 		 * buffer.  The first sample of the 1st stream was
1109 		 * already in place and didn't need copying.
1110 		 * Therefore, we've moved all of the 1st stream's
1111 		 * samples into place.  We have one sample from 2nd
1112 		 * stream in the last slot of original area, not
1113 		 * copied to the staging area (But we don't need to!).
1114 		 * Copy the remainder of the original stream into place.
1115 		 */
1116 		bcopy(dei, &sbuf[size/2], i * sizeof(short));
1117 	} else {
1118 		u_char *dei = sc->sc_deintr_buf;
1119 		u_char *sbuf = buf;
1120 		for (i = 0; i < size/2-1; i++)  {
1121 			dei[i] = sbuf[i*2+1];
1122 			sbuf[i+1] = sbuf[i*2+2];
1123 		}
1124 		bcopy(dei, &sbuf[size/2], i);
1125 	}
1126 }
1127 
1128 /*
1129  * Actually output a buffer to the DSP chip
1130  */
1131 
1132 int
1133 gusmax_dma_output(addr, buf, size, intr, arg)
1134 	void * addr;
1135 	void *buf;
1136 	int size;
1137 	void (*intr) __P((void *));
1138 	void *arg;
1139 {
1140 	struct ad1848_softc *ac = addr;
1141 	return gus_dma_output(ac->parent, buf, size, intr, arg);
1142 }
1143 
1144 /*
1145  * called at splgus() from interrupt handler.
1146  */
1147 void
1148 stereo_dmaintr(arg)
1149 	void *arg;
1150 {
1151     struct gus_softc *sc = arg;
1152     struct stereo_dma_intr *sa = &sc->sc_stereo;
1153 
1154     DMAPRINTF(("stereo_dmaintr"));
1155 
1156     /*
1157      * Put other half in its place, then call the real interrupt routine :)
1158      */
1159 
1160     sc->sc_dmaoutintr = sa->intr;
1161     sc->sc_outarg = sa->arg;
1162 
1163 #ifdef GUSPLAYDEBUG
1164     if (gusstats) {
1165       microtime(&dmarecords[dmarecord_index].tv);
1166       dmarecords[dmarecord_index].gusaddr = sa->dmabuf;
1167       dmarecords[dmarecord_index].bsdaddr = sa->buffer;
1168       dmarecords[dmarecord_index].count = sa->size;
1169       dmarecords[dmarecord_index].channel = 1;
1170       dmarecords[dmarecord_index].direction = 1;
1171       dmarecord_index = ++dmarecord_index % NDMARECS;
1172     }
1173 #endif
1174 
1175     gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size);
1176 
1177     sa->flags = 0;
1178     sa->dmabuf = 0;
1179     sa->buffer = 0;
1180     sa->size = 0;
1181     sa->intr = 0;
1182     sa->arg = 0;
1183 }
1184 
1185 /*
1186  * Start up DMA output to the card.
1187  * Called at splgus/splaudio already, either from intr handler or from
1188  * generic audio code.
1189  */
1190 int
1191 gus_dma_output(addr, buf, size, intr, arg)
1192 	void * addr;
1193 	void *buf;
1194 	int size;
1195 	void (*intr) __P((void *));
1196 	void *arg;
1197 {
1198 	struct gus_softc *sc = addr;
1199 	u_char *buffer = buf;
1200 	u_long boarddma;
1201 	int flags;
1202 
1203 	DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
1204 
1205 	if (size != sc->sc_blocksize) {
1206 	    DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
1207 		     size, sc->sc_blocksize));
1208 	    return EINVAL;
1209 	}
1210 
1211 	flags = GUSMASK_DMA_WRITE;
1212 	if (sc->sc_precision == 16)
1213 	    flags |= GUSMASK_DMA_DATA_SIZE;
1214 	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
1215 	    sc->sc_encoding == AUDIO_ENCODING_ALAW ||
1216 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
1217 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
1218 	    flags |= GUSMASK_DMA_INVBIT;
1219 
1220 	if (sc->sc_channels == 2) {
1221 		if (sc->sc_precision == 16) {
1222 			if (size & 3) {
1223 				DPRINTF(("gus_dma_output: unpaired 16bit samples"));
1224 				size &= 3;
1225 			}
1226 		} else if (size & 1) {
1227 			DPRINTF(("gus_dma_output: unpaired samples"));
1228 			size &= 1;
1229 		}
1230 		if (size == 0)
1231 			return 0;
1232 
1233 		gus_deinterleave(sc, (void *)buffer, size);
1234 
1235 		size >>= 1;
1236 
1237  		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1238 
1239 		sc->sc_stereo.intr = intr;
1240 		sc->sc_stereo.arg = arg;
1241 		sc->sc_stereo.size = size;
1242 		sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET;
1243 		sc->sc_stereo.buffer = buffer + size;
1244 		sc->sc_stereo.flags = flags;
1245 		if (gus_dostereo) {
1246 		  intr = stereo_dmaintr;
1247 		  arg = sc;
1248 		}
1249 	} else
1250 		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1251 
1252 
1253 	sc->sc_flags |= GUS_LOCKED;
1254 	sc->sc_dmaoutintr = intr;
1255 	sc->sc_outarg = arg;
1256 
1257 #ifdef GUSPLAYDEBUG
1258 	if (gusstats) {
1259 	  microtime(&dmarecords[dmarecord_index].tv);
1260 	  dmarecords[dmarecord_index].gusaddr = boarddma;
1261 	  dmarecords[dmarecord_index].bsdaddr = buffer;
1262 	  dmarecords[dmarecord_index].count = size;
1263 	  dmarecords[dmarecord_index].channel = 0;
1264 	  dmarecords[dmarecord_index].direction = 1;
1265 	  dmarecord_index = ++dmarecord_index % NDMARECS;
1266 	}
1267 #endif
1268 
1269 	gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size);
1270 
1271 	return 0;
1272 }
1273 
1274 void
1275 gusmax_close(addr)
1276 	void *addr;
1277 {
1278 	struct ad1848_softc *ac = addr;
1279 	struct gus_softc *sc = ac->parent;
1280 #if 0
1281 	ac->aux1_mute = 1;
1282 	ad1848_mute_aux1(ac, 1);	/* turn off DAC output */
1283 #endif
1284 	ad1848_close(ac);
1285 	gusclose(sc);
1286 }
1287 
1288 /*
1289  * Close out device stuff.  Called at splgus() from generic audio layer.
1290  */
1291 void
1292 gusclose(addr)
1293 	void *addr;
1294 {
1295 	struct gus_softc *sc = addr;
1296 
1297         DPRINTF(("gus_close: sc=%p\n", sc));
1298 
1299 
1300 /*	if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
1301 		gus_halt_out_dma(sc);
1302 	}
1303 /*	if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ {
1304 		gus_halt_in_dma(sc);
1305 	}
1306 	sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE);
1307 
1308 	if (sc->sc_deintr_buf) {
1309 		FREE(sc->sc_deintr_buf, M_DEVBUF);
1310 		sc->sc_deintr_buf = NULL;
1311 	}
1312 	/* turn off speaker, etc. */
1313 
1314 	/* make sure the voices shut up: */
1315 	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1316 	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1317 }
1318 
1319 /*
1320  * Service interrupts.  Farm them off to helper routines if we are using the
1321  * GUS for simple playback/record
1322  */
1323 
1324 #ifdef DIAGNOSTIC
1325 int gusintrcnt;
1326 int gusdmaintrcnt;
1327 int gusvocintrcnt;
1328 #endif
1329 
1330 int
1331 gusintr(arg)
1332 	void *arg;
1333 {
1334 	struct gus_softc *sc = arg;
1335 	bus_space_tag_t iot = sc->sc_iot;
1336 	bus_space_handle_t ioh1 = sc->sc_ioh1;
1337 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1338 	unsigned char intr;
1339 
1340 	int retval = 0;
1341 
1342 	DPRINTF(("gusintr\n"));
1343 #ifdef DIAGNOSTIC
1344 	gusintrcnt++;
1345 #endif
1346 	if (HAS_CODEC(sc))
1347 		retval = ad1848_intr(&sc->sc_codec);
1348 	if ((intr = bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
1349 		DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
1350 #ifdef DIAGNOSTIC
1351 		gusdmaintrcnt++;
1352 #endif
1353 		retval += gus_dmaout_intr(sc);
1354 		if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
1355 		    SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
1356 		    intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
1357 		    if (intr & GUSMASK_SAMPLE_DMATC) {
1358 			retval += gus_dmain_intr(sc);
1359 		    }
1360 		}
1361 	}
1362 	if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) {
1363 		DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags));
1364 #ifdef DIAGNOSTIC
1365 		gusvocintrcnt++;
1366 #endif
1367 		retval += gus_voice_intr(sc);
1368 	}
1369 	if (retval)
1370 		return 1;
1371 	return retval;
1372 }
1373 
1374 int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE];
1375 int gus_restart;				/* how many restarts? */
1376 int gus_stops;				/* how many times did voice stop? */
1377 int gus_falsestops;			/* stopped but not done? */
1378 int gus_continues;
1379 
1380 struct playcont {
1381 	struct timeval tv;
1382 	u_int playbuf;
1383 	u_int dmabuf;
1384 	u_char bufcnt;
1385 	u_char vaction;
1386 	u_char voccntl;
1387 	u_char volcntl;
1388 	u_long curaddr;
1389 	u_long endaddr;
1390 } playstats[NDMARECS];
1391 
1392 int playcntr;
1393 
1394 STATIC void
1395 gus_dmaout_timeout(arg)
1396 	void *arg;
1397 {
1398 	struct gus_softc *sc = arg;
1399 	bus_space_tag_t iot = sc->sc_iot;
1400 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1401 	int s;
1402 
1403 	printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
1404 	/*
1405 	 * Stop any DMA.
1406 	 */
1407 
1408 	s = splgus();
1409 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1410 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
1411 
1412 #if 0
1413 	/* XXX we will dmadone below? */
1414 	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
1415 #endif
1416 
1417 	gus_dmaout_dointr(sc);
1418 	splx(s);
1419 }
1420 
1421 
1422 /*
1423  * Service DMA interrupts.  This routine will only get called if we're doing
1424  * a DMA transfer for playback/record requests from the audio layer.
1425  */
1426 
1427 STATIC int
1428 gus_dmaout_intr(sc)
1429 	struct gus_softc *sc;
1430 {
1431 	bus_space_tag_t iot = sc->sc_iot;
1432 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1433 
1434 	/*
1435 	 * If we got a DMA transfer complete from the GUS DRAM, then deal
1436 	 * with it.
1437 	 */
1438 
1439 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1440  	if (bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
1441 	    untimeout(gus_dmaout_timeout, sc);
1442 	    gus_dmaout_dointr(sc);
1443 	    return 1;
1444 	}
1445 	return 0;
1446 }
1447 
1448 STATIC void
1449 gus_dmaout_dointr(sc)
1450 	struct gus_softc *sc;
1451 {
1452 	bus_space_tag_t iot = sc->sc_iot;
1453 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1454 
1455 	/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
1456 	isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
1457 	sc->sc_flags &= ~GUS_DMAOUT_ACTIVE;  /* pending DMA is done */
1458 	DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
1459 		   sc->sc_dmaoutaddr));
1460 
1461 	/*
1462 	 * to prevent clicking, we need to copy last sample
1463 	 * from last buffer to scratch area just before beginning of
1464 	 * buffer.  However, if we're doing formats that are converted by
1465 	 * the card during the DMA process, we need to pick up the converted
1466 	 * byte rather than the one we have in memory.
1467 	 */
1468 	if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
1469 	  int i;
1470 	  switch (sc->sc_encoding) {
1471 	  case AUDIO_ENCODING_SLINEAR_LE:
1472 	  case AUDIO_ENCODING_SLINEAR_BE:
1473 	    if (sc->sc_precision == 8)
1474 	      goto byte;
1475 	    /* we have the native format */
1476 	    for (i = 1; i <= 2; i++)
1477 	      guspoke(iot, ioh2, sc->sc_gusaddr -
1478 		      (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
1479 		      sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
1480 	    break;
1481 	  case AUDIO_ENCODING_ULINEAR_LE:
1482 	  case AUDIO_ENCODING_ULINEAR_BE:
1483 	    guspoke(iot, ioh2, sc->sc_gusaddr -
1484 		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
1485 		    guspeek(iot, ioh2,
1486 			    sc->sc_gusaddr + sc->sc_chanblocksize - 2));
1487 	  case AUDIO_ENCODING_ALAW:
1488 	  case AUDIO_ENCODING_ULAW:
1489 	  byte:
1490 	    /* we need to fetch the translated byte, then stuff it. */
1491 	    guspoke(iot, ioh2, sc->sc_gusaddr -
1492 		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
1493 		    guspeek(iot, ioh2,
1494 			    sc->sc_gusaddr + sc->sc_chanblocksize - 1));
1495 	    break;
1496 	  }
1497 	}
1498 	/*
1499 	 * If this is the first half of stereo, "ignore" this one
1500 	 * and copy out the second half.
1501 	 */
1502 	if (sc->sc_dmaoutintr == stereo_dmaintr) {
1503 	    (*sc->sc_dmaoutintr)(sc->sc_outarg);
1504 	    return;
1505 	}
1506 	/*
1507 	 * If the voice is stopped, then start it.  Reset the loop
1508 	 * and roll bits.  Call the audio layer routine, since if
1509 	 * we're starting a stopped voice, that means that the next
1510 	 * buffer can be filled
1511 	 */
1512 
1513 	sc->sc_flags &= ~GUS_LOCKED;
1514 	if (sc->sc_voc[GUS_VOICE_LEFT].voccntl &
1515 	    GUSMASK_VOICE_STOPPED) {
1516 	    if (sc->sc_flags & GUS_PLAYING) {
1517 		printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname);
1518 	    }
1519 	    sc->sc_bufcnt++; /* another yet to be played */
1520 	    gus_start_playing(sc, sc->sc_dmabuf);
1521 	    gus_restart++;
1522 	} else {
1523 	    /*
1524 	     * set the sound action based on which buffer we
1525 	     * just transferred.  If we just transferred buffer 0
1526 	     * we want the sound to loop when it gets to the nth
1527 	     * buffer; if we just transferred
1528 	     * any other buffer, we want the sound to roll over
1529 	     * at least one more time.  The voice interrupt
1530 	     * handlers will take care of accounting &
1531 	     * setting control bits if it's not caught up to us
1532 	     * yet.
1533 	     */
1534 	    if (++sc->sc_bufcnt == 2) {
1535 		/*
1536 		 * XXX
1537 		 * If we're too slow in reaction here,
1538 		 * the voice could be just approaching the
1539 		 * end of its run.  It should be set to stop,
1540 		 * so these adjustments might not DTRT.
1541 		 */
1542 		if (sc->sc_dmabuf == 0 &&
1543 		    sc->sc_playbuf == sc->sc_nbufs - 1) {
1544 		    /* player is just at the last buf, we're at the
1545 		       first.  Turn on looping, turn off rolling. */
1546 		    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1547 		    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL;
1548 		    playstats[playcntr].vaction = 3;
1549 		} else {
1550 		    /* player is at previous buf:
1551 		       turn on rolling, turn off looping */
1552 		    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1553 		    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1554 		    playstats[playcntr].vaction = 4;
1555 		}
1556 #ifdef GUSPLAYDEBUG
1557 		if (gusstats) {
1558 		  microtime(&playstats[playcntr].tv);
1559 		  playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1560 		  playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1561 		  playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1562 		  playstats[playcntr].playbuf = sc->sc_playbuf;
1563 		  playstats[playcntr].dmabuf = sc->sc_dmabuf;
1564 		  playstats[playcntr].bufcnt = sc->sc_bufcnt;
1565 		  playstats[playcntr].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT);
1566 		  playcntr = ++playcntr % NDMARECS;
1567 		}
1568 #endif
1569 		bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1570 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1571 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1572 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1573 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1574 	    }
1575 	}
1576 	gus_bufcnt[sc->sc_bufcnt-1]++;
1577 	/*
1578 	 * flip to the next DMA buffer
1579 	 */
1580 
1581 	sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs;
1582 	/*
1583 	 * See comments below about DMA admission control strategy.
1584 	 * We can call the upper level here if we have an
1585 	 * idle buffer (not currently playing) to DMA into.
1586 	 */
1587 	if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) {
1588 	    /* clean out to prevent double calls */
1589 	    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1590 	    void *arg = sc->sc_outarg;
1591 
1592 	    sc->sc_outarg = 0;
1593 	    sc->sc_dmaoutintr = 0;
1594 	    (*pfunc)(arg);
1595 	}
1596 }
1597 
1598 /*
1599  * Service voice interrupts
1600  */
1601 
1602 STATIC int
1603 gus_voice_intr(sc)
1604 	struct gus_softc *sc;
1605 {
1606 	bus_space_tag_t iot = sc->sc_iot;
1607 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1608 	int ignore = 0, voice, rval = 0;
1609 	unsigned char intr, status;
1610 
1611 	/*
1612 	 * The point of this may not be obvious at first.  A voice can
1613 	 * interrupt more than once; according to the GUS SDK we are supposed
1614 	 * to ignore multiple interrupts for the same voice.
1615 	 */
1616 
1617 	while(1) {
1618 		SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
1619 		intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
1620 
1621 		if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1622 			== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1623 			/*
1624 			 * No more interrupts, time to return
1625 			 */
1626 		 	return rval;
1627 
1628 		if ((intr & GUSMASK_WIRQ_VOICE) == 0) {
1629 
1630 		    /*
1631 		     * We've got a voice interrupt.  Ignore previous
1632 		     * interrupts by the same voice.
1633 		     */
1634 
1635 		    rval = 1;
1636 		    voice = intr & GUSMASK_WIRQ_VOICEMASK;
1637 
1638 		    if ((1 << voice) & ignore)
1639 			break;
1640 
1641 		    ignore |= 1 << voice;
1642 
1643 		    /*
1644 		     * If the voice is stopped, then force it to stop
1645 		     * (this stops it from continuously generating IRQs)
1646 		     */
1647 
1648 		    SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL+0x80);
1649 		    status = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
1650 		    if (status & GUSMASK_VOICE_STOPPED) {
1651 			if (voice != GUS_VOICE_LEFT) {
1652 			    DMAPRINTF(("%s: spurious voice %d stop?\n",
1653 				       sc->sc_dev.dv_xname, voice));
1654 			    gus_stop_voice(sc, voice, 0);
1655 			    continue;
1656 			}
1657 			gus_stop_voice(sc, voice, 1);
1658 			/* also kill right voice */
1659 			gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1660 			sc->sc_bufcnt--; /* it finished a buffer */
1661 			if (sc->sc_bufcnt > 0) {
1662 			    /*
1663 			     * probably a race to get here: the voice
1664 			     * stopped while the DMA code was just trying to
1665 			     * get the next buffer in place.
1666 			     * Start the voice again.
1667 			     */
1668 			    printf("%s: stopped voice not drained? (%x)\n",
1669 				   sc->sc_dev.dv_xname, sc->sc_bufcnt);
1670 			    gus_falsestops++;
1671 
1672 			    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1673 			    gus_start_playing(sc, sc->sc_playbuf);
1674 			} else if (sc->sc_bufcnt < 0) {
1675 #ifdef DDB
1676 			    printf("%s: negative bufcnt in stopped voice\n",
1677 				   sc->sc_dev.dv_xname);
1678 			    Debugger();
1679 #else
1680 			    panic("%s: negative bufcnt in stopped voice",
1681 				  sc->sc_dev.dv_xname);
1682 #endif
1683 			} else {
1684 			    sc->sc_playbuf = -1; /* none are active */
1685 			    gus_stops++;
1686 			}
1687 			/* fall through to callback and admit another
1688 			   buffer.... */
1689 		    } else if (sc->sc_bufcnt != 0) {
1690 			/*
1691 			 * This should always be taken if the voice
1692 			 * is not stopped.
1693 			 */
1694 			gus_continues++;
1695 			if (gus_continue_playing(sc, voice)) {
1696 				/*
1697 				 * we shouldn't have continued--active DMA
1698 				 * is in the way in the ring, for
1699 				 * some as-yet undebugged reason.
1700 				 */
1701 				gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1702 				/* also kill right voice */
1703 				gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1704 				sc->sc_playbuf = -1;
1705 				gus_stops++;
1706 			}
1707 		    }
1708 		    /*
1709 		     * call the upper level to send on down another
1710 		     * block. We do admission rate control as follows:
1711 		     *
1712 		     * When starting up output (in the first N
1713 		     * blocks), call the upper layer after the DMA is
1714 		     * complete (see above in gus_dmaout_intr()).
1715 		     *
1716 		     * When output is already in progress and we have
1717 		     * no more GUS buffers to use for DMA, the DMA
1718 		     * output routines do not call the upper layer.
1719 		     * Instead, we call the DMA completion routine
1720 		     * here, after the voice interrupts indicating
1721 		     * that it's finished with a buffer.
1722 		     *
1723 		     * However, don't call anything here if the DMA
1724 		     * output flag is set, (which shouldn't happen)
1725 		     * because we'll squish somebody else's DMA if
1726 		     * that's the case.  When DMA is done, it will
1727 		     * call back if there is a spare buffer.
1728 		     */
1729 		    if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) {
1730 			if (sc->sc_dmaoutintr == stereo_dmaintr)
1731 			    printf("gusdmaout botch?\n");
1732 			else {
1733 			    /* clean out to avoid double calls */
1734 			    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1735 			    void *arg = sc->sc_outarg;
1736 
1737 			    sc->sc_outarg = 0;
1738 			    sc->sc_dmaoutintr = 0;
1739 			    (*pfunc)(arg);
1740 			}
1741 		    }
1742 		}
1743 
1744 		/*
1745 		 * Ignore other interrupts for now
1746 		 */
1747 	}
1748 	return 0;
1749 }
1750 
1751 STATIC void
1752 gus_start_playing(sc, bufno)
1753 	struct gus_softc *sc;
1754 	int bufno;
1755 {
1756 	bus_space_tag_t iot = sc->sc_iot;
1757 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1758 	/*
1759 	 * Start the voices playing, with buffer BUFNO.
1760 	 */
1761 
1762 	/*
1763 	 * Loop or roll if we have buffers ready.
1764 	 */
1765 
1766 	if (sc->sc_bufcnt == 1) {
1767 		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
1768 		sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1769 	} else {
1770 		if (bufno == sc->sc_nbufs - 1) {
1771 			sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1772 			sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1773 		} else {
1774 			sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1775 			sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1776 		}
1777 	}
1778 
1779 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1780 
1781 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1782 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1783 
1784 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1785 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1786 
1787 	sc->sc_voc[GUS_VOICE_LEFT].current_addr =
1788 		GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
1789 	sc->sc_voc[GUS_VOICE_LEFT].end_addr =
1790 		sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
1791 	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
1792 		sc->sc_voc[GUS_VOICE_LEFT].current_addr +
1793 		(gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
1794 	/*
1795 	 * set up right channel to just loop forever, no interrupts,
1796 	 * starting at the buffer we just filled.  We'll feed it data
1797 	 * at the same time as left channel.
1798 	 */
1799 	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
1800 	sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1801 
1802 #ifdef GUSPLAYDEBUG
1803 	if (gusstats) {
1804 		microtime(&playstats[playcntr].tv);
1805 		playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
1806 
1807 		playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1808 		playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1809 		playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1810 		playstats[playcntr].playbuf = bufno;
1811 		playstats[playcntr].dmabuf = sc->sc_dmabuf;
1812 		playstats[playcntr].bufcnt = sc->sc_bufcnt;
1813 		playstats[playcntr].vaction = 5;
1814 		playcntr = ++playcntr % NDMARECS;
1815 	}
1816 #endif
1817 
1818 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
1819 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1820 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
1821 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1822 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
1823 
1824 	gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
1825 	gus_start_voice(sc, GUS_VOICE_LEFT, 1);
1826 	if (sc->sc_playbuf == -1)
1827 		/* mark start of playing */
1828 		sc->sc_playbuf = bufno;
1829 }
1830 
1831 STATIC int
1832 gus_continue_playing(sc, voice)
1833 	struct gus_softc *sc;
1834 	int voice;
1835 {
1836 	bus_space_tag_t iot = sc->sc_iot;
1837 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1838 
1839 	/*
1840 	 * stop this voice from interrupting while we work.
1841 	 */
1842 
1843 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1844 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
1845 
1846 	/*
1847 	 * update playbuf to point to the buffer the hardware just started
1848 	 * playing
1849 	 */
1850 	sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1851 
1852 	/*
1853 	 * account for buffer just finished
1854 	 */
1855 	if (--sc->sc_bufcnt == 0) {
1856 		DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
1857 	}
1858 	if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
1859 		printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
1860 		return 1;
1861 	}
1862 
1863 	/*
1864 	 * Select the end of the buffer based on the currently active
1865 	 * buffer, [plus extra contiguous buffers (if ready)].
1866 	 */
1867 
1868 	/*
1869 	 * set endpoint at end of buffer we just started playing.
1870 	 *
1871 	 * The total gets -1 because end addrs are one less than you might
1872 	 * think (the end_addr is the address of the last sample to play)
1873 	 */
1874 	gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
1875 			sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
1876 
1877 	if (sc->sc_bufcnt < 2) {
1878 		/*
1879 		 * Clear out the loop and roll flags, and rotate the currently
1880 		 * playing buffer.  That way, if we don't manage to get more
1881 		 * data before this buffer finishes, we'll just stop.
1882 		 */
1883 		sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1884 		sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1885 		playstats[playcntr].vaction = 0;
1886 	} else {
1887 		/*
1888 		 * We have some buffers to play.  set LOOP if we're on the
1889 		 * last buffer in the ring, otherwise set ROLL.
1890 		 */
1891 		if (sc->sc_playbuf == sc->sc_nbufs - 1) {
1892 			sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
1893 			sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1894 			playstats[playcntr].vaction = 1;
1895 		} else {
1896 			sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1897 			sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
1898 			playstats[playcntr].vaction = 2;
1899 		}
1900 	}
1901 #ifdef GUSPLAYDEBUG
1902 	if (gusstats) {
1903 		microtime(&playstats[playcntr].tv);
1904 		playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
1905 
1906 		playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
1907 		playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
1908 		playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
1909 		playstats[playcntr].playbuf = sc->sc_playbuf;
1910 		playstats[playcntr].dmabuf = sc->sc_dmabuf;
1911 		playstats[playcntr].bufcnt = sc->sc_bufcnt;
1912 		playcntr = ++playcntr % NDMARECS;
1913 	}
1914 #endif
1915 
1916 	/*
1917 	 * (re-)set voice parameters.  This will reenable interrupts from this
1918 	 * voice.
1919 	 */
1920 
1921 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1922 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1923 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1924 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
1925 	return 0;
1926 }
1927 
1928 /*
1929  * Send/receive data into GUS's DRAM using DMA.  Called at splgus()
1930  */
1931 
1932 STATIC void
1933 gusdmaout(sc, flags, gusaddr, buffaddr, length)
1934 	struct gus_softc *sc;
1935 	int flags, length;
1936 	u_long gusaddr;
1937 	caddr_t buffaddr;
1938 {
1939 	unsigned char c = (unsigned char) flags;
1940 	bus_space_tag_t iot = sc->sc_iot;
1941 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1942 
1943 	DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
1944 
1945 	sc->sc_gusaddr = gusaddr;
1946 
1947 	/*
1948 	 * If we're using a 16 bit DMA channel, we have to jump through some
1949 	 * extra hoops; this includes translating the DRAM address a bit
1950 	 */
1951 
1952 	if (sc->sc_drq >= 4) {
1953 		c |= GUSMASK_DMA_WIDTH;
1954 		gusaddr = convert_to_16bit(gusaddr);
1955 	}
1956 
1957 	/*
1958 	 * Add flag bits that we always set - fast DMA, enable IRQ
1959 	 */
1960 
1961 	c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ;
1962 
1963 	/*
1964 	 * Make sure the GUS _isn't_ setup for DMA
1965 	 */
1966 
1967  	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1968 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
1969 
1970 	/*
1971 	 * Tell the PC DMA controller to start doing DMA
1972 	 */
1973 
1974 	sc->sc_dmaoutaddr = (u_char *) buffaddr;
1975 	sc->sc_dmaoutcnt = length;
1976 	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
1977 	    NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
1978 
1979 	/*
1980 	 * Set up DMA address - use the upper 16 bits ONLY
1981 	 */
1982 
1983 	sc->sc_flags |= GUS_DMAOUT_ACTIVE;
1984 
1985  	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_START);
1986  	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (int) (gusaddr >> 4));
1987 
1988  	/*
1989  	 * Tell the GUS to start doing DMA
1990  	 */
1991 
1992  	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1993 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, c);
1994 
1995 	/*
1996 	 * XXX If we don't finish in one second, give up...
1997 	 */
1998 	untimeout(gus_dmaout_timeout, sc); /* flush old one, if there is one */
1999 	timeout(gus_dmaout_timeout, sc, hz);
2000 }
2001 
2002 /*
2003  * Start a voice playing on the GUS.  Called from interrupt handler at
2004  * splgus().
2005  */
2006 
2007 STATIC void
2008 gus_start_voice(sc, voice, intrs)
2009 	struct gus_softc *sc;
2010 	int voice;
2011 	int intrs;
2012 {
2013 	bus_space_tag_t iot = sc->sc_iot;
2014 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2015 	u_long start;
2016 	u_long current;
2017 	u_long end;
2018 
2019 	/*
2020 	 * Pick all the values for the voice out of the gus_voice struct
2021 	 * and use those to program the voice
2022 	 */
2023 
2024  	start = sc->sc_voc[voice].start_addr;
2025  	current = sc->sc_voc[voice].current_addr;
2026  	end = sc->sc_voc[voice].end_addr;
2027 
2028  	/*
2029 	 * If we're using 16 bit data, mangle the addresses a bit
2030 	 */
2031 
2032 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) {
2033 	        /* -1 on start so that we get onto sample boundary--other
2034 		   code always sets it for 1-byte rollover protection */
2035 		start = convert_to_16bit(start-1);
2036 		current = convert_to_16bit(current);
2037 		end = convert_to_16bit(end);
2038 	}
2039 
2040 	/*
2041 	 * Select the voice we want to use, and program the data addresses
2042 	 */
2043 
2044 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
2045 
2046 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
2047 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(start));
2048 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
2049 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(start));
2050 
2051 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
2052 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(current));
2053 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
2054 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(current));
2055 
2056 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
2057 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(end));
2058 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
2059 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(end));
2060 
2061 	/*
2062 	 * (maybe) enable interrupts, disable voice stopping
2063 	 */
2064 
2065 	if (intrs) {
2066 		sc->sc_flags |= GUS_PLAYING; /* playing is about to start */
2067 		sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ;
2068 		DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags));
2069 	} else
2070 		sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ;
2071 	sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED |
2072 		GUSMASK_STOP_VOICE);
2073 
2074 	/*
2075 	 * Tell the GUS about it.  Note that we're doing volume ramping here
2076 	 * from 0 up to the set volume to help reduce clicks.
2077 	 */
2078 
2079 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
2080 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2081 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
2082 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
2083 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
2084 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x00);
2085 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
2086 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 63);
2087 
2088 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
2089 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2090 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
2091 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2092 	delay(50);
2093 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
2094 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2095 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
2096 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2097 
2098 }
2099 
2100 /*
2101  * Stop a given voice.  called at splgus()
2102  */
2103 
2104 STATIC void
2105 gus_stop_voice(sc, voice, intrs_too)
2106 	struct gus_softc *sc;
2107 	int voice;
2108 	int intrs_too;
2109 {
2110 	bus_space_tag_t iot = sc->sc_iot;
2111 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2112 
2113 	sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
2114 		GUSMASK_STOP_VOICE;
2115 	if (intrs_too) {
2116 	  sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ);
2117 	  /* no more DMA to do */
2118 	  sc->sc_flags &= ~GUS_PLAYING;
2119 	}
2120 	DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
2121 
2122 	guspoke(iot, ioh2, 0L, 0);
2123 
2124 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
2125 
2126 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
2127 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2128 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
2129 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2130 	delay(100);
2131 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
2132 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2133 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
2134 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2135 
2136 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
2137 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2138 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
2139 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2140 
2141 }
2142 
2143 
2144 /*
2145  * Set the volume of a given voice.  Called at splgus().
2146  */
2147 STATIC void
2148 gus_set_volume(sc, voice, volume)
2149 	struct gus_softc *sc;
2150 	int voice, volume;
2151 {
2152 	bus_space_tag_t iot = sc->sc_iot;
2153 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2154 	unsigned int gusvol;
2155 
2156 	gusvol = gus_log_volumes[volume < 512 ? volume : 511];
2157 
2158 	sc->sc_voc[voice].current_volume = gusvol;
2159 
2160 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
2161 
2162 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
2163 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2164 
2165 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
2166 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2167 
2168 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
2169 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
2170 	delay(500);
2171 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
2172 
2173 }
2174 
2175 /*
2176  * Interface to the audio layer.
2177  */
2178 
2179 int
2180 gusmax_set_params(addr, setmode, usemode, p, r)
2181 	void *addr;
2182 	int setmode, usemode;
2183 	struct audio_params *p, *r;
2184 {
2185 	struct ad1848_softc *ac = addr;
2186 	struct gus_softc *sc = ac->parent;
2187 	int error;
2188 
2189 	error = ad1848_set_params(ac, setmode, usemode, p, r);
2190 	if (error)
2191 		return error;
2192 	error = gus_set_params(sc, setmode, usemode, p, r);
2193 	return error;
2194 }
2195 
2196 int
2197 gus_set_params(addr, setmode, usemode, p, r)
2198 	void *addr;
2199 	int setmode, usemode;
2200 	struct audio_params *p, *r;
2201 {
2202 	struct gus_softc *sc = addr;
2203 	int s;
2204 
2205 	switch (p->encoding) {
2206 	case AUDIO_ENCODING_ULAW:
2207 	case AUDIO_ENCODING_ALAW:
2208 	case AUDIO_ENCODING_SLINEAR_LE:
2209 	case AUDIO_ENCODING_ULINEAR_LE:
2210 	case AUDIO_ENCODING_SLINEAR_BE:
2211 	case AUDIO_ENCODING_ULINEAR_BE:
2212 		break;
2213 	default:
2214 		return (EINVAL);
2215 	}
2216 
2217 	s = splaudio();
2218 
2219 	if (p->precision == 8) {
2220 		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
2221 		sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
2222 	} else {
2223 		sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
2224 		sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
2225 	}
2226 
2227 	sc->sc_encoding = p->encoding;
2228 	sc->sc_precision = p->precision;
2229 	sc->sc_channels = p->channels;
2230 
2231 	splx(s);
2232 
2233 	if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
2234 		p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
2235 	if (setmode & AUMODE_RECORD)
2236 		sc->sc_irate = p->sample_rate;
2237 	if (setmode & AUMODE_PLAY)
2238 		sc->sc_orate = p->sample_rate;
2239 
2240 	switch (p->encoding) {
2241 	case AUDIO_ENCODING_ULAW:
2242 		p->sw_code = mulaw_to_ulinear8;
2243 		r->sw_code = ulinear8_to_mulaw;
2244 		break;
2245 	case AUDIO_ENCODING_ALAW:
2246 		p->sw_code = alaw_to_ulinear8;
2247 		r->sw_code = ulinear8_to_alaw;
2248 		break;
2249 	case AUDIO_ENCODING_ULINEAR_BE:
2250 	case AUDIO_ENCODING_SLINEAR_BE:
2251 		r->sw_code = p->sw_code = swap_bytes;
2252 		break;
2253 	}
2254 
2255 	return 0;
2256 }
2257 
2258 /*
2259  * Interface to the audio layer - set the blocksize to the correct number
2260  * of units
2261  */
2262 
2263 int
2264 gusmax_round_blocksize(addr, blocksize)
2265 	void * addr;
2266 	int blocksize;
2267 {
2268 	struct ad1848_softc *ac = addr;
2269 	struct gus_softc *sc = ac->parent;
2270 
2271 /*	blocksize = ad1848_round_blocksize(ac, blocksize);*/
2272 	return gus_round_blocksize(sc, blocksize);
2273 }
2274 
2275 int
2276 gus_round_blocksize(addr, blocksize)
2277 	void * addr;
2278 	int blocksize;
2279 {
2280 	struct gus_softc *sc = addr;
2281 
2282 	DPRINTF(("gus_round_blocksize called\n"));
2283 
2284 	if ((sc->sc_encoding == AUDIO_ENCODING_ULAW ||
2285 	     sc->sc_encoding == AUDIO_ENCODING_ALAW) && blocksize > 32768)
2286 		blocksize = 32768;
2287 	else if (blocksize > 65536)
2288 		blocksize = 65536;
2289 
2290 	if ((blocksize % GUS_BUFFER_MULTIPLE) != 0)
2291 		blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) *
2292 			GUS_BUFFER_MULTIPLE;
2293 
2294 	/* set up temporary buffer to hold the deinterleave, if necessary
2295 	   for stereo output */
2296 	if (sc->sc_deintr_buf) {
2297 		FREE(sc->sc_deintr_buf, M_DEVBUF);
2298 		sc->sc_deintr_buf = NULL;
2299 	}
2300 	MALLOC(sc->sc_deintr_buf, void *, blocksize>>1, M_DEVBUF, M_WAITOK);
2301 
2302 	sc->sc_blocksize = blocksize;
2303 	/* multi-buffering not quite working yet. */
2304 	sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2;
2305 
2306 	gus_set_chan_addrs(sc);
2307 
2308 	return blocksize;
2309 }
2310 
2311 int
2312 gus_get_out_gain(addr)
2313 	caddr_t addr;
2314 {
2315 	struct gus_softc *sc = (struct gus_softc *) addr;
2316 
2317 	DPRINTF(("gus_get_out_gain called\n"));
2318 	return sc->sc_ogain / 2;
2319 }
2320 
2321 STATIC inline void gus_set_voices(sc, voices)
2322 struct gus_softc *sc;
2323 int voices;
2324 {
2325 	bus_space_tag_t iot = sc->sc_iot;
2326 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2327 	/*
2328 	 * Select the active number of voices
2329 	 */
2330 
2331 	SELECT_GUS_REG(iot, ioh2, GUSREG_ACTIVE_VOICES);
2332 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (voices-1) | 0xc0);
2333 
2334 	sc->sc_voices = voices;
2335 }
2336 
2337 /*
2338  * Actually set the settings of various values on the card
2339  */
2340 
2341 int
2342 gusmax_commit_settings(addr)
2343 	void * addr;
2344 {
2345 	struct ad1848_softc *ac = addr;
2346 	struct gus_softc *sc = ac->parent;
2347 	int error;
2348 
2349 	error = ad1848_commit_settings(ac);
2350 	if (error)
2351 		return error;
2352 	return gus_commit_settings(sc);
2353 }
2354 
2355 /*
2356  * Commit the settings.  Called at normal IPL.
2357  */
2358 int
2359 gus_commit_settings(addr)
2360 	void * addr;
2361 {
2362 	struct gus_softc *sc = addr;
2363 	int s;
2364 
2365 	DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
2366 
2367 
2368 	s = splgus();
2369 
2370 	gus_set_recrate(sc, sc->sc_irate);
2371 	gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain);
2372 	gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain);
2373 	gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate);
2374 	gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate);
2375 	splx(s);
2376 	gus_set_chan_addrs(sc);
2377 
2378 	return 0;
2379 }
2380 
2381 STATIC void
2382 gus_set_chan_addrs(sc)
2383 struct gus_softc *sc;
2384 {
2385 	/*
2386 	 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS
2387 	 * ram.
2388 	 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk,
2389 	 * and both left & right channels play the same buffer.
2390 	 *
2391 	 * For stereo, each channel gets a contiguous half of the memory,
2392 	 * and each has sc_nbufs buffers of size blocksize/2.
2393 	 * Stereo data are deinterleaved in main memory before the DMA out
2394 	 * routines are called to queue the output.
2395 	 *
2396 	 * The blocksize per channel is kept in sc_chanblocksize.
2397 	 */
2398 	if (sc->sc_channels == 2)
2399 	    sc->sc_chanblocksize = sc->sc_blocksize/2;
2400 	else
2401 	    sc->sc_chanblocksize = sc->sc_blocksize;
2402 
2403 	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
2404 	sc->sc_voc[GUS_VOICE_RIGHT].start_addr =
2405 	    (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0)
2406 	      + GUS_MEM_OFFSET - 1;
2407 	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
2408 	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1;
2409 	sc->sc_voc[GUS_VOICE_RIGHT].end_addr =
2410 	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr +
2411 	    sc->sc_nbufs * sc->sc_chanblocksize;
2412 
2413 }
2414 
2415 /*
2416  * Set the sample rate of the given voice.  Called at splgus().
2417  */
2418 
2419 STATIC void
2420 gus_set_samprate(sc, voice, freq)
2421 	struct gus_softc *sc;
2422 	int voice, freq;
2423 {
2424 	bus_space_tag_t iot = sc->sc_iot;
2425 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2426 	unsigned int fc;
2427 	u_long temp, f = (u_long) freq;
2428 
2429 	/*
2430 	 * calculate fc based on the number of active voices;
2431 	 * we need to use longs to preserve enough bits
2432 	 */
2433 
2434 	temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES];
2435 
2436  	fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp);
2437 
2438  	fc <<= 1;
2439 
2440 
2441 	/*
2442 	 * Program the voice frequency, and set it in the voice data record
2443 	 */
2444 
2445 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
2446 	SELECT_GUS_REG(iot, ioh2, GUSREG_FREQ_CONTROL);
2447 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, fc);
2448 
2449 	sc->sc_voc[voice].rate = freq;
2450 
2451 }
2452 
2453 /*
2454  * Set the sample rate of the recording frequency.  Formula is from the GUS
2455  * SDK.  Called at splgus().
2456  */
2457 
2458 STATIC void
2459 gus_set_recrate(sc, rate)
2460 	struct gus_softc *sc;
2461 	u_long rate;
2462 {
2463 	bus_space_tag_t iot = sc->sc_iot;
2464 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2465 	u_char realrate;
2466 	DPRINTF(("gus_set_recrate %lu\n", rate));
2467 
2468 #if 0
2469 	realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */
2470 #endif
2471 	realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
2472 
2473 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_FREQ);
2474  	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, realrate);
2475 }
2476 
2477 /*
2478  * Interface to the audio layer - turn the output on or off.  Note that some
2479  * of these bits are flipped in the register
2480  */
2481 
2482 int
2483 gusmax_speaker_ctl(addr, newstate)
2484 	void * addr;
2485 	int newstate;
2486 {
2487 	struct ad1848_softc *sc = addr;
2488 	return gus_speaker_ctl(sc->parent, newstate);
2489 }
2490 
2491 int
2492 gus_speaker_ctl(addr, newstate)
2493 	void * addr;
2494 	int newstate;
2495 {
2496 	struct gus_softc *sc = (struct gus_softc *) addr;
2497 	bus_space_tag_t iot = sc->sc_iot;
2498 	bus_space_handle_t ioh1 = sc->sc_ioh1;
2499 
2500 	/* Line out bit is flipped: 0 enables, 1 disables */
2501 	if ((newstate == SPKR_ON) &&
2502 	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
2503 		sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
2504 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2505 	}
2506 	if ((newstate == SPKR_OFF) &&
2507 	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
2508 		sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
2509 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2510 	}
2511 
2512 	return 0;
2513 }
2514 
2515 STATIC int
2516 gus_linein_ctl(addr, newstate)
2517 	void * addr;
2518 	int newstate;
2519 {
2520 	struct gus_softc *sc = (struct gus_softc *) addr;
2521 	bus_space_tag_t iot = sc->sc_iot;
2522 	bus_space_handle_t ioh1 = sc->sc_ioh1;
2523 
2524 	/* Line in bit is flipped: 0 enables, 1 disables */
2525 	if ((newstate == SPKR_ON) &&
2526 	    (sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
2527 		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
2528 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2529 	}
2530 	if ((newstate == SPKR_OFF) &&
2531 	    (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
2532 		sc->sc_mixcontrol |= GUSMASK_LINE_IN;
2533 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2534 	}
2535 
2536 	return 0;
2537 }
2538 
2539 STATIC int
2540 gus_mic_ctl(addr, newstate)
2541 	void * addr;
2542 	int newstate;
2543 {
2544 	struct gus_softc *sc = (struct gus_softc *) addr;
2545 	bus_space_tag_t iot = sc->sc_iot;
2546 	bus_space_handle_t ioh1 = sc->sc_ioh1;
2547 
2548 	/* Mic bit is normal: 1 enables, 0 disables */
2549 	if ((newstate == SPKR_ON) &&
2550 	    (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
2551 		sc->sc_mixcontrol |= GUSMASK_MIC_IN;
2552 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2553 	}
2554 	if ((newstate == SPKR_OFF) &&
2555 	    (sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
2556 		sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
2557 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2558 	}
2559 
2560 	return 0;
2561 }
2562 
2563 /*
2564  * Set the end address of a give voice.  Called at splgus()
2565  */
2566 
2567 STATIC void
2568 gus_set_endaddr(sc, voice, addr)
2569 	struct gus_softc *sc;
2570 	int voice;
2571 	u_long addr;
2572 {
2573 	bus_space_tag_t iot = sc->sc_iot;
2574 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2575 
2576 	sc->sc_voc[voice].end_addr = addr;
2577 
2578 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2579 		addr = convert_to_16bit(addr);
2580 
2581 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
2582 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
2583 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
2584 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
2585 
2586 }
2587 
2588 #ifdef GUSPLAYDEBUG
2589 /*
2590  * Set current address.  called at splgus()
2591  */
2592 STATIC void
2593 gus_set_curaddr(sc, voice, addr)
2594 	struct gus_softc *sc;
2595 	int voice;
2596 	u_long addr;
2597 {
2598 	bus_space_tag_t iot = sc->sc_iot;
2599 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2600 
2601 	sc->sc_voc[voice].current_addr = addr;
2602 
2603 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2604 		addr = convert_to_16bit(addr);
2605 
2606 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
2607 
2608 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
2609 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
2610 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
2611 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
2612 
2613 }
2614 
2615 /*
2616  * Get current GUS playback address.  Called at splgus().
2617  */
2618 STATIC u_long
2619 gus_get_curaddr(sc, voice)
2620 	struct gus_softc *sc;
2621 	int voice;
2622 {
2623 	bus_space_tag_t iot = sc->sc_iot;
2624 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2625 	u_long addr;
2626 
2627 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
2628 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
2629 	addr = (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) & 0x1fff) << 7;
2630 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
2631 	addr |= (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) >> 9L) & 0x7f;
2632 
2633 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2634 	    addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
2635 	DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
2636 		 voice, addr, sc->sc_voc[voice].end_addr));
2637 	/* XXX sanity check the address? */
2638 
2639 	return(addr);
2640 }
2641 #endif
2642 
2643 /*
2644  * Convert an address value to a "16 bit" value - why this is necessary I
2645  * have NO idea
2646  */
2647 
2648 STATIC u_long
2649 convert_to_16bit(address)
2650 	u_long address;
2651 {
2652 	u_long old_address;
2653 
2654 	old_address = address;
2655 	address >>= 1;
2656 	address &= 0x0001ffffL;
2657 	address |= (old_address & 0x000c0000L);
2658 
2659 	return (address);
2660 }
2661 
2662 /*
2663  * Write a value into the GUS's DRAM
2664  */
2665 
2666 STATIC void
2667 guspoke(iot, ioh2, address, value)
2668 	bus_space_tag_t iot;
2669 	bus_space_handle_t ioh2;
2670 	long address;
2671 	unsigned char value;
2672 {
2673 
2674 	/*
2675 	 * Select the DRAM address
2676 	 */
2677 
2678  	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
2679  	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2680  	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
2681  	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2682 
2683 	/*
2684 	 * Actually write the data
2685 	 */
2686 
2687 	bus_space_write_1(iot, ioh2, GUS_DRAM_DATA, value);
2688 }
2689 
2690 /*
2691  * Read a value from the GUS's DRAM
2692  */
2693 
2694 STATIC unsigned char
2695 guspeek(iot, ioh2, address)
2696 	bus_space_tag_t iot;
2697 	bus_space_handle_t ioh2;
2698 	u_long address;
2699 {
2700 
2701 	/*
2702 	 * Select the DRAM address
2703 	 */
2704 
2705  	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
2706  	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2707  	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
2708  	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2709 
2710 	/*
2711 	 * Read in the data from the board
2712 	 */
2713 
2714 	return (unsigned char) bus_space_read_1(iot, ioh2, GUS_DRAM_DATA);
2715 }
2716 
2717 /*
2718  * Reset the Gravis UltraSound card, completely
2719  */
2720 
2721 STATIC void
2722 gusreset(sc, voices)
2723 	struct gus_softc *sc;
2724 	int voices;
2725 {
2726 	bus_space_tag_t iot = sc->sc_iot;
2727 	bus_space_handle_t ioh1 = sc->sc_ioh1;
2728 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2729 	bus_space_handle_t ioh4 = sc->sc_ioh4;
2730 	int i,s;
2731 
2732 	s = splgus();
2733 
2734 	/*
2735 	 * Reset the GF1 chip
2736 	 */
2737 
2738 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
2739 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2740 
2741 	delay(500);
2742 
2743 	/*
2744 	 * Release reset
2745 	 */
2746 
2747 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
2748 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
2749 
2750 	delay(500);
2751 
2752 	/*
2753 	 * Reset MIDI port as well
2754 	 */
2755 
2756 	bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, MIDI_RESET);
2757 
2758 	delay(500);
2759 
2760 	bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, 0x00);
2761 
2762 	/*
2763 	 * Clear interrupts
2764 	 */
2765 
2766 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
2767 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2768 	SELECT_GUS_REG(iot, ioh2, GUSREG_TIMER_CONTROL);
2769 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2770 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2771 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2772 
2773 	gus_set_voices(sc, voices);
2774 
2775 	bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
2776 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
2777 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2778 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2779 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2780 	SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
2781 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2782 
2783 	/*
2784 	 * Reset voice specific information
2785 	 */
2786 
2787 	for(i = 0; i < voices; i++) {
2788 		bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) i);
2789 
2790 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
2791 
2792 		sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
2793 			GUSMASK_STOP_VOICE;
2794 
2795 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
2796 
2797 		sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
2798 				GUSMASK_STOP_VOLUME;
2799 
2800 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
2801 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
2802 
2803 		delay(100);
2804 
2805 		gus_set_samprate(sc, i, 8000);
2806 		SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
2807 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2808 		SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
2809 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2810 		SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
2811 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2812 		SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
2813 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2814 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
2815 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x01);
2816 		SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
2817 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x10);
2818 		SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
2819 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0xe0);
2820 		SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
2821 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2822 
2823 		SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
2824 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2825 		SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
2826 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2827 		SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
2828 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x07);
2829 	}
2830 
2831 	/*
2832 	 * Clear out any pending IRQs
2833 	 */
2834 
2835 	bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
2836 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
2837 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2838 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2839 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2840 	SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
2841 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2842 
2843 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
2844 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
2845 		GUSMASK_IRQ_ENABLE);
2846 
2847 	splx(s);
2848 }
2849 
2850 
2851 STATIC void
2852 gus_init_cs4231(sc)
2853 	struct gus_softc *sc;
2854 {
2855 	bus_space_tag_t iot = sc->sc_iot;
2856 	bus_space_handle_t ioh1 = sc->sc_ioh1;
2857 	int port = sc->sc_iobase;
2858 	u_char ctrl;
2859 
2860 	ctrl = (port & 0xf0) >> 4;	/* set port address middle nibble */
2861 	/*
2862 	 * The codec is a bit weird--swapped dma channels.
2863 	 */
2864 	ctrl |= GUS_MAX_CODEC_ENABLE;
2865 	if (sc->sc_drq >= 4)
2866 		ctrl |= GUS_MAX_RECCHAN16;
2867 	if (sc->sc_recdrq >= 4)
2868 		ctrl |= GUS_MAX_PLAYCHAN16;
2869 
2870 	bus_space_write_1(iot, ioh1, GUS_MAX_CTRL, ctrl);
2871 
2872 	sc->sc_codec.sc_iot = sc->sc_iot;
2873 	sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
2874 
2875 	if (ad1848_probe(&sc->sc_codec) == 0) {
2876 		sc->sc_flags &= ~GUS_CODEC_INSTALLED;
2877 	} else {
2878 		struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
2879 		sc->sc_flags |= GUS_CODEC_INSTALLED;
2880 		sc->sc_codec.parent = sc;
2881 		sc->sc_codec.sc_drq = sc->sc_recdrq;
2882 		sc->sc_codec.sc_recdrq = sc->sc_drq;
2883 		gus_hw_if = gusmax_hw_if;
2884 		/* enable line in and mic in the GUS mixer; the codec chip
2885 		   will do the real mixing for them. */
2886 		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
2887 		sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
2888 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2889 
2890 		ad1848_attach(&sc->sc_codec);
2891 		/* turn on pre-MUX microphone gain. */
2892 		ad1848_set_mic_gain(&sc->sc_codec, &vol);
2893 	}
2894 }
2895 
2896 
2897 /*
2898  * Return info about the audio device, for the AUDIO_GETINFO ioctl
2899  */
2900 
2901 int
2902 gus_getdev(addr, dev)
2903 	void * addr;
2904 	struct audio_device *dev;
2905 {
2906 	*dev = gus_device;
2907 	return 0;
2908 }
2909 
2910 /*
2911  * stubs (XXX)
2912  */
2913 
2914 int
2915 gus_set_in_gain(addr, gain, balance)
2916 	caddr_t addr;
2917 	u_int gain;
2918 	u_char balance;
2919 {
2920 	DPRINTF(("gus_set_in_gain called\n"));
2921 	return 0;
2922 }
2923 
2924 int
2925 gus_get_in_gain(addr)
2926 	caddr_t addr;
2927 {
2928 	DPRINTF(("gus_get_in_gain called\n"));
2929 	return 0;
2930 }
2931 
2932 int
2933 gusmax_dma_input(addr, buf, size, callback, arg)
2934 	void * addr;
2935 	void *buf;
2936 	int size;
2937 	void (*callback) __P((void *));
2938 	void *arg;
2939 {
2940 	struct ad1848_softc *sc = addr;
2941 	return gus_dma_input(sc->parent, buf, size, callback, arg);
2942 }
2943 
2944 /*
2945  * Start sampling the input source into the requested DMA buffer.
2946  * Called at splgus(), either from top-half or from interrupt handler.
2947  */
2948 int
2949 gus_dma_input(addr, buf, size, callback, arg)
2950 	void * addr;
2951 	void *buf;
2952 	int size;
2953 	void (*callback) __P((void *));
2954 	void *arg;
2955 {
2956 	struct gus_softc *sc = addr;
2957 	bus_space_tag_t iot = sc->sc_iot;
2958 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2959 	u_char dmac;
2960 	DMAPRINTF(("gus_dma_input called\n"));
2961 
2962 	/*
2963 	 * Sample SIZE bytes of data from the card, into buffer at BUF.
2964 	 */
2965 
2966 	if (sc->sc_precision == 16)
2967 	    return EINVAL;		/* XXX */
2968 
2969 	/* set DMA modes */
2970 	dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START;
2971 	if (sc->sc_recdrq >= 4)
2972 		dmac |= GUSMASK_SAMPLE_DATA16;
2973 	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
2974 	    sc->sc_encoding == AUDIO_ENCODING_ALAW ||
2975 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
2976 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
2977 	    dmac |= GUSMASK_SAMPLE_INVBIT;
2978 	if (sc->sc_channels == 2)
2979 	    dmac |= GUSMASK_SAMPLE_STEREO;
2980 	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
2981 	    NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
2982 
2983 	DMAPRINTF(("gus_dma_input isa_dmastarted\n"));
2984 	sc->sc_flags |= GUS_DMAIN_ACTIVE;
2985 	sc->sc_dmainintr = callback;
2986 	sc->sc_inarg = arg;
2987 	sc->sc_dmaincnt = size;
2988 	sc->sc_dmainaddr = buf;
2989 
2990 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2991 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, dmac);	/* Go! */
2992 
2993 
2994 	DMAPRINTF(("gus_dma_input returning\n"));
2995 
2996 	return 0;
2997 }
2998 
2999 STATIC int
3000 gus_dmain_intr(sc)
3001 	struct gus_softc *sc;
3002 {
3003         void (*callback) __P((void *));
3004 	void *arg;
3005 
3006 	DMAPRINTF(("gus_dmain_intr called\n"));
3007 	if (sc->sc_dmainintr) {
3008 	    isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
3009 	    callback = sc->sc_dmainintr;
3010 	    arg = sc->sc_inarg;
3011 
3012 	    sc->sc_dmainaddr = 0;
3013 	    sc->sc_dmaincnt = 0;
3014 	    sc->sc_dmainintr = 0;
3015 	    sc->sc_inarg = 0;
3016 
3017 	    sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3018 	    DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
3019 	    (*callback)(arg);
3020 	    return 1;
3021 	} else {
3022 	    DMAPRINTF(("gus_dmain_intr false?\n"));
3023 	    return 0;			/* XXX ??? */
3024 	}
3025 }
3026 
3027 int
3028 gusmax_halt_out_dma(addr)
3029 	void * addr;
3030 {
3031 	struct ad1848_softc *sc = addr;
3032 	return gus_halt_out_dma(sc->parent);
3033 }
3034 
3035 
3036 int
3037 gusmax_halt_in_dma(addr)
3038 	void * addr;
3039 {
3040 	struct ad1848_softc *sc = addr;
3041 	return gus_halt_in_dma(sc->parent);
3042 }
3043 
3044 /*
3045  * Stop any DMA output.  Called at splgus().
3046  */
3047 int
3048 gus_halt_out_dma(addr)
3049 	void * addr;
3050 {
3051 	struct gus_softc *sc = addr;
3052 	bus_space_tag_t iot = sc->sc_iot;
3053 	bus_space_handle_t ioh2 = sc->sc_ioh2;
3054 
3055 	DMAPRINTF(("gus_halt_out_dma called\n"));
3056 	/*
3057 	 * Make sure the GUS _isn't_ setup for DMA
3058 	 */
3059 
3060  	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
3061 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
3062 
3063 	untimeout(gus_dmaout_timeout, sc);
3064 	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
3065 	sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
3066 	sc->sc_dmaoutintr = 0;
3067 	sc->sc_outarg = 0;
3068 	sc->sc_dmaoutaddr = 0;
3069 	sc->sc_dmaoutcnt = 0;
3070 	sc->sc_dmabuf = 0;
3071 	sc->sc_bufcnt = 0;
3072 	sc->sc_playbuf = -1;
3073 	/* also stop playing */
3074 	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
3075 	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
3076 
3077 	return 0;
3078 }
3079 
3080 /*
3081  * Stop any DMA output.  Called at splgus().
3082  */
3083 int
3084 gus_halt_in_dma(addr)
3085 	void * addr;
3086 {
3087 	struct gus_softc *sc = addr;
3088 	bus_space_tag_t iot = sc->sc_iot;
3089 	bus_space_handle_t ioh2 = sc->sc_ioh2;
3090 	DMAPRINTF(("gus_halt_in_dma called\n"));
3091 
3092 	/*
3093 	 * Make sure the GUS _isn't_ setup for DMA
3094 	 */
3095 
3096  	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
3097 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH,
3098 	     bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
3099 
3100 	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
3101 	sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3102 	sc->sc_dmainintr = 0;
3103 	sc->sc_inarg = 0;
3104 	sc->sc_dmainaddr = 0;
3105 	sc->sc_dmaincnt = 0;
3106 
3107 	return 0;
3108 }
3109 
3110 STATIC __inline int
3111 gus_to_vol(cp, vol)
3112 	mixer_ctrl_t *cp;
3113 	struct ad1848_volume *vol;
3114 {
3115 	if (cp->un.value.num_channels == 1) {
3116 		vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3117 		return(1);
3118 	}
3119 	else if (cp->un.value.num_channels == 2) {
3120 		vol->left  = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
3121 		vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
3122 		return(1);
3123 	}
3124 	return(0);
3125 }
3126 
3127 STATIC __inline int
3128 gus_from_vol(cp, vol)
3129 	mixer_ctrl_t *cp;
3130 	struct ad1848_volume *vol;
3131 {
3132 	if (cp->un.value.num_channels == 1) {
3133 		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
3134 		return(1);
3135 	}
3136 	else if (cp->un.value.num_channels == 2) {
3137 		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
3138 		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
3139 		return(1);
3140 	}
3141 	return(0);
3142 }
3143 
3144 STATIC int
3145 gusmax_mixer_get_port(addr, cp)
3146 	void *addr;
3147 	mixer_ctrl_t *cp;
3148 {
3149 	struct ad1848_softc *ac = addr;
3150 	struct gus_softc *sc = ac->parent;
3151 	struct ad1848_volume vol;
3152 	int error = EINVAL;
3153 
3154 	DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev));
3155 
3156 	switch (cp->dev) {
3157 #if 0 /* use mono level instead */
3158 	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3159 		if (cp->type == AUDIO_MIXER_VALUE) {
3160 			error = ad1848_get_mic_gain(ac, &vol);
3161 			if (!error)
3162 				gus_from_vol(cp, &vol);
3163 		}
3164 		break;
3165 #endif
3166 
3167 	case GUSMAX_DAC_LVL:		/* dac out */
3168 		if (cp->type == AUDIO_MIXER_VALUE) {
3169 			error = ad1848_get_aux1_gain(ac, &vol);
3170 			if (!error)
3171 				gus_from_vol(cp, &vol);
3172 		}
3173 		break;
3174 
3175 	case GUSMAX_LINE_IN_LVL:	/* line in */
3176 		if (cp->type == AUDIO_MIXER_VALUE) {
3177 			error = cs4231_get_linein_gain(ac, &vol);
3178 			if (!error)
3179 				gus_from_vol(cp, &vol);
3180 		}
3181 		break;
3182 
3183 	case GUSMAX_MONO_LVL:	/* mono */
3184 		if (cp->type == AUDIO_MIXER_VALUE &&
3185 		    cp->un.value.num_channels == 1) {
3186 			error = cs4231_get_mono_gain(ac, &vol);
3187 			if (!error)
3188 				gus_from_vol(cp, &vol);
3189 		}
3190 		break;
3191 
3192 	case GUSMAX_CD_LVL:	/* CD */
3193 		if (cp->type == AUDIO_MIXER_VALUE) {
3194 			error = ad1848_get_aux2_gain(ac, &vol);
3195 			if (!error)
3196 				gus_from_vol(cp, &vol);
3197 		}
3198 		break;
3199 
3200 	case GUSMAX_MONITOR_LVL:	/* monitor level */
3201 		if (cp->type == AUDIO_MIXER_VALUE &&
3202 		    cp->un.value.num_channels == 1) {
3203 			error = ad1848_get_mon_gain(ac, &vol);
3204 			if (!error)
3205 				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
3206 					vol.left;
3207 		}
3208 		break;
3209 
3210 	case GUSMAX_OUT_LVL:	/* output level */
3211 		if (cp->type == AUDIO_MIXER_VALUE) {
3212 			error = ad1848_get_out_gain(ac, &vol);
3213 			if (!error)
3214 				gus_from_vol(cp, &vol);
3215 		}
3216 		break;
3217 
3218 	case GUSMAX_SPEAKER_LVL:	/* fake speaker for mute naming */
3219 		if (cp->type == AUDIO_MIXER_VALUE) {
3220 			if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
3221 				vol.left = vol.right = AUDIO_MAX_GAIN;
3222 			else
3223 				vol.left = vol.right = AUDIO_MIN_GAIN;
3224 			error = 0;
3225 			gus_from_vol(cp, &vol);
3226 		}
3227 		break;
3228 
3229 	case GUSMAX_LINE_IN_MUTE:
3230 		if (cp->type == AUDIO_MIXER_ENUM) {
3231 			cp->un.ord = ac->line_mute;
3232 			error = 0;
3233 		}
3234 		break;
3235 
3236 
3237 	case GUSMAX_DAC_MUTE:
3238 		if (cp->type == AUDIO_MIXER_ENUM) {
3239 			cp->un.ord = ac->aux1_mute;
3240 			error = 0;
3241 		}
3242 		break;
3243 
3244 	case GUSMAX_CD_MUTE:
3245 		if (cp->type == AUDIO_MIXER_ENUM) {
3246 			cp->un.ord = ac->aux2_mute;
3247 			error = 0;
3248 		}
3249 		break;
3250 
3251 	case GUSMAX_MONO_MUTE:
3252 		if (cp->type == AUDIO_MIXER_ENUM) {
3253 			cp->un.ord = ac->mono_mute;
3254 			error = 0;
3255 		}
3256 		break;
3257 
3258 	case GUSMAX_MONITOR_MUTE:
3259 		if (cp->type == AUDIO_MIXER_ENUM) {
3260 			cp->un.ord = ac->mon_mute;
3261 			error = 0;
3262 		}
3263 		break;
3264 
3265 	case GUSMAX_SPEAKER_MUTE:
3266 		if (cp->type == AUDIO_MIXER_ENUM) {
3267 			cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3268 			error = 0;
3269 		}
3270 		break;
3271 
3272 	case GUSMAX_REC_LVL:		/* record level */
3273 		if (cp->type == AUDIO_MIXER_VALUE) {
3274 			error = ad1848_get_rec_gain(ac, &vol);
3275 			if (!error)
3276 				gus_from_vol(cp, &vol);
3277 		}
3278 		break;
3279 
3280 	case GUSMAX_RECORD_SOURCE:
3281 		if (cp->type == AUDIO_MIXER_ENUM) {
3282 			cp->un.ord = ad1848_get_rec_port(ac);
3283 			error = 0;
3284 		}
3285 		break;
3286 
3287 	default:
3288 		error = ENXIO;
3289 		break;
3290 	}
3291 
3292 	return(error);
3293 }
3294 
3295 STATIC int
3296 gus_mixer_get_port(addr, cp)
3297 	void *addr;
3298 	mixer_ctrl_t *cp;
3299 {
3300 	struct gus_softc *sc = addr;
3301 	struct ics2101_softc *ic = &sc->sc_mixer;
3302 	struct ad1848_volume vol;
3303 	int error = EINVAL;
3304 
3305 	DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type));
3306 
3307 	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3308 		return ENXIO;
3309 
3310 	switch (cp->dev) {
3311 
3312 	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3313 		if (cp->type == AUDIO_MIXER_ENUM) {
3314 			if (HAS_MIXER(sc))
3315 				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3316 			else
3317 				cp->un.ord =
3318 				    sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1;
3319 			error = 0;
3320 		}
3321 		break;
3322 
3323 	case GUSICS_LINE_IN_MUTE:
3324 		if (cp->type == AUDIO_MIXER_ENUM) {
3325 			if (HAS_MIXER(sc))
3326 				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3327 			else
3328 				cp->un.ord =
3329 				    sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0;
3330 			error = 0;
3331 		}
3332 		break;
3333 
3334 	case GUSICS_MASTER_MUTE:
3335 		if (cp->type == AUDIO_MIXER_ENUM) {
3336 			if (HAS_MIXER(sc))
3337 				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3338 			else
3339 				cp->un.ord =
3340 				    sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3341 			error = 0;
3342 		}
3343 		break;
3344 
3345 	case GUSICS_DAC_MUTE:
3346 		if (cp->type == AUDIO_MIXER_ENUM) {
3347 			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3348 			error = 0;
3349 		}
3350 		break;
3351 
3352 	case GUSICS_CD_MUTE:
3353 		if (cp->type == AUDIO_MIXER_ENUM) {
3354 			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3355 			error = 0;
3356 		}
3357 		break;
3358 
3359 	case GUSICS_MASTER_LVL:
3360 		if (cp->type == AUDIO_MIXER_VALUE) {
3361 			vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3362 			vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
3363 			if (gus_from_vol(cp, &vol))
3364 				error = 0;
3365 		}
3366 		break;
3367 
3368 	case GUSICS_MIC_IN_LVL:	/* Microphone */
3369 		if (cp->type == AUDIO_MIXER_VALUE) {
3370 			vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3371 			vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
3372 			if (gus_from_vol(cp, &vol))
3373 				error = 0;
3374 		}
3375 		break;
3376 
3377 	case GUSICS_LINE_IN_LVL:	/* line in */
3378 		if (cp->type == AUDIO_MIXER_VALUE) {
3379 			vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3380 			vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
3381 			if (gus_from_vol(cp, &vol))
3382 				error = 0;
3383 		}
3384 		break;
3385 
3386 
3387 	case GUSICS_CD_LVL:
3388 		if (cp->type == AUDIO_MIXER_VALUE) {
3389 			vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3390 			vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
3391 			if (gus_from_vol(cp, &vol))
3392 				error = 0;
3393 		}
3394 		break;
3395 
3396 	case GUSICS_DAC_LVL:		/* dac out */
3397 		if (cp->type == AUDIO_MIXER_VALUE) {
3398 			vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3399 			vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
3400 			if (gus_from_vol(cp, &vol))
3401 				error = 0;
3402 		}
3403 		break;
3404 
3405 
3406 	case GUSICS_RECORD_SOURCE:
3407 		if (cp->type == AUDIO_MIXER_ENUM) {
3408 			/* Can't set anything else useful, sigh. */
3409 			 cp->un.ord = 0;
3410 		}
3411 		break;
3412 
3413 	default:
3414 		return ENXIO;
3415 	    /*NOTREACHED*/
3416 	}
3417 	return error;
3418 }
3419 
3420 STATIC void
3421 gusics_master_mute(ic, mute)
3422 	struct ics2101_softc *ic;
3423 	int mute;
3424 {
3425 	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute);
3426 	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
3427 }
3428 
3429 STATIC void
3430 gusics_mic_mute(ic, mute)
3431 	struct ics2101_softc *ic;
3432 	int mute;
3433 {
3434 	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute);
3435 	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
3436 }
3437 
3438 STATIC void
3439 gusics_linein_mute(ic, mute)
3440 	struct ics2101_softc *ic;
3441 	int mute;
3442 {
3443 	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute);
3444 	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
3445 }
3446 
3447 STATIC void
3448 gusics_cd_mute(ic, mute)
3449 	struct ics2101_softc *ic;
3450 	int mute;
3451 {
3452 	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute);
3453 	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
3454 }
3455 
3456 STATIC void
3457 gusics_dac_mute(ic, mute)
3458 	struct ics2101_softc *ic;
3459 	int mute;
3460 {
3461 	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute);
3462 	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
3463 }
3464 
3465 STATIC int
3466 gusmax_mixer_set_port(addr, cp)
3467 	void *addr;
3468 	mixer_ctrl_t *cp;
3469 {
3470 	struct ad1848_softc *ac = addr;
3471 	struct gus_softc *sc = ac->parent;
3472 	struct ad1848_volume vol;
3473 	int error = EINVAL;
3474 
3475 	DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3476 
3477 	switch (cp->dev) {
3478 #if 0
3479 	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3480 		if (cp->type == AUDIO_MIXER_VALUE &&
3481 		    cp->un.value.num_channels == 1) {
3482 			/* XXX enable/disable pre-MUX fixed gain */
3483 			if (gus_to_vol(cp, &vol))
3484 				error = ad1848_set_mic_gain(ac, &vol);
3485 		}
3486 		break;
3487 #endif
3488 
3489 	case GUSMAX_DAC_LVL:		/* dac out */
3490 		if (cp->type == AUDIO_MIXER_VALUE) {
3491 			if (gus_to_vol(cp, &vol))
3492 				error = ad1848_set_aux1_gain(ac, &vol);
3493 		}
3494 		break;
3495 
3496 	case GUSMAX_LINE_IN_LVL:	/* line in */
3497 		if (cp->type == AUDIO_MIXER_VALUE) {
3498 			if (gus_to_vol(cp, &vol))
3499 				error = cs4231_set_linein_gain(ac, &vol);
3500 		}
3501 		break;
3502 
3503 	case GUSMAX_MONO_LVL:	/* mic/mono in */
3504 		if (cp->type == AUDIO_MIXER_VALUE &&
3505 		    cp->un.value.num_channels == 1) {
3506 			if (gus_to_vol(cp, &vol))
3507 				error = cs4231_set_mono_gain(ac, &vol);
3508 		}
3509 		break;
3510 
3511 	case GUSMAX_CD_LVL:	/* CD: AUX2 */
3512 		if (cp->type == AUDIO_MIXER_VALUE) {
3513 			if (gus_to_vol(cp, &vol))
3514 				error = ad1848_set_aux2_gain(ac, &vol);
3515 		}
3516 		break;
3517 
3518 	case GUSMAX_MONITOR_LVL:
3519 		if (cp->type == AUDIO_MIXER_VALUE &&
3520 		    cp->un.value.num_channels == 1) {
3521 			vol.left  = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3522 			error = ad1848_set_mon_gain(ac, &vol);
3523 		}
3524 		break;
3525 
3526 	case GUSMAX_OUT_LVL:	/* output volume */
3527 		if (cp->type == AUDIO_MIXER_VALUE) {
3528 			if (gus_to_vol(cp, &vol))
3529 				error = ad1848_set_out_gain(ac, &vol);
3530 		}
3531 		break;
3532 
3533 	case GUSMAX_SPEAKER_LVL:
3534 		if (cp->type == AUDIO_MIXER_VALUE &&
3535 		    cp->un.value.num_channels == 1) {
3536 			if (gus_to_vol(cp, &vol)) {
3537 				gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
3538 						SPKR_ON : SPKR_OFF);
3539 				error = 0;
3540 			}
3541 		}
3542 		break;
3543 
3544 	case GUSMAX_LINE_IN_MUTE:
3545 		if (cp->type == AUDIO_MIXER_ENUM) {
3546 			ac->line_mute = cp->un.ord ? 1 : 0;
3547 			DPRINTF(("line mute %d\n", cp->un.ord));
3548 			cs4231_mute_line(ac, ac->line_mute);
3549 			gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON);
3550 			error = 0;
3551 		}
3552 		break;
3553 
3554 	case GUSMAX_DAC_MUTE:
3555 		if (cp->type == AUDIO_MIXER_ENUM) {
3556 			ac->aux1_mute = cp->un.ord ? 1 : 0;
3557 			DPRINTF(("dac mute %d\n", cp->un.ord));
3558 			ad1848_mute_aux1(ac, ac->aux1_mute);
3559 			error = 0;
3560 		}
3561 		break;
3562 
3563 	case GUSMAX_CD_MUTE:
3564 		if (cp->type == AUDIO_MIXER_ENUM) {
3565 			ac->aux2_mute = cp->un.ord ? 1 : 0;
3566 			DPRINTF(("cd mute %d\n", cp->un.ord));
3567 			ad1848_mute_aux2(ac, ac->aux2_mute);
3568 			error = 0;
3569 		}
3570 		break;
3571 
3572 	case GUSMAX_MONO_MUTE:	/* Microphone */
3573 		if (cp->type == AUDIO_MIXER_ENUM) {
3574 			ac->mono_mute = cp->un.ord ? 1 : 0;
3575 			DPRINTF(("mono mute %d\n", cp->un.ord));
3576 			cs4231_mute_mono(ac, ac->mono_mute);
3577 			gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON);
3578 			error = 0;
3579 		}
3580 		break;
3581 
3582 	case GUSMAX_MONITOR_MUTE:
3583 		if (cp->type == AUDIO_MIXER_ENUM) {
3584 			ac->mon_mute = cp->un.ord ? 1 : 0;
3585 			DPRINTF(("mono mute %d\n", cp->un.ord));
3586 			cs4231_mute_monitor(ac, ac->mon_mute);
3587 			error = 0;
3588 		}
3589 		break;
3590 
3591 	case GUSMAX_SPEAKER_MUTE:
3592 		if (cp->type == AUDIO_MIXER_ENUM) {
3593 			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3594 			error = 0;
3595 		}
3596 		break;
3597 
3598 	case GUSMAX_REC_LVL:		/* record level */
3599 		if (cp->type == AUDIO_MIXER_VALUE) {
3600 			if (gus_to_vol(cp, &vol))
3601 				error = ad1848_set_rec_gain(ac, &vol);
3602 		}
3603 		break;
3604 
3605 	case GUSMAX_RECORD_SOURCE:
3606 		if (cp->type == AUDIO_MIXER_ENUM) {
3607 			error = ad1848_set_rec_port(ac, cp->un.ord);
3608 		}
3609 		break;
3610 
3611 	default:
3612 		return ENXIO;
3613 	    /*NOTREACHED*/
3614     }
3615     return error;
3616 }
3617 
3618 STATIC int
3619 gus_mixer_set_port(addr, cp)
3620 	void *addr;
3621 	mixer_ctrl_t *cp;
3622 {
3623 	struct gus_softc *sc = addr;
3624 	struct ics2101_softc *ic = &sc->sc_mixer;
3625 	struct ad1848_volume vol;
3626 	int error = EINVAL;
3627 
3628 	DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3629 
3630 	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3631 		return ENXIO;
3632 
3633 	switch (cp->dev) {
3634 
3635 	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3636 		if (cp->type == AUDIO_MIXER_ENUM) {
3637 			DPRINTF(("mic mute %d\n", cp->un.ord));
3638 			if (HAS_MIXER(sc)) {
3639 				gusics_mic_mute(ic, cp->un.ord);
3640 			}
3641 			gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3642 			error = 0;
3643 		}
3644 		break;
3645 
3646 	case GUSICS_LINE_IN_MUTE:
3647 		if (cp->type == AUDIO_MIXER_ENUM) {
3648 			DPRINTF(("linein mute %d\n", cp->un.ord));
3649 			if (HAS_MIXER(sc)) {
3650 				gusics_linein_mute(ic, cp->un.ord);
3651 			}
3652 			gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3653 			error = 0;
3654 		}
3655 		break;
3656 
3657 	case GUSICS_MASTER_MUTE:
3658 		if (cp->type == AUDIO_MIXER_ENUM) {
3659 			DPRINTF(("master mute %d\n", cp->un.ord));
3660 			if (HAS_MIXER(sc)) {
3661 				gusics_master_mute(ic, cp->un.ord);
3662 			}
3663 			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3664 			error = 0;
3665 		}
3666 		break;
3667 
3668 	case GUSICS_DAC_MUTE:
3669 		if (cp->type == AUDIO_MIXER_ENUM) {
3670 			gusics_dac_mute(ic, cp->un.ord);
3671 			error = 0;
3672 		}
3673 		break;
3674 
3675 	case GUSICS_CD_MUTE:
3676 		if (cp->type == AUDIO_MIXER_ENUM) {
3677 			gusics_cd_mute(ic, cp->un.ord);
3678 			error = 0;
3679 		}
3680 		break;
3681 
3682 	case GUSICS_MASTER_LVL:
3683 		if (cp->type == AUDIO_MIXER_VALUE) {
3684 			if (gus_to_vol(cp, &vol)) {
3685 				ics2101_mix_attenuate(ic,
3686 						      GUSMIX_CHAN_MASTER,
3687 						      ICSMIX_LEFT,
3688 						      vol.left);
3689 				ics2101_mix_attenuate(ic,
3690 						      GUSMIX_CHAN_MASTER,
3691 						      ICSMIX_RIGHT,
3692 						      vol.right);
3693 				error = 0;
3694 			}
3695 		}
3696 		break;
3697 
3698 	case GUSICS_MIC_IN_LVL:	/* Microphone */
3699 		if (cp->type == AUDIO_MIXER_VALUE) {
3700 			if (gus_to_vol(cp, &vol)) {
3701 				ics2101_mix_attenuate(ic,
3702 						      GUSMIX_CHAN_MIC,
3703 						      ICSMIX_LEFT,
3704 						      vol.left);
3705 				ics2101_mix_attenuate(ic,
3706 						      GUSMIX_CHAN_MIC,
3707 						      ICSMIX_RIGHT,
3708 						      vol.right);
3709 				error = 0;
3710 			}
3711 		}
3712 		break;
3713 
3714 	case GUSICS_LINE_IN_LVL:	/* line in */
3715 		if (cp->type == AUDIO_MIXER_VALUE) {
3716 			if (gus_to_vol(cp, &vol)) {
3717 				ics2101_mix_attenuate(ic,
3718 						      GUSMIX_CHAN_LINE,
3719 						      ICSMIX_LEFT,
3720 						      vol.left);
3721 				ics2101_mix_attenuate(ic,
3722 						      GUSMIX_CHAN_LINE,
3723 						      ICSMIX_RIGHT,
3724 						      vol.right);
3725 				error = 0;
3726 			}
3727 		}
3728 		break;
3729 
3730 
3731 	case GUSICS_CD_LVL:
3732 		if (cp->type == AUDIO_MIXER_VALUE) {
3733 			if (gus_to_vol(cp, &vol)) {
3734 				ics2101_mix_attenuate(ic,
3735 						      GUSMIX_CHAN_CD,
3736 						      ICSMIX_LEFT,
3737 						      vol.left);
3738 				ics2101_mix_attenuate(ic,
3739 						      GUSMIX_CHAN_CD,
3740 						      ICSMIX_RIGHT,
3741 						      vol.right);
3742 				error = 0;
3743 			}
3744 		}
3745 		break;
3746 
3747 	case GUSICS_DAC_LVL:		/* dac out */
3748 		if (cp->type == AUDIO_MIXER_VALUE) {
3749 			if (gus_to_vol(cp, &vol)) {
3750 				ics2101_mix_attenuate(ic,
3751 						      GUSMIX_CHAN_DAC,
3752 						      ICSMIX_LEFT,
3753 						      vol.left);
3754 				ics2101_mix_attenuate(ic,
3755 						      GUSMIX_CHAN_DAC,
3756 						      ICSMIX_RIGHT,
3757 						      vol.right);
3758 				error = 0;
3759 			}
3760 		}
3761 		break;
3762 
3763 
3764 	case GUSICS_RECORD_SOURCE:
3765 		if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) {
3766 			/* Can't set anything else useful, sigh. */
3767 			error = 0;
3768 		}
3769 		break;
3770 
3771 	default:
3772 		return ENXIO;
3773 	    /*NOTREACHED*/
3774 	}
3775 	return error;
3776 }
3777 
3778 STATIC int
3779 gus_get_props(addr)
3780 	void *addr;
3781 {
3782 	struct gus_softc *sc = addr;
3783 	return sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX;
3784 }
3785 
3786 STATIC int
3787 gusmax_get_props(addr)
3788 	void *addr;
3789 {
3790 	struct ad1848_softc *ac = addr;
3791 	return gus_get_props(ac->parent);
3792 }
3793 
3794 STATIC int
3795 gusmax_mixer_query_devinfo(addr, dip)
3796 	void *addr;
3797 	mixer_devinfo_t *dip;
3798 {
3799 	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
3800 
3801 	switch(dip->index) {
3802 #if 0
3803     case GUSMAX_MIC_IN_LVL:	/* Microphone */
3804 	dip->type = AUDIO_MIXER_VALUE;
3805 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3806 	dip->prev = AUDIO_MIXER_LAST;
3807 	dip->next = GUSMAX_MIC_IN_MUTE;
3808 	strcpy(dip->label.name, AudioNmicrophone);
3809 	dip->un.v.num_channels = 2;
3810 	strcpy(dip->un.v.units.name, AudioNvolume);
3811 	break;
3812 #endif
3813 
3814     case GUSMAX_MONO_LVL:	/* mono/microphone mixer */
3815 	dip->type = AUDIO_MIXER_VALUE;
3816 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3817 	dip->prev = AUDIO_MIXER_LAST;
3818 	dip->next = GUSMAX_MONO_MUTE;
3819 	strcpy(dip->label.name, AudioNmicrophone);
3820 	dip->un.v.num_channels = 1;
3821 	strcpy(dip->un.v.units.name, AudioNvolume);
3822 	break;
3823 
3824     case GUSMAX_DAC_LVL:		/*  dacout */
3825 	dip->type = AUDIO_MIXER_VALUE;
3826 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3827 	dip->prev = AUDIO_MIXER_LAST;
3828 	dip->next = GUSMAX_DAC_MUTE;
3829 	strcpy(dip->label.name, AudioNdac);
3830 	dip->un.v.num_channels = 2;
3831 	strcpy(dip->un.v.units.name, AudioNvolume);
3832 	break;
3833 
3834     case GUSMAX_LINE_IN_LVL:	/* line */
3835 	dip->type = AUDIO_MIXER_VALUE;
3836 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3837 	dip->prev = AUDIO_MIXER_LAST;
3838 	dip->next = GUSMAX_LINE_IN_MUTE;
3839 	strcpy(dip->label.name, AudioNline);
3840 	dip->un.v.num_channels = 2;
3841 	strcpy(dip->un.v.units.name, AudioNvolume);
3842 	break;
3843 
3844     case GUSMAX_CD_LVL:		/* cd */
3845 	dip->type = AUDIO_MIXER_VALUE;
3846 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3847 	dip->prev = AUDIO_MIXER_LAST;
3848 	dip->next = GUSMAX_CD_MUTE;
3849 	strcpy(dip->label.name, AudioNcd);
3850 	dip->un.v.num_channels = 2;
3851 	strcpy(dip->un.v.units.name, AudioNvolume);
3852 	break;
3853 
3854 
3855     case GUSMAX_MONITOR_LVL:	/* monitor level */
3856 	dip->type = AUDIO_MIXER_VALUE;
3857 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3858 	dip->next = GUSMAX_MONITOR_MUTE;
3859 	dip->prev = AUDIO_MIXER_LAST;
3860 	strcpy(dip->label.name, AudioNmonitor);
3861 	dip->un.v.num_channels = 1;
3862 	strcpy(dip->un.v.units.name, AudioNvolume);
3863 	break;
3864 
3865     case GUSMAX_OUT_LVL:		/* cs4231 output volume: not useful? */
3866 	dip->type = AUDIO_MIXER_VALUE;
3867 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3868 	dip->prev = dip->next = AUDIO_MIXER_LAST;
3869 	strcpy(dip->label.name, AudioNoutput);
3870 	dip->un.v.num_channels = 2;
3871 	strcpy(dip->un.v.units.name, AudioNvolume);
3872 	break;
3873 
3874     case GUSMAX_SPEAKER_LVL:		/* fake speaker volume */
3875 	dip->type = AUDIO_MIXER_VALUE;
3876 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3877 	dip->prev = AUDIO_MIXER_LAST;
3878 	dip->next = GUSMAX_SPEAKER_MUTE;
3879 	strcpy(dip->label.name, AudioNmaster);
3880 	dip->un.v.num_channels = 2;
3881 	strcpy(dip->un.v.units.name, AudioNvolume);
3882 	break;
3883 
3884     case GUSMAX_LINE_IN_MUTE:
3885 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3886 	dip->type = AUDIO_MIXER_ENUM;
3887 	dip->prev = GUSMAX_LINE_IN_LVL;
3888 	dip->next = AUDIO_MIXER_LAST;
3889 	goto mute;
3890 
3891     case GUSMAX_DAC_MUTE:
3892 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3893 	dip->type = AUDIO_MIXER_ENUM;
3894 	dip->prev = GUSMAX_DAC_LVL;
3895 	dip->next = AUDIO_MIXER_LAST;
3896 	goto mute;
3897 
3898     case GUSMAX_CD_MUTE:
3899 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3900 	dip->type = AUDIO_MIXER_ENUM;
3901 	dip->prev = GUSMAX_CD_LVL;
3902 	dip->next = AUDIO_MIXER_LAST;
3903 	goto mute;
3904 
3905     case GUSMAX_MONO_MUTE:
3906 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3907 	dip->type = AUDIO_MIXER_ENUM;
3908 	dip->prev = GUSMAX_MONO_LVL;
3909 	dip->next = AUDIO_MIXER_LAST;
3910 	goto mute;
3911 
3912     case GUSMAX_MONITOR_MUTE:
3913 	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3914 	dip->type = AUDIO_MIXER_ENUM;
3915 	dip->prev = GUSMAX_MONITOR_LVL;
3916 	dip->next = AUDIO_MIXER_LAST;
3917 	goto mute;
3918 
3919     case GUSMAX_SPEAKER_MUTE:
3920 	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3921 	dip->type = AUDIO_MIXER_ENUM;
3922 	dip->prev = GUSMAX_SPEAKER_LVL;
3923 	dip->next = AUDIO_MIXER_LAST;
3924     mute:
3925 	strcpy(dip->label.name, AudioNmute);
3926 	dip->un.e.num_mem = 2;
3927 	strcpy(dip->un.e.member[0].label.name, AudioNoff);
3928 	dip->un.e.member[0].ord = 0;
3929 	strcpy(dip->un.e.member[1].label.name, AudioNon);
3930 	dip->un.e.member[1].ord = 1;
3931 	break;
3932 
3933     case GUSMAX_REC_LVL:	/* record level */
3934 	dip->type = AUDIO_MIXER_VALUE;
3935 	dip->mixer_class = GUSMAX_RECORD_CLASS;
3936 	dip->prev = AUDIO_MIXER_LAST;
3937 	dip->next = GUSMAX_RECORD_SOURCE;
3938 	strcpy(dip->label.name, AudioNrecord);
3939 	dip->un.v.num_channels = 2;
3940 	strcpy(dip->un.v.units.name, AudioNvolume);
3941 	break;
3942 
3943     case GUSMAX_RECORD_SOURCE:
3944 	dip->mixer_class = GUSMAX_RECORD_CLASS;
3945 	dip->type = AUDIO_MIXER_ENUM;
3946 	dip->prev = GUSMAX_REC_LVL;
3947 	dip->next = AUDIO_MIXER_LAST;
3948 	strcpy(dip->label.name, AudioNsource);
3949 	dip->un.e.num_mem = 4;
3950 	strcpy(dip->un.e.member[0].label.name, AudioNoutput);
3951 	dip->un.e.member[0].ord = DAC_IN_PORT;
3952 	strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
3953 	dip->un.e.member[1].ord = MIC_IN_PORT;
3954 	strcpy(dip->un.e.member[2].label.name, AudioNdac);
3955 	dip->un.e.member[2].ord = AUX1_IN_PORT;
3956 	strcpy(dip->un.e.member[3].label.name, AudioNline);
3957 	dip->un.e.member[3].ord = LINE_IN_PORT;
3958 	break;
3959 
3960     case GUSMAX_INPUT_CLASS:			/* input class descriptor */
3961 	dip->type = AUDIO_MIXER_CLASS;
3962 	dip->mixer_class = GUSMAX_INPUT_CLASS;
3963 	dip->next = dip->prev = AUDIO_MIXER_LAST;
3964 	strcpy(dip->label.name, AudioCinputs);
3965 	break;
3966 
3967     case GUSMAX_OUTPUT_CLASS:			/* output class descriptor */
3968 	dip->type = AUDIO_MIXER_CLASS;
3969 	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3970 	dip->next = dip->prev = AUDIO_MIXER_LAST;
3971 	strcpy(dip->label.name, AudioCoutputs);
3972 	break;
3973 
3974     case GUSMAX_MONITOR_CLASS:			/* monitor class descriptor */
3975 	dip->type = AUDIO_MIXER_CLASS;
3976 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3977 	dip->next = dip->prev = AUDIO_MIXER_LAST;
3978 	strcpy(dip->label.name, AudioCmonitor);
3979 	break;
3980 
3981     case GUSMAX_RECORD_CLASS:			/* record source class */
3982 	dip->type = AUDIO_MIXER_CLASS;
3983 	dip->mixer_class = GUSMAX_RECORD_CLASS;
3984 	dip->next = dip->prev = AUDIO_MIXER_LAST;
3985 	strcpy(dip->label.name, AudioCrecord);
3986 	break;
3987 
3988     default:
3989 	return ENXIO;
3990 	/*NOTREACHED*/
3991     }
3992     DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
3993 	return 0;
3994 }
3995 
3996 STATIC int
3997 gus_mixer_query_devinfo(addr, dip)
3998 	void *addr;
3999 	mixer_devinfo_t *dip;
4000 {
4001 	struct gus_softc *sc = addr;
4002 
4003 	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
4004 
4005 	if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE)
4006 		return ENXIO;
4007 
4008 	switch(dip->index) {
4009 
4010 	case GUSICS_MIC_IN_LVL:	/* Microphone */
4011 		dip->type = AUDIO_MIXER_VALUE;
4012 		dip->mixer_class = GUSICS_INPUT_CLASS;
4013 		dip->prev = AUDIO_MIXER_LAST;
4014 		dip->next = GUSICS_MIC_IN_MUTE;
4015 		strcpy(dip->label.name, AudioNmicrophone);
4016 		dip->un.v.num_channels = 2;
4017 		strcpy(dip->un.v.units.name, AudioNvolume);
4018 		break;
4019 
4020 	case GUSICS_LINE_IN_LVL:	/* line */
4021 		dip->type = AUDIO_MIXER_VALUE;
4022 		dip->mixer_class = GUSICS_INPUT_CLASS;
4023 		dip->prev = AUDIO_MIXER_LAST;
4024 		dip->next = GUSICS_LINE_IN_MUTE;
4025 		strcpy(dip->label.name, AudioNline);
4026 		dip->un.v.num_channels = 2;
4027 		strcpy(dip->un.v.units.name, AudioNvolume);
4028 		break;
4029 
4030 	case GUSICS_CD_LVL:		/* cd */
4031 		dip->type = AUDIO_MIXER_VALUE;
4032 		dip->mixer_class = GUSICS_INPUT_CLASS;
4033 		dip->prev = AUDIO_MIXER_LAST;
4034 		dip->next = GUSICS_CD_MUTE;
4035 		strcpy(dip->label.name, AudioNcd);
4036 		dip->un.v.num_channels = 2;
4037 		strcpy(dip->un.v.units.name, AudioNvolume);
4038 		break;
4039 
4040 	case GUSICS_DAC_LVL:		/*  dacout */
4041 		dip->type = AUDIO_MIXER_VALUE;
4042 		dip->mixer_class = GUSICS_INPUT_CLASS;
4043 		dip->prev = AUDIO_MIXER_LAST;
4044 		dip->next = GUSICS_DAC_MUTE;
4045 		strcpy(dip->label.name, AudioNdac);
4046 		dip->un.v.num_channels = 2;
4047 		strcpy(dip->un.v.units.name, AudioNvolume);
4048 		break;
4049 
4050 	case GUSICS_MASTER_LVL:		/*  master output */
4051 		dip->type = AUDIO_MIXER_VALUE;
4052 		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4053 		dip->prev = AUDIO_MIXER_LAST;
4054 		dip->next = GUSICS_MASTER_MUTE;
4055 		strcpy(dip->label.name, AudioNmaster);
4056 		dip->un.v.num_channels = 2;
4057 		strcpy(dip->un.v.units.name, AudioNvolume);
4058 		break;
4059 
4060 
4061 	case GUSICS_LINE_IN_MUTE:
4062 		dip->mixer_class = GUSICS_INPUT_CLASS;
4063 		dip->type = AUDIO_MIXER_ENUM;
4064 		dip->prev = GUSICS_LINE_IN_LVL;
4065 		dip->next = AUDIO_MIXER_LAST;
4066 		goto mute;
4067 
4068 	case GUSICS_DAC_MUTE:
4069 		dip->mixer_class = GUSICS_INPUT_CLASS;
4070 		dip->type = AUDIO_MIXER_ENUM;
4071 		dip->prev = GUSICS_DAC_LVL;
4072 		dip->next = AUDIO_MIXER_LAST;
4073 		goto mute;
4074 
4075 	case GUSICS_CD_MUTE:
4076 		dip->mixer_class = GUSICS_INPUT_CLASS;
4077 		dip->type = AUDIO_MIXER_ENUM;
4078 		dip->prev = GUSICS_CD_LVL;
4079 		dip->next = AUDIO_MIXER_LAST;
4080 		goto mute;
4081 
4082 	case GUSICS_MIC_IN_MUTE:
4083 		dip->mixer_class = GUSICS_INPUT_CLASS;
4084 		dip->type = AUDIO_MIXER_ENUM;
4085 		dip->prev = GUSICS_MIC_IN_LVL;
4086 		dip->next = AUDIO_MIXER_LAST;
4087 		goto mute;
4088 
4089 	case GUSICS_MASTER_MUTE:
4090 		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4091 		dip->type = AUDIO_MIXER_ENUM;
4092 		dip->prev = GUSICS_MASTER_LVL;
4093 		dip->next = AUDIO_MIXER_LAST;
4094 mute:
4095 		strcpy(dip->label.name, AudioNmute);
4096 		dip->un.e.num_mem = 2;
4097 		strcpy(dip->un.e.member[0].label.name, AudioNoff);
4098 		dip->un.e.member[0].ord = 0;
4099 		strcpy(dip->un.e.member[1].label.name, AudioNon);
4100 		dip->un.e.member[1].ord = 1;
4101 		break;
4102 
4103 	case GUSICS_RECORD_SOURCE:
4104 		dip->mixer_class = GUSICS_RECORD_CLASS;
4105 		dip->type = AUDIO_MIXER_ENUM;
4106 		dip->prev = dip->next = AUDIO_MIXER_LAST;
4107 		strcpy(dip->label.name, AudioNsource);
4108 		dip->un.e.num_mem = 1;
4109 		strcpy(dip->un.e.member[0].label.name, AudioNoutput);
4110 		dip->un.e.member[0].ord = GUSICS_MASTER_LVL;
4111 		break;
4112 
4113 	case GUSICS_INPUT_CLASS:
4114 		dip->type = AUDIO_MIXER_CLASS;
4115 		dip->mixer_class = GUSICS_INPUT_CLASS;
4116 		dip->next = dip->prev = AUDIO_MIXER_LAST;
4117 		strcpy(dip->label.name, AudioCinputs);
4118 		break;
4119 
4120 	case GUSICS_OUTPUT_CLASS:
4121 		dip->type = AUDIO_MIXER_CLASS;
4122 		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4123 		dip->next = dip->prev = AUDIO_MIXER_LAST;
4124 		strcpy(dip->label.name, AudioCoutputs);
4125 		break;
4126 
4127 	case GUSICS_RECORD_CLASS:
4128 		dip->type = AUDIO_MIXER_CLASS;
4129 		dip->mixer_class = GUSICS_RECORD_CLASS;
4130 		dip->next = dip->prev = AUDIO_MIXER_LAST;
4131 		strcpy(dip->label.name, AudioCrecord);
4132 		break;
4133 
4134 	default:
4135 		return ENXIO;
4136 	/*NOTREACHED*/
4137 	}
4138 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4139 	return 0;
4140 }
4141 
4142 STATIC int
4143 gus_query_encoding(addr, fp)
4144 	void *addr;
4145 	struct audio_encoding *fp;
4146 {
4147 	switch (fp->index) {
4148 	case 0:
4149 		strcpy(fp->name, AudioEmulaw);
4150 		fp->encoding = AUDIO_ENCODING_ULAW;
4151 		fp->precision = 8;
4152 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4153 		break;
4154 	case 1:
4155 		strcpy(fp->name, AudioEslinear);
4156 		fp->encoding = AUDIO_ENCODING_SLINEAR;
4157 		fp->precision = 8;
4158 		fp->flags = 0;
4159 		break;
4160 	case 2:
4161 		strcpy(fp->name, AudioEslinear_le);
4162 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
4163 		fp->precision = 16;
4164 		fp->flags = 0;
4165 		break;
4166 	case 3:
4167 		strcpy(fp->name, AudioEulinear);
4168 		fp->encoding = AUDIO_ENCODING_ULINEAR;
4169 		fp->precision = 8;
4170 		fp->flags = 0;
4171 		break;
4172 	case 4:
4173 		strcpy(fp->name, AudioEulinear_le);
4174 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
4175 		fp->precision = 16;
4176 		fp->flags = 0;
4177 		break;
4178 	case 5:
4179 		strcpy(fp->name, AudioEslinear_be);
4180 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
4181 		fp->precision = 16;
4182 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4183 		break;
4184 	case 6:
4185 		strcpy(fp->name, AudioEulinear_be);
4186 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
4187 		fp->precision = 16;
4188 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4189 		break;
4190 	case 7:
4191 		strcpy(fp->name, AudioEalaw);
4192 		fp->encoding = AUDIO_ENCODING_ALAW;
4193 		fp->precision = 8;
4194 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4195 		break;
4196 
4197 	default:
4198 		return(EINVAL);
4199 		/*NOTREACHED*/
4200 	}
4201 	return (0);
4202 }
4203 
4204 /*
4205  * Setup the ICS mixer in "transparent" mode: reset everything to a sensible
4206  * level.  Levels as suggested by GUS SDK code.
4207  */
4208 
4209 STATIC void
4210 gus_init_ics2101(sc)
4211 	struct gus_softc *sc;
4212 {
4213 	struct ics2101_softc *ic = &sc->sc_mixer;
4214 	sc->sc_mixer.sc_iot = sc->sc_iot;
4215 	sc->sc_mixer.sc_selio = GUS_MIXER_SELECT;
4216 	sc->sc_mixer.sc_selio_ioh = sc->sc_ioh3;
4217 	sc->sc_mixer.sc_dataio = GUS_MIXER_DATA;
4218 	sc->sc_mixer.sc_dataio_ioh = sc->sc_ioh2;
4219 	sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
4220 
4221 	ics2101_mix_attenuate(ic,
4222 			      GUSMIX_CHAN_MIC,
4223 			      ICSMIX_LEFT,
4224 			      ICSMIX_MIN_ATTN);
4225 	ics2101_mix_attenuate(ic,
4226 			      GUSMIX_CHAN_MIC,
4227 			      ICSMIX_RIGHT,
4228 			      ICSMIX_MIN_ATTN);
4229 	/*
4230 	 * Start with microphone muted by the mixer...
4231 	 */
4232 	gusics_mic_mute(ic, 1);
4233 
4234 	/* ... and enabled by the GUS master mix control */
4235 	gus_mic_ctl(sc, SPKR_ON);
4236 
4237 	ics2101_mix_attenuate(ic,
4238 			      GUSMIX_CHAN_LINE,
4239 			      ICSMIX_LEFT,
4240 			      ICSMIX_MIN_ATTN);
4241 	ics2101_mix_attenuate(ic,
4242 			      GUSMIX_CHAN_LINE,
4243 			      ICSMIX_RIGHT,
4244 			      ICSMIX_MIN_ATTN);
4245 
4246 	ics2101_mix_attenuate(ic,
4247 			      GUSMIX_CHAN_CD,
4248 			      ICSMIX_LEFT,
4249 			      ICSMIX_MIN_ATTN);
4250 	ics2101_mix_attenuate(ic,
4251 			      GUSMIX_CHAN_CD,
4252 			      ICSMIX_RIGHT,
4253 			      ICSMIX_MIN_ATTN);
4254 
4255 	ics2101_mix_attenuate(ic,
4256 			      GUSMIX_CHAN_DAC,
4257 			      ICSMIX_LEFT,
4258 			      ICSMIX_MIN_ATTN);
4259 	ics2101_mix_attenuate(ic,
4260 			      GUSMIX_CHAN_DAC,
4261 			      ICSMIX_RIGHT,
4262 			      ICSMIX_MIN_ATTN);
4263 
4264 	ics2101_mix_attenuate(ic,
4265 			      ICSMIX_CHAN_4,
4266 			      ICSMIX_LEFT,
4267 			      ICSMIX_MAX_ATTN);
4268 	ics2101_mix_attenuate(ic,
4269 			      ICSMIX_CHAN_4,
4270 			      ICSMIX_RIGHT,
4271 			      ICSMIX_MAX_ATTN);
4272 
4273 	ics2101_mix_attenuate(ic,
4274 			      GUSMIX_CHAN_MASTER,
4275 			      ICSMIX_LEFT,
4276 			      ICSMIX_MIN_ATTN);
4277 	ics2101_mix_attenuate(ic,
4278 			      GUSMIX_CHAN_MASTER,
4279 			      ICSMIX_RIGHT,
4280 			      ICSMIX_MIN_ATTN);
4281 	/* unmute other stuff: */
4282 	gusics_cd_mute(ic, 0);
4283 	gusics_dac_mute(ic, 0);
4284 	gusics_linein_mute(ic, 0);
4285 	return;
4286 }
4287 
4288 
4289 #endif /* NGUS */
4290