sb16.c revision 54212
1145036Speter/*
2145036Speter * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3145036Speter * Copyright 1997,1998 Luigi Rizzo.
4145036Speter *
5145036Speter * Derived from files in the Voxware 3.5 distribution,
6145036Speter * Copyright by Hannu Savolainen 1994, under the same copyright
7145036Speter * conditions.
8145036Speter * All rights reserved.
9145036Speter *
10145036Speter * Redistribution and use in source and binary forms, with or without
11145036Speter * modification, are permitted provided that the following conditions
12145036Speter * are met:
13145036Speter * 1. Redistributions of source code must retain the above copyright
14145036Speter *    notice, this list of conditions and the following disclaimer.
15145036Speter * 2. Redistributions in binary form must reproduce the above copyright
16145036Speter *    notice, this list of conditions and the following disclaimer in the
17145036Speter *    documentation and/or other materials provided with the distribution.
18145036Speter *
19145036Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20145036Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21145036Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22145036Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23145036Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24145036Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25145036Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26145036Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27145036Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28145036Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29145036Speter * SUCH DAMAGE.
30145036Speter *
31145036Speter * $FreeBSD: head/sys/dev/sound/isa/sb16.c 54212 1999-12-06 18:26:33Z peter $
32145036Speter */
33145036Speter
34145036Speter#include <dev/sound/pcm/sound.h>
35145036Speter
36145036Speter#include "sbc.h"
37145036Speter
38#define __SB_MIXER_C__	/* XXX warning... */
39#include  <dev/sound/isa/sb.h>
40#include  <dev/sound/chip.h>
41
42/* channel interface */
43static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
44static int sbchan_setdir(void *data, int dir);
45static int sbchan_setformat(void *data, u_int32_t format);
46static int sbchan_setspeed(void *data, u_int32_t speed);
47static int sbchan_setblocksize(void *data, u_int32_t blocksize);
48static int sbchan_trigger(void *data, int go);
49static int sbchan_getptr(void *data);
50static pcmchan_caps *sbchan_getcaps(void *data);
51
52/* channel interface for ESS */
53#ifdef notyet
54static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
55#endif
56static int esschan_setdir(void *data, int dir);
57static int esschan_setformat(void *data, u_int32_t format);
58static int esschan_setspeed(void *data, u_int32_t speed);
59static int esschan_setblocksize(void *data, u_int32_t blocksize);
60static int esschan_trigger(void *data, int go);
61static int esschan_getptr(void *data);
62static pcmchan_caps *esschan_getcaps(void *data);
63static pcmchan_caps sb_playcaps = {
64	4000, 22050,
65	AFMT_U8,
66	AFMT_U8
67};
68
69static pcmchan_caps sb_reccaps = {
70	4000, 13000,
71	AFMT_U8,
72	AFMT_U8
73};
74
75static pcmchan_caps sbpro_playcaps = {
76	4000, 45000,
77	AFMT_STEREO | AFMT_U8,
78	AFMT_STEREO | AFMT_U8
79};
80
81static pcmchan_caps sbpro_reccaps = {
82	4000, 15000,
83	AFMT_STEREO | AFMT_U8,
84	AFMT_STEREO | AFMT_U8
85};
86
87static pcmchan_caps sb16_playcaps = {
88	5000, 45000,
89	AFMT_STEREO | AFMT_S16_LE,
90	AFMT_STEREO | AFMT_S16_LE
91};
92
93static pcmchan_caps sb16_reccaps = {
94	5000, 45000,
95	AFMT_STEREO | AFMT_U8,
96	AFMT_STEREO | AFMT_U8
97};
98
99static pcmchan_caps ess_playcaps = {
100	5000, 49000,
101	AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
102	AFMT_STEREO | AFMT_S16_LE
103};
104
105static pcmchan_caps ess_reccaps = {
106	5000, 49000,
107	AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
108	AFMT_STEREO | AFMT_S16_LE
109};
110
111static pcm_channel sb_chantemplate = {
112	sbchan_init,
113	sbchan_setdir,
114	sbchan_setformat,
115	sbchan_setspeed,
116	sbchan_setblocksize,
117	sbchan_trigger,
118	sbchan_getptr,
119	sbchan_getcaps,
120};
121
122static pcm_channel ess_chantemplate = {
123	sbchan_init,
124	esschan_setdir,
125	esschan_setformat,
126	esschan_setspeed,
127	esschan_setblocksize,
128	esschan_trigger,
129	esschan_getptr,
130	esschan_getcaps,
131};
132#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
133
134struct sb_info;
135
136struct sb_chinfo {
137	struct sb_info *parent;
138	pcm_channel *channel;
139	snd_dbuf *buffer;
140	int dir;
141	u_int32_t fmt;
142	int ess_dma_started;
143};
144
145struct sb_info {
146    	struct resource *io_base;	/* I/O address for the board */
147    	int		     io_rid;
148    	struct resource *irq;
149    	int		     irq_rid;
150    	struct resource *drq1; /* play */
151    	int		     drq1_rid;
152    	struct resource *drq2; /* rec */
153    	int		     drq2_rid;
154    	bus_dma_tag_t    parent_dmat;
155
156    	int dma16, dma8;
157    	int bd_id;
158    	u_long bd_flags;       /* board-specific flags */
159    	struct sb_chinfo pch, rch;
160};
161
162static int sb_rd(struct sb_info *sb, int reg);
163static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
164static int sb_dspready(struct sb_info *sb);
165static int sb_cmd(struct sb_info *sb, u_char val);
166static int sb_cmd1(struct sb_info *sb, u_char cmd, int val);
167static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
168static u_int sb_get_byte(struct sb_info *sb);
169static int ess_write(struct sb_info *sb, u_char reg, int val);
170static int ess_read(struct sb_info *sb, u_char reg);
171
172/*
173 * in the SB, there is a set of indirect "mixer" registers with
174 * address at offset 4, data at offset 5
175 */
176static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
177static int sb_getmixer(struct sb_info *sb, u_int port);
178
179static void sb_intr(void *arg);
180static void ess_intr(void *arg);
181static int sb_init(device_t dev, struct sb_info *sb);
182static int sb_reset_dsp(struct sb_info *sb);
183
184static int sb_format(struct sb_chinfo *ch, u_int32_t format);
185static int sb_speed(struct sb_chinfo *ch, int speed);
186static int sb_start(struct sb_chinfo *ch);
187static int sb_stop(struct sb_chinfo *ch);
188
189static int ess_format(struct sb_chinfo *ch, u_int32_t format);
190static int ess_speed(struct sb_chinfo *ch, int speed);
191static int ess_start(struct sb_chinfo *ch);
192static int ess_stop(struct sb_chinfo *ch);
193static int ess_abort(struct sb_chinfo *ch);
194static int sbmix_init(snd_mixer *m);
195static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
196static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src);
197
198static snd_mixer sb_mixer = {
199    "SoundBlaster mixer",
200    sbmix_init,
201    sbmix_set,
202    sbmix_setrecsrc,
203};
204
205static devclass_t pcm_devclass;
206
207/*
208 * Common code for the midi and pcm functions
209 *
210 * sb_cmd write a single byte to the CMD port.
211 * sb_cmd1 write a CMD + 1 byte arg
212 * sb_cmd2 write a CMD + 2 byte arg
213 * sb_get_byte returns a single byte from the DSP data port
214 *
215 * ess_write is actually sb_cmd1
216 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte
217 */
218
219static int
220port_rd(struct resource *port, int off)
221{
222	return bus_space_read_1(rman_get_bustag(port),
223				rman_get_bushandle(port),
224				off);
225}
226
227static void
228port_wr(struct resource *port, int off, u_int8_t data)
229{
230	return bus_space_write_1(rman_get_bustag(port),
231				 rman_get_bushandle(port),
232				 off, data);
233}
234
235static int
236sb_rd(struct sb_info *sb, int reg)
237{
238	return port_rd(sb->io_base, reg);
239}
240
241static void
242sb_wr(struct sb_info *sb, int reg, u_int8_t val)
243{
244	port_wr(sb->io_base, reg, val);
245}
246
247static int
248sb_dspready(struct sb_info *sb)
249{
250	return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
251}
252
253static int
254sb_dspwr(struct sb_info *sb, u_char val)
255{
256    	int  i;
257
258    	for (i = 0; i < 1000; i++) {
259		if (sb_dspready(sb)) {
260	    		sb_wr(sb, SBDSP_CMD, val);
261	    		return 1;
262		}
263		if (i > 10) DELAY((i > 100)? 1000 : 10);
264    	}
265    	printf("sb_dspwr(0x%02x) timed out.\n", val);
266    	return 0;
267}
268
269static int
270sb_cmd(struct sb_info *sb, u_char val)
271{
272#if 0
273	printf("sb_cmd: %x\n", val);
274#endif
275    	return sb_dspwr(sb, val);
276}
277
278static int
279sb_cmd1(struct sb_info *sb, u_char cmd, int val)
280{
281#if 0
282    	printf("sb_cmd1: %x, %x\n", cmd, val);
283#endif
284    	if (sb_dspwr(sb, cmd)) {
285		return sb_dspwr(sb, val & 0xff);
286    	} else return 0;
287}
288
289static int
290sb_cmd2(struct sb_info *sb, u_char cmd, int val)
291{
292#if 0
293    	printf("sb_cmd2: %x, %x\n", cmd, val);
294#endif
295    	if (sb_dspwr(sb, cmd)) {
296		return sb_dspwr(sb, val & 0xff) &&
297		       sb_dspwr(sb, (val >> 8) & 0xff);
298    	} else return 0;
299}
300
301/*
302 * in the SB, there is a set of indirect "mixer" registers with
303 * address at offset 4, data at offset 5
304 */
305static void
306sb_setmixer(struct sb_info *sb, u_int port, u_int value)
307{
308    	u_long   flags;
309
310    	flags = spltty();
311    	sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
312    	DELAY(10);
313    	sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
314    	DELAY(10);
315    	splx(flags);
316}
317
318static int
319sb_getmixer(struct sb_info *sb, u_int port)
320{
321    	int val;
322    	u_long flags;
323
324    	flags = spltty();
325    	sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
326    	DELAY(10);
327    	val = sb_rd(sb, SB_MIX_DATA);
328    	DELAY(10);
329    	splx(flags);
330
331    	return val;
332}
333
334static u_int
335sb_get_byte(struct sb_info *sb)
336{
337    	int i;
338
339    	for (i = 1000; i > 0; i--) {
340		if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
341			return sb_rd(sb, DSP_READ);
342		else
343			DELAY(20);
344    	}
345    	return 0xffff;
346}
347
348static int
349ess_write(struct sb_info *sb, u_char reg, int val)
350{
351    	return sb_cmd1(sb, reg, val);
352}
353
354static int
355ess_read(struct sb_info *sb, u_char reg)
356{
357    	return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff;
358}
359
360static int
361sb_reset_dsp(struct sb_info *sb)
362{
363    	sb_wr(sb, SBDSP_RST, 3);
364    	DELAY(100);
365    	sb_wr(sb, SBDSP_RST, 0);
366    	if (sb_get_byte(sb) != 0xAA) {
367        	DEB(printf("sb_reset_dsp 0x%lx failed\n",
368			   rman_get_start(d->io_base)));
369		return ENXIO;	/* Sorry */
370    	}
371    	if (sb->bd_flags & BD_F_ESS) sb_cmd(sb, 0xc6);
372    	return 0;
373}
374
375static void
376sb_release_resources(struct sb_info *sb, device_t dev)
377{
378    	/* should we bus_teardown_intr here? */
379    	if (sb->irq) {
380		bus_release_resource(dev, SYS_RES_IRQ, sb->irq_rid, sb->irq);
381		sb->irq = 0;
382    	}
383    	if (sb->drq1) {
384		bus_release_resource(dev, SYS_RES_DRQ, sb->drq1_rid, sb->drq1);
385		sb->drq1 = 0;
386    	}
387    	if (sb->drq2) {
388		bus_release_resource(dev, SYS_RES_DRQ, sb->drq2_rid, sb->drq2);
389		sb->drq2 = 0;
390    	}
391    	if (sb->io_base) {
392		bus_release_resource(dev, SYS_RES_IOPORT, sb->io_rid,
393				     sb->io_base);
394		sb->io_base = 0;
395    	}
396    	free(sb, M_DEVBUF);
397}
398
399static int
400sb_alloc_resources(struct sb_info *sb, device_t dev)
401{
402	if (!sb->io_base)
403    		sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
404						 &sb->io_rid, 0, ~0, 1,
405						 RF_ACTIVE);
406	if (!sb->irq)
407    		sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
408					     &sb->irq_rid, 0, ~0, 1,
409					     RF_ACTIVE);
410	if (!sb->drq1)
411    		sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ,
412					      &sb->drq1_rid, 0, ~0, 1,
413					      RF_ACTIVE);
414	if (!sb->drq2 && sb->drq2_rid > 0)
415        	sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ,
416					      &sb->drq2_rid, 0, ~0, 1,
417					      RF_ACTIVE);
418
419    	if (sb->io_base && sb->drq1 && sb->irq) {
420		sb->dma8 = rman_get_start(sb->drq1);
421		isa_dma_acquire(sb->dma8);
422		isa_dmainit(sb->dma8, DSP_BUFFSIZE);
423
424		if (sb->drq2) {
425			sb->dma16 = rman_get_start(sb->drq2);
426			isa_dma_acquire(sb->dma16);
427			isa_dmainit(sb->dma16, DSP_BUFFSIZE);
428		} else sb->dma16 = sb->dma8;
429
430		if (sb->dma8 > sb->dma16) {
431			int tmp = sb->dma16;
432			sb->dma16 = sb->dma8;
433			sb->dma8 = tmp;
434		}
435		return 0;
436	} else return ENXIO;
437}
438
439static int
440sb_identify_board(device_t dev, struct sb_info *sb)
441{
442    	char *fmt = NULL;
443    	static char buf[64];
444	int essver = 0;
445
446    	sb_cmd(sb, DSP_CMD_GETVER);	/* Get version */
447    	sb->bd_id = (sb_get_byte(sb) << 8) | sb_get_byte(sb);
448
449    	switch (sb->bd_id >> 8) {
450    	case 1: /* old sound blaster has nothing... */
451    	case 2:
452		fmt = "SoundBlaster %d.%d" ; /* default */
453		break;
454
455    	case 3:
456		fmt = "SoundBlaster Pro %d.%d";
457		if (sb->bd_id == 0x301) {
458	    		int rev;
459
460	    		/* Try to detect ESS chips. */
461	    		sb_cmd(sb, DSP_CMD_GETID); /* Return ident. bytes. */
462	    		essver = (sb_get_byte(sb) << 8) | sb_get_byte(sb);
463	    		rev = essver & 0x000f;
464	    		essver &= 0xfff0;
465	    		if (essver == 0x4880) {
466				/* the ESS488 can be treated as an SBPRO */
467				fmt = "SoundBlaster Pro (ESS488 rev %d)";
468	    		} else if (essver == 0x6880) {
469				if (rev < 8) fmt = "ESS688 rev %d";
470				else fmt = "ESS1868 rev %d";
471	        		sb->bd_flags |= BD_F_ESS;
472	    		} else return ENXIO;
473	    		sb->bd_id &= 0xff00;
474	    		sb->bd_id |= ((essver & 0xf000) >> 8) | rev;
475		}
476		break;
477
478    	case 4:
479		sb->bd_flags |= BD_F_SB16;
480		if (sb->bd_flags & BD_F_SB16X) fmt = "SB16 ViBRA16X %d.%d";
481        	else fmt = "SoundBlaster 16 %d.%d";
482		break;
483
484    	default:
485		device_printf(dev, "failed to get SB version (%x)\n",
486			      sb->bd_id);
487		return ENXIO;
488    	}
489    	if (essver) snprintf(buf, sizeof buf, fmt, sb->bd_id & 0x000f);
490	else snprintf(buf, sizeof buf, fmt, sb->bd_id >> 8, sb->bd_id & 0xff);
491    	device_set_desc_copy(dev, buf);
492    	return sb_reset_dsp(sb);
493}
494
495static int
496sb_init(device_t dev, struct sb_info *sb)
497{
498    	int x, irq;
499
500    	sb->bd_flags &= ~BD_F_MIX_MASK;
501    	/* do various initializations depending on board id. */
502    	switch (sb->bd_id >> 8) {
503    	case 1: /* old sound blaster has nothing... */
504		break;
505
506    	case 2:
507		sb->bd_flags |= BD_F_DUP_MIDI;
508		if (sb->bd_id > 0x200) sb->bd_flags |= BD_F_MIX_CT1335;
509		break;
510
511    	case 3:
512		sb->bd_flags |= BD_F_DUP_MIDI | BD_F_MIX_CT1345;
513		break;
514
515    	case 4:
516    		sb->bd_flags |= BD_F_SB16 | BD_F_MIX_CT1745;
517		if (sb->dma16 != sb->dma8) sb->bd_flags |= BD_F_DUPLEX;
518
519		/* soft irq/dma configuration */
520		x = -1;
521		irq = rman_get_start(sb->irq);
522		if      (irq == 5) x = 2;
523		else if (irq == 7) x = 4;
524		else if (irq == 9) x = 1;
525		else if (irq == 10) x = 8;
526		if (x == -1) device_printf(dev,
527					   "bad irq %d (5/7/9/10 valid)\n",
528					   irq);
529		else sb_setmixer(sb, IRQ_NR, x);
530		sb_setmixer(sb, DMA_NR, (1 << sb->dma16) | (1 << sb->dma8));
531		break;
532    	}
533    	return 0;
534}
535
536static int
537sb_probe(device_t dev)
538{
539    	snddev_info *d = device_get_softc(dev);
540    	struct sb_info *sb;
541    	int allocated, i;
542    	int error;
543
544    	if (isa_get_vendorid(dev)) return ENXIO; /* not yet */
545
546    	device_set_desc(dev, "SoundBlaster");
547    	bzero(d, sizeof *d);
548    	sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
549    	if (!sb) return ENXIO;
550    	bzero(sb, sizeof *sb);
551
552    	allocated = 0;
553    	sb->io_rid = 0;
554    	sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid,
555				    	0, ~0, 16, RF_ACTIVE);
556    	if (!sb->io_base) {
557		BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n"));
558		allocated = 1;
559		sb->io_rid = 0;
560		sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
561						 &sb->io_rid, 0x220, 0x22f,
562						 16, RF_ACTIVE);
563		if (!sb->io_base) {
564		    	sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
565							 &sb->io_rid, 0x240,
566							 0x24f, 16, RF_ACTIVE);
567		}
568    	}
569    	if (!sb->io_base) return ENXIO;
570
571    	error = sb_reset_dsp(sb);
572    	if (error) goto no;
573    	error = sb_identify_board(dev, sb);
574    	if (error) goto no;
575no:
576    	i = sb->io_rid;
577    	sb_release_resources(sb, dev);
578    	if (allocated) bus_delete_resource(dev, SYS_RES_IOPORT, i);
579    	return error;
580}
581
582static int
583sb_doattach(device_t dev, struct sb_info *sb)
584{
585    	snddev_info *d = device_get_softc(dev);
586    	void *ih;
587    	int error;
588    	char status[SND_STATUSLEN];
589
590    	sb->irq_rid = 0;
591    	sb->drq1_rid = 0;
592    	sb->drq2_rid = 1;
593    	if (sb_alloc_resources(sb, dev)) goto no;
594    	error = sb_reset_dsp(sb);
595    	if (error) goto no;
596    	error = sb_identify_board(dev, sb);
597    	if (error) goto no;
598
599    	sb_init(dev, sb);
600    	mixer_init(d, &sb_mixer, sb);
601	if (sb->bd_flags & BD_F_ESS)
602		bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih);
603	else
604		bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih);
605
606    	if (sb->bd_flags & BD_F_SB16)
607		pcm_setflags(dev, pcm_getflags(dev) | SD_F_EVILSB16);
608    	if (sb->dma16 == sb->dma8)
609		pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
610    	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
611			/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
612			/*highaddr*/BUS_SPACE_MAXADDR,
613			/*filter*/NULL, /*filterarg*/NULL,
614			/*maxsize*/DSP_BUFFSIZE, /*nsegments*/1,
615			/*maxsegz*/0x3ffff,
616			/*flags*/0, &sb->parent_dmat) != 0) {
617		device_printf(dev, "unable to create dma tag\n");
618		goto no;
619    	}
620
621    	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d",
622    	     	rman_get_start(sb->io_base), rman_get_start(sb->irq),
623		sb->dma8);
624    	if (sb->dma16 != sb->dma8) snprintf(status + strlen(status),
625    		SND_STATUSLEN - strlen(status), ":%d", sb->dma16);
626
627    	if (pcm_register(dev, sb, 1, 1)) goto no;
628	if (sb->bd_flags & BD_F_ESS) {
629		pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb);
630		pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb);
631	} else {
632		pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb);
633		pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb);
634	}
635    	pcm_setstatus(dev, status);
636
637    	return 0;
638
639no:
640    	sb_release_resources(sb, dev);
641    	return ENXIO;
642}
643
644static int
645sb_attach(device_t dev)
646{
647    	struct sb_info *sb;
648    	int flags = device_get_flags(dev);
649
650    	if (flags & DV_F_DUAL_DMA) {
651        	bus_set_resource(dev, SYS_RES_DRQ, 1,
652				 flags & DV_F_DRQ_MASK, 1);
653    	}
654    	sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
655    	if (!sb) return ENXIO;
656    	bzero(sb, sizeof *sb);
657
658    	/* XXX in probe should set io resource to right val instead of this */
659    	sb->io_rid = 0;
660    	sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid,
661				    	0, ~0, 16, RF_ACTIVE);
662    	if (!sb->io_base) {
663		BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n"));
664		sb->io_rid = 0;
665		sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
666						 &sb->io_rid, 0x220, 0x22f,
667						 16, RF_ACTIVE);
668		if (!sb->io_base) {
669	    		sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
670							 &sb->io_rid, 0x240,
671							 0x24f, 16, RF_ACTIVE);
672		}
673    	}
674    	if (!sb->io_base) return ENXIO;
675
676    	return sb_doattach(dev, sb);
677}
678
679static device_method_t sb_methods[] = {
680	/* Device interface */
681	DEVMETHOD(device_probe,		sb_probe),
682	DEVMETHOD(device_attach,	sb_attach),
683
684	{ 0, 0 }
685};
686
687static driver_t sb_driver = {
688	"pcm",
689	sb_methods,
690	sizeof(snddev_info),
691};
692
693DRIVER_MODULE(sb, isa, sb_driver, pcm_devclass, 0, 0);
694
695static void
696sb_intr(void *arg)
697{
698    	struct sb_info *sb = (struct sb_info *)arg;
699    	int reason = 3, c;
700
701    	/*
702     	* SB < 4.0 is half duplex and has only 1 bit for int source,
703     	* so we fake it. SB 4.x (SB16) has the int source in a separate
704     	* register.
705     	* The Vibra16X has separate flags for 8 and 16 bit transfers, but
706     	* I have no idea how to tell capture from playback interrupts...
707     	*/
708    	if (sb->bd_flags & BD_F_SB16) {
709    		c = sb_getmixer(sb, IRQ_STAT);
710    		/* this tells us if the source is 8-bit or 16-bit dma. We
711     		* have to check the io channel to map it to read or write...
712     		*/
713    		reason = 0;
714    		if (c & 1) { /* 8-bit dma */
715			if (sb->pch.fmt & AFMT_U8) reason |= 1;
716			if (sb->rch.fmt & AFMT_U8) reason |= 2;
717    		}
718    		if (c & 2) { /* 16-bit dma */
719			if (sb->pch.fmt & AFMT_S16_LE) reason |= 1;
720			if (sb->rch.fmt & AFMT_S16_LE) reason |= 2;
721    		}
722    	} else c = 1;
723#if 0
724    	printf("sb_intr: reason=%d c=0x%x\n", reason, c);
725#endif
726    	if ((reason & 1) && (sb->pch.buffer->dl > 0))
727		chn_intr(sb->pch.channel);
728    	if ((reason & 2) && (sb->rch.buffer->dl > 0))
729		chn_intr(sb->rch.channel);
730    	if (c & 1) sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
731    	if (c & 2) sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
732}
733
734static void
735ess_intr(void *arg)
736{
737    struct sb_info *sb = (struct sb_info *)arg;
738    sb_rd(sb, DSP_DATA_AVAIL); /* int ack */
739#ifdef notyet
740    /*
741     * XXX
742     * for full-duplex mode:
743     * should read port 0x6 to identify where interrupt came from.
744     */
745#endif
746    /*
747     * We are transferring data in DSP normal mode,
748     * so clear the dl to indicate the DMA is stopped.
749     */
750    if (sb->pch.buffer->dl > 0) {
751	sb->pch.buffer->dl = -1;
752	chn_intr(sb->pch.channel);
753    }
754    if (sb->rch.buffer->dl > 0) {
755	sb->rch.buffer->dl = -1;
756	chn_intr(sb->rch.channel);
757    }
758}
759
760static int
761sb_format(struct sb_chinfo *ch, u_int32_t format)
762{
763	ch->fmt = format;
764	return 0;
765}
766
767static int
768sb_speed(struct sb_chinfo *ch, int speed)
769{
770    	struct sb_info *sb = ch->parent;
771    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
772    	int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
773
774    	if (sb->bd_flags & BD_F_SB16) {
775		RANGE(speed, 5000, 45000);
776		sb_cmd(sb, 0x42 - play);
777    		sb_cmd(sb, speed >> 8);
778		sb_cmd(sb, speed & 0xff);
779    	} else {
780		u_char tconst;
781		int max_speed = 45000, tmp;
782        	u_long flags;
783
784    		/* here enforce speed limitations - max 22050 on sb 1.x*/
785    		if (sb->bd_id <= 0x200) max_speed = 22050;
786
787    		/*
788     	 	* SB models earlier than SB Pro have low limit for the
789     	 	* input rate. Note that this is only for input, but since
790     	 	* we do not support separate values for rec & play....
791     	 	*/
792		if (!play) {
793    			if (sb->bd_id <= 0x200) max_speed = 13000;
794    			else if (sb->bd_id < 0x300) max_speed = 15000;
795		}
796    		RANGE(speed, 4000, max_speed);
797    		if (stereo) speed <<= 1;
798
799    		/*
800     	 	* Now the speed should be valid. Compute the value to be
801     	 	* programmed into the board.
802     	 	*/
803    		if (speed > 22050) { /* High speed mode on 2.01/3.xx */
804			tconst = (u_char)
805				((65536 - ((256000000 + speed / 2) / speed))
806				>> 8);
807			sb->bd_flags |= BD_F_HISPEED;
808			tmp = 65536 - (tconst << 8);
809			speed = (256000000 + tmp / 2) / tmp;
810    		} else {
811			sb->bd_flags &= ~BD_F_HISPEED;
812			tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
813			tmp = 256 - tconst;
814			speed = (1000000 + tmp / 2) / tmp;
815    		}
816		flags = spltty();
817		sb_cmd1(sb, 0x40, tconst); /* set time constant */
818		splx(flags);
819    		if (stereo) speed >>= 1;
820    	}
821    	return speed;
822}
823
824static int
825sb_start(struct sb_chinfo *ch)
826{
827	struct sb_info *sb = ch->parent;
828    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
829    	int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
830    	int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
831	int l = ch->buffer->dl;
832	u_char i1, i2 = 0;
833
834	if (b16) l >>= 1;
835	l--;
836	if (play) sb_cmd(sb, DSP_CMD_SPKON);
837	if (sb->bd_flags & BD_F_SB16) {
838	    i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON |
839	         (play? DSP_F16_DAC : DSP_F16_ADC);
840	    i1 |= (b16 && (sb->bd_flags & BD_F_DUPLEX))? DSP_DMA16 : DSP_DMA8;
841	    i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0);
842	    sb_cmd(sb, i1);
843	    sb_cmd2(sb, i2, l);
844	} else {
845	    if (sb->bd_flags & BD_F_HISPEED) i1 = play? 0x90 : 0x98;
846	    else i1 = play? 0x1c : 0x2c;
847	    sb_setmixer(sb, 0x0e, stereo? 2 : 0);
848	    /* an ESS extension -- they can do 16 bits */
849	    if (b16) i1 |= 1;
850	    sb_cmd2(sb, 0x48, l);
851	    sb_cmd(sb, i1);
852	}
853	sb->bd_flags |= BD_F_DMARUN << b16;
854	return 0;
855}
856
857static int
858sb_stop(struct sb_chinfo *ch)
859{
860	struct sb_info *sb = ch->parent;
861    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
862    	int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
863
864    	if (sb->bd_flags & BD_F_HISPEED) sb_reset_dsp(sb);
865	else {
866		sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8);
867	       /*
868		* The above seems to have the undocumented side effect of
869		* blocking the other side as well. If the other
870		* channel was active (SB16) I have to re-enable it :(
871		*/
872		if (sb->bd_flags & (BD_F_DMARUN << (1 - b16)))
873			sb_cmd(sb, b16? 0xd4 : 0xd6 );
874	}
875	if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
876	sb->bd_flags &= ~(BD_F_DMARUN << b16);
877	return 0;
878}
879
880/* utility functions for ESS */
881static int
882ess_format(struct sb_chinfo *ch, u_int32_t format)
883{
884	struct sb_info *sb = ch->parent;
885	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
886	int b16 = (format & AFMT_S16_LE)? 1 : 0;
887	int stereo = (format & AFMT_STEREO)? 1 : 0;
888	u_char c;
889	ch->fmt = format;
890	sb_reset_dsp(sb);
891	/* normal DMA mode */
892	ess_write(sb, 0xb8, play ? 0x00 : 0x0a);
893	/* mono/stereo */
894	c = (ess_read(sb, 0xa8) & ~0x03) | 1;
895	if (!stereo) c++;
896	ess_write(sb, 0xa8, c);
897	/* demand mode, 4 bytes/xfer */
898	ess_write(sb, 0xb9, 2);
899	/* setup dac/adc */
900	if (play) ess_write(sb, 0xb6, b16? 0x00 : 0x80);
901	ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00));
902	ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38));
903	/* irq/drq control */
904	ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50);
905	ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50);
906	return 0;
907}
908
909static int
910ess_speed(struct sb_chinfo *ch, int speed)
911{
912	struct sb_info *sb = ch->parent;
913	int t;
914	RANGE (speed, 5000, 49000);
915	if (speed > 22000) {
916		t = (795500 + speed / 2) / speed;
917		speed = (795500 + t / 2) / t;
918		t = (256 - t ) | 0x80;
919	} else {
920		t = (397700 + speed / 2) / speed;
921		speed = (397700 + t / 2) / t;
922		t = 128 - t;
923	}
924	ess_write(sb, 0xa1, t); /* set time constant */
925#if 0
926	d->play_speed = d->rec_speed = speed;
927	speed = (speed * 9 ) / 20;
928#endif
929	t = 256 - 7160000 / ((speed * 9 / 20) * 82);
930	ess_write(sb, 0xa2, t);
931	return speed;
932}
933
934static int
935ess_start(struct sb_chinfo *ch)
936{
937	struct sb_info *sb = ch->parent;
938    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
939	short c = - ch->buffer->dl;
940	u_char c1;
941	/*
942	 * clear bit 0 of register B8h
943	 */
944#if 1
945	c1 = play ? 0x00 : 0x0a;
946	ess_write(sb, 0xb8, c1++);
947#else
948	c1 = ess_read(sb, 0xb8) & 0xfe;
949	ess_write(sb, 0xb8, c1++);
950#endif
951	/*
952	 * update ESS Transfer Count Register
953	 */
954	ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff));
955	ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff));
956	/*
957	 * set bit 0 of register B8h
958	 */
959	ess_write(sb, 0xb8, c1);
960	if (play)
961		sb_cmd(sb, DSP_CMD_SPKON);
962	return 0;
963}
964
965static int
966ess_stop(struct sb_chinfo *ch)
967{
968	struct sb_info *sb = ch->parent;
969	/*
970	 * no need to send a stop command if the DMA has already stopped.
971	 */
972	if (ch->buffer->dl > 0) {
973		sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */
974	}
975	return 0;
976}
977
978static int
979ess_abort(struct sb_chinfo *ch)
980{
981	struct sb_info *sb = ch->parent;
982    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
983	if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
984	sb_reset_dsp(sb);
985	ess_format(ch, ch->fmt);
986	ess_speed(ch, ch->channel->speed);
987	return 0;
988}
989
990/* channel interface */
991static void *
992sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
993{
994	struct sb_info *sb = devinfo;
995	struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
996
997	ch->parent = sb;
998	ch->channel = c;
999	ch->buffer = b;
1000	ch->buffer->bufsize = DSP_BUFFSIZE;
1001	if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) return NULL;
1002	ch->buffer->chan = (dir == PCMDIR_PLAY)? sb->dma16 : sb->dma8;
1003	return ch;
1004}
1005
1006static int
1007sbchan_setdir(void *data, int dir)
1008{
1009	struct sb_chinfo *ch = data;
1010	ch->dir = dir;
1011	return 0;
1012}
1013
1014static int
1015sbchan_setformat(void *data, u_int32_t format)
1016{
1017	struct sb_chinfo *ch = data;
1018	sb_format(ch, format);
1019	return 0;
1020}
1021
1022static int
1023sbchan_setspeed(void *data, u_int32_t speed)
1024{
1025	struct sb_chinfo *ch = data;
1026	return sb_speed(ch, speed);
1027}
1028
1029static int
1030sbchan_setblocksize(void *data, u_int32_t blocksize)
1031{
1032	return blocksize;
1033}
1034
1035static int
1036sbchan_trigger(void *data, int go)
1037{
1038	struct sb_chinfo *ch = data;
1039	buf_isadma(ch->buffer, go);
1040	if (go == PCMTRIG_START) sb_start(ch); else sb_stop(ch);
1041	return 0;
1042}
1043
1044static int
1045sbchan_getptr(void *data)
1046{
1047	struct sb_chinfo *ch = data;
1048	return buf_isadmaptr(ch->buffer);
1049}
1050
1051static pcmchan_caps *
1052sbchan_getcaps(void *data)
1053{
1054	struct sb_chinfo *ch = data;
1055	int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
1056	if (ch->parent->bd_id <= 0x200)
1057		return p? &sb_playcaps : &sb_reccaps;
1058	else if (ch->parent->bd_id >= 0x400)
1059		return p? &sb16_playcaps : &sb16_reccaps;
1060	else
1061		return p? &sbpro_playcaps : &sbpro_reccaps;
1062}
1063/* channel interface for ESS18xx */
1064#ifdef notyet
1065static void *
1066esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
1067{
1068	/* the same as sbchan_init()? */
1069}
1070#endif
1071
1072static int
1073esschan_setdir(void *data, int dir)
1074{
1075	struct sb_chinfo *ch = data;
1076	ch->dir = dir;
1077	return 0;
1078}
1079
1080static int
1081esschan_setformat(void *data, u_int32_t format)
1082{
1083	struct sb_chinfo *ch = data;
1084	ess_format(ch, format);
1085	return 0;
1086}
1087
1088static int
1089esschan_setspeed(void *data, u_int32_t speed)
1090{
1091	struct sb_chinfo *ch = data;
1092	return ess_speed(ch, speed);
1093}
1094
1095static int
1096esschan_setblocksize(void *data, u_int32_t blocksize)
1097{
1098	return blocksize;
1099}
1100
1101static int
1102esschan_trigger(void *data, int go)
1103{
1104	struct sb_chinfo *ch = data;
1105	switch (go) {
1106	case PCMTRIG_START:
1107		if (!ch->ess_dma_started)
1108			buf_isadma(ch->buffer, go);
1109		ch->ess_dma_started = 1;
1110		ess_start(ch);
1111		break;
1112	case PCMTRIG_STOP:
1113		if (ch->buffer->dl >= 0) {
1114			buf_isadma(ch->buffer, go);
1115			ch->ess_dma_started = 0;
1116			ess_stop(ch);
1117		}
1118		break;
1119	case PCMTRIG_ABORT:
1120	default:
1121		ch->ess_dma_started = 0;
1122		ess_abort(ch);
1123		buf_isadma(ch->buffer, go);
1124		break;
1125	}
1126	return 0;
1127}
1128
1129static int
1130esschan_getptr(void *data)
1131{
1132	struct sb_chinfo *ch = data;
1133	return buf_isadmaptr(ch->buffer);
1134}
1135
1136static pcmchan_caps *
1137esschan_getcaps(void *data)
1138{
1139	struct sb_chinfo *ch = data;
1140	return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
1141}
1142
1143/************************************************************/
1144
1145static int
1146sbmix_init(snd_mixer *m)
1147{
1148    	struct sb_info *sb = mix_getdevinfo(m);
1149
1150    	switch (sb->bd_flags & BD_F_MIX_MASK) {
1151    	case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */
1152		mix_setdevs(m, SBPRO_MIXER_DEVICES);
1153		mix_setrecdevs(m, SBPRO_RECORDING_DEVICES);
1154		sb_setmixer(sb, 0, 1); /* reset mixer */
1155		sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */
1156		sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */
1157		sb_setmixer(sb, FM_VOL, 0x0); /* no midi */
1158		break;
1159
1160    	case BD_F_MIX_CT1745: /* SB16 mixer ... */
1161		mix_setdevs(m, SB16_MIXER_DEVICES);
1162		mix_setrecdevs(m, SB16_RECORDING_DEVICES);
1163		sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
1164		sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
1165		sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
1166    	}
1167    	return 0;
1168}
1169
1170static int
1171sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1172{
1173    	struct sb_info *sb = mix_getdevinfo(m);
1174    	int regoffs;
1175    	u_char   val;
1176    	mixer_tab *iomap;
1177
1178    	switch (sb->bd_flags & BD_F_MIX_MASK) {
1179    	case BD_F_MIX_CT1345:
1180		if (sb->bd_flags & BD_F_ESS)
1181			iomap = &ess_mix;
1182		else
1183			iomap = &sbpro_mix;
1184		break;
1185
1186    	case BD_F_MIX_CT1745:
1187		iomap = &sb16_mix;
1188		break;
1189
1190    	default:
1191        	return -1;
1192    	/* XXX how about the SG NX Pro, iomap = sgnxpro_mix */
1193    	}
1194
1195	/* Change left channel */
1196    	regoffs = (*iomap)[dev][LEFT_CHN].regno;
1197    	if (regoffs != 0) {
1198		val = sb_getmixer(sb, regoffs);
1199		change_bits(iomap, &val, dev, LEFT_CHN, left);
1200		sb_setmixer(sb, regoffs, val);
1201	}
1202
1203	/* Change right channel */
1204	regoffs = (*iomap)[dev][RIGHT_CHN].regno;
1205	if (regoffs != 0) {
1206		val = sb_getmixer(sb, regoffs); /* Read the new one */
1207		change_bits(iomap, &val, dev, RIGHT_CHN, right);
1208		sb_setmixer(sb, regoffs, val);
1209	} else
1210		right = left;
1211
1212    	return left | (right << 8);
1213}
1214
1215static int
1216sbmix_setrecsrc(snd_mixer *m, u_int32_t src)
1217{
1218    	struct sb_info *sb = mix_getdevinfo(m);
1219    	u_char recdev;
1220
1221    	switch (sb->bd_flags & BD_F_MIX_MASK) {
1222    	case BD_F_MIX_CT1345:
1223		if      (src == SOUND_MASK_LINE) 	recdev = 0x06;
1224		else if (src == SOUND_MASK_CD) 		recdev = 0x02;
1225		else { /* default: mic */
1226	    		src = SOUND_MASK_MIC;
1227	    		recdev = 0;
1228		}
1229		sb_setmixer(sb, RECORD_SRC, recdev |
1230			    (sb_getmixer(sb, RECORD_SRC) & ~0x07));
1231		break;
1232
1233    	case BD_F_MIX_CT1745: /* sb16 */
1234		recdev = 0;
1235		if (src & SOUND_MASK_MIC)   recdev |= 0x01; /* mono mic */
1236		if (src & SOUND_MASK_CD)    recdev |= 0x06; /* l+r cd */
1237		if (src & SOUND_MASK_LINE)  recdev |= 0x18; /* l+r line */
1238		if (src & SOUND_MASK_SYNTH) recdev |= 0x60; /* l+r midi */
1239		sb_setmixer(sb, SB16_IMASK_L, recdev);
1240		sb_setmixer(sb, SB16_IMASK_R, recdev);
1241		/*
1242	 	* since the same volume controls apply to the input and
1243	 	* output sections, the best approach to have a consistent
1244	 	* behaviour among cards would be to disable the output path
1245	 	* on devices which are used to record.
1246	 	* However, since users like to have feedback, we only disable
1247	 	* the mic -- permanently.
1248	 	*/
1249        	sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
1250		break;
1251       	}
1252    	return src;
1253}
1254
1255static int
1256sbpnp_probe(device_t dev)
1257{
1258    	char *s = NULL;
1259    	u_int32_t logical_id = isa_get_logicalid(dev);
1260
1261    	switch(logical_id) {
1262    	case 0x01100000: /* @@@1001 */
1263    		s = "Avance Asound 110";
1264		break;
1265
1266    	case 0x01200000: /* @@@2001 */
1267        	s = "Avance Logic ALS120";
1268		break;
1269
1270    	case 0x68187316: /* ESS1868 */
1271		s = "ESS1868";
1272		break;
1273
1274	case 0x69187316: /* ESS1869 */
1275	case 0xacb0110e: /* Compaq's Presario 1621 ESS1869 */
1276		s = "ESS1869";
1277		break;
1278
1279	case 0x79187316: /* ESS1879 */
1280		s = "ESS1879";
1281		break;
1282
1283	case 0x88187316: /* ESS1888 */
1284		s = "ESS1888";
1285		break;
1286    	}
1287    	if (s) {
1288		device_set_desc(dev, s);
1289		return (0);
1290    	}
1291    	return ENXIO;
1292}
1293
1294static int
1295sbpnp_attach(device_t dev)
1296{
1297    	struct sb_info *sb;
1298    	u_int32_t vend_id = isa_get_vendorid(dev);
1299
1300    	sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1301    	if (!sb) return ENXIO;
1302    	bzero(sb, sizeof *sb);
1303
1304    	switch(vend_id) {
1305    	case 0xf0008c0e:
1306    	case 0x10019305:
1307    	case 0x20019305:
1308		/* XXX add here the vend_id for other vibra16X cards... */
1309		sb->bd_flags = BD_F_SB16X;
1310    	}
1311    	return sb_doattach(dev, sb);
1312}
1313
1314static device_method_t sbpnp_methods[] = {
1315	/* Device interface */
1316	DEVMETHOD(device_probe,		sbpnp_probe),
1317	DEVMETHOD(device_attach,	sbpnp_attach),
1318
1319	{ 0, 0 }
1320};
1321
1322static driver_t sbpnp_driver = {
1323	"pcm",
1324	sbpnp_methods,
1325	sizeof(snddev_info),
1326};
1327
1328DRIVER_MODULE(sbpnp, isa, sbpnp_driver, pcm_devclass, 0, 0);
1329
1330#if NSBC > 0
1331#define DESCSTR " PCM Audio"
1332static int
1333sbsbc_probe(device_t dev)
1334{
1335    	char *s = NULL;
1336	struct sndcard_func *func;
1337
1338	/* The parent device has already been probed. */
1339
1340	func = device_get_ivars(dev);
1341	if (func == NULL || func->func != SCF_PCM)
1342		return (ENXIO);
1343
1344	s = "SB PCM Audio";
1345
1346	device_set_desc(dev, s);
1347	return 0;
1348}
1349
1350static int
1351sbsbc_attach(device_t dev)
1352{
1353    	struct sb_info *sb;
1354    	u_int32_t vend_id;
1355	device_t sbc;
1356
1357	sbc = device_get_parent(dev);
1358	vend_id = isa_get_vendorid(sbc);
1359    	sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1360    	if (!sb) return ENXIO;
1361    	bzero(sb, sizeof *sb);
1362
1363    	switch(vend_id) {
1364    	case 0xf0008c0e:
1365    	case 0x10019305:
1366    	case 0x20019305:
1367		/* XXX add here the vend_id for other vibra16X cards... */
1368		sb->bd_flags = BD_F_SB16X;
1369    	}
1370    	return sb_doattach(dev, sb);
1371}
1372
1373static device_method_t sbsbc_methods[] = {
1374	/* Device interface */
1375	DEVMETHOD(device_probe,		sbsbc_probe),
1376	DEVMETHOD(device_attach,	sbsbc_attach),
1377
1378	{ 0, 0 }
1379};
1380
1381static driver_t sbsbc_driver = {
1382	"pcm",
1383	sbsbc_methods,
1384	sizeof(snddev_info),
1385};
1386
1387DRIVER_MODULE(sbsbc, sbc, sbsbc_driver, pcm_devclass, 0, 0);
1388
1389#endif /* NSBC > 0 */
1390