1160383Snetchild/*-
2160383Snetchild * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3172150Sariff * Copyright (c) 2003-2007 Yuriy Tsibizov <yuriy.tsibizov@gfk.ru>
4160383Snetchild * All rights reserved.
5160383Snetchild *
6160383Snetchild * Redistribution and use in source and binary forms, with or without
7160383Snetchild * modification, are permitted provided that the following conditions
8160383Snetchild * are met:
9160383Snetchild * 1. Redistributions of source code must retain the above copyright
10160383Snetchild *    notice, this list of conditions and the following disclaimer.
11160383Snetchild * 2. Redistributions in binary form must reproduce the above copyright
12160383Snetchild *    notice, this list of conditions and the following disclaimer in the
13160383Snetchild *    documentation and/or other materials provided with the distribution.
14160383Snetchild *
15160383Snetchild * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16160383Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17160383Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18160383Snetchild * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19160383Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20160383Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21160383Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22160383Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
23160383Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24160383Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25160383Snetchild * SUCH DAMAGE.
26160383Snetchild *
27160383Snetchild * $FreeBSD$
28160383Snetchild */
29160383Snetchild
30160383Snetchild#include <sys/param.h>
31160383Snetchild#include <sys/types.h>
32160383Snetchild#include <sys/bus.h>
33160383Snetchild#include <machine/bus.h>
34160383Snetchild#include <sys/rman.h>
35160383Snetchild#include <sys/systm.h>
36160383Snetchild#include <sys/sbuf.h>
37160383Snetchild#include <sys/queue.h>
38160383Snetchild#include <sys/lock.h>
39160383Snetchild#include <sys/mutex.h>
40160383Snetchild#include <sys/sysctl.h>
41172150Sariff#include <sys/kdb.h>
42160383Snetchild
43160383Snetchild#include <dev/pci/pcireg.h>
44160383Snetchild#include <dev/pci/pcivar.h>
45160383Snetchild
46160383Snetchild#include <machine/clock.h>	/* for DELAY */
47160383Snetchild
48193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS
49193640Sariff#include "opt_snd.h"
50193640Sariff#endif
51193640Sariff
52160383Snetchild#include <dev/sound/chip.h>
53160383Snetchild#include <dev/sound/pcm/sound.h>
54160383Snetchild#include <dev/sound/pcm/ac97.h>
55160383Snetchild
56229981Spfg#include <dev/sound/pci/emuxkireg.h>
57160383Snetchild#include <dev/sound/pci/emu10kx.h>
58160383Snetchild
59160383Snetchild/* hw flags */
60160383Snetchild#define	HAS_51		0x0001
61160383Snetchild#define	HAS_71		0x0002
62160383Snetchild#define	HAS_AC97	0x0004
63160383Snetchild
64160383Snetchild#define	IS_EMU10K1	0x0008
65160383Snetchild#define	IS_EMU10K2	0x0010
66160383Snetchild#define	IS_CA0102	0x0020
67160383Snetchild#define	IS_CA0108	0x0040
68160383Snetchild#define	IS_UNKNOWN	0x0080
69160383Snetchild
70160383Snetchild#define	BROKEN_DIGITAL	0x0100
71160383Snetchild#define	DIGITAL_ONLY	0x0200
72160383Snetchild
73160383Snetchild#define	IS_CARDBUS	0x0400
74160383Snetchild
75160383Snetchild#define	MODE_ANALOG	1
76160383Snetchild#define	MODE_DIGITAL	2
77160383Snetchild#define	SPDIF_MODE_PCM	1
78160383Snetchild#define	SPDIF_MODE_AC3	2
79160383Snetchild
80160383Snetchild#define	MACS	0x0
81160383Snetchild#define	MACS1	0x1
82160383Snetchild#define	MACW	0x2
83160383Snetchild#define	MACW1	0x3
84160383Snetchild#define	MACINTS	0x4
85160383Snetchild#define	MACINTW	0x5
86160383Snetchild#define	ACC3	0x6
87160383Snetchild#define	MACMV	0x7
88160383Snetchild#define	ANDXOR	0x8
89160383Snetchild#define	TSTNEG	0x9
90160383Snetchild#define	LIMIT	0xA
91160383Snetchild#define	LIMIT1	0xB
92160383Snetchild#define	LOG	0xC
93160383Snetchild#define	EXP	0xD
94160383Snetchild#define	INTERP	0xE
95160383Snetchild#define	SKIP	0xF
96160383Snetchild
97160383Snetchild#define	GPR(i)	(sc->gpr_base+(i))
98160383Snetchild#define	INP(i)	(sc->input_base+(i))
99160383Snetchild#define	OUTP(i)	(sc->output_base+(i))
100160383Snetchild#define	FX(i)	(i)
101160383Snetchild#define	FX2(i)	(sc->efxc_base+(i))
102160383Snetchild#define	DSP_CONST(i) (sc->dsp_zero+(i))
103160383Snetchild
104160383Snetchild#define	COND_NORMALIZED	DSP_CONST(0x1)
105160383Snetchild#define	COND_BORROW	DSP_CONST(0x2)
106160383Snetchild#define	COND_MINUS	DSP_CONST(0x3)
107160383Snetchild#define	COND_LESS_ZERO	DSP_CONST(0x4)
108160383Snetchild#define	COND_EQ_ZERO	DSP_CONST(0x5)
109160383Snetchild#define	COND_SATURATION	DSP_CONST(0x6)
110160383Snetchild#define	COND_NEQ_ZERO	DSP_CONST(0x8)
111160383Snetchild
112172150Sariff#define	DSP_ACCUM	DSP_CONST(0x16)
113172150Sariff#define	DSP_CCR		DSP_CONST(0x17)
114172150Sariff
115160383Snetchild/* Live! Inputs */
116160383Snetchild#define	IN_AC97_L 	0x00
117160383Snetchild#define	IN_AC97_R 	0x01
118160383Snetchild#define	IN_AC97		IN_AC97_L
119160383Snetchild#define	IN_SPDIF_CD_L	0x02
120160383Snetchild#define	IN_SPDIF_CD_R	0x03
121160383Snetchild#define	IN_SPDIF_CD	IN_SPDIF_CD_L
122160383Snetchild#define	IN_ZOOM_L 	0x04
123160383Snetchild#define	IN_ZOOM_R 	0x05
124160383Snetchild#define	IN_ZOOM		IN_ZOOM_L
125160383Snetchild#define	IN_TOSLINK_L	0x06
126160383Snetchild#define	IN_TOSLINK_R	0x07
127160383Snetchild#define	IN_TOSLINK	IN_TOSLINK_L
128160383Snetchild#define	IN_LINE1_L	0x08
129160383Snetchild#define	IN_LINE1_R	0x09
130160383Snetchild#define	IN_LINE1	IN_LINE1_L
131160383Snetchild#define	IN_COAX_SPDIF_L	0x0a
132160383Snetchild#define	IN_COAX_SPDIF_R	0x0b
133160383Snetchild#define	IN_COAX_SPDIF	IN_COAX_SPDIF_L
134160383Snetchild#define	IN_LINE2_L	0x0c
135160383Snetchild#define	IN_LINE2_R	0x0d
136160383Snetchild#define	IN_LINE2	IN_LINE2_L
137160383Snetchild#define	IN_0E		0x0e
138160383Snetchild#define	IN_0F		0x0f
139160383Snetchild
140160383Snetchild/* Outputs */
141160383Snetchild#define	OUT_AC97_L	0x00
142160383Snetchild#define	OUT_AC97_R	0x01
143160383Snetchild#define	OUT_AC97	OUT_AC97_L
144160383Snetchild#define	OUT_A_FRONT	OUT_AC97
145160383Snetchild#define	OUT_TOSLINK_L 	0x02
146160383Snetchild#define	OUT_TOSLINK_R 	0x03
147160383Snetchild#define	OUT_TOSLINK	OUT_TOSLINK_L
148160383Snetchild#define	OUT_D_CENTER	0x04
149160383Snetchild#define	OUT_D_SUB	0x05
150160383Snetchild#define	OUT_HEADPHONE_L	0x06
151160383Snetchild#define	OUT_HEADPHONE_R	0x07
152160383Snetchild#define	OUT_HEADPHONE	OUT_HEADPHONE_L
153160383Snetchild#define	OUT_REAR_L	0x08
154160383Snetchild#define	OUT_REAR_R	0x09
155160383Snetchild#define	OUT_REAR	OUT_REAR_L
156160383Snetchild#define	OUT_ADC_REC_L 	0x0a
157160383Snetchild#define	OUT_ADC_REC_R	0x0b
158160383Snetchild#define	OUT_ADC_REC	OUT_ADC_REC_L
159160383Snetchild#define	OUT_MIC_CAP	0x0c
160165833Snetchild
161230137Sjoel/* Live! 5.1 Digital, non-standard 5.1 (center & sub) outputs */
162160383Snetchild#define	OUT_A_CENTER	0x11
163160383Snetchild#define	OUT_A_SUB	0x12
164160383Snetchild
165160383Snetchild/* Audigy Inputs */
166160383Snetchild#define	A_IN_AC97_L	0x00
167160383Snetchild#define	A_IN_AC97_R	0x01
168160383Snetchild#define	A_IN_AC97	A_IN_AC97_L
169160383Snetchild#define	A_IN_SPDIF_CD_L	0x02
170160383Snetchild#define	A_IN_SPDIF_CD_R	0x03
171160383Snetchild#define	A_IN_SPDIF_CD	A_IN_SPDIF_CD_L
172160383Snetchild#define	A_IN_O_SPDIF_L	0x04
173160383Snetchild#define	A_IN_O_SPDIF_R	0x05
174160383Snetchild#define	A_IN_O_SPDIF	A_IN_O_SPDIF_L
175160383Snetchild#define	A_IN_LINE2_L	0x08
176160383Snetchild#define	A_IN_LINE2_R	0x09
177160383Snetchild#define	A_IN_LINE2	A_IN_LINE2_L
178160383Snetchild#define	A_IN_R_SPDIF_L	0x0a
179160383Snetchild#define	A_IN_R_SPDIF_R	0x0b
180160383Snetchild#define	A_IN_R_SPDIF	A_IN_R_SPDIF_L
181160383Snetchild#define	A_IN_AUX2_L	0x0c
182160383Snetchild#define	A_IN_AUX2_R	0x0d
183160383Snetchild#define	A_IN_AUX2	A_IN_AUX2_L
184160383Snetchild
185229981Spfg/* Audigy Outputs */
186160383Snetchild#define	A_OUT_D_FRONT_L	0x00
187160383Snetchild#define	A_OUT_D_FRONT_R	0x01
188160383Snetchild#define	A_OUT_D_FRONT	A_OUT_D_FRONT_L
189160383Snetchild#define	A_OUT_D_CENTER	0x02
190160383Snetchild#define	A_OUT_D_SUB	0x03
191160383Snetchild#define	A_OUT_D_SIDE_L	0x04
192160383Snetchild#define	A_OUT_D_SIDE_R	0x05
193160383Snetchild#define	A_OUT_D_SIDE	A_OUT_D_SIDE_L
194160383Snetchild#define	A_OUT_D_REAR_L	0x06
195160383Snetchild#define	A_OUT_D_REAR_R	0x07
196160383Snetchild#define	A_OUT_D_REAR	A_OUT_D_REAR_L
197160383Snetchild
198160383Snetchild/* on Audigy Platinum only */
199160383Snetchild#define	A_OUT_HPHONE_L	0x04
200160383Snetchild#define	A_OUT_HPHONE_R	0x05
201160383Snetchild#define	A_OUT_HPHONE	A_OUT_HPHONE_L
202160383Snetchild
203160383Snetchild#define	A_OUT_A_FRONT_L	0x08
204160383Snetchild#define	A_OUT_A_FRONT_R	0x09
205160383Snetchild#define	A_OUT_A_FRONT	A_OUT_A_FRONT_L
206160383Snetchild#define	A_OUT_A_CENTER	0x0a
207160383Snetchild#define	A_OUT_A_SUB	0x0b
208160383Snetchild#define	A_OUT_A_SIDE_L	0x0c
209160383Snetchild#define	A_OUT_A_SIDE_R	0x0d
210160383Snetchild#define	A_OUT_A_SIDE	A_OUT_A_SIDE_L
211160383Snetchild#define	A_OUT_A_REAR_L	0x0e
212160383Snetchild#define	A_OUT_A_REAR_R	0x0f
213160383Snetchild#define	A_OUT_A_REAR	A_OUT_A_REAR_L
214160383Snetchild#define	A_OUT_AC97_L	0x10
215160383Snetchild#define	A_OUT_AC97_R	0x11
216160383Snetchild#define	A_OUT_AC97	A_OUT_AC97_L
217160383Snetchild#define	A_OUT_ADC_REC_L	0x16
218160383Snetchild#define	A_OUT_ADC_REC_R	0x17
219160383Snetchild#define	A_OUT_ADC_REC	A_OUT_ADC_REC_L
220160383Snetchild
221229981Spfg#define EMU_DATA2	0x24
222229981Spfg#define EMU_IPR2	0x28
223229981Spfg#define EMU_INTE2	0x2c
224229981Spfg#define EMU_IPR3	0x38
225229981Spfg#define EMU_INTE3	0x3c
226160383Snetchild
227229981Spfg#define EMU_A2_SRCSel		0x60
228229981Spfg#define EMU_A2_SRCMULTI_ENABLE	0x6e
229229981Spfg
230229981Spfg#define EMU_A_I2S_CAPTURE_96000	0x00000400
231229981Spfg
232229981Spfg#define EMU_A2_MIXER_I2S_ENABLE           0x7B
233229981Spfg#define EMU_A2_MIXER_SPDIF_ENABLE         0x7A
234229981Spfg
235160383Snetchild#define	C_FRONT_L	0
236160383Snetchild#define	C_FRONT_R	1
237160383Snetchild#define	C_REC_L		2
238160383Snetchild#define	C_REC_R		3
239160383Snetchild#define	C_REAR_L	4
240160383Snetchild#define	C_REAR_R	5
241160383Snetchild#define	C_CENTER	6
242160383Snetchild#define	C_SUB		7
243160383Snetchild#define	C_SIDE_L	8
244160383Snetchild#define	C_SIDE_R	9
245160383Snetchild#define	NUM_CACHES	10
246160383Snetchild
247172150Sariff#define	CDSPDIFMUTE	0
248172150Sariff#define	ANALOGMUTE	1
249172150Sariff#define	NUM_MUTE	2
250165833Snetchild
251160383Snetchild#define	EMU_MAX_GPR	512
252160383Snetchild#define	EMU_MAX_IRQ_CONSUMERS 32
253160383Snetchild
254160383Snetchildstruct emu_voice {
255160383Snetchild	int	vnum;
256161055Snetchild	unsigned int	b16:1, stereo:1, busy:1, running:1, ismaster:1;
257160383Snetchild	int	speed;
258160383Snetchild	int	start;
259160383Snetchild	int	end;
260160383Snetchild	int	vol;
261160383Snetchild	uint32_t buf;
262160383Snetchild	void	*vbuf;
263160383Snetchild	struct emu_voice *slave;
264160383Snetchild	uint32_t sa;
265160383Snetchild	uint32_t ea;
266172150Sariff	uint32_t routing[8];
267172150Sariff	uint32_t amounts[8];
268160383Snetchild};
269160383Snetchild
270160383Snetchildstruct emu_memblk {
271160383Snetchild	SLIST_ENTRY(emu_memblk)	link;
272160383Snetchild	void		*buf;
273160383Snetchild	char		owner[16];
274160383Snetchild	bus_addr_t	buf_addr;
275160383Snetchild	uint32_t	pte_start, pte_size;
276160383Snetchild};
277160383Snetchild
278160383Snetchildstruct emu_mem {
279161054Snetchild	uint8_t		bmap[EMU_MAXPAGES / 8];
280160383Snetchild	uint32_t	*ptb_pages;
281160383Snetchild	void		*silent_page;
282160383Snetchild	bus_addr_t	silent_page_addr;
283160383Snetchild	bus_addr_t	ptb_pages_addr;
284160383Snetchild	bus_dma_tag_t	dmat;
285172150Sariff	struct emu_sc_info *card;
286160383Snetchild	SLIST_HEAD(, emu_memblk) blocks;
287160383Snetchild};
288160383Snetchild
289160383Snetchild/* rm */
290160383Snetchildstruct emu_rm {
291160383Snetchild	struct emu_sc_info *card;
292160383Snetchild	struct mtx	gpr_lock;
293160383Snetchild	signed int	allocmap[EMU_MAX_GPR];
294160383Snetchild	int		num_gprs;
295160383Snetchild	int		last_free_gpr;
296160383Snetchild	int 		num_used;
297160383Snetchild};
298160383Snetchild
299160383Snetchildstruct emu_intr_handler {
300160383Snetchild	void*		softc;
301160383Snetchild	uint32_t	intr_mask;
302160383Snetchild	uint32_t	inte_mask;
303160383Snetchild	uint32_t(*irq_func) (void *softc, uint32_t irq);
304160383Snetchild};
305160383Snetchild
306160383Snetchildstruct emu_sc_info {
307160383Snetchild	struct mtx	lock;
308160383Snetchild	struct mtx	rw;		/* Hardware exclusive access lock */
309160383Snetchild
310160383Snetchild	/* Hardware and subdevices */
311160383Snetchild	device_t	dev;
312165833Snetchild	device_t	pcm[RT_COUNT];
313160383Snetchild	device_t	midi[2];
314160383Snetchild	uint32_t	type;
315160383Snetchild	uint32_t	rev;
316160383Snetchild
317160383Snetchild	bus_space_tag_t	st;
318160383Snetchild	bus_space_handle_t sh;
319160383Snetchild
320160383Snetchild	struct cdev	*cdev;		/* /dev/emu10k character device */
321160383Snetchild	struct mtx	emu10kx_lock;
322160383Snetchild	int		emu10kx_isopen;
323160383Snetchild	struct sbuf	emu10kx_sbuf;
324160383Snetchild	int		emu10kx_bufptr;
325160383Snetchild
326160383Snetchild
327160383Snetchild	/* Resources */
328160383Snetchild	struct resource	*reg;
329160383Snetchild	struct resource	*irq;
330160383Snetchild	void 		*ih;
331160383Snetchild
332160383Snetchild	/* IRQ handlers */
333160383Snetchild	struct emu_intr_handler ihandler[EMU_MAX_IRQ_CONSUMERS];
334160383Snetchild
335160383Snetchild	/* Card HW configuration */
336172150Sariff	unsigned int	mode;	/* analog / digital */
337160383Snetchild	unsigned int	mchannel_fx;
338160383Snetchild	unsigned int	dsp_zero;
339160383Snetchild	unsigned int	code_base;
340160383Snetchild	unsigned int	code_size;
341160383Snetchild	unsigned int	gpr_base;
342160383Snetchild	unsigned int	num_gprs;
343160383Snetchild	unsigned int	input_base;
344160383Snetchild	unsigned int	output_base;
345160383Snetchild	unsigned int	efxc_base;
346160383Snetchild	unsigned int	opcode_shift;
347160383Snetchild	unsigned int	high_operand_shift;
348160383Snetchild	unsigned int	address_mask;
349160383Snetchild	uint32_t 	is_emu10k1:1, is_emu10k2, is_ca0102, is_ca0108:1,
350160383Snetchild			has_ac97:1, has_51:1, has_71:1,
351172150Sariff			enable_ir:1,
352160383Snetchild			broken_digital:1, is_cardbus:1;
353160383Snetchild
354172150Sariff	signed int	mch_disabled, mch_rec, dbg_level;
355172150Sariff	signed int 	num_inputs;
356160383Snetchild	unsigned int 	num_outputs;
357160383Snetchild	unsigned int 	num_fxbuses;
358160383Snetchild	unsigned int 	routing_code_start;
359160383Snetchild	unsigned int	routing_code_end;
360160383Snetchild
361160383Snetchild	/* HW resources */
362160383Snetchild	struct emu_voice voice[NUM_G];			/* Hardware voices */
363160383Snetchild	uint32_t	irq_mask[EMU_MAX_IRQ_CONSUMERS]; /* IRQ manager data */
364160383Snetchild	int 		timer[EMU_MAX_IRQ_CONSUMERS];	/* timer */
365160383Snetchild	int		timerinterval;
366160383Snetchild	struct		emu_rm *rm;
367160383Snetchild	struct		emu_mem mem;			/* memory */
368160383Snetchild
369160383Snetchild	/* Mixer */
370160383Snetchild	int		mixer_gpr[NUM_MIXERS];
371160383Snetchild	int		mixer_volcache[NUM_MIXERS];
372160383Snetchild	int		cache_gpr[NUM_CACHES];
373172150Sariff	int		dummy_gpr;
374172150Sariff	int		mute_gpr[NUM_MUTE];
375160383Snetchild	struct sysctl_ctx_list	*ctx;
376160383Snetchild	struct sysctl_oid	*root;
377160383Snetchild};
378160383Snetchild
379160383Snetchildstatic void	emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error);
380160383Snetchildstatic void*	emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr);
381160383Snetchildstatic void	emu_free(struct emu_mem *mem, void *dmabuf);
382160383Snetchildstatic void*	emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner);
383160383Snetchildstatic int	emu_memfree(struct emu_mem *mem, void *membuf);
384160383Snetchildstatic int	emu_memstart(struct emu_mem *mem, void *membuf);
385160383Snetchild
386160383Snetchild/* /dev */
387160383Snetchildstatic int	emu10kx_dev_init(struct emu_sc_info *sc);
388160383Snetchildstatic int	emu10kx_dev_uninit(struct emu_sc_info *sc);
389160383Snetchildstatic int	emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s);
390160383Snetchild
391160383Snetchildstatic void	emumix_set_mode(struct emu_sc_info *sc, int mode);
392160383Snetchildstatic void	emumix_set_spdif_mode(struct emu_sc_info *sc, int mode);
393160383Snetchildstatic void	emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol);
394160383Snetchildstatic void	emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val);
395160383Snetchildstatic int	sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS);
396160383Snetchild
397160383Snetchildstatic int	emu_rm_init(struct emu_sc_info *sc);
398160383Snetchildstatic int	emu_rm_uninit(struct emu_sc_info *sc);
399160383Snetchildstatic int	emu_rm_gpr_alloc(struct emu_rm *rm, int count);
400160383Snetchild
401165833Snetchildstatic unsigned int emu_getcard(device_t dev);
402160383Snetchildstatic uint32_t	emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size);
403160383Snetchildstatic void	emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size);
404160383Snetchildstatic void	emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data);
405160383Snetchild
406160383Snetchildstatic void	emu_vstop(struct emu_sc_info *sc, char channel, int enable);
407160383Snetchild
408160383Snetchildstatic void	emu_intr(void *p);
409160383Snetchildstatic void	emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data);
410160383Snetchildstatic void	emu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc);
411160383Snetchildstatic void	emu_initefx(struct emu_sc_info *sc);
412160383Snetchild
413160383Snetchildstatic int	emu_cardbus_init(struct emu_sc_info *sc);
414166919Sariffstatic int	emu_init(struct emu_sc_info *sc);
415160383Snetchildstatic int	emu_uninit(struct emu_sc_info *sc);
416160383Snetchild
417160383Snetchildstatic int	emu_read_ivar(device_t bus __unused, device_t dev, int ivar_index, uintptr_t * result);
418160383Snetchildstatic int	emu_write_ivar(device_t bus __unused, device_t dev __unused,
419160383Snetchild    int ivar_index, uintptr_t value __unused);
420160383Snetchild
421160383Snetchildstatic int	emu_pci_probe(device_t dev);
422160383Snetchildstatic int	emu_pci_attach(device_t dev);
423160383Snetchildstatic int	emu_pci_detach(device_t dev);
424160383Snetchildstatic int	emu_modevent(module_t mod __unused, int cmd, void *data __unused);
425160383Snetchild
426172150Sariff#ifdef	SND_EMU10KX_DEBUG
427172150Sariff
428172150Sariff#define EMU_MTX_DEBUG() do { 						\
429172150Sariff		if (mtx_owned(&sc->rw)) {				\
430172150Sariff		printf("RW owned in %s line %d for %s\n", __func__,	\
431172150Sariff			__LINE__ , device_get_nameunit(sc->dev));	\
432172150Sariff		printf("rw lock owned: %d\n", mtx_owned(&sc->rw));	\
433172150Sariff		printf("rw lock: value %x thread %x\n",			\
434172150Sariff			((&sc->rw)->mtx_lock & ~MTX_FLAGMASK), 		\
435172150Sariff			(uintptr_t)curthread);				\
436172150Sariff		printf("rw lock: recursed %d\n", mtx_recursed(&sc->rw));\
437172150Sariff		db_show_mtx(&sc->rw);					\
438172150Sariff		}							\
439172150Sariff	} while (0)
440172150Sariff#else
441172150Sariff#define EMU_MTX_DEBUG() do { 						\
442172150Sariff	} while (0)
443172150Sariff#endif
444172150Sariff
445172150Sariff#define EMU_RWLOCK() do {		\
446172150Sariff	EMU_MTX_DEBUG();		\
447172150Sariff	mtx_lock(&(sc->rw));		\
448172150Sariff	} while (0)
449172150Sariff
450172150Sariff#define EMU_RWUNLOCK() do {		\
451172150Sariff	mtx_unlock(&(sc->rw));		\
452172150Sariff	EMU_MTX_DEBUG();		\
453172150Sariff	} while (0)
454172150Sariff
455160383Snetchild/* Supported cards */
456160383Snetchildstruct emu_hwinfo {
457160383Snetchild	uint16_t	vendor;
458160383Snetchild	uint16_t	device;
459160383Snetchild	uint16_t	subvendor;
460160383Snetchild	uint16_t	subdevice;
461160383Snetchild	char		SBcode[8];
462160383Snetchild	char		desc[32];
463160383Snetchild	int		flags;
464160383Snetchild};
465160383Snetchild
466160383Snetchildstatic struct emu_hwinfo emu_cards[] = {
467165833Snetchild	{0xffff, 0xffff, 0xffff, 0xffff, "BADCRD", "Not a compatible card", 0},
468160383Snetchild	/* 0x0020..0x002f 4.0 EMU10K1 cards */
469160383Snetchild	{0x1102, 0x0002, 0x1102, 0x0020, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
470160383Snetchild	{0x1102, 0x0002, 0x1102, 0x0021, "CT4620", "SBLive!", HAS_AC97 | IS_EMU10K1},
471160383Snetchild	{0x1102, 0x0002, 0x1102, 0x002f, "CT????", "SBLive! mainboard implementation", HAS_AC97 | IS_EMU10K1},
472160383Snetchild
473160383Snetchild	/* (range unknown) 5.1 EMU10K1 cards */
474160383Snetchild	{0x1102, 0x0002, 0x1102, 0x100a, "CT????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
475160383Snetchild
476160383Snetchild	/* 0x80??..0x805? 4.0 EMU10K1 cards */
477160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8022, "CT4780", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
478160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8023, "CT4790", "SB PCI512", HAS_AC97 | IS_EMU10K1},
479160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8024, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1},
480160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8025, "CT????", "SBLive! Mainboard Implementation", HAS_AC97 | IS_EMU10K1},
481160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8026, "CT4830", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
482160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8027, "CT4832", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
483160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8028, "CT4760", "SBLive! OEM version", HAS_AC97 | IS_EMU10K1},
484160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8031, "CT4831", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
485160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8040, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1},
486160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8051, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
487160383Snetchild
488160383Snetchild	/* 0x8061..0x???? 5.1 EMU10K1  cards */
489160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8061, "SB????", "SBLive! Player 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
490172150Sariff	{0x1102, 0x0002, 0x1102, 0x8062, "CT4830", "SBLive! 1024", HAS_AC97 | HAS_51 | IS_EMU10K1},
491160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8064, "SB????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
492160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8065, "SB0220", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1},
493160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8066, "CT4780", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1},
494160383Snetchild	{0x1102, 0x0002, 0x1102, 0x8067, "SB????", "SBLive!", HAS_AC97 | HAS_51 | IS_EMU10K1},
495160383Snetchild
496160383Snetchild	/* Generic SB Live! */
497160383Snetchild	{0x1102, 0x0002, 0x1102, 0x0000, "SB????", "SBLive! (Unknown model)", HAS_AC97 | IS_EMU10K1},
498160383Snetchild
499160383Snetchild	/* 0x0041..0x0043 EMU10K2 (some kind of Audigy) cards */
500160383Snetchild
501160383Snetchild	/* 0x0051..0x0051 5.1 CA0100-IAF cards */
502160383Snetchild	{0x1102, 0x0004, 0x1102, 0x0051, "SB0090", "Audigy", HAS_AC97 | HAS_51 | IS_EMU10K2},
503160383Snetchild	/* ES is CA0100-IDF chip that don't work in digital mode */
504160383Snetchild	{0x1102, 0x0004, 0x1102, 0x0052, "SB0160", "Audigy ES", HAS_AC97 | HAS_71 | IS_EMU10K2 | BROKEN_DIGITAL},
505160383Snetchild	/* 0x0053..0x005C 5.1 CA0101-NAF cards */
506160383Snetchild	{0x1102, 0x0004, 0x1102, 0x0053, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2},
507160383Snetchild	{0x1102, 0x0004, 0x1102, 0x0058, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2},
508160383Snetchild
509160383Snetchild	/* 0x1002..0x1009 5.1 CA0102-IAT cards */
510160383Snetchild	{0x1102, 0x0004, 0x1102, 0x1002, "SB????", "Audigy 2 Platinum", HAS_51 | IS_CA0102},
511160383Snetchild	{0x1102, 0x0004, 0x1102, 0x1005, "SB????", "Audigy 2 Platinum EX", HAS_51 | IS_CA0102},
512160383Snetchild	{0x1102, 0x0004, 0x1102, 0x1007, "SB0240", "Audigy 2", HAS_AC97 | HAS_51 | IS_CA0102},
513160383Snetchild
514160383Snetchild	/* 0x2001..0x2003 7.1 CA0102-ICT cards */
515160383Snetchild	{0x1102, 0x0004, 0x1102, 0x2001, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
516160383Snetchild	{0x1102, 0x0004, 0x1102, 0x2002, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
517165833Snetchild	/* XXX No reports about 0x2003 & 0x2004 cards */
518165833Snetchild	{0x1102, 0x0004, 0x1102, 0x2003, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
519165833Snetchild	{0x1102, 0x0004, 0x1102, 0x2004, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
520165833Snetchild	{0x1102, 0x0004, 0x1102, 0x2005, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
521160383Snetchild
522160383Snetchild	/* (range unknown) 7.1 CA0102-xxx Audigy 4 cards */
523160383Snetchild	{0x1102, 0x0004, 0x1102, 0x2007, "SB0380", "Audigy 4 Pro", HAS_AC97 | HAS_71 | IS_CA0102},
524160383Snetchild
525160383Snetchild	/* Generic Audigy or Audigy 2 */
526160383Snetchild	{0x1102, 0x0004, 0x1102, 0x0000, "SB????", "Audigy (Unknown model)", HAS_AC97 | HAS_51 | IS_EMU10K2},
527160383Snetchild
528160383Snetchild	/* We don't support CA0103-DAT (Audigy LS) cards */
529160383Snetchild	/* There is NO CA0104-xxx cards */
530160383Snetchild	/* There is NO CA0105-xxx cards */
531160383Snetchild	/* We don't support CA0106-DAT (SB Live! 24 bit) cards */
532160383Snetchild	/* There is NO CA0107-xxx cards */
533160383Snetchild
534160383Snetchild	/* 0x1000..0x1001 7.1 CA0108-IAT cards */
535160383Snetchild	{0x1102, 0x0008, 0x1102, 0x1000, "SB????", "Audigy 2 LS", HAS_AC97 | HAS_51 | IS_CA0108 | DIGITAL_ONLY},
536160383Snetchild	{0x1102, 0x0008, 0x1102, 0x1001, "SB0400", "Audigy 2 Value", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY},
537160383Snetchild	{0x1102, 0x0008, 0x1102, 0x1021, "SB0610", "Audigy 4", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY},
538160383Snetchild
539160383Snetchild	{0x1102, 0x0008, 0x1102, 0x2001, "SB0530", "Audigy 2 ZS CardBus", HAS_AC97 | HAS_71 | IS_CA0108 | IS_CARDBUS},
540160383Snetchild
541160383Snetchild	{0x1102, 0x0008, 0x0000, 0x0000, "SB????", "Audigy 2 Value (Unknown model)", HAS_AC97 | HAS_51 | IS_CA0108},
542160383Snetchild};
543160383Snetchild/* Unsupported cards */
544160383Snetchild
545160383Snetchildstatic struct emu_hwinfo emu_bad_cards[] = {
546160383Snetchild	/* APS cards should be possible to support */
547160383Snetchild	{0x1102, 0x0002, 0x1102, 0x4001, "EMUAPS", "E-mu APS", 0},
548160383Snetchild	{0x1102, 0x0002, 0x1102, 0x4002, "EMUAPS", "E-mu APS", 0},
549160383Snetchild	{0x1102, 0x0004, 0x1102, 0x4001, "EMU???", "E-mu 1212m [4001]", 0},
550160383Snetchild	/* Similar-named ("Live!" or "Audigy") cards on different chipsets */
551160383Snetchild	{0x1102, 0x8064, 0x0000, 0x0000, "SB0100", "SBLive! 5.1 OEM", 0},
552160383Snetchild	{0x1102, 0x0006, 0x0000, 0x0000, "SB0200", "DELL OEM SBLive! Value", 0},
553160383Snetchild	{0x1102, 0x0007, 0x0000, 0x0000, "SB0310", "Audigy LS", 0},
554160383Snetchild};
555160383Snetchild
556160383Snetchild/*
557160383Snetchild * Get best known information about device.
558160383Snetchild */
559165833Snetchildstatic unsigned int
560160383Snetchildemu_getcard(device_t dev)
561160383Snetchild{
562160383Snetchild	uint16_t device;
563160383Snetchild	uint16_t subdevice;
564160383Snetchild	int n_cards;
565165833Snetchild	unsigned int thiscard;
566160383Snetchild	int i;
567160383Snetchild
568160383Snetchild	device = pci_read_config(dev, PCIR_DEVICE, /* bytes */ 2);
569160383Snetchild	subdevice = pci_read_config(dev, PCIR_SUBDEV_0, /* bytes */ 2);
570160383Snetchild
571160383Snetchild	n_cards = sizeof(emu_cards) / sizeof(struct emu_hwinfo);
572165833Snetchild	thiscard = 0;
573165833Snetchild	for (i = 1; i < n_cards; i++) {
574160383Snetchild		if (device == emu_cards[i].device) {
575160383Snetchild			if (subdevice == emu_cards[i].subdevice) {
576160383Snetchild				thiscard = i;
577160383Snetchild				break;
578160383Snetchild			}
579160383Snetchild			if (0x0000 == emu_cards[i].subdevice) {
580160383Snetchild				thiscard = i;
581172150Sariff				/*
582172150Sariff				 * don't break, we can get more specific card
583172150Sariff				 * later in the list.
584172150Sariff				 */
585160383Snetchild			}
586160383Snetchild		}
587160383Snetchild	}
588160383Snetchild
589160383Snetchild	n_cards = sizeof(emu_bad_cards) / sizeof(struct emu_hwinfo);
590160383Snetchild	for (i = 0; i < n_cards; i++) {
591160383Snetchild		if (device == emu_bad_cards[i].device) {
592160383Snetchild			if (subdevice == emu_bad_cards[i].subdevice) {
593165833Snetchild				thiscard = 0;
594160383Snetchild				break;
595160383Snetchild			}
596160383Snetchild			if (0x0000 == emu_bad_cards[i].subdevice) {
597165833Snetchild				thiscard = 0;
598160383Snetchild				break;	/* we avoid all this cards */
599160383Snetchild			}
600160383Snetchild		}
601160383Snetchild	}
602160383Snetchild	return (thiscard);
603160383Snetchild}
604160383Snetchild
605160383Snetchild
606160383Snetchild/*
607160383Snetchild * Base hardware interface are 32 (Audigy) or 64 (Audigy2) registers.
608160383Snetchild * Some of them are used directly, some of them provide pointer / data pairs.
609160383Snetchild */
610160383Snetchildstatic uint32_t
611160383Snetchildemu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size)
612160383Snetchild{
613160383Snetchild
614160383Snetchild	KASSERT(sc != NULL, ("emu_rd: NULL sc"));
615160383Snetchild	switch (size) {
616160383Snetchild	case 1:
617160383Snetchild		return (bus_space_read_1(sc->st, sc->sh, regno));
618160383Snetchild	case 2:
619160383Snetchild		return (bus_space_read_2(sc->st, sc->sh, regno));
620160383Snetchild	case 4:
621160383Snetchild		return (bus_space_read_4(sc->st, sc->sh, regno));
622160383Snetchild	}
623160383Snetchild	return (0xffffffff);
624160383Snetchild}
625160383Snetchild
626160383Snetchildstatic void
627160383Snetchildemu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size)
628160383Snetchild{
629160383Snetchild
630160383Snetchild	KASSERT(sc != NULL, ("emu_rd: NULL sc"));
631160383Snetchild	switch (size) {
632160383Snetchild	case 1:
633160383Snetchild		bus_space_write_1(sc->st, sc->sh, regno, data);
634160383Snetchild		break;
635160383Snetchild	case 2:
636160383Snetchild		bus_space_write_2(sc->st, sc->sh, regno, data);
637160383Snetchild		break;
638160383Snetchild	case 4:
639160383Snetchild		bus_space_write_4(sc->st, sc->sh, regno, data);
640160383Snetchild		break;
641160383Snetchild	}
642160383Snetchild}
643160383Snetchild/*
644229981Spfg * EMU_PTR / EMU_DATA interface. Access to EMU10Kx is made
645160383Snetchild * via (channel, register) pair. Some registers are channel-specific,
646160383Snetchild * some not.
647160383Snetchild */
648160383Snetchilduint32_t
649160383Snetchildemu_rdptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg)
650160383Snetchild{
651160383Snetchild	uint32_t ptr, val, mask, size, offset;
652160383Snetchild
653229981Spfg	ptr = ((reg << 16) & sc->address_mask) | (chn & EMU_PTR_CHNO_MASK);
654172150Sariff
655172150Sariff	EMU_RWLOCK();
656229981Spfg	emu_wr_nolock(sc, EMU_PTR, ptr, 4);
657229981Spfg	val = emu_rd_nolock(sc, EMU_DATA, 4);
658172150Sariff	EMU_RWUNLOCK();
659172150Sariff
660160383Snetchild	/*
661160383Snetchild	 * XXX Some register numbers has data size and offset encoded in
662160383Snetchild	 * it to get only part of 32bit register. This use is not described
663160383Snetchild	 * in register name, be careful!
664160383Snetchild	 */
665160383Snetchild	if (reg & 0xff000000) {
666160383Snetchild		size = (reg >> 24) & 0x3f;
667160383Snetchild		offset = (reg >> 16) & 0x1f;
668160383Snetchild		mask = ((1 << size) - 1) << offset;
669160383Snetchild		val &= mask;
670160383Snetchild		val >>= offset;
671160383Snetchild	}
672160383Snetchild	return (val);
673160383Snetchild}
674160383Snetchild
675160383Snetchildvoid
676160383Snetchildemu_wrptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg, uint32_t data)
677160383Snetchild{
678160383Snetchild	uint32_t ptr, mask, size, offset;
679172150Sariff
680229981Spfg	ptr = ((reg << 16) & sc->address_mask) | (chn & EMU_PTR_CHNO_MASK);
681172150Sariff
682172150Sariff	EMU_RWLOCK();
683229981Spfg	emu_wr_nolock(sc, EMU_PTR, ptr, 4);
684160383Snetchild	/*
685160383Snetchild	 * XXX Another kind of magic encoding in register number. This can
686160383Snetchild	 * give you side effect - it will read previous data from register
687160383Snetchild	 * and change only required bits.
688160383Snetchild	 */
689160383Snetchild	if (reg & 0xff000000) {
690160383Snetchild		size = (reg >> 24) & 0x3f;
691160383Snetchild		offset = (reg >> 16) & 0x1f;
692160383Snetchild		mask = ((1 << size) - 1) << offset;
693160383Snetchild		data <<= offset;
694160383Snetchild		data &= mask;
695229981Spfg		data |= emu_rd_nolock(sc, EMU_DATA, 4) & ~mask;
696160383Snetchild	}
697229981Spfg	emu_wr_nolock(sc, EMU_DATA, data, 4);
698172150Sariff	EMU_RWUNLOCK();
699160383Snetchild}
700160383Snetchild/*
701229981Spfg * EMU_A2_PTR / EMU_DATA2 interface. Access to P16v is made
702160383Snetchild * via (channel, register) pair. Some registers are channel-specific,
703160383Snetchild * some not. This interface is supported by CA0102 and CA0108 chips only.
704160383Snetchild */
705160383Snetchilduint32_t
706160383Snetchildemu_rd_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg)
707160383Snetchild{
708160383Snetchild	uint32_t val;
709160383Snetchild
710172150Sariff	/* XXX separate lock? */
711172150Sariff	EMU_RWLOCK();
712229981Spfg	emu_wr_nolock(sc, EMU_A2_PTR, (reg << 16) | chn, 4);
713229981Spfg	val = emu_rd_nolock(sc, EMU_DATA2, 4);
714172150Sariff
715172150Sariff	EMU_RWUNLOCK();
716172150Sariff
717160383Snetchild	return (val);
718160383Snetchild}
719160383Snetchild
720160383Snetchildvoid
721160383Snetchildemu_wr_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg, uint32_t data)
722160383Snetchild{
723160383Snetchild
724172150Sariff	EMU_RWLOCK();
725229981Spfg	emu_wr_nolock(sc, EMU_A2_PTR, (reg << 16) | chn, 4);
726229981Spfg	emu_wr_nolock(sc, EMU_DATA2, data, 4);
727172150Sariff	EMU_RWUNLOCK();
728160383Snetchild}
729160383Snetchild/*
730160383Snetchild * XXX CardBus interface. Not tested on any real hardware.
731160383Snetchild */
732160383Snetchildstatic void
733160383Snetchildemu_wr_cbptr(struct emu_sc_info *sc, uint32_t data)
734160383Snetchild{
735160383Snetchild	uint32_t val;
736160383Snetchild
737172150Sariff	/*
738172150Sariff	 * 0x38 is IPE3 (CD S/PDIF interrupt pending register) on CA0102. Seems
739160383Snetchild	 * to be some reg/value accessible kind of config register on CardBus
740172150Sariff	 * CA0108, with value(?) in top 16 bit, address(?) in low 16
741172150Sariff	 */
742172150Sariff
743160383Snetchild	val = emu_rd_nolock(sc, 0x38, 4);
744160383Snetchild	emu_wr_nolock(sc, 0x38, data, 4);
745160383Snetchild	val = emu_rd_nolock(sc, 0x38, 4);
746172150Sariff
747160383Snetchild}
748160383Snetchild
749160383Snetchild/*
750160383Snetchild * Direct hardware register access
751229981Spfg * Assume that it is never used to access EMU_PTR-based registers and can run unlocked.
752160383Snetchild */
753160383Snetchildvoid
754160383Snetchildemu_wr(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size)
755160383Snetchild{
756229981Spfg	KASSERT(regno != EMU_PTR, ("emu_wr: attempt to write to EMU_PTR"));
757229981Spfg	KASSERT(regno != EMU_A2_PTR, ("emu_wr: attempt to write to EMU_A2_PTR"));
758160383Snetchild
759160383Snetchild	emu_wr_nolock(sc, regno, data, size);
760160383Snetchild}
761160383Snetchild
762160383Snetchilduint32_t
763160383Snetchildemu_rd(struct emu_sc_info *sc, unsigned int regno, unsigned int size)
764160383Snetchild{
765160383Snetchild	uint32_t rd;
766160383Snetchild
767229981Spfg	KASSERT(regno != EMU_DATA, ("emu_rd: attempt to read DATA"));
768229981Spfg	KASSERT(regno != EMU_DATA2, ("emu_rd: attempt to read DATA2"));
769172150Sariff
770160383Snetchild	rd = emu_rd_nolock(sc, regno, size);
771160383Snetchild	return (rd);
772160383Snetchild}
773160383Snetchild
774160383Snetchild/*
775160383Snetchild * Enabling IR MIDI messages is another kind of black magic. It just
776160383Snetchild * has to be made this way. It really do it.
777160383Snetchild */
778160383Snetchildvoid
779160383Snetchildemu_enable_ir(struct emu_sc_info *sc)
780160383Snetchild{
781160383Snetchild	uint32_t iocfg;
782160383Snetchild
783160383Snetchild	if (sc->is_emu10k2 || sc->is_ca0102) {
784229981Spfg		iocfg = emu_rd_nolock(sc, EMU_A_IOCFG, 2);
785229981Spfg		emu_wr_nolock(sc, EMU_A_IOCFG, iocfg | EMU_A_IOCFG_GPOUT2, 2);
786160383Snetchild		DELAY(500);
787229981Spfg		emu_wr_nolock(sc, EMU_A_IOCFG, iocfg | EMU_A_IOCFG_GPOUT1 | EMU_A_IOCFG_GPOUT2, 2);
788160383Snetchild		DELAY(500);
789229981Spfg		emu_wr_nolock(sc, EMU_A_IOCFG, iocfg | EMU_A_IOCFG_GPOUT1, 2);
790160383Snetchild		DELAY(100);
791229981Spfg		emu_wr_nolock(sc, EMU_A_IOCFG, iocfg, 2);
792160383Snetchild		device_printf(sc->dev, "Audigy IR MIDI events enabled.\n");
793160383Snetchild		sc->enable_ir = 1;
794160383Snetchild	}
795160383Snetchild	if (sc->is_emu10k1) {
796229981Spfg		iocfg = emu_rd_nolock(sc, EMU_HCFG, 4);
797229981Spfg		emu_wr_nolock(sc, EMU_HCFG, iocfg | EMU_HCFG_GPOUT2, 4);
798160383Snetchild		DELAY(500);
799229981Spfg		emu_wr_nolock(sc, EMU_HCFG, iocfg | EMU_HCFG_GPOUT1 | EMU_HCFG_GPOUT2, 4);
800160383Snetchild		DELAY(100);
801229981Spfg		emu_wr_nolock(sc, EMU_HCFG, iocfg, 4);
802160383Snetchild		device_printf(sc->dev, "SB Live! IR MIDI events enabled.\n");
803160383Snetchild		sc->enable_ir = 1;
804160383Snetchild	}
805160383Snetchild}
806160383Snetchild
807160383Snetchild
808160383Snetchild/*
809230137Sjoel * emu_timer_ - HW timer management
810160383Snetchild */
811160383Snetchildint
812160383Snetchildemu_timer_create(struct emu_sc_info *sc)
813160383Snetchild{
814160383Snetchild	int i, timer;
815160383Snetchild
816160383Snetchild	timer = -1;
817172150Sariff
818172150Sariff	mtx_lock(&sc->lock);
819160383Snetchild	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
820160383Snetchild		if (sc->timer[i] == 0) {
821160383Snetchild			sc->timer[i] = -1;	/* disable it */
822160383Snetchild			timer = i;
823172150Sariff			mtx_unlock(&sc->lock);
824160383Snetchild			return (timer);
825160383Snetchild		}
826172150Sariff	mtx_unlock(&sc->lock);
827160383Snetchild
828160383Snetchild	return (-1);
829160383Snetchild}
830160383Snetchild
831160383Snetchildint
832160383Snetchildemu_timer_set(struct emu_sc_info *sc, int timer, int delay)
833160383Snetchild{
834160383Snetchild	int i;
835160383Snetchild
836172150Sariff	if (timer < 0)
837165833Snetchild		return (-1);
838165833Snetchild
839160383Snetchild	RANGE(delay, 16, 1024);
840165833Snetchild	RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
841160383Snetchild
842172150Sariff	mtx_lock(&sc->lock);
843160383Snetchild	sc->timer[timer] = delay;
844160383Snetchild	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
845160383Snetchild		if (sc->timerinterval > sc->timer[i])
846160383Snetchild			sc->timerinterval = sc->timer[i];
847160383Snetchild
848172150Sariff	/* XXX */
849229981Spfg	emu_wr(sc, EMU_TIMER, sc->timerinterval & 0x03ff, 2);
850172150Sariff	mtx_unlock(&sc->lock);
851172150Sariff
852160383Snetchild	return (timer);
853160383Snetchild}
854160383Snetchild
855160383Snetchildint
856160383Snetchildemu_timer_enable(struct emu_sc_info *sc, int timer, int go)
857160383Snetchild{
858160383Snetchild	uint32_t x;
859160383Snetchild	int ena_int;
860160383Snetchild	int i;
861160383Snetchild
862172150Sariff	if (timer < 0)
863165833Snetchild		return (-1);
864165833Snetchild
865165833Snetchild	RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
866165833Snetchild
867160383Snetchild	mtx_lock(&sc->lock);
868160383Snetchild
869160383Snetchild	if ((go == 1) && (sc->timer[timer] < 0))
870160383Snetchild		sc->timer[timer] = -sc->timer[timer];
871160383Snetchild	if ((go == 0) && (sc->timer[timer] > 0))
872160383Snetchild		sc->timer[timer] = -sc->timer[timer];
873160383Snetchild
874160383Snetchild	ena_int = 0;
875160383Snetchild	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) {
876160383Snetchild		if (sc->timerinterval > sc->timer[i])
877160383Snetchild			sc->timerinterval = sc->timer[i];
878160383Snetchild		if (sc->timer[i] > 0)
879160383Snetchild			ena_int = 1;
880160383Snetchild	}
881160383Snetchild
882229981Spfg	emu_wr(sc, EMU_TIMER, sc->timerinterval & 0x03ff, 2);
883160383Snetchild
884160383Snetchild	if (ena_int == 1) {
885229981Spfg		x = emu_rd(sc, EMU_INTE, 4);
886229981Spfg		x |= EMU_INTE_INTERTIMERENB;
887229981Spfg		emu_wr(sc, EMU_INTE, x, 4);
888160383Snetchild	} else {
889229981Spfg		x = emu_rd(sc, EMU_INTE, 4);
890229981Spfg		x &= ~EMU_INTE_INTERTIMERENB;
891229981Spfg		emu_wr(sc, EMU_INTE, x, 4);
892160383Snetchild	}
893160383Snetchild	mtx_unlock(&sc->lock);
894160383Snetchild	return (0);
895160383Snetchild}
896160383Snetchild
897160383Snetchildint
898160383Snetchildemu_timer_clear(struct emu_sc_info *sc, int timer)
899160383Snetchild{
900172150Sariff	if (timer < 0)
901165833Snetchild		return (-1);
902165833Snetchild
903165833Snetchild	RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
904165833Snetchild
905160383Snetchild	emu_timer_enable(sc, timer, 0);
906160383Snetchild
907160383Snetchild	mtx_lock(&sc->lock);
908160383Snetchild	if (sc->timer[timer] != 0)
909160383Snetchild		sc->timer[timer] = 0;
910160383Snetchild	mtx_unlock(&sc->lock);
911160383Snetchild
912160383Snetchild	return (timer);
913160383Snetchild}
914160383Snetchild
915160383Snetchild/*
916230137Sjoel * emu_intr_ - HW interrupt handler management
917160383Snetchild */
918160383Snetchildint
919160383Snetchildemu_intr_register(struct emu_sc_info *sc, uint32_t inte_mask, uint32_t intr_mask, uint32_t(*func) (void *softc, uint32_t irq), void *isc)
920160383Snetchild{
921160383Snetchild	int i;
922160383Snetchild	uint32_t x;
923160383Snetchild
924160383Snetchild	mtx_lock(&sc->lock);
925160383Snetchild	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
926160383Snetchild		if (sc->ihandler[i].inte_mask == 0) {
927160383Snetchild			sc->ihandler[i].inte_mask = inte_mask;
928160383Snetchild			sc->ihandler[i].intr_mask = intr_mask;
929160383Snetchild			sc->ihandler[i].softc = isc;
930160383Snetchild			sc->ihandler[i].irq_func = func;
931229981Spfg			x = emu_rd(sc, EMU_INTE, 4);
932160383Snetchild			x |= inte_mask;
933229981Spfg			emu_wr(sc, EMU_INTE, x, 4);
934160383Snetchild			mtx_unlock(&sc->lock);
935172150Sariff			if (sc->dbg_level > 1)
936172150Sariff				device_printf(sc->dev, "ihandle %d registered\n", i);
937172150Sariff
938160383Snetchild			return (i);
939160383Snetchild		}
940160383Snetchild	mtx_unlock(&sc->lock);
941172150Sariff	if (sc->dbg_level > 1)
942172150Sariff		device_printf(sc->dev, "ihandle not registered\n");
943172150Sariff
944160383Snetchild	return (-1);
945160383Snetchild}
946160383Snetchild
947160383Snetchildint
948160383Snetchildemu_intr_unregister(struct emu_sc_info *sc, int hnumber)
949160383Snetchild{
950160383Snetchild	uint32_t x;
951160383Snetchild	int i;
952160383Snetchild
953160383Snetchild	mtx_lock(&sc->lock);
954160383Snetchild
955160383Snetchild	if (sc->ihandler[hnumber].inte_mask == 0) {
956160383Snetchild		mtx_unlock(&sc->lock);
957160383Snetchild		return (-1);
958160383Snetchild	}
959160383Snetchild
960229981Spfg	x = emu_rd(sc, EMU_INTE, 4);
961160383Snetchild	x &= ~sc->ihandler[hnumber].inte_mask;
962160383Snetchild
963160383Snetchild	sc->ihandler[hnumber].inte_mask = 0;
964160383Snetchild	sc->ihandler[hnumber].intr_mask = 0;
965160383Snetchild	sc->ihandler[hnumber].softc = NULL;
966160383Snetchild	sc->ihandler[hnumber].irq_func = NULL;
967160383Snetchild
968229981Spfg	/* other interrupt handlers may use this EMU_INTE value */
969160383Snetchild	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
970160383Snetchild		if (sc->ihandler[i].inte_mask != 0)
971160383Snetchild			x |= sc->ihandler[i].inte_mask;
972160383Snetchild
973229981Spfg	emu_wr(sc, EMU_INTE, x, 4);
974160383Snetchild
975160383Snetchild	mtx_unlock(&sc->lock);
976160383Snetchild	return (hnumber);
977160383Snetchild}
978160383Snetchild
979160383Snetchildstatic void
980160383Snetchildemu_intr(void *p)
981160383Snetchild{
982160383Snetchild	struct emu_sc_info *sc = (struct emu_sc_info *)p;
983160383Snetchild	uint32_t stat, ack;
984160383Snetchild	int i;
985160383Snetchild
986160383Snetchild	for (;;) {
987229981Spfg		stat = emu_rd(sc, EMU_IPR, 4);
988160383Snetchild		ack = 0;
989160383Snetchild		if (stat == 0)
990160383Snetchild			break;
991229981Spfg		emu_wr(sc, EMU_IPR, stat, 4);
992160383Snetchild		for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) {
993160383Snetchild			if ((((sc->ihandler[i].intr_mask) & stat) != 0) &&
994160383Snetchild			    (((void *)sc->ihandler[i].irq_func) != NULL)) {
995160383Snetchild				ack |= sc->ihandler[i].irq_func(sc->ihandler[i].softc,
996160383Snetchild				    (sc->ihandler[i].intr_mask) & stat);
997160383Snetchild			}
998160383Snetchild		}
999172150Sariff	if (sc->dbg_level > 1)
1000172150Sariff		if (stat & (~ack))
1001172150Sariff			device_printf(sc->dev, "Unhandled interrupt: %08x\n", stat & (~ack));
1002172150Sariff
1003160383Snetchild	}
1004160383Snetchild
1005160383Snetchild	if ((sc->is_ca0102) || (sc->is_ca0108))
1006160383Snetchild		for (;;) {
1007229981Spfg			stat = emu_rd(sc, EMU_IPR2, 4);
1008160383Snetchild			ack = 0;
1009160383Snetchild			if (stat == 0)
1010160383Snetchild				break;
1011229981Spfg			emu_wr(sc, EMU_IPR2, stat, 4);
1012172150Sariff			if (sc->dbg_level > 1)
1013229981Spfg				device_printf(sc->dev, "EMU_IPR2: %08x\n", stat);
1014172150Sariff
1015230137Sjoel			break;	/* to avoid infinite loop. should be removed
1016160383Snetchild				 * after completion of P16V interface. */
1017160383Snetchild		}
1018160383Snetchild
1019160383Snetchild	if (sc->is_ca0102)
1020160383Snetchild		for (;;) {
1021229981Spfg			stat = emu_rd(sc, EMU_IPR3, 4);
1022160383Snetchild			ack = 0;
1023160383Snetchild			if (stat == 0)
1024160383Snetchild				break;
1025229981Spfg			emu_wr(sc, EMU_IPR3, stat, 4);
1026172150Sariff			if (sc->dbg_level > 1)
1027229981Spfg				device_printf(sc->dev, "EMU_IPR3: %08x\n", stat);
1028172150Sariff
1029160383Snetchild			break;	/* to avoid infinite loop. should be removed
1030160383Snetchild				 * after completion of S/PDIF interface */
1031160383Snetchild		}
1032160383Snetchild}
1033160383Snetchild
1034160383Snetchild
1035160383Snetchild/*
1036160383Snetchild * Get data from private emu10kx structure for PCM buffer allocation.
1037160383Snetchild * Used by PCM code only.
1038160383Snetchild */
1039160383Snetchildbus_dma_tag_t
1040160383Snetchildemu_gettag(struct emu_sc_info *sc)
1041160383Snetchild{
1042160383Snetchild	return (sc->mem.dmat);
1043160383Snetchild}
1044160383Snetchild
1045160383Snetchildstatic void
1046160383Snetchildemu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error)
1047160383Snetchild{
1048160383Snetchild	bus_addr_t *phys = (bus_addr_t *) arg;
1049160383Snetchild
1050160383Snetchild	*phys = error ? 0 : (bus_addr_t) segs->ds_addr;
1051160383Snetchild
1052160383Snetchild	if (bootverbose) {
1053160383Snetchild		printf("emu10kx: setmap (%lx, %lx), nseg=%d, error=%d\n",
1054160383Snetchild		    (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
1055160383Snetchild		    nseg, error);
1056160383Snetchild	}
1057160383Snetchild}
1058160383Snetchild
1059160383Snetchildstatic void *
1060160383Snetchildemu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr)
1061160383Snetchild{
1062160383Snetchild	void *dmabuf;
1063160383Snetchild	bus_dmamap_t map;
1064172150Sariff	int error;
1065160383Snetchild
1066160383Snetchild	*addr = 0;
1067172150Sariff	if ((error = bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, &map))) {
1068172150Sariff		if (mem->card->dbg_level > 2)
1069172150Sariff			device_printf(mem->card->dev, "emu_malloc: failed to alloc DMA map: %d\n", error);
1070160383Snetchild		return (NULL);
1071172150Sariff		}
1072172150Sariff	if ((error = bus_dmamap_load(mem->dmat, map, dmabuf, sz, emu_setmap, addr, 0)) || !*addr) {
1073172150Sariff		if (mem->card->dbg_level > 2)
1074172150Sariff			device_printf(mem->card->dev, "emu_malloc: failed to load DMA memory: %d\n", error);
1075160383Snetchild		return (NULL);
1076172150Sariff		}
1077160383Snetchild	return (dmabuf);
1078160383Snetchild}
1079160383Snetchild
1080160383Snetchildstatic void
1081160383Snetchildemu_free(struct emu_mem *mem, void *dmabuf)
1082160383Snetchild{
1083160383Snetchild	bus_dmamem_free(mem->dmat, dmabuf, NULL);
1084160383Snetchild}
1085160383Snetchild
1086160383Snetchildstatic void *
1087160383Snetchildemu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char *owner)
1088160383Snetchild{
1089160383Snetchild	uint32_t blksz, start, idx, ofs, tmp, found;
1090160383Snetchild	struct emu_memblk *blk;
1091160383Snetchild	void *membuf;
1092160383Snetchild
1093160383Snetchild	blksz = sz / EMUPAGESIZE;
1094160383Snetchild	if (sz > (blksz * EMUPAGESIZE))
1095160383Snetchild		blksz++;
1096172150Sariff	if (blksz > EMU_MAX_BUFSZ / EMUPAGESIZE) {
1097172150Sariff		if (mem->card->dbg_level > 2)
1098172150Sariff			device_printf(mem->card->dev, "emu_memalloc: memory request tool large\n");
1099161054Snetchild		return (NULL);
1100172150Sariff		}
1101160383Snetchild	/* find a free block in the bitmap */
1102160383Snetchild	found = 0;
1103160383Snetchild	start = 1;
1104161054Snetchild	while (!found && start + blksz < EMU_MAXPAGES) {
1105160383Snetchild		found = 1;
1106160383Snetchild		for (idx = start; idx < start + blksz; idx++)
1107160383Snetchild			if (mem->bmap[idx >> 3] & (1 << (idx & 7)))
1108160383Snetchild				found = 0;
1109160383Snetchild		if (!found)
1110160383Snetchild			start++;
1111160383Snetchild	}
1112172150Sariff	if (!found) {
1113172150Sariff		if (mem->card->dbg_level > 2)
1114172150Sariff			device_printf(mem->card->dev, "emu_memalloc: no free space in bitmap\n");
1115160383Snetchild		return (NULL);
1116172150Sariff		}
1117160383Snetchild	blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT);
1118172150Sariff	if (blk == NULL) {
1119172150Sariff		if (mem->card->dbg_level > 2)
1120172150Sariff			device_printf(mem->card->dev, "emu_memalloc: buffer allocation failed\n");
1121160383Snetchild		return (NULL);
1122172150Sariff		}
1123160383Snetchild	bzero(blk, sizeof(*blk));
1124160383Snetchild	membuf = emu_malloc(mem, sz, &blk->buf_addr);
1125160383Snetchild	*addr = blk->buf_addr;
1126160383Snetchild	if (membuf == NULL) {
1127172150Sariff		if (mem->card->dbg_level > 2)
1128172150Sariff			device_printf(mem->card->dev, "emu_memalloc: can't setup HW memory\n");
1129160383Snetchild		free(blk, M_DEVBUF);
1130160383Snetchild		return (NULL);
1131160383Snetchild	}
1132160383Snetchild	blk->buf = membuf;
1133160383Snetchild	blk->pte_start = start;
1134160383Snetchild	blk->pte_size = blksz;
1135160383Snetchild	strncpy(blk->owner, owner, 15);
1136160383Snetchild	blk->owner[15] = '\0';
1137160383Snetchild	ofs = 0;
1138160383Snetchild	for (idx = start; idx < start + blksz; idx++) {
1139160383Snetchild		mem->bmap[idx >> 3] |= 1 << (idx & 7);
1140233362Sjhb		tmp = (uint32_t) (blk->buf_addr + ofs);
1141160383Snetchild		mem->ptb_pages[idx] = (tmp << 1) | idx;
1142160383Snetchild		ofs += EMUPAGESIZE;
1143160383Snetchild	}
1144160383Snetchild	SLIST_INSERT_HEAD(&mem->blocks, blk, link);
1145160383Snetchild	return (membuf);
1146160383Snetchild}
1147160383Snetchild
1148160383Snetchildstatic int
1149160383Snetchildemu_memfree(struct emu_mem *mem, void *membuf)
1150160383Snetchild{
1151160383Snetchild	uint32_t idx, tmp;
1152160383Snetchild	struct emu_memblk *blk, *i;
1153160383Snetchild
1154160383Snetchild	blk = NULL;
1155160383Snetchild	SLIST_FOREACH(i, &mem->blocks, link) {
1156160383Snetchild		if (i->buf == membuf)
1157160383Snetchild			blk = i;
1158160383Snetchild	}
1159160383Snetchild	if (blk == NULL)
1160160383Snetchild		return (EINVAL);
1161160383Snetchild	SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
1162160383Snetchild	emu_free(mem, membuf);
1163160383Snetchild	tmp = (uint32_t) (mem->silent_page_addr) << 1;
1164160383Snetchild	for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
1165160383Snetchild		mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
1166160383Snetchild		mem->ptb_pages[idx] = tmp | idx;
1167160383Snetchild	}
1168160383Snetchild	free(blk, M_DEVBUF);
1169160383Snetchild	return (0);
1170160383Snetchild}
1171160383Snetchild
1172160383Snetchildstatic int
1173160383Snetchildemu_memstart(struct emu_mem *mem, void *membuf)
1174160383Snetchild{
1175160383Snetchild	struct emu_memblk *blk, *i;
1176160383Snetchild
1177160383Snetchild	blk = NULL;
1178160383Snetchild	SLIST_FOREACH(i, &mem->blocks, link) {
1179160383Snetchild		if (i->buf == membuf)
1180160383Snetchild			blk = i;
1181160383Snetchild	}
1182160383Snetchild	if (blk == NULL)
1183160383Snetchild		return (-1);
1184160383Snetchild	return (blk->pte_start);
1185160383Snetchild}
1186160383Snetchild
1187160383Snetchild
1188160383Snetchildstatic uint32_t
1189160383Snetchildemu_rate_to_pitch(uint32_t rate)
1190160383Snetchild{
1191160383Snetchild	static uint32_t logMagTable[128] = {
1192160383Snetchild		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
1193160383Snetchild		0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
1194160383Snetchild		0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
1195160383Snetchild		0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
1196160383Snetchild		0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
1197160383Snetchild		0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
1198160383Snetchild		0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
1199160383Snetchild		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
1200160383Snetchild		0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
1201160383Snetchild		0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
1202160383Snetchild		0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
1203160383Snetchild		0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
1204160383Snetchild		0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
1205160383Snetchild		0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
1206160383Snetchild		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
1207160383Snetchild		0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
1208160383Snetchild	};
1209160383Snetchild	static char logSlopeTable[128] = {
1210160383Snetchild		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
1211160383Snetchild		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
1212160383Snetchild		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
1213160383Snetchild		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
1214160383Snetchild		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
1215160383Snetchild		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
1216160383Snetchild		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
1217160383Snetchild		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
1218160383Snetchild		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
1219160383Snetchild		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
1220160383Snetchild		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
1221160383Snetchild		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
1222160383Snetchild		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
1223160383Snetchild		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
1224160383Snetchild		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
1225160383Snetchild		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
1226160383Snetchild	};
1227160383Snetchild	int i;
1228160383Snetchild
1229160383Snetchild	if (rate == 0)
1230160383Snetchild		return (0);
1231160383Snetchild	rate *= 11185;		/* Scale 48000 to 0x20002380 */
1232160383Snetchild	for (i = 31; i > 0; i--) {
1233160383Snetchild		if (rate & 0x80000000) {	/* Detect leading "1" */
1234160383Snetchild			return (((uint32_t) (i - 15) << 20) +
1235160383Snetchild			    logMagTable[0x7f & (rate >> 24)] +
1236160383Snetchild			    (0x7f & (rate >> 17)) *
1237160383Snetchild			    logSlopeTable[0x7f & (rate >> 24)]);
1238160383Snetchild		}
1239160383Snetchild		rate <<= 1;
1240160383Snetchild	}
1241160383Snetchild	/* NOTREACHED */
1242160383Snetchild	return (0);
1243160383Snetchild}
1244160383Snetchild
1245160383Snetchildstatic uint32_t
1246160383Snetchildemu_rate_to_linearpitch(uint32_t rate)
1247160383Snetchild{
1248160383Snetchild	rate = (rate << 8) / 375;
1249160383Snetchild	return ((rate >> 1) + (rate & 1));
1250160383Snetchild}
1251160383Snetchild
1252160383Snetchildstruct emu_voice *
1253160383Snetchildemu_valloc(struct emu_sc_info *sc)
1254160383Snetchild{
1255160383Snetchild	struct emu_voice *v;
1256160383Snetchild	int i;
1257160383Snetchild
1258160383Snetchild	v = NULL;
1259160383Snetchild	mtx_lock(&sc->lock);
1260160383Snetchild	for (i = 0; i < NUM_G && sc->voice[i].busy; i++);
1261160383Snetchild	if (i < NUM_G) {
1262160383Snetchild		v = &sc->voice[i];
1263160383Snetchild		v->busy = 1;
1264160383Snetchild	}
1265160383Snetchild	mtx_unlock(&sc->lock);
1266160383Snetchild	return (v);
1267160383Snetchild}
1268160383Snetchild
1269160383Snetchildvoid
1270160383Snetchildemu_vfree(struct emu_sc_info *sc, struct emu_voice *v)
1271160383Snetchild{
1272160383Snetchild	int i, r;
1273160383Snetchild
1274160383Snetchild	mtx_lock(&sc->lock);
1275160383Snetchild	for (i = 0; i < NUM_G; i++) {
1276160383Snetchild		if (v == &sc->voice[i] && sc->voice[i].busy) {
1277160383Snetchild			v->busy = 0;
1278172150Sariff			/*
1279172150Sariff			 * XXX What we should do with mono channels?
1280172150Sariff			 * See -pcm.c emupchan_init for other side of
1281172150Sariff			 * this problem
1282172150Sariff			 */
1283160383Snetchild			if (v->slave != NULL)
1284160383Snetchild				r = emu_memfree(&sc->mem, v->vbuf);
1285160383Snetchild		}
1286160383Snetchild	}
1287160383Snetchild	mtx_unlock(&sc->lock);
1288160383Snetchild}
1289160383Snetchild
1290160383Snetchildint
1291160383Snetchildemu_vinit(struct emu_sc_info *sc, struct emu_voice *m, struct emu_voice *s,
1292160383Snetchild    uint32_t sz, struct snd_dbuf *b)
1293160383Snetchild{
1294160383Snetchild	void *vbuf;
1295160383Snetchild	bus_addr_t tmp_addr;
1296160383Snetchild
1297160383Snetchild	vbuf = emu_memalloc(&sc->mem, sz, &tmp_addr, "vinit");
1298172150Sariff	if (vbuf == NULL) {
1299172150Sariff		if(sc->dbg_level > 2)
1300172150Sariff			device_printf(sc->dev, "emu_memalloc returns NULL in enu_vinit\n");
1301160383Snetchild		return (ENOMEM);
1302172150Sariff		}
1303160383Snetchild	if (b != NULL)
1304160383Snetchild		sndbuf_setup(b, vbuf, sz);
1305160383Snetchild	m->start = emu_memstart(&sc->mem, vbuf) * EMUPAGESIZE;
1306172150Sariff	if (m->start < 0) {
1307172150Sariff		if(sc->dbg_level > 2)
1308172150Sariff			device_printf(sc->dev, "emu_memstart returns (-1) in enu_vinit\n");
1309160383Snetchild		emu_memfree(&sc->mem, vbuf);
1310160383Snetchild		return (ENOMEM);
1311160383Snetchild	}
1312160383Snetchild	m->end = m->start + sz;
1313160383Snetchild	m->speed = 0;
1314160383Snetchild	m->b16 = 0;
1315160383Snetchild	m->stereo = 0;
1316160383Snetchild	m->running = 0;
1317160383Snetchild	m->ismaster = 1;
1318160383Snetchild	m->vol = 0xff;
1319160383Snetchild	m->buf = tmp_addr;
1320160383Snetchild	m->vbuf = vbuf;
1321160383Snetchild	m->slave = s;
1322160383Snetchild	if (s != NULL) {
1323160383Snetchild		s->start = m->start;
1324160383Snetchild		s->end = m->end;
1325160383Snetchild		s->speed = 0;
1326160383Snetchild		s->b16 = 0;
1327160383Snetchild		s->stereo = 0;
1328160383Snetchild		s->running = 0;
1329160383Snetchild		s->ismaster = 0;
1330160383Snetchild		s->vol = m->vol;
1331160383Snetchild		s->buf = m->buf;
1332160383Snetchild		s->vbuf = NULL;
1333160383Snetchild		s->slave = NULL;
1334160383Snetchild	}
1335160383Snetchild	return (0);
1336160383Snetchild}
1337160383Snetchild
1338160383Snetchildvoid
1339160383Snetchildemu_vsetup(struct emu_voice *v, int fmt, int spd)
1340160383Snetchild{
1341160383Snetchild	if (fmt) {
1342160383Snetchild		v->b16 = (fmt & AFMT_16BIT) ? 1 : 0;
1343193640Sariff		v->stereo = (AFMT_CHANNEL(fmt) > 1) ? 1 : 0;
1344160383Snetchild		if (v->slave != NULL) {
1345160383Snetchild			v->slave->b16 = v->b16;
1346160383Snetchild			v->slave->stereo = v->stereo;
1347160383Snetchild		}
1348160383Snetchild	}
1349160383Snetchild	if (spd) {
1350160383Snetchild		v->speed = spd;
1351160383Snetchild		if (v->slave != NULL)
1352160383Snetchild			v->slave->speed = v->speed;
1353160383Snetchild	}
1354160383Snetchild}
1355160383Snetchild
1356160383Snetchildvoid
1357160383Snetchildemu_vroute(struct emu_sc_info *sc, struct emu_route *rt,  struct emu_voice *v)
1358160383Snetchild{
1359160383Snetchild	int i;
1360160383Snetchild
1361160383Snetchild	for (i = 0; i < 8; i++) {
1362172150Sariff		v->routing[i] = rt->routing_left[i];
1363172150Sariff		v->amounts[i] = rt->amounts_left[i];
1364160383Snetchild	}
1365160383Snetchild	if ((v->stereo) && (v->ismaster == 0))
1366160383Snetchild		for (i = 0; i < 8; i++) {
1367172150Sariff			v->routing[i] = rt->routing_right[i];
1368172150Sariff			v->amounts[i] = rt->amounts_right[i];
1369160383Snetchild		}
1370160383Snetchild
1371160383Snetchild	if ((v->stereo) && (v->slave != NULL))
1372160383Snetchild		emu_vroute(sc, rt, v->slave);
1373160383Snetchild}
1374160383Snetchild
1375160383Snetchildvoid
1376160383Snetchildemu_vwrite(struct emu_sc_info *sc, struct emu_voice *v)
1377160383Snetchild{
1378160383Snetchild	int s;
1379172150Sariff	uint32_t start, val, silent_page;
1380160383Snetchild
1381160383Snetchild	s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0);
1382160383Snetchild
1383160383Snetchild	v->sa = v->start >> s;
1384160383Snetchild	v->ea = v->end >> s;
1385160383Snetchild
1386160383Snetchild
1387160383Snetchild	if (v->stereo) {
1388229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CPF, EMU_CHAN_CPF_STEREO_MASK);
1389160383Snetchild	} else {
1390229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CPF, 0);
1391160383Snetchild	}
1392160383Snetchild	val = v->stereo ? 28 : 30;
1393160383Snetchild	val *= v->b16 ? 1 : 2;
1394160383Snetchild	start = v->sa + val;
1395160383Snetchild
1396172150Sariff	if (sc->is_emu10k1) {
1397229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_FXRT, ((v->routing[3] << 12) |
1398172150Sariff		    (v->routing[2] << 8) |
1399172150Sariff		    (v->routing[1] << 4) |
1400172150Sariff		    (v->routing[0] << 0)) << 16);
1401172150Sariff	} else {
1402229981Spfg		emu_wrptr(sc, v->vnum, EMU_A_CHAN_FXRT1, (v->routing[3] << 24) |
1403172150Sariff		    (v->routing[2] << 16) |
1404172150Sariff		    (v->routing[1] << 8) |
1405172150Sariff		    (v->routing[0] << 0));
1406229981Spfg		emu_wrptr(sc, v->vnum, EMU_A_CHAN_FXRT2, (v->routing[7] << 24) |
1407172150Sariff		    (v->routing[6] << 16) |
1408172150Sariff		    (v->routing[5] << 8) |
1409172150Sariff		    (v->routing[4] << 0));
1410229981Spfg		emu_wrptr(sc, v->vnum, EMU_A_CHAN_SENDAMOUNTS, (v->amounts[7] << 24) |
1411172150Sariff		    (v->amounts[6] << 26) |
1412172150Sariff		    (v->amounts[5] << 8) |
1413172150Sariff		    (v->amounts[4] << 0));
1414172150Sariff	}
1415229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX, (v->amounts[0] << 8) | (v->amounts[1] << 0));
1416229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_DSL, v->ea | (v->amounts[3] << 24));
1417229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_PSST, v->sa | (v->amounts[2] << 24));
1418160383Snetchild
1419229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_CCCA, start | (v->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT));
1420229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_Z1, 0);
1421229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_Z2, 0);
1422160383Snetchild
1423229981Spfg	silent_page = ((uint32_t) (sc->mem.silent_page_addr) << 1) | EMU_CHAN_MAP_PTI_MASK;
1424229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_MAPA, silent_page);
1425229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_MAPB, silent_page);
1426160383Snetchild
1427229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, EMU_CHAN_CVCF_CURRFILTER_MASK);
1428229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, EMU_CHAN_VTFT_FILTERTARGET_MASK);
1429229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_ATKHLDM, 0);
1430229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_DCYSUSM, EMU_CHAN_DCYSUSM_DECAYTIME_MASK);
1431229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_LFOVAL1, 0x8000);
1432229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_LFOVAL2, 0x8000);
1433229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_FMMOD, 0);
1434229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_TREMFRQ, 0);
1435229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_FM2FRQ2, 0);
1436229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_ENVVAL, 0x8000);
1437160383Snetchild
1438229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_ATKHLDV, EMU_CHAN_ATKHLDV_HOLDTIME_MASK | EMU_CHAN_ATKHLDV_ATTACKTIME_MASK);
1439229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_ENVVOL, 0x8000);
1440160383Snetchild
1441229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_PEFE_FILTERAMOUNT, 0x7f);
1442229981Spfg	emu_wrptr(sc, v->vnum, EMU_CHAN_PEFE_PITCHAMOUNT, 0);
1443160383Snetchild	if ((v->stereo) && (v->slave != NULL))
1444160383Snetchild		emu_vwrite(sc, v->slave);
1445160383Snetchild}
1446160383Snetchild
1447160383Snetchildstatic void
1448160383Snetchildemu_vstop(struct emu_sc_info *sc, char channel, int enable)
1449160383Snetchild{
1450160383Snetchild	int reg;
1451160383Snetchild
1452229981Spfg	reg = (channel & 0x20) ? EMU_SOLEH : EMU_SOLEL;
1453160383Snetchild	channel &= 0x1f;
1454160383Snetchild	reg |= 1 << 24;
1455160383Snetchild	reg |= channel << 16;
1456160383Snetchild	emu_wrptr(sc, 0, reg, enable);
1457160383Snetchild}
1458160383Snetchild
1459160383Snetchildvoid
1460160383Snetchildemu_vtrigger(struct emu_sc_info *sc, struct emu_voice *v, int go)
1461160383Snetchild{
1462160383Snetchild	uint32_t pitch_target, initial_pitch;
1463160383Snetchild	uint32_t cra, cs, ccis;
1464160383Snetchild	uint32_t sample, i;
1465160383Snetchild
1466160383Snetchild	if (go) {
1467160383Snetchild		cra = 64;
1468160383Snetchild		cs = v->stereo ? 4 : 2;
1469160383Snetchild		ccis = v->stereo ? 28 : 30;
1470160383Snetchild		ccis *= v->b16 ? 1 : 2;
1471160383Snetchild		sample = v->b16 ? 0x00000000 : 0x80808080;
1472160383Snetchild		for (i = 0; i < cs; i++)
1473229981Spfg			emu_wrptr(sc, v->vnum, EMU_CHAN_CD0 + i, sample);
1474229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
1475229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_READADDRESS, cra);
1476229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CCR_CACHEINVALIDSIZE, ccis);
1477160383Snetchild
1478229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_IFATN, 0xff00);
1479229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, 0xffffffff);
1480229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, 0xffffffff);
1481229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_DCYSUSV, 0x00007f7f);
1482160383Snetchild		emu_vstop(sc, v->vnum, 0);
1483160383Snetchild
1484160383Snetchild		pitch_target = emu_rate_to_linearpitch(v->speed);
1485160383Snetchild		initial_pitch = emu_rate_to_pitch(v->speed) >> 8;
1486229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX_PITCHTARGET, pitch_target);
1487229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CPF_PITCH, pitch_target);
1488229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_IP, initial_pitch);
1489160383Snetchild	} else {
1490229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_PTRX_PITCHTARGET, 0);
1491229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CPF_PITCH, 0);
1492229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_IFATN, 0xffff);
1493229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_VTFT, 0x0000ffff);
1494229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_CVCF, 0x0000ffff);
1495229981Spfg		emu_wrptr(sc, v->vnum, EMU_CHAN_IP, 0);
1496160383Snetchild		emu_vstop(sc, v->vnum, 1);
1497160383Snetchild	}
1498160383Snetchild	if ((v->stereo) && (v->slave != NULL))
1499160383Snetchild		emu_vtrigger(sc, v->slave, go);
1500160383Snetchild}
1501160383Snetchild
1502160383Snetchildint
1503160383Snetchildemu_vpos(struct emu_sc_info *sc, struct emu_voice *v)
1504160383Snetchild{
1505160383Snetchild	int s, ptr;
1506160383Snetchild
1507160383Snetchild	s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0);
1508229981Spfg	ptr = (emu_rdptr(sc, v->vnum, EMU_CHAN_CCCA_CURRADDR) - (v->start >> s)) << s;
1509160383Snetchild	return (ptr & ~0x0000001f);
1510160383Snetchild}
1511160383Snetchild
1512160383Snetchild
1513160383Snetchild/* fx */
1514160383Snetchildstatic void
1515160383Snetchildemu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data)
1516160383Snetchild{
1517160383Snetchild	emu_wrptr(sc, 0, sc->code_base + pc, data);
1518160383Snetchild}
1519160383Snetchild
1520160383Snetchild
1521160383Snetchildstatic void
1522160383Snetchildemu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc)
1523160383Snetchild{
1524160383Snetchild	if ((*pc) + 1 > sc->code_size) {
1525160383Snetchild		device_printf(sc->dev, "DSP CODE OVERRUN: attept to write past code_size (pc=%d)\n", (*pc));
1526160383Snetchild		return;
1527160383Snetchild	}
1528160383Snetchild	emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y);
1529160383Snetchild	emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w);
1530160383Snetchild	(*pc)++;
1531160383Snetchild}
1532160383Snetchild
1533160383Snetchildstatic int
1534160383Snetchildsysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS)
1535160383Snetchild{
1536160383Snetchild	struct emu_sc_info *sc;
1537160383Snetchild	int	mixer_id;
1538160383Snetchild	int	new_vol;
1539160383Snetchild	int	err;
1540160383Snetchild
1541160383Snetchild	sc = arg1;
1542160383Snetchild	mixer_id = arg2;
1543160383Snetchild
1544160383Snetchild	new_vol = emumix_get_volume(sc, mixer_id);
1545170289Sdwmalone	err = sysctl_handle_int(oidp, &new_vol, 0, req);
1546160383Snetchild
1547160383Snetchild	if (err || req->newptr == NULL)
1548160383Snetchild		return (err);
1549160383Snetchild	if (new_vol < 0 || new_vol > 100)
1550160383Snetchild		return (EINVAL);
1551160383Snetchild	emumix_set_volume(sc, mixer_id, new_vol);
1552160383Snetchild
1553160383Snetchild	return (0);
1554160383Snetchild}
1555160383Snetchild
1556160383Snetchildstatic int
1557160383Snetchildemu_addefxmixer(struct emu_sc_info *sc, const char *mix_name, const int mix_id, uint32_t defvolume)
1558160383Snetchild{
1559160383Snetchild	int volgpr;
1560160438Snetchild	char	sysctl_name[32];
1561160383Snetchild
1562160383Snetchild	volgpr = emu_rm_gpr_alloc(sc->rm, 1);
1563160383Snetchild	emumix_set_fxvol(sc, volgpr, defvolume);
1564172150Sariff	/*
1565172150Sariff	 * Mixer controls with NULL mix_name are handled
1566172150Sariff	 * by AC97 emulation code or PCM mixer.
1567172150Sariff	 */
1568160383Snetchild	if (mix_name != NULL) {
1569172150Sariff		/*
1570172150Sariff		 * Temporary sysctls should start with underscore,
1571160438Snetchild		 * see freebsd-current mailing list, emu10kx driver
1572172150Sariff		 * discussion around 2006-05-24.
1573172150Sariff		 */
1574160438Snetchild		snprintf(sysctl_name, 32, "_%s", mix_name);
1575160383Snetchild		SYSCTL_ADD_PROC(sc->ctx,
1576160383Snetchild			SYSCTL_CHILDREN(sc->root),
1577160438Snetchild			OID_AUTO, sysctl_name,
1578160383Snetchild			CTLTYPE_INT | CTLFLAG_RW, sc, mix_id,
1579172150Sariff			sysctl_emu_mixer_control, "I", "");
1580160383Snetchild	}
1581160383Snetchild
1582160383Snetchild	return (volgpr);
1583160383Snetchild}
1584160383Snetchild
1585172150Sariffstatic int
1586172150Sariffsysctl_emu_digitalswitch_control(SYSCTL_HANDLER_ARGS)
1587172150Sariff{
1588172150Sariff	struct emu_sc_info *sc;
1589172150Sariff	int	new_val;
1590172150Sariff	int	err;
1591172150Sariff
1592172150Sariff	sc = arg1;
1593172150Sariff
1594172150Sariff	new_val = (sc->mode == MODE_DIGITAL) ? 1 : 0;
1595172150Sariff	err = sysctl_handle_int(oidp, &new_val, 0, req);
1596172150Sariff
1597172150Sariff	if (err || req->newptr == NULL)
1598172150Sariff		return (err);
1599172150Sariff	if (new_val < 0 || new_val > 1)
1600172150Sariff		return (EINVAL);
1601172150Sariff
1602172150Sariff	switch (new_val) {
1603172150Sariff		case 0:
1604172150Sariff			emumix_set_mode(sc, MODE_ANALOG);
1605172150Sariff			break;
1606172150Sariff		case 1:
1607172150Sariff			emumix_set_mode(sc, MODE_DIGITAL);
1608172150Sariff			break;
1609172150Sariff	}
1610172150Sariff	return (0);
1611172150Sariff}
1612172150Sariff
1613172150Sariffstatic void
1614172150Sariffemu_digitalswitch(struct emu_sc_info *sc)
1615172150Sariff{
1616172150Sariff	/* XXX temporary? */
1617172150Sariff	SYSCTL_ADD_PROC(sc->ctx,
1618172150Sariff		SYSCTL_CHILDREN(sc->root),
1619172150Sariff		OID_AUTO, "_digital",
1620172150Sariff		CTLTYPE_INT | CTLFLAG_RW, sc, 0,
1621172150Sariff		sysctl_emu_digitalswitch_control, "I", "Enable digital output");
1622172150Sariff
1623172150Sariff	return;
1624172150Sariff}
1625172150Sariff
1626172150Sariff/*
1627172150Sariff * Allocate cache GPRs that will hold mixed output channels
1628160383Snetchild * and clear it on every DSP run.
1629160383Snetchild */
1630160383Snetchild#define	EFX_CACHE(CACHE_IDX) do {				\
1631160383Snetchild	sc->cache_gpr[CACHE_IDX] = emu_rm_gpr_alloc(sc->rm, 1); \
1632160383Snetchild	emu_addefxop(sc, ACC3, 					\
1633160383Snetchild		GPR(sc->cache_gpr[CACHE_IDX]), 			\
1634160383Snetchild		DSP_CONST(0), 					\
1635160383Snetchild		DSP_CONST(0), 					\
1636160383Snetchild		DSP_CONST(0), 					\
1637160383Snetchild		&pc);						\
1638160383Snetchild} while (0)
1639160383Snetchild
1640160383Snetchild/* Allocate GPR for volume control and route sound: OUT = OUT + IN * VOL */
1641160383Snetchild#define	EFX_ROUTE(TITLE, INP_NR, IN_GPR_IDX, OUT_CACHE_IDX, DEF) do { 	\
1642160383Snetchild	sc->mixer_gpr[IN_GPR_IDX] = emu_addefxmixer(sc, TITLE, IN_GPR_IDX,  DEF); \
1643160383Snetchild	sc->mixer_volcache[IN_GPR_IDX] = DEF; 			\
1644160383Snetchild	emu_addefxop(sc, MACS, 					\
1645160383Snetchild		GPR(sc->cache_gpr[OUT_CACHE_IDX]), 		\
1646160383Snetchild		GPR(sc->cache_gpr[OUT_CACHE_IDX]),		\
1647160383Snetchild		INP_NR,						\
1648160383Snetchild		GPR(sc->mixer_gpr[IN_GPR_IDX]),			\
1649160383Snetchild		&pc);						\
1650160383Snetchild} while (0)
1651160383Snetchild
1652160383Snetchild/* allocate GPR, OUT = IN * VOL */
1653172150Sariff#define	EFX_OUTPUT(TITLE, OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR, DEF) do {	\
1654160383Snetchild	sc->mixer_gpr[OUT_GPR_IDX] = emu_addefxmixer(sc, TITLE, OUT_GPR_IDX, DEF); \
1655160383Snetchild	sc->mixer_volcache[OUT_GPR_IDX] = DEF;			\
1656160383Snetchild	emu_addefxop(sc, MACS,					\
1657160383Snetchild		OUTP(OUTP_NR),					\
1658160383Snetchild		DSP_CONST(0),					\
1659160383Snetchild		GPR(sc->cache_gpr[OUT_CACHE_IDX]),		\
1660160383Snetchild		GPR(sc->mixer_gpr[OUT_GPR_IDX]),		\
1661160383Snetchild		&pc);						\
1662160383Snetchild} while (0)
1663160383Snetchild
1664160383Snetchild/* like EFX_OUTPUT, but don't allocate mixer gpr */
1665172150Sariff#define	EFX_OUTPUTD(OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR) do {	\
1666160383Snetchild	emu_addefxop(sc, MACS,					\
1667160383Snetchild		OUTP(OUTP_NR),					\
1668160383Snetchild		DSP_CONST(0),					\
1669160383Snetchild		GPR(sc->cache_gpr[OUT_CACHE_IDX]),		\
1670160383Snetchild		GPR(sc->mixer_gpr[OUT_GPR_IDX]),		\
1671160383Snetchild		&pc);						\
1672172150Sariff} while (0)
1673160383Snetchild
1674172150Sariff/* skip next OPCOUNT instructions if FLAG != 0 */
1675172150Sariff#define EFX_SKIP(OPCOUNT, FLAG_GPR) do {			\
1676172150Sariff	emu_addefxop(sc, MACS,					\
1677172150Sariff		DSP_CONST(0),					\
1678172150Sariff		GPR(sc->mute_gpr[FLAG_GPR]),					\
1679172150Sariff		DSP_CONST(0),					\
1680172150Sariff		DSP_CONST(0),					\
1681172150Sariff		&pc);						\
1682172150Sariff	emu_addefxop(sc, SKIP,					\
1683172150Sariff		DSP_CCR,					\
1684172150Sariff		DSP_CCR,					\
1685172150Sariff		COND_NEQ_ZERO,					\
1686172150Sariff		OPCOUNT,					\
1687172150Sariff		&pc);						\
1688172150Sariff} while (0)
1689165833Snetchild
1690172150Sariff#define EFX_COPY(TO, FROM) do {					\
1691172150Sariff	emu_addefxop(sc, ACC3,					\
1692172150Sariff		TO,						\
1693165833Snetchild		DSP_CONST(0),					\
1694165833Snetchild		DSP_CONST(0),					\
1695172150Sariff		FROM,						\
1696165833Snetchild		&pc);						\
1697165833Snetchild} while (0)
1698165833Snetchild
1699165833Snetchild
1700160383Snetchildstatic void
1701160383Snetchildemu_initefx(struct emu_sc_info *sc)
1702160383Snetchild{
1703165833Snetchild	unsigned int i;
1704160383Snetchild	uint32_t pc;
1705160383Snetchild
1706160383Snetchild	/* stop DSP */
1707160383Snetchild	if (sc->is_emu10k1) {
1708229981Spfg		emu_wrptr(sc, 0, EMU_DBG, EMU_DBG_SINGLE_STEP);
1709160383Snetchild	} else {
1710229981Spfg		emu_wrptr(sc, 0, EMU_A_DBG, EMU_A_DBG_SINGLE_STEP);
1711160383Snetchild	}
1712160383Snetchild
1713160383Snetchild	/* code size is in instructions */
1714160383Snetchild	pc = 0;
1715165833Snetchild	for (i = 0; i < sc->code_size; i++) {
1716160383Snetchild		if (sc->is_emu10k1) {
1717160383Snetchild			emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), &pc);
1718160383Snetchild		} else {
1719160383Snetchild			emu_addefxop(sc, SKIP, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0xf), DSP_CONST(0x0), &pc);
1720160383Snetchild		}
1721160383Snetchild	}
1722160383Snetchild
1723172150Sariff	/* allocate GPRs for mute switches (EFX_SKIP). Mute by default */
1724172150Sariff	for (i = 0; i < NUM_MUTE; i++) {
1725172150Sariff		sc->mute_gpr[i] = emu_rm_gpr_alloc(sc->rm, 1);
1726172150Sariff		emumix_set_gpr(sc, sc->mute_gpr[i], 1);
1727172150Sariff	}
1728172150Sariff	emu_digitalswitch(sc);
1729172150Sariff
1730160383Snetchild	pc = 0;
1731160383Snetchild
1732172150Sariff	/*
1733160383Snetchild	 * DSP code below is not good, because:
1734160383Snetchild	 * 1. It can be written smaller, if it can use DSP accumulator register
1735160383Snetchild	 * instead of cache_gpr[].
1736160383Snetchild	 * 2. It can be more careful when volume is 100%, because in DSP
1737160383Snetchild	 * x*0x7fffffff may not be equal to x !
1738160383Snetchild	 */
1739160383Snetchild
1740160383Snetchild	/* clean outputs */
1741165833Snetchild	for (i = 0; i < 16 ; i++) {
1742165833Snetchild		emu_addefxop(sc, ACC3, OUTP(i), DSP_CONST(0), DSP_CONST(0), DSP_CONST(0), &pc);
1743160383Snetchild	}
1744160383Snetchild
1745160383Snetchild
1746160383Snetchild	if (sc->is_emu10k1) {
1747160383Snetchild		EFX_CACHE(C_FRONT_L);
1748160383Snetchild		EFX_CACHE(C_FRONT_R);
1749160383Snetchild		EFX_CACHE(C_REC_L);
1750160383Snetchild		EFX_CACHE(C_REC_R);
1751160383Snetchild
1752160383Snetchild		/* fx0 to front/record, 100%/muted by default */
1753160383Snetchild		EFX_ROUTE("pcm_front_l", FX(0), M_FX0_FRONT_L, C_FRONT_L, 100);
1754160383Snetchild		EFX_ROUTE("pcm_front_r", FX(1), M_FX1_FRONT_R, C_FRONT_R, 100);
1755172150Sariff		EFX_ROUTE(NULL, FX(0), M_FX0_REC_L, C_REC_L, 0);
1756172150Sariff		EFX_ROUTE(NULL, FX(1), M_FX1_REC_R, C_REC_R, 0);
1757160383Snetchild
1758160383Snetchild		/* in0, from AC97 codec output */
1759160383Snetchild		EFX_ROUTE("ac97_front_l", INP(IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 0);
1760160383Snetchild		EFX_ROUTE("ac97_front_r", INP(IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 0);
1761160383Snetchild		EFX_ROUTE("ac97_rec_l", INP(IN_AC97_L), M_IN0_REC_L, C_REC_L, 0);
1762160383Snetchild		EFX_ROUTE("ac97_rec_r", INP(IN_AC97_R), M_IN0_REC_R, C_REC_R, 0);
1763160383Snetchild
1764160383Snetchild		/* in1, from CD S/PDIF */
1765172150Sariff		/* XXX EFX_SKIP 4 assumes that each EFX_ROUTE is one DSP op */
1766172150Sariff		EFX_SKIP(4, CDSPDIFMUTE);
1767172150Sariff		EFX_ROUTE(NULL, INP(IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0);
1768172150Sariff		EFX_ROUTE(NULL, INP(IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0);
1769172150Sariff		EFX_ROUTE(NULL, INP(IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0);
1770172150Sariff		EFX_ROUTE(NULL, INP(IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0);
1771172150Sariff
1772172150Sariff		if (sc->dbg_level > 0) {
1773172150Sariff			/* in2, ZoomVide (???) */
1774172150Sariff			EFX_ROUTE("zoom_front_l", INP(IN_ZOOM_L), M_IN2_FRONT_L, C_FRONT_L, 0);
1775172150Sariff			EFX_ROUTE("zoom_front_r", INP(IN_ZOOM_R), M_IN2_FRONT_R, C_FRONT_R, 0);
1776172150Sariff			EFX_ROUTE("zoom_rec_l", INP(IN_ZOOM_L), M_IN2_REC_L, C_REC_L, 0);
1777172150Sariff			EFX_ROUTE("zoom_rec_r", INP(IN_ZOOM_R), M_IN2_REC_R, C_REC_R, 0);
1778172150Sariff		}
1779172150Sariff
1780172150Sariff		/* in3, TOSLink  */
1781172150Sariff		EFX_ROUTE(NULL, INP(IN_TOSLINK_L), M_IN3_FRONT_L, C_FRONT_L, 0);
1782172150Sariff		EFX_ROUTE(NULL, INP(IN_TOSLINK_R), M_IN3_FRONT_R, C_FRONT_R, 0);
1783172150Sariff		EFX_ROUTE(NULL, INP(IN_TOSLINK_L), M_IN3_REC_L, C_REC_L, 0);
1784172150Sariff		EFX_ROUTE(NULL, INP(IN_TOSLINK_R), M_IN3_REC_R, C_REC_R, 0);
1785160383Snetchild		/* in4, LineIn  */
1786172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE1_L), M_IN4_FRONT_L, C_FRONT_L, 0);
1787172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE1_R), M_IN4_FRONT_R, C_FRONT_R, 0);
1788172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE1_L), M_IN4_REC_L, C_REC_L, 0);
1789172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE1_R), M_IN4_REC_R, C_REC_R, 0);
1790160383Snetchild
1791160383Snetchild		/* in5, on-card S/PDIF */
1792172150Sariff		EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0);
1793172150Sariff		EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0);
1794172150Sariff		EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_L), M_IN5_REC_L, C_REC_L, 0);
1795172150Sariff		EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_R), M_IN5_REC_R, C_REC_R, 0);
1796160383Snetchild
1797160383Snetchild		/* in6, Line2 on Live!Drive */
1798172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE2_L), M_IN6_FRONT_L, C_FRONT_L, 0);
1799172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE2_R), M_IN6_FRONT_R, C_FRONT_R, 0);
1800172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE2_L), M_IN6_REC_L, C_REC_L, 0);
1801172150Sariff		EFX_ROUTE(NULL, INP(IN_LINE2_R), M_IN6_REC_R, C_REC_R, 0);
1802172150Sariff
1803172150Sariff		if (sc->dbg_level > 0) {
1804172150Sariff			/* in7, unknown */
1805172150Sariff			EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0);
1806172150Sariff			EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0);
1807172150Sariff			EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0);
1808172150Sariff			EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0);
1809172150Sariff		}
1810172150Sariff
1811172150Sariff		/* analog and digital */
1812160383Snetchild		EFX_OUTPUT("master_front_l", C_FRONT_L, M_MASTER_FRONT_L, OUT_AC97_L, 100);
1813160383Snetchild		EFX_OUTPUT("master_front_r", C_FRONT_R, M_MASTER_FRONT_R, OUT_AC97_R, 100);
1814172150Sariff		/* S/PDIF */
1815172150Sariff		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_TOSLINK_L);
1816172150Sariff		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_TOSLINK_R);
1817172150Sariff		/* Headphones */
1818165833Snetchild		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_HEADPHONE_L);
1819165833Snetchild		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_HEADPHONE_R);
1820160383Snetchild
1821160383Snetchild		/* rec output to "ADC" */
1822160383Snetchild		EFX_OUTPUT("master_rec_l", C_REC_L, M_MASTER_REC_L, OUT_ADC_REC_L, 100);
1823160383Snetchild		EFX_OUTPUT("master_rec_r", C_REC_R, M_MASTER_REC_R, OUT_ADC_REC_R, 100);
1824160383Snetchild
1825172150Sariff		if (!(sc->mch_disabled)) {
1826172150Sariff			/*
1827172150Sariff			 * Additional channel volume is controlled by mixer in
1828172150Sariff			 * emu_dspmixer_set() in -pcm.c
1829172150Sariff			 */
1830160383Snetchild
1831172150Sariff			/* fx2/3 (pcm1) to rear */
1832172150Sariff			EFX_CACHE(C_REAR_L);
1833172150Sariff			EFX_CACHE(C_REAR_R);
1834172150Sariff			EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100);
1835172150Sariff			EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100);
1836172150Sariff
1837172150Sariff			EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, OUT_REAR_L, 100);
1838172150Sariff			EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, OUT_REAR_R, 100);
1839172150Sariff			if (sc->has_51) {
1840172150Sariff				/* fx4 (pcm2) to center */
1841172150Sariff				EFX_CACHE(C_CENTER);
1842172150Sariff				EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100);
1843172150Sariff				EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100);
1844172150Sariff
1845172150Sariff				/* XXX in digital mode (default) this should be muted because
1846172150Sariff				this output is shared with digital out */
1847172150Sariff				EFX_SKIP(1, ANALOGMUTE);
1848172150Sariff				EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER);
1849172150Sariff
1850172150Sariff				/* fx5 (pcm3) to sub */
1851172150Sariff				EFX_CACHE(C_SUB);
1852172150Sariff				EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100);
1853172150Sariff				EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100);
1854172150Sariff
1855172150Sariff				/* XXX in digital mode (default) this should be muted because
1856172150Sariff				this output is shared with digital out */
1857172150Sariff				EFX_SKIP(1, ANALOGMUTE);
1858172150Sariff				EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB);
1859172150Sariff
1860172150Sariff			}
1861172150Sariff		} else {
1862172150Sariff			/* SND_EMU10KX_MULTICHANNEL_DISABLED */
1863172150Sariff			EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_REAR_L, OUT_REAR_L, 57); /* 75%*75% */
1864172150Sariff			EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_REAR_R, OUT_REAR_R, 57); /* 75%*75% */
1865172150Sariff
1866165833Snetchild#if 0
1867172150Sariff			/* XXX 5.1 does not work */
1868172150Sariff
1869172150Sariff			if (sc->has_51) {
1870172150Sariff				/* (fx0+fx1)/2 to center */
1871172150Sariff				EFX_CACHE(C_CENTER);
1872172150Sariff				emu_addefxop(sc, MACS,
1873172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1874172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1875172150Sariff					DSP_CONST(0xd), /* = 1/2 */
1876172150Sariff					GPR(sc->cache_gpr[C_FRONT_L]),
1877172150Sariff					&pc);
1878172150Sariff				emu_addefxop(sc, MACS,
1879172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1880172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1881172150Sariff					DSP_CONST(0xd), /* = 1/2 */
1882172150Sariff					GPR(sc->cache_gpr[C_FRONT_R]),
1883172150Sariff					&pc);
1884172150Sariff				EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100);
1885172150Sariff
1886172150Sariff				/* XXX in digital mode (default) this should be muted because
1887172150Sariff				this output is shared with digital out */
1888172150Sariff				EFX_SKIP(1, ANALOGMUTE);
1889172150Sariff				EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER);
1890172150Sariff
1891172150Sariff				/* (fx0+fx1)/2  to sub */
1892172150Sariff				EFX_CACHE(C_SUB);
1893172150Sariff				emu_addefxop(sc, MACS,
1894172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1895172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1896172150Sariff					DSP_CONST(0xd), /* = 1/2 */
1897172150Sariff					GPR(sc->cache_gpr[C_FRONT_L]),
1898172150Sariff					&pc);
1899172150Sariff				emu_addefxop(sc, MACS,
1900172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1901172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
1902172150Sariff					DSP_CONST(0xd), /* = 1/2 */
1903172150Sariff					GPR(sc->cache_gpr[C_FRONT_R]),
1904172150Sariff					&pc);
1905172150Sariff				/* XXX add lowpass filter here */
1906172150Sariff
1907172150Sariff				EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100);
1908172150Sariff
1909172150Sariff				/* XXX in digital mode (default) this should be muted because
1910172150Sariff				this output is shared with digital out */
1911172150Sariff				EFX_SKIP(1, ANALOGMUTE);
1912172150Sariff				EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB);
1913172150Sariff			}
1914165833Snetchild#endif
1915172150Sariff		} /* !mch_disabled */
1916172150Sariff		if (sc->mch_rec) {
1917172150Sariff			/*
1918172150Sariff			 * MCH RECORDING , hight 16 slots. On 5.1 cards first 4 slots
1919172150Sariff			 * are used as outputs and already filled with data
1920172150Sariff			 */
1921172150Sariff			/*
1922172150Sariff			 * XXX On Live! cards stream does not begin at zero offset.
1923172150Sariff			 * It can be HW, driver or sound buffering problem.
1924172150Sariff			 * Use sync substream (offset 0x3E) to let userland find
1925172150Sariff			 * correct data.
1926172150Sariff			 */
1927165833Snetchild
1928172150Sariff			/*
1929172150Sariff			 * Substream map (in byte offsets, each substream is 2 bytes):
1930172150Sariff			 *	0x00..0x1E - outputs
1931249587Sgabor			 *	0x20..0x3E - FX, inputs and sync stream
1932172150Sariff			 */
1933172150Sariff
1934172150Sariff			/* First 2 channels (offset 0x20,0x22) are empty */
1935172150Sariff			for(i = (sc->has_51 ? 2 : 0); i < 2; i++)
1936172150Sariff				EFX_COPY(FX2(i), DSP_CONST(0));
1937172150Sariff
1938172150Sariff			/* PCM Playback monitoring, offset 0x24..0x2A */
1939172150Sariff			for(i = 0; i < 4; i++)
1940172150Sariff				EFX_COPY(FX2(i+2), FX(i));
1941172150Sariff
1942172150Sariff			/* Copy of some inputs, offset 0x2C..0x3C */
1943172150Sariff			for(i = 0; i < 9; i++)
1944172150Sariff				EFX_COPY(FX2(i+8), INP(i));
1945172150Sariff
1946172150Sariff			/* sync data (0xc0de, offset 0x3E) */
1947172150Sariff			sc->dummy_gpr = emu_rm_gpr_alloc(sc->rm, 1);
1948172150Sariff			emumix_set_gpr(sc, sc->dummy_gpr, 0xc0de0000);
1949172150Sariff
1950172150Sariff			EFX_COPY(FX2(15), GPR(sc->dummy_gpr));
1951172150Sariff		} /* mch_rec */
1952160383Snetchild	} else /* emu10k2 and later */ {
1953160383Snetchild		EFX_CACHE(C_FRONT_L);
1954160383Snetchild		EFX_CACHE(C_FRONT_R);
1955160383Snetchild		EFX_CACHE(C_REC_L);
1956160383Snetchild		EFX_CACHE(C_REC_R);
1957160383Snetchild
1958160383Snetchild		/* fx0 to front/record, 100%/muted by default */
1959160383Snetchild		/*
1960160383Snetchild		 * FRONT_[L|R] is controlled by AC97 emulation in
1961160383Snetchild		 * emu_ac97_[read|write]_emulation in -pcm.c
1962160383Snetchild		 */
1963160383Snetchild		EFX_ROUTE(NULL, FX(0), M_FX0_FRONT_L, C_FRONT_L, 100);
1964160383Snetchild		EFX_ROUTE(NULL, FX(1), M_FX1_FRONT_R, C_FRONT_R, 100);
1965172150Sariff		EFX_ROUTE(NULL, FX(0), M_FX0_REC_L, C_REC_L, 0);
1966172150Sariff		EFX_ROUTE(NULL, FX(1), M_FX1_REC_R, C_REC_R, 0);
1967160383Snetchild
1968160383Snetchild		/* in0, from AC97 codec output */
1969172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 100);
1970172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 100);
1971172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AC97_L), M_IN0_REC_L, C_REC_L, 0);
1972172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AC97_R), M_IN0_REC_R, C_REC_R, 0);
1973160383Snetchild
1974160383Snetchild		/* in1, from CD S/PDIF */
1975172150Sariff		EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0);
1976172150Sariff		EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0);
1977172150Sariff		EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0);
1978172150Sariff		EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0);
1979160383Snetchild
1980160383Snetchild		/* in2, optical & coax S/PDIF on AudigyDrive*/
1981165833Snetchild		/* XXX Should be muted when GPRSCS valid stream == 0 */
1982172150Sariff		EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_L), M_IN2_FRONT_L, C_FRONT_L, 0);
1983172150Sariff		EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_R), M_IN2_FRONT_R, C_FRONT_R, 0);
1984172150Sariff		EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_L), M_IN2_REC_L, C_REC_L, 0);
1985172150Sariff		EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_R), M_IN2_REC_R, C_REC_R, 0);
1986172150Sariff
1987172150Sariff		if (sc->dbg_level > 0) {
1988172150Sariff			/* in3, unknown */
1989172150Sariff			EFX_ROUTE("in3_front_l", INP(0x6), M_IN3_FRONT_L, C_FRONT_L, 0);
1990172150Sariff			EFX_ROUTE("in3_front_r", INP(0x7), M_IN3_FRONT_R, C_FRONT_R, 0);
1991172150Sariff			EFX_ROUTE("in3_rec_l", INP(0x6), M_IN3_REC_L, C_REC_L, 0);
1992172150Sariff			EFX_ROUTE("in3_rec_r", INP(0x7), M_IN3_REC_R, C_REC_R, 0);
1993172150Sariff		}
1994172150Sariff
1995160383Snetchild		/* in4, LineIn 2 on AudigyDrive */
1996172150Sariff		EFX_ROUTE(NULL, INP(A_IN_LINE2_L), M_IN4_FRONT_L, C_FRONT_L, 0);
1997172150Sariff		EFX_ROUTE(NULL, INP(A_IN_LINE2_R), M_IN4_FRONT_R, C_FRONT_R, 0);
1998172150Sariff		EFX_ROUTE(NULL, INP(A_IN_LINE2_L), M_IN4_REC_L, C_REC_L, 0);
1999172150Sariff		EFX_ROUTE(NULL, INP(A_IN_LINE2_R), M_IN4_REC_R, C_REC_R, 0);
2000160383Snetchild
2001160383Snetchild		/* in5, on-card S/PDIF */
2002172150Sariff		EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0);
2003172150Sariff		EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0);
2004172150Sariff		EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_L), M_IN5_REC_L, C_REC_L, 0);
2005172150Sariff		EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_R), M_IN5_REC_R, C_REC_R, 0);
2006160383Snetchild
2007160383Snetchild		/* in6, AUX2 on AudigyDrive */
2008172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AUX2_L), M_IN6_FRONT_L, C_FRONT_L, 0);
2009172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AUX2_R), M_IN6_FRONT_R, C_FRONT_R, 0);
2010172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AUX2_L), M_IN6_REC_L, C_REC_L, 0);
2011172150Sariff		EFX_ROUTE(NULL, INP(A_IN_AUX2_R), M_IN6_REC_R, C_REC_R, 0);
2012172150Sariff
2013172150Sariff		if (sc->dbg_level > 0) {
2014172150Sariff			/* in7, unknown */
2015172150Sariff			EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0);
2016172150Sariff			EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0);
2017172150Sariff			EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0);
2018172150Sariff			EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0);
2019172150Sariff		}
2020172150Sariff
2021160383Snetchild		/* front output to headphones and  alog and digital *front */
2022160383Snetchild		/* volume controlled by AC97 emulation */
2023160383Snetchild		EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_FRONT_L, 100);
2024160383Snetchild		EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_FRONT_R, 100);
2025160383Snetchild		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_FRONT_L);
2026160383Snetchild		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_FRONT_R);
2027160383Snetchild		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_HPHONE_L);
2028160383Snetchild		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_HPHONE_R);
2029160383Snetchild
2030160383Snetchild		/* rec output to "ADC" */
2031160383Snetchild		/* volume controlled by AC97 emulation */
2032160383Snetchild		EFX_OUTPUT(NULL, C_REC_L, M_MASTER_REC_L, A_OUT_ADC_REC_L, 100);
2033161057Snetchild		EFX_OUTPUT(NULL, C_REC_R, M_MASTER_REC_R, A_OUT_ADC_REC_R, 100);
2034160383Snetchild
2035172150Sariff		if (!(sc->mch_disabled)) {
2036172150Sariff			/*
2037172150Sariff			 * Additional channel volume is controlled by mixer in
2038172150Sariff			 * emu_dspmixer_set() in -pcm.c
2039172150Sariff			 */
2040160383Snetchild
2041172150Sariff			/* fx2/3 (pcm1) to rear */
2042172150Sariff			EFX_CACHE(C_REAR_L);
2043172150Sariff			EFX_CACHE(C_REAR_R);
2044172150Sariff			EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100);
2045172150Sariff			EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100);
2046160383Snetchild
2047172150Sariff			EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, A_OUT_A_REAR_L, 100);
2048172150Sariff			EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, A_OUT_A_REAR_R, 100);
2049172150Sariff			EFX_OUTPUTD(C_REAR_L, M_MASTER_REAR_L, A_OUT_D_REAR_L);
2050172150Sariff			EFX_OUTPUTD(C_REAR_R, M_MASTER_REAR_R, A_OUT_D_REAR_R);
2051172150Sariff
2052172150Sariff			/* fx4 (pcm2) to center */
2053172150Sariff			EFX_CACHE(C_CENTER);
2054172150Sariff			EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100);
2055172150Sariff			EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100);
2056160383Snetchild#if 0
2057172150Sariff			/*
2058172150Sariff			 * XXX in digital mode (default) this should be muted
2059172150Sariff			 * because this output is shared with digital out
2060172150Sariff			 */
2061172150Sariff			EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER);
2062160383Snetchild#endif
2063172150Sariff			/* fx5 (pcm3) to sub */
2064172150Sariff			EFX_CACHE(C_SUB);
2065172150Sariff			EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100);
2066172150Sariff			EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100);
2067160383Snetchild#if 0
2068172150Sariff			/*
2069172150Sariff			 * XXX in digital mode (default) this should be muted
2070172150Sariff			 * because this output is shared with digital out
2071172150Sariff			 */
2072172150Sariff			EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB);
2073160383Snetchild#endif
2074172150Sariff			if (sc->has_71) {
2075172150Sariff				/* XXX this will broke headphones on AudigyDrive */
2076172150Sariff				/* fx6/7 (pcm4) to side */
2077172150Sariff				EFX_CACHE(C_SIDE_L);
2078172150Sariff				EFX_CACHE(C_SIDE_R);
2079172150Sariff				EFX_ROUTE(NULL, FX(6), M_FX6_SIDE_L, C_SIDE_L, 100);
2080172150Sariff				EFX_ROUTE(NULL, FX(7), M_FX7_SIDE_R, C_SIDE_R, 100);
2081172150Sariff				EFX_OUTPUT(NULL, C_SIDE_L, M_MASTER_SIDE_L, A_OUT_A_SIDE_L, 100);
2082172150Sariff				EFX_OUTPUT(NULL, C_SIDE_R, M_MASTER_SIDE_R, A_OUT_A_SIDE_R, 100);
2083172150Sariff				EFX_OUTPUTD(C_SIDE_L, M_MASTER_SIDE_L, A_OUT_D_SIDE_L);
2084172150Sariff				EFX_OUTPUTD(C_SIDE_R, M_MASTER_SIDE_R, A_OUT_D_SIDE_R);
2085172150Sariff			}
2086172150Sariff		} else {	/* mch_disabled */
2087172150Sariff			EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_REAR_L);
2088172150Sariff			EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_REAR_R);
2089160383Snetchild
2090172150Sariff			EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_REAR_L);
2091172150Sariff			EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_REAR_R);
2092172150Sariff
2093172150Sariff			if (sc->has_51) {
2094172150Sariff				/* (fx0+fx1)/2 to center */
2095172150Sariff				EFX_CACHE(C_CENTER);
2096172150Sariff				emu_addefxop(sc, MACS,
2097172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
2098172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
2099172150Sariff					DSP_CONST(0xd), /* = 1/2 */
2100172150Sariff					GPR(sc->cache_gpr[C_FRONT_L]),
2101172150Sariff					&pc);
2102172150Sariff				emu_addefxop(sc, MACS,
2103172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
2104172150Sariff					GPR(sc->cache_gpr[C_CENTER]),
2105172150Sariff					DSP_CONST(0xd), /* = 1/2 */
2106172150Sariff					GPR(sc->cache_gpr[C_FRONT_R]),
2107172150Sariff					&pc);
2108172150Sariff				EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100);
2109172150Sariff
2110172150Sariff				/* XXX in digital mode (default) this should be muted because
2111172150Sariff				this output is shared with digital out */
2112172150Sariff				EFX_SKIP(1, ANALOGMUTE);
2113172150Sariff				EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER);
2114172150Sariff
2115172150Sariff				/* (fx0+fx1)/2  to sub */
2116172150Sariff				EFX_CACHE(C_SUB);
2117172150Sariff				emu_addefxop(sc, MACS,
2118172150Sariff					GPR(sc->cache_gpr[C_SUB]),
2119172150Sariff					GPR(sc->cache_gpr[C_SUB]),
2120172150Sariff					DSP_CONST(0xd), /* = 1/2 */
2121172150Sariff					GPR(sc->cache_gpr[C_FRONT_L]),
2122172150Sariff					&pc);
2123172150Sariff				emu_addefxop(sc, MACS,
2124172150Sariff					GPR(sc->cache_gpr[C_SUB]),
2125172150Sariff					GPR(sc->cache_gpr[C_SUB]),
2126172150Sariff					DSP_CONST(0xd), /* = 1/2 */
2127172150Sariff					GPR(sc->cache_gpr[C_FRONT_R]),
2128172150Sariff					&pc);
2129172150Sariff				/* XXX add lowpass filter here */
2130172150Sariff
2131172150Sariff				EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100);
2132172150Sariff
2133172150Sariff				/* XXX in digital mode (default) this should be muted because
2134172150Sariff				this output is shared with digital out */
2135172150Sariff				EFX_SKIP(1, ANALOGMUTE);
2136172150Sariff				EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB);
2137172150Sariff			}
2138172150Sariff		} /* mch_disabled */
2139172150Sariff		if (sc->mch_rec) {
2140172150Sariff			/* MCH RECORDING, high 32 slots */
2141172150Sariff
2142172150Sariff			/*
2143172150Sariff			 * Stream map (in byte offsets):
2144172150Sariff			 *	0x00..0x3E - outputs
2145172150Sariff			 *	0x40..0x7E - FX, inputs
2146172150Sariff			 *	each substream is 2 bytes.
2147172150Sariff			 */
2148172150Sariff			/*
2149172150Sariff			 * XXX Audigy 2 Value cards (and, possibly,
2150172150Sariff			 * Audigy 4) write some unknown data in place of
2151172150Sariff			 * some outputs (offsets 0x20..0x3F) and one
2152172150Sariff			 * input (offset 0x7E).
2153172150Sariff			 */
2154172150Sariff
2155172150Sariff			/* PCM Playback monitoring, offsets 0x40..0x5E */
2156172150Sariff			for(i = 0; i < 16; i++)
2157172150Sariff				EFX_COPY(FX2(i), FX(i));
2158172150Sariff
2159172150Sariff			/* Copy of all inputs, offsets 0x60..0x7E */
2160172150Sariff			for(i = 0; i < 16; i++)
2161172150Sariff				EFX_COPY(FX2(i+16), INP(i));
2162172150Sariff#if 0
2163172150Sariff			/* XXX Audigy seems to work correct and does not need this */
2164172150Sariff			/* sync data (0xc0de), offset 0x7E */
2165172150Sariff			sc->dummy_gpr = emu_rm_gpr_alloc(sc->rm, 1);
2166172150Sariff			emumix_set_gpr(sc, sc->dummy_gpr, 0xc0de0000);
2167172150Sariff			EFX_COPY(FX2(31), GPR(sc->dummy_gpr));
2168160383Snetchild#endif
2169172150Sariff		} /* mch_rec */
2170160383Snetchild	}
2171160383Snetchild
2172160383Snetchild	sc->routing_code_end = pc;
2173160383Snetchild
2174160383Snetchild	/* start DSP */
2175160383Snetchild	if (sc->is_emu10k1) {
2176229981Spfg		emu_wrptr(sc, 0, EMU_DBG, 0);
2177160383Snetchild	} else {
2178229981Spfg		emu_wrptr(sc, 0, EMU_A_DBG, 0);
2179160383Snetchild	}
2180160383Snetchild}
2181160383Snetchild
2182160383Snetchild/* /dev/em10kx */
2183160383Snetchildstatic d_open_t		emu10kx_open;
2184160383Snetchildstatic d_close_t	emu10kx_close;
2185160383Snetchildstatic d_read_t		emu10kx_read;
2186160383Snetchild
2187160383Snetchildstatic struct cdevsw emu10kx_cdevsw = {
2188160383Snetchild	.d_open = 	emu10kx_open,
2189160383Snetchild	.d_close =	emu10kx_close,
2190160383Snetchild	.d_read = 	emu10kx_read,
2191160383Snetchild	.d_name = 	"emu10kx",
2192160383Snetchild	.d_version = 	D_VERSION,
2193160383Snetchild};
2194160383Snetchild
2195160383Snetchild
2196160383Snetchildstatic int
2197160383Snetchildemu10kx_open(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused)
2198160383Snetchild{
2199160383Snetchild	int error;
2200160383Snetchild	struct emu_sc_info *sc;
2201160383Snetchild
2202160383Snetchild	sc = i_dev->si_drv1;
2203160383Snetchild	mtx_lock(&sc->emu10kx_lock);
2204160383Snetchild	if (sc->emu10kx_isopen) {
2205160383Snetchild		mtx_unlock(&sc->emu10kx_lock);
2206160383Snetchild		return (EBUSY);
2207160383Snetchild	}
2208160383Snetchild	sc->emu10kx_isopen = 1;
2209160383Snetchild	mtx_unlock(&sc->emu10kx_lock);
2210160383Snetchild	if (sbuf_new(&sc->emu10kx_sbuf, NULL, 4096, 0) == NULL) {
2211160383Snetchild		error = ENXIO;
2212160383Snetchild		goto out;
2213160383Snetchild	}
2214160383Snetchild	sc->emu10kx_bufptr = 0;
2215160383Snetchild	error = (emu10kx_prepare(sc, &sc->emu10kx_sbuf) > 0) ? 0 : ENOMEM;
2216160383Snetchildout:
2217160383Snetchild	if (error) {
2218160383Snetchild		mtx_lock(&sc->emu10kx_lock);
2219160383Snetchild		sc->emu10kx_isopen = 0;
2220160383Snetchild		mtx_unlock(&sc->emu10kx_lock);
2221160383Snetchild	}
2222160383Snetchild	return (error);
2223160383Snetchild}
2224160383Snetchild
2225160383Snetchildstatic int
2226160383Snetchildemu10kx_close(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused)
2227160383Snetchild{
2228160383Snetchild	struct emu_sc_info *sc;
2229160383Snetchild
2230160383Snetchild	sc = i_dev->si_drv1;
2231160383Snetchild
2232160383Snetchild	mtx_lock(&sc->emu10kx_lock);
2233160383Snetchild	if (!(sc->emu10kx_isopen)) {
2234160383Snetchild		mtx_unlock(&sc->emu10kx_lock);
2235160383Snetchild		return (EBADF);
2236160383Snetchild	}
2237160383Snetchild	sbuf_delete(&sc->emu10kx_sbuf);
2238160383Snetchild	sc->emu10kx_isopen = 0;
2239160383Snetchild	mtx_unlock(&sc->emu10kx_lock);
2240160383Snetchild
2241160383Snetchild	return (0);
2242160383Snetchild}
2243160383Snetchild
2244160383Snetchildstatic int
2245160383Snetchildemu10kx_read(struct cdev *i_dev, struct uio *buf, int flag __unused)
2246160383Snetchild{
2247160383Snetchild	int l, err;
2248160383Snetchild	struct emu_sc_info *sc;
2249160383Snetchild
2250160383Snetchild	sc = i_dev->si_drv1;
2251160383Snetchild	mtx_lock(&sc->emu10kx_lock);
2252160383Snetchild	if (!(sc->emu10kx_isopen)) {
2253160383Snetchild		mtx_unlock(&sc->emu10kx_lock);
2254160383Snetchild		return (EBADF);
2255160383Snetchild	}
2256160383Snetchild	mtx_unlock(&sc->emu10kx_lock);
2257160383Snetchild
2258160383Snetchild	l = min(buf->uio_resid, sbuf_len(&sc->emu10kx_sbuf) - sc->emu10kx_bufptr);
2259160383Snetchild	err = (l > 0) ? uiomove(sbuf_data(&sc->emu10kx_sbuf) + sc->emu10kx_bufptr, l, buf) : 0;
2260160383Snetchild	sc->emu10kx_bufptr += l;
2261160383Snetchild
2262160383Snetchild	return (err);
2263160383Snetchild}
2264160383Snetchild
2265160383Snetchildstatic int
2266160383Snetchildemu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s)
2267160383Snetchild{
2268160383Snetchild	int i;
2269160383Snetchild
2270160383Snetchild	sbuf_printf(s, "FreeBSD EMU10Kx Audio Driver\n");
2271160383Snetchild	sbuf_printf(s, "\nHardware resource usage:\n");
2272160383Snetchild	sbuf_printf(s, "DSP General Purpose Registers: %d used, %d total\n", sc->rm->num_used, sc->rm->num_gprs);
2273160383Snetchild	sbuf_printf(s, "DSP Instruction Registers: %d used, %d total\n", sc->routing_code_end, sc->code_size);
2274160383Snetchild	sbuf_printf(s, "Card supports");
2275160383Snetchild	if (sc->has_ac97) {
2276160383Snetchild		sbuf_printf(s, " AC97 codec");
2277160383Snetchild	} else {
2278160383Snetchild		sbuf_printf(s, " NO AC97 codec");
2279160383Snetchild	}
2280160383Snetchild	if (sc->has_51) {
2281160383Snetchild		if (sc->has_71)
2282160383Snetchild			sbuf_printf(s, " and 7.1 output");
2283160383Snetchild		else
2284160383Snetchild			sbuf_printf(s, " and 5.1 output");
2285160383Snetchild	}
2286160383Snetchild	if (sc->is_emu10k1)
2287160383Snetchild		sbuf_printf(s, ", SBLive! DSP code");
2288160383Snetchild	if (sc->is_emu10k2)
2289160383Snetchild		sbuf_printf(s, ", Audigy DSP code");
2290160383Snetchild	if (sc->is_ca0102)
2291160383Snetchild		sbuf_printf(s, ", Audigy DSP code with Audigy2 hacks");
2292160383Snetchild	if (sc->is_ca0108)
2293160383Snetchild		sbuf_printf(s, ", Audigy DSP code with Audigy2Value hacks");
2294160383Snetchild	sbuf_printf(s, "\n");
2295160383Snetchild	if (sc->broken_digital)
2296160383Snetchild		sbuf_printf(s, "Digital mode unsupported\n");
2297160383Snetchild	sbuf_printf(s, "\nInstalled devices:\n");
2298165833Snetchild	for (i = 0; i < RT_COUNT; i++)
2299160383Snetchild		if (sc->pcm[i] != NULL)
2300160383Snetchild			if (device_is_attached(sc->pcm[i])) {
2301160383Snetchild				sbuf_printf(s, "%s on %s\n", device_get_desc(sc->pcm[i]), device_get_nameunit(sc->pcm[i]));
2302160383Snetchild			}
2303160383Snetchild	if (sc->midi[0] != NULL)
2304160383Snetchild		if (device_is_attached(sc->midi[0])) {
2305160383Snetchild			sbuf_printf(s, "EMU10Kx MIDI Interface\n");
2306160383Snetchild			sbuf_printf(s, "\tOn-card connector on %s\n", device_get_nameunit(sc->midi[0]));
2307160383Snetchild		}
2308160383Snetchild	if (sc->midi[1] != NULL)
2309160383Snetchild		if (device_is_attached(sc->midi[1])) {
2310160383Snetchild			sbuf_printf(s, "\tOn-Drive connector on %s\n", device_get_nameunit(sc->midi[1]));
2311160383Snetchild		}
2312160383Snetchild	if (sc->midi[0] != NULL)
2313160383Snetchild		if (device_is_attached(sc->midi[0])) {
2314160383Snetchild			sbuf_printf(s, "\tIR reciever MIDI events %s\n", sc->enable_ir ? "enabled" : "disabled");
2315160383Snetchild		}
2316172150Sariff	sbuf_printf(s, "Card is in %s mode\n", (sc->mode == MODE_ANALOG) ? "analog" : "digital");
2317172150Sariff
2318160383Snetchild	sbuf_finish(s);
2319160383Snetchild	return (sbuf_len(s));
2320160383Snetchild}
2321160383Snetchild
2322160383Snetchild/* INIT & UNINIT */
2323160383Snetchildstatic int
2324160383Snetchildemu10kx_dev_init(struct emu_sc_info *sc)
2325160383Snetchild{
2326160383Snetchild	int unit;
2327160383Snetchild
2328172150Sariff	mtx_init(&sc->emu10kx_lock, device_get_nameunit(sc->dev), "kxdevlock", 0);
2329160383Snetchild	unit = device_get_unit(sc->dev);
2330160383Snetchild
2331193640Sariff	sc->cdev = make_dev(&emu10kx_cdevsw, PCMMINOR(unit), UID_ROOT, GID_WHEEL, 0640, "emu10kx%d", unit);
2332160383Snetchild	if (sc->cdev != NULL) {
2333160383Snetchild		sc->cdev->si_drv1 = sc;
2334160383Snetchild		return (0);
2335160383Snetchild	}
2336160383Snetchild	return (ENXIO);
2337160383Snetchild}
2338160383Snetchild
2339160383Snetchildstatic int
2340160383Snetchildemu10kx_dev_uninit(struct emu_sc_info *sc)
2341160383Snetchild{
2342160383Snetchild	mtx_lock(&sc->emu10kx_lock);
2343160383Snetchild	if (sc->emu10kx_isopen) {
2344160383Snetchild		mtx_unlock(&sc->emu10kx_lock);
2345160383Snetchild		return (EBUSY);
2346160383Snetchild	}
2347160383Snetchild	if (sc->cdev)
2348160383Snetchild		destroy_dev(sc->cdev);
2349160383Snetchild	sc->cdev = 0;
2350160383Snetchild
2351160383Snetchild	mtx_destroy(&sc->emu10kx_lock);
2352160383Snetchild	return (0);
2353160383Snetchild}
2354160383Snetchild
2355160383Snetchild/* resource manager */
2356160383Snetchildint
2357160383Snetchildemu_rm_init(struct emu_sc_info *sc)
2358160383Snetchild{
2359160383Snetchild	int i;
2360160383Snetchild	int maxcount;
2361160383Snetchild	struct emu_rm *rm;
2362160383Snetchild
2363160383Snetchild	rm = malloc(sizeof(struct emu_rm), M_DEVBUF, M_NOWAIT | M_ZERO);
2364160383Snetchild	if (rm == NULL) {
2365160383Snetchild		return (ENOMEM);
2366160383Snetchild	}
2367160383Snetchild	sc->rm = rm;
2368160383Snetchild	rm->card = sc;
2369160383Snetchild	maxcount = sc->num_gprs;
2370160383Snetchild	rm->num_used = 0;
2371172150Sariff	mtx_init(&(rm->gpr_lock), device_get_nameunit(sc->dev), "gpr alloc", MTX_DEF);
2372160383Snetchild	rm->num_gprs = (maxcount < EMU_MAX_GPR ? maxcount : EMU_MAX_GPR);
2373160383Snetchild	for (i = 0; i < rm->num_gprs; i++)
2374160383Snetchild		rm->allocmap[i] = 0;
2375172150Sariff	/* pre-allocate gpr[0] */
2376172150Sariff	rm->allocmap[0] = 1;
2377172150Sariff	rm->last_free_gpr = 1;
2378160383Snetchild
2379160383Snetchild	return (0);
2380160383Snetchild}
2381160383Snetchild
2382160383Snetchildint
2383160383Snetchildemu_rm_uninit(struct emu_sc_info *sc)
2384160383Snetchild{
2385160383Snetchild	int i;
2386160383Snetchild
2387172150Sariff	if (sc->dbg_level > 1) {
2388172150Sariff		mtx_lock(&(sc->rm->gpr_lock));
2389172150Sariff		for (i = 1; i < sc->rm->last_free_gpr; i++)
2390172150Sariff			if (sc->rm->allocmap[i] > 0)
2391172150Sariff				device_printf(sc->dev, "rm: gpr %d not free before uninit\n", i);
2392172150Sariff		mtx_unlock(&(sc->rm->gpr_lock));
2393172150Sariff	}
2394172150Sariff
2395160383Snetchild	mtx_destroy(&(sc->rm->gpr_lock));
2396160383Snetchild	free(sc->rm, M_DEVBUF);
2397160383Snetchild	return (0);
2398160383Snetchild}
2399160383Snetchild
2400160383Snetchildstatic int
2401160383Snetchildemu_rm_gpr_alloc(struct emu_rm *rm, int count)
2402160383Snetchild{
2403160383Snetchild	int i, j;
2404160383Snetchild	int allocated_gpr;
2405160383Snetchild
2406160383Snetchild	allocated_gpr = rm->num_gprs;
2407160383Snetchild	/* try fast way first */
2408160383Snetchild	mtx_lock(&(rm->gpr_lock));
2409160383Snetchild	if (rm->last_free_gpr + count <= rm->num_gprs) {
2410160383Snetchild		allocated_gpr = rm->last_free_gpr;
2411160383Snetchild		rm->last_free_gpr += count;
2412160383Snetchild		rm->allocmap[allocated_gpr] = count;
2413160383Snetchild		for (i = 1; i < count; i++)
2414160383Snetchild			rm->allocmap[allocated_gpr + i] = -(count - i);
2415160383Snetchild	} else {
2416160383Snetchild		/* longer */
2417160383Snetchild		i = 0;
2418160383Snetchild		allocated_gpr = rm->num_gprs;
2419160383Snetchild		while (i < rm->last_free_gpr - count) {
2420160383Snetchild			if (rm->allocmap[i] > 0) {
2421160383Snetchild				i += rm->allocmap[i];
2422160383Snetchild			} else {
2423160383Snetchild				allocated_gpr = i;
2424160383Snetchild				for (j = 1; j < count; j++) {
2425160383Snetchild					if (rm->allocmap[i + j] != 0)
2426160383Snetchild						allocated_gpr = rm->num_gprs;
2427160383Snetchild				}
2428160383Snetchild				if (allocated_gpr == i)
2429160383Snetchild					break;
2430160383Snetchild			}
2431160383Snetchild		}
2432160383Snetchild		if (allocated_gpr + count < rm->last_free_gpr) {
2433160383Snetchild			rm->allocmap[allocated_gpr] = count;
2434160383Snetchild			for (i = 1; i < count; i++)
2435160383Snetchild				rm->allocmap[allocated_gpr + i] = -(count - i);
2436160383Snetchild
2437160383Snetchild		}
2438160383Snetchild	}
2439160383Snetchild	if (allocated_gpr == rm->num_gprs)
2440160383Snetchild		allocated_gpr = (-1);
2441160383Snetchild	if (allocated_gpr >= 0)
2442160383Snetchild		rm->num_used += count;
2443160383Snetchild	mtx_unlock(&(rm->gpr_lock));
2444160383Snetchild	return (allocated_gpr);
2445160383Snetchild}
2446160383Snetchild
2447160383Snetchild/* mixer */
2448160383Snetchildvoid
2449160383Snetchildemumix_set_mode(struct emu_sc_info *sc, int mode)
2450160383Snetchild{
2451160383Snetchild	uint32_t a_iocfg;
2452160383Snetchild	uint32_t hcfg;
2453160383Snetchild	uint32_t tmp;
2454160383Snetchild
2455160383Snetchild	switch (mode) {
2456160383Snetchild	case MODE_DIGITAL:
2457160383Snetchild		/* FALLTHROUGH */
2458160383Snetchild	case MODE_ANALOG:
2459160383Snetchild		break;
2460160383Snetchild	default:
2461160383Snetchild		return;
2462160383Snetchild	}
2463160383Snetchild
2464229981Spfg	hcfg = EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE;
2465160383Snetchild	a_iocfg = 0;
2466160383Snetchild
2467160383Snetchild	if (sc->rev >= 6)
2468229981Spfg		hcfg |= EMU_HCFG_JOYENABLE;
2469160383Snetchild
2470160383Snetchild	if (sc->is_emu10k1)
2471229981Spfg		hcfg |= EMU_HCFG_LOCKTANKCACHE_MASK;
2472160383Snetchild	else
2473229981Spfg		hcfg |= EMU_HCFG_CODECFMT_I2S | EMU_HCFG_JOYENABLE;
2474160383Snetchild
2475160383Snetchild
2476160383Snetchild	if (mode == MODE_DIGITAL) {
2477160383Snetchild		if (sc->broken_digital) {
2478172150Sariff			device_printf(sc->dev, "Digital mode is reported as broken on this card.\n");
2479160383Snetchild		}
2480229981Spfg		a_iocfg |= EMU_A_IOCFG_GPOUT1;
2481229981Spfg		hcfg |= EMU_HCFG_GPOUT0;
2482160383Snetchild	}
2483160383Snetchild
2484160383Snetchild	if (mode == MODE_ANALOG)
2485160383Snetchild		emumix_set_spdif_mode(sc, SPDIF_MODE_PCM);
2486160383Snetchild
2487160383Snetchild	if (sc->is_emu10k2)
2488160383Snetchild		a_iocfg |= 0x80; /* XXX */
2489160383Snetchild
2490160383Snetchild	if ((sc->is_ca0102) || (sc->is_ca0108))
2491172150Sariff		/*
2492229981Spfg		 * Setting EMU_A_IOCFG_DISABLE_ANALOG will do opposite things
2493172150Sariff		 * on diffrerent cards.
2494172150Sariff		 * "don't disable analog outs" on Audigy 2 (ca0102/ca0108)
2495172150Sariff		 * "disable analog outs" on Audigy (emu10k2)
2496172150Sariff		 */
2497229981Spfg		a_iocfg |= EMU_A_IOCFG_DISABLE_ANALOG;
2498160383Snetchild
2499160383Snetchild	if (sc->is_ca0108)
2500160383Snetchild		a_iocfg |= 0x20; /* XXX */
2501160383Snetchild
2502172150Sariff	/* Mute analog center & subwoofer before mode change */
2503172150Sariff	if (mode == MODE_DIGITAL)
2504172150Sariff		emumix_set_gpr(sc, sc->mute_gpr[ANALOGMUTE], 1);
2505172150Sariff
2506229981Spfg	emu_wr(sc, EMU_HCFG, hcfg, 4);
2507160383Snetchild
2508160383Snetchild	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2509229981Spfg		tmp = emu_rd(sc, EMU_A_IOCFG, 2);
2510160383Snetchild		tmp = a_iocfg;
2511229981Spfg		emu_wr(sc, EMU_A_IOCFG, tmp, 2);
2512160383Snetchild	}
2513160383Snetchild
2514172150Sariff	/* Unmute if we have changed mode to analog. */
2515172150Sariff
2516172150Sariff	if (mode == MODE_ANALOG)
2517172150Sariff		emumix_set_gpr(sc, sc->mute_gpr[ANALOGMUTE], 0);
2518172150Sariff
2519172150Sariff	sc->mode = mode;
2520160383Snetchild}
2521160383Snetchild
2522160383Snetchildvoid
2523160383Snetchildemumix_set_spdif_mode(struct emu_sc_info *sc, int mode)
2524160383Snetchild{
2525160383Snetchild	uint32_t spcs;
2526160383Snetchild
2527160383Snetchild	switch (mode) {
2528160383Snetchild	case SPDIF_MODE_PCM:
2529160383Snetchild		break;
2530160383Snetchild	case SPDIF_MODE_AC3:
2531160383Snetchild		device_printf(sc->dev, "AC3 mode does not work and disabled\n");
2532160383Snetchild		return;
2533160383Snetchild	default:
2534160383Snetchild		return;
2535160383Snetchild	}
2536160383Snetchild
2537229981Spfg	spcs = EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
2538229981Spfg	    EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
2539229981Spfg	    EMU_SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 |
2540229981Spfg	    EMU_SPCS_EMPHASIS_NONE | EMU_SPCS_COPYRIGHT;
2541160383Snetchild
2542160383Snetchild	mode = SPDIF_MODE_PCM;
2543160383Snetchild
2544229981Spfg	emu_wrptr(sc, 0, EMU_SPCS0, spcs);
2545229981Spfg	emu_wrptr(sc, 0, EMU_SPCS1, spcs);
2546229981Spfg	emu_wrptr(sc, 0, EMU_SPCS2, spcs);
2547160383Snetchild}
2548160383Snetchild
2549160383Snetchild#define	L2L_POINTS	10
2550160383Snetchild
2551160383Snetchildstatic int l2l_df[L2L_POINTS] = {
2552160383Snetchild	0x572C5CA,		/* 100..90 */
2553160383Snetchild	0x3211625,		/* 90..80 */
2554160383Snetchild	0x1CC1A76,		/* 80..70 */
2555160383Snetchild	0x108428F,		/* 70..60 */
2556160383Snetchild	0x097C70A,		/* 60..50 */
2557160383Snetchild	0x0572C5C,		/* 50..40 */
2558160383Snetchild	0x0321162,		/* 40..30 */
2559160383Snetchild	0x01CC1A7,		/* 30..20 */
2560160383Snetchild	0x0108428,		/* 20..10 */
2561160383Snetchild	0x016493D		/* 10..0 */
2562160383Snetchild};
2563160383Snetchild
2564160383Snetchildstatic int l2l_f[L2L_POINTS] = {
2565160383Snetchild	0x4984461A,		/* 90 */
2566160383Snetchild	0x2A3968A7,		/* 80 */
2567160383Snetchild	0x18406003,		/* 70 */
2568160383Snetchild	0x0DEDC66D,		/* 60 */
2569160383Snetchild	0x07FFFFFF,		/* 50 */
2570160383Snetchild	0x04984461,		/* 40 */
2571160383Snetchild	0x02A3968A,		/* 30 */
2572160383Snetchild	0x01840600,		/* 20 */
2573160383Snetchild	0x00DEDC66,		/* 10 */
2574160383Snetchild	0x00000000		/* 0 */
2575160383Snetchild};
2576160383Snetchild
2577160383Snetchild
2578160383Snetchildstatic int
2579160383Snetchildlog2lin(int log_t)
2580160383Snetchild{
2581160383Snetchild	int lin_t;
2582160383Snetchild	int idx, lin;
2583160383Snetchild
2584160383Snetchild	if (log_t <= 0) {
2585160383Snetchild		lin_t = 0x00000000;
2586160383Snetchild		return (lin_t);
2587160383Snetchild	}
2588160383Snetchild
2589160383Snetchild	if (log_t >= 100) {
2590160383Snetchild		lin_t = 0x7fffffff;
2591160383Snetchild		return (lin_t);
2592160383Snetchild	}
2593160383Snetchild
2594160383Snetchild	idx = (L2L_POINTS - 1) - log_t / (L2L_POINTS);
2595160383Snetchild	lin = log_t % (L2L_POINTS);
2596160383Snetchild	lin_t = l2l_df[idx] * lin + l2l_f[idx];
2597160383Snetchild	return (lin_t);
2598160383Snetchild}
2599160383Snetchild
2600160383Snetchild
2601160383Snetchildvoid
2602160383Snetchildemumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol)
2603160383Snetchild{
2604160383Snetchild
2605160383Snetchild	vol = log2lin(vol);
2606160383Snetchild	emumix_set_gpr(sc, gpr, vol);
2607160383Snetchild}
2608160383Snetchild
2609160383Snetchildvoid
2610160383Snetchildemumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val)
2611160383Snetchild{
2612172150Sariff	if (sc->dbg_level > 1)
2613172150Sariff		if (gpr == 0) {
2614172150Sariff			device_printf(sc->dev, "Zero gpr write access\n");
2615172150Sariff#ifdef KDB
2616172150Sariff			kdb_backtrace();
2617172150Sariff#endif
2618172150Sariff			return;
2619172150Sariff			}
2620160383Snetchild
2621160383Snetchild	emu_wrptr(sc, 0, GPR(gpr), val);
2622160383Snetchild}
2623160383Snetchild
2624160383Snetchildvoid
2625160383Snetchildemumix_set_volume(struct emu_sc_info *sc, int mixer_idx, int volume)
2626160383Snetchild{
2627160383Snetchild
2628160383Snetchild	RANGE(volume, 0, 100);
2629160383Snetchild	if (mixer_idx < NUM_MIXERS) {
2630160383Snetchild		sc->mixer_volcache[mixer_idx] = volume;
2631160383Snetchild		emumix_set_fxvol(sc, sc->mixer_gpr[mixer_idx], volume);
2632160383Snetchild	}
2633160383Snetchild}
2634160383Snetchild
2635160383Snetchildint
2636160383Snetchildemumix_get_volume(struct emu_sc_info *sc, int mixer_idx)
2637160383Snetchild{
2638160383Snetchild	if ((mixer_idx < NUM_MIXERS) && (mixer_idx >= 0))
2639160383Snetchild		return (sc->mixer_volcache[mixer_idx]);
2640160383Snetchild	return (-1);
2641160383Snetchild}
2642160383Snetchild
2643160383Snetchild/* Init CardBus part */
2644160383Snetchildstatic int
2645160383Snetchildemu_cardbus_init(struct emu_sc_info *sc)
2646160383Snetchild{
2647160383Snetchild
2648160383Snetchild	/*
2649229981Spfg	 * XXX May not need this if we have EMU_IPR3 handler.
2650229981Spfg	 * Is it a real init calls, or EMU_IPR3 interrupt acknowledgments?
2651160383Snetchild	 * Looks much like "(data << 16) | register".
2652160383Snetchild	 */
2653160383Snetchild	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0000);
2654160383Snetchild	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0001);
2655160383Snetchild	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x005f);
2656160383Snetchild	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x007f);
2657160383Snetchild
2658160383Snetchild	emu_wr_cbptr(sc, (0x0090 << 16) | 0x007f);
2659160383Snetchild
2660160383Snetchild	return (0);
2661160383Snetchild}
2662160383Snetchild
2663160383Snetchild/* Probe and attach the card */
2664160383Snetchildstatic int
2665166919Sariffemu_init(struct emu_sc_info *sc)
2666160383Snetchild{
2667160383Snetchild	uint32_t ch, tmp;
2668160383Snetchild	uint32_t spdif_sr;
2669160383Snetchild	uint32_t ac97slot;
2670160383Snetchild	int def_mode;
2671160383Snetchild	int i;
2672160383Snetchild
2673160383Snetchild	/* disable audio and lock cache */
2674229981Spfg	emu_wr(sc, EMU_HCFG, EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_MUTEBUTTONENABLE, 4);
2675160383Snetchild
2676160383Snetchild	/* reset recording buffers */
2677229981Spfg	emu_wrptr(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
2678229981Spfg	emu_wrptr(sc, 0, EMU_MICBA, 0);
2679229981Spfg	emu_wrptr(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
2680229981Spfg	emu_wrptr(sc, 0, EMU_FXBA, 0);
2681229981Spfg	emu_wrptr(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
2682229981Spfg	emu_wrptr(sc, 0, EMU_ADCBA, 0);
2683160383Snetchild
2684160383Snetchild	/* disable channel interrupt */
2685229981Spfg	emu_wr(sc, EMU_INTE, EMU_INTE_INTERTIMERENB | EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE, 4);
2686229981Spfg	emu_wrptr(sc, 0, EMU_CLIEL, 0);
2687229981Spfg	emu_wrptr(sc, 0, EMU_CLIEH, 0);
2688229981Spfg	emu_wrptr(sc, 0, EMU_SOLEL, 0);
2689229981Spfg	emu_wrptr(sc, 0, EMU_SOLEH, 0);
2690160383Snetchild
2691160383Snetchild	/* disable P16V and S/PDIF interrupts */
2692160383Snetchild	if ((sc->is_ca0102) || (sc->is_ca0108))
2693229981Spfg		emu_wr(sc, EMU_INTE2, 0, 4);
2694160383Snetchild
2695160383Snetchild	if (sc->is_ca0102)
2696229981Spfg		emu_wr(sc, EMU_INTE3, 0, 4);
2697160383Snetchild
2698160383Snetchild	/* init phys inputs and outputs */
2699160383Snetchild	ac97slot = 0;
2700160383Snetchild	if (sc->has_51)
2701229981Spfg		ac97slot = EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE;
2702160383Snetchild	if (sc->has_71)
2703229981Spfg		ac97slot = EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE | EMU_AC97SLOT_REAR_LEFT | EMU_AC97SLOT_REAR_RIGHT;
2704160383Snetchild	if (sc->is_emu10k2)
2705160383Snetchild		ac97slot |= 0x40;
2706229981Spfg	emu_wrptr(sc, 0, EMU_AC97SLOT, ac97slot);
2707160383Snetchild
2708160383Snetchild	if (sc->is_emu10k2)	/* XXX for later cards? */
2709229981Spfg		emu_wrptr(sc, 0, EMU_SPBYPASS, 0xf00);	/* What will happen if
2710160383Snetchild							 * we write 1 here? */
2711160383Snetchild
2712166919Sariff	if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(sc->dev),
2713166904Snetchild	     /* alignment */ 2, /* boundary */ 0,
2714218478Smarius	     /* lowaddr */ (1U << 31) - 1,	/* can only access 0-2gb */
2715160383Snetchild	     /* highaddr */ BUS_SPACE_MAXADDR,
2716160383Snetchild	     /* filter */ NULL, /* filterarg */ NULL,
2717161054Snetchild	     /* maxsize */ EMU_MAX_BUFSZ, /* nsegments */ 1, /* maxsegz */ 0x3ffff,
2718160383Snetchild	     /* flags */ 0, /* lockfunc */ busdma_lock_mutex,
2719160383Snetchild	     /* lockarg */ &Giant, &(sc->mem.dmat)) != 0) {
2720160383Snetchild		device_printf(sc->dev, "unable to create dma tag\n");
2721160383Snetchild		bus_dma_tag_destroy(sc->mem.dmat);
2722160383Snetchild		return (ENOMEM);
2723160383Snetchild	}
2724160383Snetchild
2725172150Sariff	sc->mem.card = sc;
2726160383Snetchild	SLIST_INIT(&sc->mem.blocks);
2727161054Snetchild	sc->mem.ptb_pages = emu_malloc(&sc->mem, EMU_MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr);
2728160383Snetchild	if (sc->mem.ptb_pages == NULL)
2729160383Snetchild		return (ENOMEM);
2730160383Snetchild
2731160383Snetchild	sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr);
2732160383Snetchild	if (sc->mem.silent_page == NULL) {
2733160383Snetchild		emu_free(&sc->mem, sc->mem.ptb_pages);
2734160383Snetchild		return (ENOMEM);
2735160383Snetchild	}
2736160383Snetchild	/* Clear page with silence & setup all pointers to this page */
2737160383Snetchild	bzero(sc->mem.silent_page, EMUPAGESIZE);
2738160383Snetchild	tmp = (uint32_t) (sc->mem.silent_page_addr) << 1;
2739161054Snetchild	for (i = 0; i < EMU_MAXPAGES; i++)
2740160383Snetchild		sc->mem.ptb_pages[i] = tmp | i;
2741160383Snetchild
2742160383Snetchild	for (ch = 0; ch < NUM_G; ch++) {
2743229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_MAPA, tmp | EMU_CHAN_MAP_PTI_MASK);
2744229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_MAPB, tmp | EMU_CHAN_MAP_PTI_MASK);
2745160383Snetchild	}
2746229981Spfg	emu_wrptr(sc, 0, EMU_PTB, (sc->mem.ptb_pages_addr));
2747229981Spfg	emu_wrptr(sc, 0, EMU_TCB, 0);	/* taken from original driver */
2748229981Spfg	emu_wrptr(sc, 0, EMU_TCBS, 0);	/* taken from original driver */
2749160383Snetchild
2750160383Snetchild	/* init envelope engine */
2751160383Snetchild	for (ch = 0; ch < NUM_G; ch++) {
2752229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_DCYSUSV, 0);
2753229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_IP, 0);
2754229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_VTFT, 0xffff);
2755229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_CVCF, 0xffff);
2756229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_PTRX, 0);
2757229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_CPF, 0);
2758229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_CCR, 0);
2759160383Snetchild
2760229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_PSST, 0);
2761229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_DSL, 0x10);
2762229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_CCCA, 0);
2763229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_Z1, 0);
2764229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_Z2, 0);
2765229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_FXRT, 0xd01c0000);
2766160383Snetchild
2767229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_ATKHLDM, 0);
2768229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_DCYSUSM, 0);
2769229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_IFATN, 0xffff);
2770229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_PEFE, 0);
2771229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_FMMOD, 0);
2772229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_TREMFRQ, 24);	/* 1 Hz */
2773229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_FM2FRQ2, 24);	/* 1 Hz */
2774229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_TEMPENV, 0);
2775160383Snetchild
2776160383Snetchild		/*** these are last so OFF prevents writing ***/
2777229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_LFOVAL2, 0);
2778229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_LFOVAL1, 0);
2779229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_ATKHLDV, 0);
2780229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_ENVVOL, 0);
2781229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_ENVVAL, 0);
2782160383Snetchild
2783160383Snetchild		if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2784160383Snetchild			emu_wrptr(sc, ch, 0x4c, 0x0);
2785160383Snetchild			emu_wrptr(sc, ch, 0x4d, 0x0);
2786160383Snetchild			emu_wrptr(sc, ch, 0x4e, 0x0);
2787160383Snetchild			emu_wrptr(sc, ch, 0x4f, 0x0);
2788229981Spfg			emu_wrptr(sc, ch, EMU_A_CHAN_FXRT1, 0x3f3f3f3f);
2789229981Spfg			emu_wrptr(sc, ch, EMU_A_CHAN_FXRT2, 0x3f3f3f3f);
2790229981Spfg			emu_wrptr(sc, ch, EMU_A_CHAN_SENDAMOUNTS, 0x0);
2791160383Snetchild		}
2792160383Snetchild	}
2793160383Snetchild
2794160383Snetchild	emumix_set_spdif_mode(sc, SPDIF_MODE_PCM);
2795160383Snetchild
2796160383Snetchild	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108))
2797229981Spfg		emu_wrptr(sc, 0, EMU_A_SPDIF_SAMPLERATE, EMU_A_SPDIF_48000);
2798160383Snetchild
2799160383Snetchild	/*
2800160383Snetchild	 * CAxxxx cards needs additional setup:
2801160383Snetchild	 * 1. Set I2S capture sample rate to 96000
2802160383Snetchild	 * 2. Disable P16v / P17v proceesing
2803160383Snetchild	 * 3. Allow EMU10K DSP inputs
2804160383Snetchild	 */
2805160383Snetchild	if ((sc->is_ca0102) || (sc->is_ca0108)) {
2806160383Snetchild
2807229981Spfg		spdif_sr = emu_rdptr(sc, 0, EMU_A_SPDIF_SAMPLERATE);
2808160383Snetchild		spdif_sr &= 0xfffff1ff;
2809229981Spfg		spdif_sr |= EMU_A_I2S_CAPTURE_96000;
2810229981Spfg		emu_wrptr(sc, 0, EMU_A_SPDIF_SAMPLERATE, spdif_sr);
2811160383Snetchild
2812160383Snetchild		/* Disable P16v processing */
2813229981Spfg		emu_wr_p16vptr(sc, 0, EMU_A2_SRCSel, 0x14);
2814160383Snetchild
2815160383Snetchild		/* Setup P16v/P17v sound routing */
2816160383Snetchild		if (sc->is_ca0102)
2817229981Spfg			emu_wr_p16vptr(sc, 0, EMU_A2_SRCMULTI_ENABLE, 0xFF00FF00);
2818160383Snetchild		else {
2819229981Spfg			emu_wr_p16vptr(sc, 0, EMU_A2_MIXER_I2S_ENABLE, 0xFF000000);
2820229981Spfg			emu_wr_p16vptr(sc, 0, EMU_A2_MIXER_SPDIF_ENABLE, 0xFF000000);
2821160383Snetchild
2822229981Spfg			tmp = emu_rd(sc, EMU_A_IOCFG, 2);
2823229981Spfg			emu_wr(sc, EMU_A_IOCFG, tmp & ~0x8, 2);
2824160383Snetchild		}
2825160383Snetchild	}
2826160383Snetchild	emu_initefx(sc);
2827160383Snetchild
2828160383Snetchild	def_mode = MODE_ANALOG;
2829160383Snetchild	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108))
2830160383Snetchild		def_mode = MODE_DIGITAL;
2831160383Snetchild	if (((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) && (sc->broken_digital)) {
2832160383Snetchild		device_printf(sc->dev, "Audigy card initialized in analog mode.\n");
2833160383Snetchild		def_mode = MODE_ANALOG;
2834160383Snetchild	}
2835160383Snetchild	emumix_set_mode(sc, def_mode);
2836160383Snetchild
2837160383Snetchild	if (bootverbose) {
2838229981Spfg		tmp = emu_rd(sc, EMU_HCFG, 4);
2839160383Snetchild		device_printf(sc->dev, "Card Configuration (   0x%08x )\n", tmp);
2840160383Snetchild		device_printf(sc->dev, "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n",
2841160383Snetchild		    (tmp & 0x80000000 ? "[Legacy MPIC] " : ""),
2842160383Snetchild		    (tmp & 0x40000000 ? "[0x40] " : ""),
2843160383Snetchild		    (tmp & 0x20000000 ? "[0x20] " : ""),
2844160383Snetchild		    (tmp & 0x10000000 ? "[0x10] " : ""),
2845160383Snetchild		    (tmp & 0x08000000 ? "[0x08] " : ""),
2846160383Snetchild		    (tmp & 0x04000000 ? "[0x04] " : ""),
2847160383Snetchild		    (tmp & 0x02000000 ? "[0x02] " : ""),
2848160383Snetchild		    (tmp & 0x01000000 ? "[0x01]" : " "));
2849160383Snetchild		device_printf(sc->dev, "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n",
2850160383Snetchild		    (tmp & 0x00800000 ? "[0x80] " : ""),
2851160383Snetchild		    (tmp & 0x00400000 ? "[0x40] " : ""),
2852160383Snetchild		    (tmp & 0x00200000 ? "[Legacy INT] " : ""),
2853160383Snetchild		    (tmp & 0x00100000 ? "[0x10] " : ""),
2854160383Snetchild		    (tmp & 0x00080000 ? "[0x08] " : ""),
2855160383Snetchild		    (tmp & 0x00040000 ? "[Codec4] " : ""),
2856160383Snetchild		    (tmp & 0x00020000 ? "[Codec2] " : ""),
2857160383Snetchild		    (tmp & 0x00010000 ? "[I2S Codec]" : " "));
2858160383Snetchild		device_printf(sc->dev, "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n",
2859160383Snetchild		    (tmp & 0x00008000 ? "[0x80] " : ""),
2860160383Snetchild		    (tmp & 0x00004000 ? "[GPINPUT0] " : ""),
2861160383Snetchild		    (tmp & 0x00002000 ? "[GPINPUT1] " : ""),
2862160383Snetchild		    (tmp & 0x00001000 ? "[GPOUT0] " : ""),
2863160383Snetchild		    (tmp & 0x00000800 ? "[GPOUT1] " : ""),
2864160383Snetchild		    (tmp & 0x00000400 ? "[GPOUT2] " : ""),
2865160383Snetchild		    (tmp & 0x00000200 ? "[Joystick] " : ""),
2866160383Snetchild		    (tmp & 0x00000100 ? "[0x01]" : " "));
2867160383Snetchild		device_printf(sc->dev, "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n",
2868160383Snetchild		    (tmp & 0x00000080 ? "[0x80] " : ""),
2869160383Snetchild		    (tmp & 0x00000040 ? "[0x40] " : ""),
2870160383Snetchild		    (tmp & 0x00000020 ? "[0x20] " : ""),
2871160383Snetchild		    (tmp & 0x00000010 ? "[AUTOMUTE] " : ""),
2872160383Snetchild		    (tmp & 0x00000008 ? "[LOCKSOUNDCACHE] " : ""),
2873160383Snetchild		    (tmp & 0x00000004 ? "[LOCKTANKCACHE] " : ""),
2874160383Snetchild		    (tmp & 0x00000002 ? "[MUTEBUTTONENABLE] " : ""),
2875160383Snetchild		    (tmp & 0x00000001 ? "[AUDIOENABLE]" : " "));
2876160383Snetchild
2877160383Snetchild		if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2878229981Spfg			tmp = emu_rd(sc, EMU_A_IOCFG, 2);
2879160383Snetchild			device_printf(sc->dev, "Audigy Card Configuration (    0x%04x )\n", tmp);
2880160383Snetchild			device_printf(sc->dev, "Audigy Card Configuration (  & 0xff00 )");
2881160383Snetchild			printf(" : %s%s%s%s%s%s%s%s\n",
2882160383Snetchild			    (tmp & 0x8000 ? "[Rear Speakers] " : ""),
2883160383Snetchild			    (tmp & 0x4000 ? "[Front Speakers] " : ""),
2884160383Snetchild			    (tmp & 0x2000 ? "[0x20] " : ""),
2885160383Snetchild			    (tmp & 0x1000 ? "[0x10] " : ""),
2886160383Snetchild			    (tmp & 0x0800 ? "[0x08] " : ""),
2887160383Snetchild			    (tmp & 0x0400 ? "[0x04] " : ""),
2888160383Snetchild			    (tmp & 0x0200 ? "[0x02] " : ""),
2889160383Snetchild			    (tmp & 0x0100 ? "[AudigyDrive Phones]" : " "));
2890160383Snetchild			device_printf(sc->dev, "Audigy Card Configuration (  & 0x00ff )");
2891160383Snetchild			printf(" : %s%s%s%s%s%s%s%s\n",
2892160383Snetchild			    (tmp & 0x0080 ? "[0x80] " : ""),
2893160383Snetchild			    (tmp & 0x0040 ? "[Mute AnalogOut] " : ""),
2894160383Snetchild			    (tmp & 0x0020 ? "[0x20] " : ""),
2895160383Snetchild			    (tmp & 0x0010 ? "[0x10] " : ""),
2896160383Snetchild			    (tmp & 0x0008 ? "[0x08] " : ""),
2897160383Snetchild			    (tmp & 0x0004 ? "[GPOUT0] " : ""),
2898160383Snetchild			    (tmp & 0x0002 ? "[GPOUT1] " : ""),
2899160383Snetchild			    (tmp & 0x0001 ? "[GPOUT2]" : " "));
2900160383Snetchild		}		/* is_emu10k2 or ca* */
2901160383Snetchild	}			/* bootverbose */
2902160383Snetchild	return (0);
2903160383Snetchild}
2904160383Snetchild
2905160383Snetchildstatic int
2906160383Snetchildemu_uninit(struct emu_sc_info *sc)
2907160383Snetchild{
2908160383Snetchild	uint32_t ch;
2909160383Snetchild	struct emu_memblk *blk;
2910160383Snetchild
2911229981Spfg	emu_wr(sc, EMU_INTE, 0, 4);
2912160383Snetchild	for (ch = 0; ch < NUM_G; ch++)
2913229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_DCYSUSV, 0);
2914160383Snetchild	for (ch = 0; ch < NUM_G; ch++) {
2915229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_VTFT, 0);
2916229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_CVCF, 0);
2917229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_PTRX, 0);
2918229981Spfg		emu_wrptr(sc, ch, EMU_CHAN_CPF, 0);
2919160383Snetchild	}
2920160383Snetchild
2921160383Snetchild	/* disable audio and lock cache */
2922229981Spfg	emu_wr(sc, EMU_HCFG, EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_MUTEBUTTONENABLE, 4);
2923160383Snetchild
2924229981Spfg	emu_wrptr(sc, 0, EMU_PTB, 0);
2925160383Snetchild	/* reset recording buffers */
2926229981Spfg	emu_wrptr(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
2927229981Spfg	emu_wrptr(sc, 0, EMU_MICBA, 0);
2928229981Spfg	emu_wrptr(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
2929229981Spfg	emu_wrptr(sc, 0, EMU_FXBA, 0);
2930229981Spfg	emu_wrptr(sc, 0, EMU_FXWC, 0);
2931229981Spfg	emu_wrptr(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
2932229981Spfg	emu_wrptr(sc, 0, EMU_ADCBA, 0);
2933229981Spfg	emu_wrptr(sc, 0, EMU_TCB, 0);
2934229981Spfg	emu_wrptr(sc, 0, EMU_TCBS, 0);
2935160383Snetchild
2936160383Snetchild	/* disable channel interrupt */
2937229981Spfg	emu_wrptr(sc, 0, EMU_CLIEL, 0);
2938229981Spfg	emu_wrptr(sc, 0, EMU_CLIEH, 0);
2939229981Spfg	emu_wrptr(sc, 0, EMU_SOLEL, 0);
2940229981Spfg	emu_wrptr(sc, 0, EMU_SOLEH, 0);
2941160383Snetchild
2942160383Snetchild	if (!SLIST_EMPTY(&sc->mem.blocks))
2943160383Snetchild		device_printf(sc->dev, "warning: memblock list not empty\n");
2944160383Snetchild
2945160383Snetchild	SLIST_FOREACH(blk, &sc->mem.blocks, link)
2946160383Snetchild		if (blk != NULL)
2947160383Snetchild		device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner);
2948160383Snetchild
2949160383Snetchild	emu_free(&sc->mem, sc->mem.ptb_pages);
2950160383Snetchild	emu_free(&sc->mem, sc->mem.silent_page);
2951160383Snetchild
2952160383Snetchild	return (0);
2953160383Snetchild}
2954160383Snetchild
2955160383Snetchildstatic int
2956160383Snetchildemu_read_ivar(device_t bus, device_t dev, int ivar_index, uintptr_t * result)
2957160383Snetchild{
2958160383Snetchild	struct sndcard_func *func = device_get_ivars(dev);
2959160383Snetchild	struct emu_sc_info *sc = device_get_softc(bus);
2960160383Snetchild
2961172150Sariff	if (func==NULL)
2962172150Sariff		return (ENOMEM);
2963172150Sariff	if (sc == NULL)
2964172150Sariff		return (ENOMEM);
2965172150Sariff
2966160383Snetchild	switch (ivar_index) {
2967160383Snetchild	case EMU_VAR_FUNC:
2968160383Snetchild		*result = func->func;
2969160383Snetchild		break;
2970160383Snetchild	case EMU_VAR_ROUTE:
2971172150Sariff		if (func->varinfo == NULL)
2972172150Sariff			return (ENOMEM);
2973160383Snetchild		*result = ((struct emu_pcminfo *)func->varinfo)->route;
2974160383Snetchild		break;
2975160383Snetchild	case EMU_VAR_ISEMU10K1:
2976160383Snetchild		*result = sc->is_emu10k1;
2977160383Snetchild		break;
2978172150Sariff	case EMU_VAR_MCH_DISABLED:
2979172150Sariff		*result = sc->mch_disabled;
2980172150Sariff		break;
2981172150Sariff	case EMU_VAR_MCH_REC:
2982172150Sariff		*result = sc->mch_rec;
2983172150Sariff		break;
2984160383Snetchild	default:
2985160383Snetchild		return (ENOENT);
2986160383Snetchild	}
2987160383Snetchild
2988160383Snetchild	return (0);
2989160383Snetchild}
2990160383Snetchild
2991160383Snetchildstatic int
2992160383Snetchildemu_write_ivar(device_t bus __unused, device_t dev __unused,
2993160383Snetchild    int ivar_index, uintptr_t value __unused)
2994160383Snetchild{
2995160383Snetchild
2996160383Snetchild	switch (ivar_index) {
2997160383Snetchild		case 0:
2998160383Snetchild		return (EINVAL);
2999160383Snetchild
3000160383Snetchild	default:
3001160383Snetchild		return (ENOENT);
3002160383Snetchild	}
3003160383Snetchild}
3004160383Snetchild
3005160383Snetchildstatic int
3006160383Snetchildemu_pci_probe(device_t dev)
3007160383Snetchild{
3008160383Snetchild	struct sbuf *s;
3009165833Snetchild	unsigned int thiscard = 0;
3010160383Snetchild	uint16_t vendor;
3011160383Snetchild
3012160383Snetchild	vendor = pci_read_config(dev, PCIR_DEVVENDOR, /* bytes */ 2);
3013160383Snetchild	if (vendor != 0x1102)
3014160383Snetchild		return (ENXIO);	/* Not Creative */
3015160383Snetchild
3016160383Snetchild	thiscard = emu_getcard(dev);
3017165833Snetchild	if (thiscard == 0)
3018160383Snetchild		return (ENXIO);
3019160383Snetchild
3020160383Snetchild	s = sbuf_new(NULL, NULL, 4096, 0);
3021160383Snetchild	if (s == NULL)
3022160383Snetchild		return (ENOMEM);
3023160383Snetchild	sbuf_printf(s, "Creative %s [%s]", emu_cards[thiscard].desc, emu_cards[thiscard].SBcode);
3024160383Snetchild	sbuf_finish(s);
3025160383Snetchild
3026160383Snetchild	device_set_desc_copy(dev, sbuf_data(s));
3027172150Sariff
3028172150Sariff	sbuf_delete(s);
3029172150Sariff
3030160383Snetchild	return (BUS_PROBE_DEFAULT);
3031160383Snetchild}
3032160383Snetchild
3033160383Snetchild
3034160383Snetchildstatic int
3035160383Snetchildemu_pci_attach(device_t dev)
3036160383Snetchild{
3037160383Snetchild	struct sndcard_func *func;
3038160383Snetchild	struct emu_sc_info *sc;
3039160383Snetchild	struct emu_pcminfo *pcminfo;
3040172150Sariff#if 0
3041172150Sariff	struct emu_midiinfo *midiinfo;
3042172150Sariff#endif
3043160383Snetchild	int i;
3044160383Snetchild	int device_flags;
3045160383Snetchild	char status[255];
3046160383Snetchild	int error = ENXIO;
3047172150Sariff	int unit;
3048160383Snetchild
3049160383Snetchild	sc = device_get_softc(dev);
3050172150Sariff	unit = device_get_unit(dev);
3051160383Snetchild
3052172150Sariff	/* Get configuration */
3053172150Sariff
3054172150Sariff	sc->ctx = device_get_sysctl_ctx(dev);
3055172150Sariff	if (sc->ctx == NULL)
3056172150Sariff		goto bad;
3057172150Sariff	sc->root = device_get_sysctl_tree(dev);
3058172150Sariff	if (sc->root == NULL)
3059172150Sariff		goto bad;
3060172150Sariff
3061172150Sariff	if (resource_int_value("emu10kx", unit, "multichannel_disabled", &(sc->mch_disabled)))
3062172150Sariff		RANGE(sc->mch_disabled, 0, 1);
3063172150Sariff	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
3064172150Sariff	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
3065172150Sariff            OID_AUTO, "multichannel_disabled", CTLFLAG_RD, &(sc->mch_disabled), 0, "Multichannel playback setting");
3066172150Sariff
3067172150Sariff	if (resource_int_value("emu10kx", unit, "multichannel_recording", &(sc->mch_rec)))
3068172150Sariff		RANGE(sc->mch_rec, 0, 1);
3069172150Sariff	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
3070172150Sariff	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
3071172150Sariff            OID_AUTO, "multichannel_recording", CTLFLAG_RD,  &(sc->mch_rec), 0, "Multichannel recording setting");
3072172150Sariff
3073172150Sariff	if (resource_int_value("emu10kx", unit, "debug", &(sc->dbg_level)))
3074172150Sariff		RANGE(sc->mch_rec, 0, 2);
3075172150Sariff	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
3076172150Sariff	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
3077172150Sariff            OID_AUTO, "debug", CTLFLAG_RW, &(sc->dbg_level), 0, "Debug level");
3078172150Sariff
3079160383Snetchild	/* Fill in the softc. */
3080172150Sariff	mtx_init(&sc->lock, device_get_nameunit(dev), "bridge conf", MTX_DEF);
3081172150Sariff	mtx_init(&sc->rw, device_get_nameunit(dev), "exclusive io", MTX_DEF);
3082160383Snetchild	sc->dev = dev;
3083160383Snetchild	sc->type = pci_get_devid(dev);
3084160383Snetchild	sc->rev = pci_get_revid(dev);
3085160383Snetchild	sc->enable_ir = 0;
3086160383Snetchild	sc->has_ac97 = 0;
3087160383Snetchild	sc->has_51 = 0;
3088160383Snetchild	sc->has_71 = 0;
3089160383Snetchild	sc->broken_digital = 0;
3090160383Snetchild	sc->is_emu10k1 = 0;
3091160383Snetchild	sc->is_emu10k2 = 0;
3092160383Snetchild	sc->is_ca0102 = 0;
3093160383Snetchild	sc->is_ca0108 = 0;
3094160383Snetchild	sc->is_cardbus = 0;
3095160383Snetchild
3096160383Snetchild	device_flags = emu_cards[emu_getcard(dev)].flags;
3097160383Snetchild	if (device_flags & HAS_51)
3098160383Snetchild		sc->has_51 = 1;
3099160383Snetchild	if (device_flags & HAS_71) {
3100160383Snetchild		sc->has_51 = 1;
3101160383Snetchild		sc->has_71 = 1;
3102160383Snetchild	}
3103160383Snetchild	if (device_flags & IS_EMU10K1)
3104160383Snetchild		sc->is_emu10k1 = 1;
3105160383Snetchild	if (device_flags & IS_EMU10K2)
3106160383Snetchild		sc->is_emu10k2 = 1;
3107160383Snetchild	if (device_flags & IS_CA0102)
3108160383Snetchild		sc->is_ca0102 = 1;
3109160383Snetchild	if (device_flags & IS_CA0108)
3110160383Snetchild		sc->is_ca0108 = 1;
3111160383Snetchild	if ((sc->is_emu10k2) && (sc->rev == 4)) {
3112160383Snetchild		sc->is_emu10k2 = 0;
3113160383Snetchild		sc->is_ca0102 = 1;	/* for unknown Audigy 2 cards */
3114160383Snetchild	}
3115160383Snetchild	if ((sc->is_ca0102 == 1) || (sc->is_ca0108 == 1))
3116160383Snetchild		if (device_flags & IS_CARDBUS)
3117160383Snetchild			sc->is_cardbus = 1;
3118160383Snetchild
3119160383Snetchild	if ((sc->is_emu10k1 + sc->is_emu10k2 + sc->is_ca0102 + sc->is_ca0108) != 1) {
3120160383Snetchild		device_printf(sc->dev, "Unable to detect HW chipset\n");
3121160383Snetchild		goto bad;
3122160383Snetchild	}
3123160383Snetchild	if (device_flags & BROKEN_DIGITAL)
3124160383Snetchild		sc->broken_digital = 1;
3125160383Snetchild	if (device_flags & HAS_AC97)
3126160383Snetchild		sc->has_ac97 = 1;
3127160383Snetchild
3128160383Snetchild	sc->opcode_shift = 0;
3129160383Snetchild	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
3130160383Snetchild		sc->opcode_shift = 24;
3131160383Snetchild		sc->high_operand_shift = 12;
3132172150Sariff
3133172150Sariff	/*	DSP map				*/
3134165833Snetchild	/*	sc->fx_base = 0x0		*/
3135160383Snetchild		sc->input_base = 0x40;
3136165833Snetchild	/*	sc->p16vinput_base = 0x50;	*/
3137160383Snetchild		sc->output_base = 0x60;
3138160383Snetchild		sc->efxc_base = 0x80;
3139165833Snetchild	/*	sc->output32h_base = 0xa0;	*/
3140165833Snetchild	/*	sc->output32l_base = 0xb0;	*/
3141160383Snetchild		sc->dsp_zero = 0xc0;
3142165833Snetchild	/*	0xe0...0x100 are unknown	*/
3143165833Snetchild	/*	sc->tram_base = 0x200		*/
3144165833Snetchild	/*	sc->tram_addr_base = 0x300	*/
3145229981Spfg		sc->gpr_base = EMU_A_FXGPREGBASE;
3146165833Snetchild		sc->num_gprs = 0x200;
3147229981Spfg		sc->code_base = EMU_A_MICROCODEBASE;
3148165833Snetchild		sc->code_size = 0x800 / 2;	/* 0x600-0xdff,  2048 words,
3149165833Snetchild						 * 1024 instructions */
3150165833Snetchild
3151160383Snetchild		sc->mchannel_fx = 8;
3152160383Snetchild		sc->num_fxbuses = 16;
3153160383Snetchild		sc->num_inputs = 8;
3154160383Snetchild		sc->num_outputs = 16;
3155229981Spfg		sc->address_mask = EMU_A_PTR_ADDR_MASK;
3156160383Snetchild	}
3157160383Snetchild	if (sc->is_emu10k1) {
3158172150Sariff		sc->has_51 = 0;	/* We don't support 5.1 sound on SB Live! 5.1 */
3159160383Snetchild		sc->opcode_shift = 20;
3160160383Snetchild		sc->high_operand_shift = 10;
3161229981Spfg		sc->code_base = EMU_MICROCODEBASE;
3162160383Snetchild		sc->code_size = 0x400 / 2;	/* 0x400-0x7ff,  1024 words,
3163160383Snetchild						 * 512 instructions */
3164229981Spfg		sc->gpr_base = EMU_FXGPREGBASE;
3165160383Snetchild		sc->num_gprs = 0x100;
3166160383Snetchild		sc->input_base = 0x10;
3167160383Snetchild		sc->output_base = 0x20;
3168172150Sariff		/*
3169172150Sariff		 * XXX 5.1 Analog outputs are inside efxc address space!
3170242692Skevlo		 * They use output+0x11/+0x12 (=efxc+1/+2).
3171165833Snetchild		 * Don't use this efx registers for recording on SB Live! 5.1!
3172165833Snetchild		 */
3173160383Snetchild		sc->efxc_base = 0x30;
3174160383Snetchild		sc->dsp_zero = 0x40;
3175160383Snetchild		sc->mchannel_fx = 0;
3176160383Snetchild		sc->num_fxbuses = 8;
3177160383Snetchild		sc->num_inputs = 8;
3178160383Snetchild		sc->num_outputs = 16;
3179229981Spfg		sc->address_mask = EMU_PTR_ADDR_MASK;
3180160383Snetchild	}
3181160383Snetchild	if (sc->opcode_shift == 0)
3182160383Snetchild		goto bad;
3183160383Snetchild
3184160383Snetchild	pci_enable_busmaster(dev);
3185160383Snetchild
3186160383Snetchild	i = PCIR_BAR(0);
3187160383Snetchild	sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE);
3188160383Snetchild	if (sc->reg == NULL) {
3189160383Snetchild		device_printf(dev, "unable to map register space\n");
3190160383Snetchild		goto bad;
3191160383Snetchild	}
3192160383Snetchild	sc->st = rman_get_bustag(sc->reg);
3193160383Snetchild	sc->sh = rman_get_bushandle(sc->reg);
3194160383Snetchild
3195160383Snetchild	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
3196160383Snetchild		sc->timer[i] = 0;	/* disable it */
3197160383Snetchild
3198160383Snetchild	i = 0;
3199160383Snetchild	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE | RF_SHAREABLE);
3200193640Sariff	if ((sc->irq == NULL) || bus_setup_intr(dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV,
3201193640Sariff#if __FreeBSD_version >= 700031
3202193640Sariff	    NULL,
3203193640Sariff#endif
3204193640Sariff	    emu_intr, sc, &sc->ih)) {
3205160383Snetchild		device_printf(dev, "unable to map interrupt\n");
3206160383Snetchild		goto bad;
3207160383Snetchild	}
3208160383Snetchild	if (emu_rm_init(sc) != 0) {
3209160383Snetchild		device_printf(dev, "unable to create resource manager\n");
3210160383Snetchild		goto bad;
3211160383Snetchild	}
3212160383Snetchild	if (sc->is_cardbus)
3213160383Snetchild		if (emu_cardbus_init(sc) != 0) {
3214160383Snetchild			device_printf(dev, "unable to initialize CardBus interface\n");
3215160383Snetchild			goto bad;
3216160383Snetchild		}
3217172150Sariff	if (emu_init(sc) != 0) {
3218160383Snetchild		device_printf(dev, "unable to initialize the card\n");
3219160383Snetchild		goto bad;
3220160383Snetchild	}
3221172150Sariff	if (emu10kx_dev_init(sc) != 0) {
3222160383Snetchild		device_printf(dev, "unable to create control device\n");
3223160383Snetchild		goto bad;
3224160383Snetchild	}
3225160383Snetchild	snprintf(status, 255, "rev %d at io 0x%lx irq %ld", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq));
3226160383Snetchild
3227160383Snetchild	/* Voices */
3228160383Snetchild	for (i = 0; i < NUM_G; i++) {
3229160383Snetchild		sc->voice[i].vnum = i;
3230160383Snetchild		sc->voice[i].slave = NULL;
3231160383Snetchild		sc->voice[i].busy = 0;
3232160383Snetchild		sc->voice[i].ismaster = 0;
3233160383Snetchild		sc->voice[i].running = 0;
3234160383Snetchild		sc->voice[i].b16 = 0;
3235160383Snetchild		sc->voice[i].stereo = 0;
3236160383Snetchild		sc->voice[i].speed = 0;
3237160383Snetchild		sc->voice[i].start = 0;
3238160383Snetchild		sc->voice[i].end = 0;
3239160383Snetchild	}
3240160383Snetchild
3241160383Snetchild	/* PCM Audio */
3242172150Sariff	for (i = 0; i < RT_COUNT; i++)
3243172150Sariff		sc->pcm[i] = NULL;
3244172150Sariff
3245160383Snetchild	/* FRONT */
3246160383Snetchild	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3247160383Snetchild	if (func == NULL) {
3248160383Snetchild		error = ENOMEM;
3249160383Snetchild		goto bad;
3250160383Snetchild	}
3251160383Snetchild	pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3252160383Snetchild	if (pcminfo == NULL) {
3253160383Snetchild		error = ENOMEM;
3254160383Snetchild		goto bad;
3255160383Snetchild	}
3256160383Snetchild	pcminfo->card = sc;
3257160383Snetchild	pcminfo->route = RT_FRONT;
3258160383Snetchild
3259160383Snetchild	func->func = SCF_PCM;
3260160383Snetchild	func->varinfo = pcminfo;
3261160383Snetchild	sc->pcm[RT_FRONT] = device_add_child(dev, "pcm", -1);
3262160383Snetchild	device_set_ivars(sc->pcm[RT_FRONT], func);
3263165833Snetchild
3264172150Sariff	if (!(sc->mch_disabled)) {
3265172150Sariff		/* REAR */
3266160383Snetchild		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3267160383Snetchild		if (func == NULL) {
3268160383Snetchild			error = ENOMEM;
3269160383Snetchild			goto bad;
3270160383Snetchild		}
3271160383Snetchild		pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3272160383Snetchild		if (pcminfo == NULL) {
3273160383Snetchild			error = ENOMEM;
3274160383Snetchild			goto bad;
3275160383Snetchild		}
3276160383Snetchild		pcminfo->card = sc;
3277172150Sariff		pcminfo->route = RT_REAR;
3278160383Snetchild
3279160383Snetchild		func->func = SCF_PCM;
3280160383Snetchild		func->varinfo = pcminfo;
3281172150Sariff		sc->pcm[RT_REAR] = device_add_child(dev, "pcm", -1);
3282172150Sariff		device_set_ivars(sc->pcm[RT_REAR], func);
3283172150Sariff		if (sc->has_51) {
3284172150Sariff			/* CENTER */
3285172150Sariff			func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3286172150Sariff			if (func == NULL) {
3287172150Sariff				error = ENOMEM;
3288172150Sariff				goto bad;
3289172150Sariff			}
3290172150Sariff			pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3291172150Sariff			if (pcminfo == NULL) {
3292172150Sariff				error = ENOMEM;
3293172150Sariff				goto bad;
3294172150Sariff			}
3295172150Sariff			pcminfo->card = sc;
3296172150Sariff			pcminfo->route = RT_CENTER;
3297172150Sariff
3298172150Sariff			func->func = SCF_PCM;
3299172150Sariff			func->varinfo = pcminfo;
3300172150Sariff			sc->pcm[RT_CENTER] = device_add_child(dev, "pcm", -1);
3301172150Sariff			device_set_ivars(sc->pcm[RT_CENTER], func);
3302172150Sariff			/* SUB */
3303172150Sariff			func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3304172150Sariff			if (func == NULL) {
3305172150Sariff				error = ENOMEM;
3306172150Sariff				goto bad;
3307172150Sariff			}
3308172150Sariff			pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3309172150Sariff			if (pcminfo == NULL) {
3310172150Sariff				error = ENOMEM;
3311172150Sariff				goto bad;
3312172150Sariff			}
3313172150Sariff			pcminfo->card = sc;
3314172150Sariff			pcminfo->route = RT_SUB;
3315172150Sariff
3316172150Sariff			func->func = SCF_PCM;
3317172150Sariff			func->varinfo = pcminfo;
3318172150Sariff			sc->pcm[RT_SUB] = device_add_child(dev, "pcm", -1);
3319172150Sariff			device_set_ivars(sc->pcm[RT_SUB], func);
3320160383Snetchild		}
3321172150Sariff		if (sc->has_71) {
3322172150Sariff			/* SIDE */
3323172150Sariff			func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3324172150Sariff			if (func == NULL) {
3325172150Sariff				error = ENOMEM;
3326172150Sariff				goto bad;
3327172150Sariff			}
3328172150Sariff			pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3329172150Sariff			if (pcminfo == NULL) {
3330172150Sariff				error = ENOMEM;
3331172150Sariff				goto bad;
3332172150Sariff			}
3333172150Sariff			pcminfo->card = sc;
3334172150Sariff			pcminfo->route = RT_SIDE;
3335172150Sariff
3336172150Sariff			func->func = SCF_PCM;
3337172150Sariff			func->varinfo = pcminfo;
3338172150Sariff			sc->pcm[RT_SIDE] = device_add_child(dev, "pcm", -1);
3339172150Sariff			device_set_ivars(sc->pcm[RT_SIDE], func);
3340160383Snetchild		}
3341172150Sariff	} /* mch_disabled */
3342160383Snetchild
3343172150Sariff	if (sc->mch_rec) {
3344160383Snetchild		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3345160383Snetchild		if (func == NULL) {
3346160383Snetchild			error = ENOMEM;
3347160383Snetchild			goto bad;
3348160383Snetchild		}
3349160383Snetchild		pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3350160383Snetchild		if (pcminfo == NULL) {
3351160383Snetchild			error = ENOMEM;
3352160383Snetchild			goto bad;
3353160383Snetchild		}
3354160383Snetchild		pcminfo->card = sc;
3355172150Sariff		pcminfo->route = RT_MCHRECORD;
3356160383Snetchild
3357160383Snetchild		func->func = SCF_PCM;
3358160383Snetchild		func->varinfo = pcminfo;
3359172150Sariff		sc->pcm[RT_MCHRECORD] = device_add_child(dev, "pcm", -1);
3360172150Sariff		device_set_ivars(sc->pcm[RT_MCHRECORD], func);
3361172150Sariff	} /*mch_rec */
3362165833Snetchild
3363172150Sariff	for (i = 0; i < 2; i++)
3364172150Sariff		sc->midi[i] = NULL;
3365165833Snetchild
3366172150Sariff	/* MIDI has some memory mangament and (possible) locking problems */
3367172150Sariff#if 0
3368160383Snetchild	/* Midi Interface 1: Live!, Audigy, Audigy 2 */
3369160383Snetchild	if ((sc->is_emu10k1) || (sc->is_emu10k2) || (sc->is_ca0102)) {
3370160383Snetchild		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3371160383Snetchild		if (func == NULL) {
3372160383Snetchild			error = ENOMEM;
3373160383Snetchild			goto bad;
3374160383Snetchild		}
3375172150Sariff		midiinfo = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3376172150Sariff		if (midiinfo == NULL) {
3377160383Snetchild			error = ENOMEM;
3378160383Snetchild			goto bad;
3379160383Snetchild		}
3380172150Sariff		midiinfo->card = sc;
3381160383Snetchild		if (sc->is_emu10k2 || (sc->is_ca0102)) {
3382229981Spfg			midiinfo->port = EMU_A_MUDATA1;
3383172150Sariff			midiinfo->portnr = 1;
3384160383Snetchild		}
3385160383Snetchild		if (sc->is_emu10k1) {
3386172150Sariff			midiinfo->port = MUDATA;
3387172150Sariff			midiinfo->portnr = 1;
3388160383Snetchild		}
3389160383Snetchild		func->func = SCF_MIDI;
3390172150Sariff		func->varinfo = midiinfo;
3391160383Snetchild		sc->midi[0] = device_add_child(dev, "midi", -1);
3392160383Snetchild		device_set_ivars(sc->midi[0], func);
3393160383Snetchild	}
3394160383Snetchild	/* Midi Interface 2: Audigy, Audigy 2 (on AudigyDrive) */
3395160383Snetchild	if (sc->is_emu10k2 || (sc->is_ca0102)) {
3396160383Snetchild		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3397160383Snetchild		if (func == NULL) {
3398160383Snetchild			error = ENOMEM;
3399160383Snetchild			goto bad;
3400160383Snetchild		}
3401172150Sariff		midiinfo = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3402172150Sariff		if (midiinfo == NULL) {
3403160383Snetchild			error = ENOMEM;
3404160383Snetchild			goto bad;
3405160383Snetchild		}
3406172150Sariff		midiinfo->card = sc;
3407160383Snetchild
3408229981Spfg		midiinfo->port = EMU_A_MUDATA2;
3409172150Sariff		midiinfo->portnr = 2;
3410160383Snetchild
3411160383Snetchild		func->func = SCF_MIDI;
3412172150Sariff		func->varinfo = midiinfo;
3413160383Snetchild		sc->midi[1] = device_add_child(dev, "midi", -1);
3414160383Snetchild		device_set_ivars(sc->midi[1], func);
3415160383Snetchild	}
3416172150Sariff#endif
3417160383Snetchild	return (bus_generic_attach(dev));
3418160383Snetchild
3419160383Snetchildbad:
3420160383Snetchild	/* XXX can we just call emu_pci_detach here? */
3421160383Snetchild	if (sc->cdev)
3422160383Snetchild		emu10kx_dev_uninit(sc);
3423160383Snetchild	if (sc->rm != NULL)
3424160383Snetchild		emu_rm_uninit(sc);
3425160383Snetchild	if (sc->reg)
3426160383Snetchild		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
3427160383Snetchild	if (sc->ih)
3428160383Snetchild		bus_teardown_intr(dev, sc->irq, sc->ih);
3429160383Snetchild	if (sc->irq)
3430160383Snetchild		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
3431172150Sariff	mtx_destroy(&sc->rw);
3432160383Snetchild	mtx_destroy(&sc->lock);
3433160383Snetchild	return (error);
3434160383Snetchild}
3435160383Snetchild
3436160383Snetchildstatic int
3437160383Snetchildemu_pci_detach(device_t dev)
3438160383Snetchild{
3439160383Snetchild	struct emu_sc_info *sc;
3440172150Sariff	struct sndcard_func *func;
3441160383Snetchild	int devcount, i;
3442160383Snetchild	device_t *childlist;
3443160383Snetchild	int r = 0;
3444160383Snetchild
3445160383Snetchild	sc = device_get_softc(dev);
3446172150Sariff
3447165833Snetchild	for (i = 0; i < RT_COUNT; i++) {
3448172150Sariff		if (sc->pcm[i] != NULL) {
3449172150Sariff			func = device_get_ivars(sc->pcm[i]);
3450172150Sariff			if (func != NULL && func->func == SCF_PCM) {
3451172150Sariff				device_set_ivars(sc->pcm[i], NULL);
3452172150Sariff				free(func->varinfo, M_DEVBUF);
3453172150Sariff				free(func, M_DEVBUF);
3454172150Sariff			}
3455160383Snetchild			r = device_delete_child(dev, sc->pcm[i]);
3456172150Sariff			if (r)	return (r);
3457172150Sariff		}
3458160383Snetchild	}
3459172150Sariff
3460172150Sariff	if (sc->midi[0] != NULL) {
3461172150Sariff		func = device_get_ivars(sc->midi[0]);
3462172150Sariff		if (func != NULL && func->func == SCF_MIDI) {
3463172150Sariff			device_set_ivars(sc->midi[0], NULL);
3464172150Sariff			free(func->varinfo, M_DEVBUF);
3465172150Sariff			free(func, M_DEVBUF);
3466172150Sariff		}
3467160383Snetchild		r = device_delete_child(dev, sc->midi[0]);
3468172150Sariff		if (r)	return (r);
3469172150Sariff	}
3470172150Sariff
3471172150Sariff	if (sc->midi[1] != NULL) {
3472172150Sariff		func = device_get_ivars(sc->midi[1]);
3473172150Sariff		if (func != NULL && func->func == SCF_MIDI) {
3474172150Sariff			device_set_ivars(sc->midi[1], NULL);
3475172150Sariff			free(func->varinfo, M_DEVBUF);
3476172150Sariff			free(func, M_DEVBUF);
3477172150Sariff		}
3478160383Snetchild		r = device_delete_child(dev, sc->midi[1]);
3479172150Sariff		if (r)	return (r);
3480172150Sariff	}
3481172150Sariff
3482172150Sariff	if (device_get_children(dev, &childlist, &devcount) == 0)
3483172150Sariff		for (i = 0; i < devcount - 1; i++) {
3484172150Sariff			device_printf(dev, "removing stale child %d (unit %d)\n", i, device_get_unit(childlist[i]));
3485172150Sariff			func = device_get_ivars(childlist[i]);
3486172150Sariff			if (func != NULL && (func->func == SCF_MIDI || func->func == SCF_PCM)) {
3487172150Sariff				device_set_ivars(childlist[i], NULL);
3488172150Sariff				free(func->varinfo, M_DEVBUF);
3489172150Sariff				free(func, M_DEVBUF);
3490172150Sariff			}
3491172150Sariff			device_delete_child(dev, childlist[i]);
3492172150Sariff		}
3493172150Sariff	if (childlist != NULL)
3494172150Sariff		free(childlist, M_TEMP);
3495172150Sariff
3496172150Sariff	r = emu10kx_dev_uninit(sc);
3497160383Snetchild	if (r)
3498160383Snetchild		return (r);
3499160383Snetchild
3500160383Snetchild	/* shutdown chip */
3501160383Snetchild	emu_uninit(sc);
3502160383Snetchild	emu_rm_uninit(sc);
3503169246Sariff
3504169246Sariff	if (sc->mem.dmat)
3505169246Sariff		bus_dma_tag_destroy(sc->mem.dmat);
3506169246Sariff
3507160383Snetchild	if (sc->reg)
3508160383Snetchild		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
3509160383Snetchild	bus_teardown_intr(dev, sc->irq, sc->ih);
3510160383Snetchild	bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
3511172150Sariff	mtx_destroy(&sc->rw);
3512160383Snetchild	mtx_destroy(&sc->lock);
3513172150Sariff
3514160383Snetchild	return (bus_generic_detach(dev));
3515160383Snetchild}
3516160383Snetchild/* add suspend, resume */
3517160383Snetchildstatic device_method_t emu_methods[] = {
3518160383Snetchild	/* Device interface */
3519160383Snetchild	DEVMETHOD(device_probe, emu_pci_probe),
3520160383Snetchild	DEVMETHOD(device_attach, emu_pci_attach),
3521160383Snetchild	DEVMETHOD(device_detach, emu_pci_detach),
3522160383Snetchild	/* Bus methods */
3523160383Snetchild	DEVMETHOD(bus_read_ivar, emu_read_ivar),
3524160383Snetchild	DEVMETHOD(bus_write_ivar, emu_write_ivar),
3525160383Snetchild
3526246128Ssbz	DEVMETHOD_END
3527160383Snetchild};
3528160383Snetchild
3529160383Snetchild
3530160383Snetchildstatic driver_t emu_driver = {
3531160383Snetchild	"emu10kx",
3532160383Snetchild	emu_methods,
3533160383Snetchild	sizeof(struct emu_sc_info),
3534160383Snetchild	NULL,
3535160383Snetchild	0,
3536160383Snetchild	NULL
3537160383Snetchild};
3538160383Snetchild
3539160383Snetchildstatic int
3540160383Snetchildemu_modevent(module_t mod __unused, int cmd, void *data __unused)
3541160383Snetchild{
3542160383Snetchild	int err = 0;
3543160383Snetchild
3544160383Snetchild	switch (cmd) {
3545160383Snetchild	case MOD_LOAD:
3546160383Snetchild		break;		/* Success */
3547160383Snetchild
3548160383Snetchild	case MOD_UNLOAD:
3549160383Snetchild	case MOD_SHUTDOWN:
3550160383Snetchild
3551160383Snetchild		/* XXX  Should we check state of pcm & midi subdevices here? */
3552160383Snetchild
3553160383Snetchild		break;		/* Success */
3554160383Snetchild
3555160383Snetchild	default:
3556160383Snetchild		err = EINVAL;
3557160383Snetchild		break;
3558160383Snetchild	}
3559160383Snetchild
3560160383Snetchild	return (err);
3561160383Snetchild
3562160383Snetchild}
3563160383Snetchild
3564160383Snetchildstatic devclass_t emu_devclass;
3565160383Snetchild
3566160383SnetchildDRIVER_MODULE(snd_emu10kx, pci, emu_driver, emu_devclass, emu_modevent, NULL);
3567160383SnetchildMODULE_VERSION(snd_emu10kx, SND_EMU10KX_PREFVER);
3568