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