sb16.c revision 42192
1/*
2 * sound/sb_dsp.c
3 *
4 * driver for the SoundBlaster and clones.
5 *
6 * Copyright 1997,1998 Luigi Rizzo.
7 *
8 * Derived from files in the Voxware 3.5 distribution,
9 * Copyright by Hannu Savolainen 1994, under the same copyright
10 * conditions.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in
19 *    the documentation and/or other materials provided with the
20 *    distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37/*
38 * use this as a template file for board-specific drivers.
39 * The next two lines (and the final #endif) are in all drivers:
40 */
41
42#include <i386/isa/snd/sound.h>
43#if NPCM > 0
44
45/*
46 * Begin with the board-specific include files...
47 */
48
49#define __SB_MIXER_C__	/* XXX warning... */
50#include  <i386/isa/snd/sbcard.h>
51
52/*
53 * then prototypes of functions which go in the snddev_info
54 * (usually static, unless they are shared by other modules)...
55 */
56
57static	int sb_probe(struct isa_device *dev);
58static	int sb_attach(struct isa_device *dev);
59
60static	d_open_t	sb_dsp_open;
61static	d_close_t	sb_dsp_close;
62static	d_ioctl_t	sb_dsp_ioctl;
63static	irq_proc_t	sb_intr;
64static	snd_callback_t	sb_callback;
65
66/*
67 * and prototypes for other private functions defined in this module.
68 */
69
70static	void sb_dsp_init(snddev_info *d, struct isa_device *dev);
71static	void sb_mix_init(snddev_info *d);
72static int sb_mixer_set(snddev_info *d, int dev, int value);
73static int dsp_speed(snddev_info *d);
74static void sb_mixer_reset(snddev_info *d);
75
76u_int sb_get_byte(int io_base);
77int ess_write(int io_base, u_char reg, int val);
78int ess_read(int io_base, u_char reg);
79
80/*
81 * Then put here the descriptors for the various boards supported
82 * by this module, properly initialized.
83 */
84
85snddev_info sb_op_desc = {
86    "basic soundblaster",
87
88    SNDCARD_SB,
89    sb_probe,
90    sb_attach,
91
92    sb_dsp_open,
93    sb_dsp_close /* sb_close */,
94    NULL /* use generic sndread */,
95    NULL /* use generic sndwrite */,
96    sb_dsp_ioctl,
97    sndselect,
98
99    sb_intr,
100    sb_callback,
101
102    DSP_BUFFSIZE,	/* bufsize */
103
104    AFMT_STEREO | AFMT_U8,		/* audio format */
105
106} ;
107
108/*
109 * Then the file continues with the body of all functions
110 * directly referenced in the descriptor.
111 */
112
113/*
114 * the probe routine for the SoundBlaster only consists in
115 * resetting the dsp and testing if it is there.
116 * Version detection etc. will be done at attach time.
117 *
118 * Remember, ISA probe routines are supposed to return the
119 * size of io space used.
120 */
121
122static int
123sb_probe(struct isa_device *dev)
124{
125    bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) );
126    if (dev->id_iobase == -1) {
127	dev->id_iobase = 0x220;
128	BVDDB(printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n");)
129        if (snd_conflict(dev->id_iobase))
130	    dev->id_iobase = 0x240;
131    }
132    if (snd_conflict(dev->id_iobase))
133	return 0 ;
134
135    if (sb_reset_dsp(dev->id_iobase))
136	return 16 ; /* the SB uses 16 registers... */
137    else
138	return 0;
139}
140
141static int
142sb_attach(struct isa_device *dev)
143{
144    snddev_info *d = &pcm_info[dev->id_unit] ;
145
146    dev->id_alive = 16 ; /* number of io ports */
147    /* should be already set but just in case... */
148    sb_dsp_init(d, dev);
149    return 0 ;
150}
151
152/*
153 * here are the main routines from the switches.
154 */
155
156/*
157 * Unlike MSS, the sb only supports a single open (does not mean
158 * that only a single process is using it, since it can fork
159 * afterwards, or pass the descriptor to another process).
160 *
161 */
162static int
163sb_dsp_open(dev_t dev, int flags, int mode, struct proc * p)
164{
165    snddev_info *d;
166    int unit ;
167
168    dev = minor(dev);
169    unit = dev >> 4 ;
170    d = &pcm_info[unit] ;
171
172    DEB(printf("<%s>%d : open\n", d->name, unit));
173
174    if (d->flags & SND_F_BUSY) {
175	DEB(printf("<%s>%d open: device busy\n", d->name, unit));
176	return EBUSY ;
177    }
178
179    d->wsel.si_pid = 0;
180    d->wsel.si_flags = 0;
181
182    d->rsel.si_pid = 0;
183    d->rsel.si_flags = 0;
184
185    d->dbuf_out.total = d->dbuf_out.prev_total = 0 ;
186    d->dbuf_in.total = d->dbuf_in.prev_total = 0 ;
187
188    d->flags = 0 ;
189    d->bd_flags &= ~BD_F_HISPEED ;
190
191    switch ( dev & 0xf ) {
192    case SND_DEV_DSP16 :
193	if ((d->audio_fmt & AFMT_S16_LE) == 0) {
194	    printf("sorry, 16-bit not supported on SB %d.%02d\n",
195		(d->bd_id >>8) & 0xff, d->bd_id & 0xff);
196	    return ENXIO;
197	}
198	d->play_fmt = d->rec_fmt = AFMT_S16_LE ;
199	break;
200    case SND_DEV_AUDIO :
201	d->play_fmt = d->rec_fmt = AFMT_MU_LAW ;
202	break ;
203    case SND_DEV_DSP :
204	d->play_fmt = d->rec_fmt = AFMT_U8 ;
205	break ;
206    }
207    /*
208     * since the SB is not simmetric, I use the open mode to select
209     * which channel should be privileged, and disable I/O in the
210     * other direction.
211     * In case the board is opened RW, we don't have enough
212     * information on what to do. Temporarily, privilege the
213     * playback channel, which is used more often, and set the other
214     * one to U8.
215     */
216    if ( (flags & FREAD) == 0)		/* opened write only	*/
217	d->rec_fmt = 0 ;
218    else if ( (flags & FWRITE) == 0)	/* opened read only	*/
219	d->play_fmt = 0 ;
220    else				/* opened read/write	*/
221	d->rec_fmt = (d->play_fmt == AFMT_S16_LE) ? AFMT_U8 : AFMT_S16_LE ;
222
223    d->flags |= SND_F_BUSY ;
224    d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED ;
225
226    if (flags & O_NONBLOCK)
227	d->flags |= SND_F_NBIO ;
228
229    sb_reset_dsp(d->io_base);
230    if (d->bd_flags & BD_F_ESS)
231	sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */
232    ask_init(d);
233
234    return 0;
235}
236
237static int
238sb_dsp_close(dev_t dev, int flags, int mode, struct proc * p)
239{
240    int unit;
241    snddev_info *d;
242    u_long s;
243
244    dev = minor(dev);
245    unit = dev >> 4 ;
246    d = &pcm_info[unit] ;
247
248    s = spltty();
249    d->flags |= SND_F_CLOSING ;
250    splx(s);
251    snd_flush(d);
252
253    sb_cmd(d->io_base, DSP_CMD_SPKOFF ); /* XXX useless ? */
254
255    d->flags = 0 ;
256    return 0 ;
257}
258
259static int
260sb_dsp_ioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
261{
262    int unit;
263    snddev_info *d;
264
265    dev = minor(dev);
266    unit = dev >> 4 ;
267    d = &pcm_info[unit] ;
268
269    /*
270     * handle mixer calls first. Reads are in the default handler,
271     * so do not bother about them.
272     */
273    if ( (cmd & MIXER_WRITE(0)) == MIXER_WRITE(0) )
274	return sb_mixer_set(d, cmd & 0xff, *(int *)arg) ;
275
276    /*
277     * for the remaining functions, use the default handler.
278     * ENOSYS means that the default handler should take care
279     * of implementing the ioctl.
280     */
281
282    return ENOSYS ;
283}
284
285static void
286sb_intr(int unit)
287{
288    snddev_info *d = &pcm_info[unit];
289    int reason = 3, c=1, io_base = d->io_base;
290
291    DEB(printf("got sb_intr for unit %d, flags 0x%08lx\n", unit, d->flags));
292
293    /*
294     * SB < 4.0 is half duplex and has only 1 bit for int source,
295     * so we fake it. SB 4.x (SB16) has the int source in a separate
296     * register.
297     * The Vibra16X has separate flags for 8 and 16 bit transfers, but
298     * I have no idea how to tell capture from playback interrupts...
299     */
300#define PLAIN_SB16(x) ( ( (x) & (BD_F_SB16|BD_F_SB16X) ) == BD_F_SB16)
301again:
302    if (d->bd_flags & BD_F_SB16) {
303	c = sb_getmixer(io_base, IRQ_STAT);
304	/* this tells us if the source is 8-bit or 16-bit dma. We
305	 * have to check the io channel to map it to read or write...
306	 */
307	reason = 0 ;
308	if ( c & 1 ) { /* 8-bit dma */
309	    if (d->play_fmt == AFMT_U8 || d->play_fmt == AFMT_MU_LAW )
310		reason |= 1;
311	    if (d->rec_fmt == AFMT_U8 || d->rec_fmt == AFMT_MU_LAW )
312		reason |= 2;
313	}
314	if ( c & 2 ) { /* 16-bit dma */
315	    if (d->play_fmt == AFMT_S16_LE)
316		reason |= 1;
317	    if (d->rec_fmt == AFMT_S16_LE)
318		reason |= 2;
319	}
320    }
321    /* XXX previous location of ack... */
322    DEB(printf("sb_intr, flags 0x%08lx reason %d c 0x%x\n",
323	d->flags, reason, c));
324    if ( reason & 1 ) { /* possibly a write interrupt */
325	if ( d->dbuf_out.dl )
326	    dsp_wrintr(d);
327    }
328    if ( reason & 2 ) {
329	if ( d->dbuf_in.dl )
330	    dsp_rdintr(d);
331    }
332    if ( c & 2 )
333	inb(DSP_DATA_AVL16); /* 16-bit int ack */
334    if (c & 1)
335	inb(DSP_DATA_AVAIL);	/* 8-bit int ack */
336
337    /*
338     * the sb16 might have multiple sources etc.
339     */
340    if ((d->bd_flags & BD_F_SB16) && (c & 3))
341	goto again;
342}
343
344/*
345 * device-specific function called back from the dma module.
346 * The reason of the callback is the second argument.
347 * NOTE: during operations, some ioctl can be called to change
348 * settings (e.g. speed, channels, format), and the default
349 * ioctl handler will just record the change and set the
350 * flag SND_F_INIT. The callback routine is in charge of applying
351 * the changes at the next convenient time (typically, at the
352 * start of operations). For full duplex devices, in some cases the
353 * init requires both channels to be idle.
354 */
355static int
356sb_callback(snddev_info *d, int reason)
357{
358    int rd = reason & SND_CB_RD ;
359    snd_dbuf *b = (rd) ? & (d->dbuf_in) : & (d->dbuf_out) ;
360    int l = b->dl ;
361
362    switch (reason & SND_CB_REASON_MASK) {
363    case SND_CB_INIT : /* called with int enabled and no pending io */
364	/*
365	 * set the speed
366	 */
367	dsp_speed(d);
368	/*
369	 * set the desired DMA blocksize (influences select behaviour)
370	 */
371	snd_set_blocksize(d);
372	/*
373	 * since native mulaw is not present, emulate it.
374	 */
375	if ( (d->play_fmt & AFMT_MU_LAW) || (d->rec_fmt & AFMT_MU_LAW) )
376	    d->flags |= SND_F_XLAT8 ;
377	else
378	    d->flags &= ~SND_F_XLAT8 ;
379
380	/*
381	 * there are too many flavours of SB for my taste... here i try to do
382	 * the proper initialization for each one.
383	 */
384	if (PLAIN_SB16(d->bd_flags)) {
385
386	    /* the original SB16 (non-PnP, or PnP, or Vibra16C)
387	     * can do full duplex using one 16-bit channel
388	     * and one 8-bit channel. It needs to be programmed to
389	     * use split format though.
390	     * I DON'T do this for the Vibra16X because I have no idea
391	     * of what needs to be done there...
392	     *
393	     * I use the following algorithm:
394	     * 1. check which direction(s) are active;
395	     * 2. check if we should swap dma channels
396	     * 3. check if we can do the swap.
397	     */
398	    int swap = 1 ; /* default... */
399
400	    if (d->play_fmt == 0) {
401		/* do whatever the read channel wants */
402		if ( d->rec_fmt == AFMT_S16_LE && d->dbuf_in.chan > 4 )
403		    swap = 0;
404		if ( d->rec_fmt != AFMT_S16_LE && d->dbuf_in.chan < 4 )
405		    swap = 0;
406	    } else {
407		/* privilege the write channel */
408		if ( d->play_fmt == AFMT_S16_LE && d->dbuf_out.chan > 4 )
409		    swap = 0;
410		if ( d->play_fmt != AFMT_S16_LE && d->dbuf_out.chan < 4 )
411		    swap = 0;
412		if ( d->rec_fmt ) {
413		    /* check for possible config errors.
414		     * This cannot happen at open time since even in
415		     * case of opening rw we privilege the play
416		     * channel.
417		     */
418		    if (d->rec_fmt == d->play_fmt) {
419			DDB(printf("sorry, read DMA channel unavailable\n"));
420		    }
421		}
422	    }
423	    DEB(printf("sb16: play_fmt %d, rec_fmt %x, swap %d\n",
424		d->play_fmt, d->rec_fmt, swap);)
425	    if (swap) {
426	        int c = d->dbuf_in.chan ;
427		d->dbuf_in.chan = d->dbuf_out.chan;
428		d->dbuf_out.chan = c ;
429	    }
430	}
431	else if (d->bd_flags & BD_F_ESS) {
432		u_char c;
433
434		DEB(printf("SND_CB_INIT, play_fmt == 0x%x, rec_fmt == 0x%x\n",
435			(int) d->play_fmt, (int) d->rec_fmt));
436
437		/* autoinit DMA mode */
438		if (d->play_fmt)
439			ess_write(d->io_base, 0xb8, 0x04);
440		else
441			ess_write(d->io_base, 0xb8, 0x0e);
442
443		c = (ess_read(d->io_base, 0xa8) & ~0x03) | 0x01;
444		if ((d->flags & SND_F_STEREO) == 0)
445			c++;
446		ess_write(d->io_base, 0xa8, c);	/* select mono/stereo */
447		ess_write(d->io_base, 0xb9, 2);	/* demand 4 bytes/transfer */
448
449		switch (d->play_fmt ? d->play_fmt : d->rec_fmt) {
450		case AFMT_S16_LE:
451			if (d->flags & SND_F_STEREO) {
452				/* 16 bit stereo */
453				if (d->play_fmt)
454					ess_write(d->io_base, 0xb6, 0x00);
455				ess_write(d->io_base, 0xb7, 0x71);
456				ess_write(d->io_base, 0xb7, 0xbc);
457			}
458			else {
459				/* 16 bit mono */
460				if (d->play_fmt)
461					ess_write(d->io_base, 0xb6, 0x00);
462				ess_write(d->io_base, 0xb7, 0x71);
463				ess_write(d->io_base, 0xb7, 0xf4);
464			}
465			break;
466		case AFMT_U8:
467			if (d->flags & SND_F_STEREO) {
468				/* 8 bit stereo */
469				if (d->play_fmt)
470					ess_write(d->io_base, 0xb6, 0x80);
471				ess_write(d->io_base, 0xb7, 0x51);
472				ess_write(d->io_base, 0xb7, 0x98);
473			}
474			else {
475				/* 8 bit mono */
476				if (d->play_fmt)
477					ess_write(d->io_base, 0xb6, 0x80);
478				ess_write(d->io_base, 0xb7, 0x51);
479				ess_write(d->io_base, 0xb7, 0xd0);
480			}
481			break;
482		}
483		ess_write(d->io_base, 0xb1,
484			  ess_read(d->io_base, 0xb1) | 0x50);
485		ess_write(d->io_base, 0xb2,
486			  ess_read(d->io_base, 0xb1) | 0x50);
487	}
488	reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
489	reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
490	break ;
491
492    case SND_CB_START : /* called with int disabled */
493	if (d->bd_flags & BD_F_SB16) {
494	    u_char c, c1 ;
495
496            if (d->bd_flags & BD_F_SB16X) {
497                /* just a guess: on the Vibra16X, the first
498                 * op started takes the first dma channel,
499                 * the second one takes the next...
500                 * The default is to be ready for play.
501                 */
502		DEB(printf("start %s -- now dma %d:%d\n",
503			rd ? "rd" : "wr",
504			d->dbuf_out.chan, d->dbuf_in.chan););
505		/* swap only if both channels are idle
506		 *   play: dl=0, since there is no pause;
507		 *   rec: rl=0
508		 */
509                if ( rd && d->dbuf_out.dl == 0 && d->dbuf_in.rl == 0 ) {
510		    /* must swap channels, but also save dl */
511		    int c = d->dbuf_in.chan ;
512		    int dl = d->dbuf_in.dl ;
513		    d->dbuf_in.chan = d->dbuf_out.chan;
514		    d->dbuf_out.chan = c ;
515		    reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
516		    reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
517		    d->dbuf_in.dl = dl ;
518		    printf("swapped -- now dma %d:%d\n",
519			d->dbuf_out.chan, d->dbuf_in.chan);
520                }
521            }
522
523	    /*
524	     * XXX note: c1 and l should be set basing on d->rec_fmt,
525	     * but there is no choice once a 16 or 8-bit channel
526	     * is assigned. This means that if the application
527	     * tries to use a bad format, the sound will not be nice.
528	     */
529	    if ( b->chan > 4
530		 || (rd && d->rec_fmt == AFMT_S16_LE)
531		 || (!rd && d->play_fmt == AFMT_S16_LE)
532	       ) {
533		c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA16 ;
534		c1 = DSP_F16_SIGNED ;
535		l /= 2 ;
536	    } else {
537		c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA8 ;
538		c1 = 0 ;
539	    }
540	    c |=  (rd) ? DSP_F16_ADC : DSP_F16_DAC ;
541	    if (d->flags & SND_F_STEREO)
542		c1 |= DSP_F16_STEREO ;
543
544	    sb_cmd(d->io_base, c );
545	    sb_cmd3(d->io_base, c1 , l - 1) ;
546	} else if (d->bd_flags & BD_F_ESS) {
547		u_long fmt = rd ? d->rec_fmt : d->play_fmt;
548
549		DEB(printf("SND_CB_START: %s (%d)\n", rd ? "rd" : "wr", l));
550		if (fmt == AFMT_S16_LE)
551			l >>= 1;
552		l--;
553		if (!rd)
554			sb_cmd(d->io_base, DSP_CMD_SPKON);
555		ess_write(d->io_base, 0xa4, l);
556		ess_write(d->io_base, 0xa5, l >> 8);
557		ess_write(d->io_base, 0xb8,
558			  ess_read(d->io_base, 0xb8) | (rd ? 0x0f : 0x05));
559	} else { /* SBPro -- stereo not supported */
560	    u_char c ;
561	    if (!rd)
562		sb_cmd(d->io_base, DSP_CMD_SPKON);
563	    /* code for the SB2 and SB3, only MONO */
564	    if (d->bd_flags & BD_F_HISPEED)
565		c = (rd) ? 0x98 : 0x90 ;
566	    else
567		c = (rd) ? 0x2c : 0x1c ;
568	    if (d->flags & SND_F_STEREO)
569	        sb_setmixer(d->io_base, 0xe, 2 );
570	    else
571	        sb_setmixer(d->io_base, 0xe, 0 );
572	    /*
573	     * some ESS extensions -- they can do 16 bits
574	     */
575	    if ( (rd && d->rec_fmt == AFMT_S16_LE) ||
576	         (!rd && d->play_fmt == AFMT_S16_LE) ) {
577		c |= 1;
578		l /= 2 ;
579	    }
580	    sb_cmd3(d->io_base, 0x48 , l - 1) ;
581	    sb_cmd(d->io_base, c ) ;
582	}
583	break;
584
585    case SND_CB_ABORT : /* XXX */
586    case SND_CB_STOP :
587	{
588	    int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */
589		DEB(printf("SND_CB_XXX: reason 0x%x\n", reason));
590	    if ( b->chan > 4
591		 || (rd && d->rec_fmt == AFMT_S16_LE)
592		 || (!rd && d->play_fmt == AFMT_S16_LE)
593	       )
594		cmd = DSP_CMD_DMAPAUSE_16 ;
595	    if (d->bd_flags & BD_F_HISPEED) {
596		sb_reset_dsp(d->io_base);
597		if (d->bd_flags & BD_F_ESS)
598		    sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */
599		d->flags |= SND_F_INIT ;
600	    } else {
601		sb_cmd(d->io_base, cmd); /* pause dma. */
602	       /*
603		* The above seems to have the undocumented side effect of
604		* blocking the other side as well. If the other
605		* channel was active (SB16) I have to re-enable it :(
606		*/
607		if ( (rd && d->dbuf_out.dl) ||
608		     (!rd && d->dbuf_in.dl) )
609		    sb_cmd(d->io_base, cmd == DSP_CMD_DMAPAUSE_8 ?
610			0xd6 : 0xd4); /* continue other dma */
611	    }
612            if (d->bd_flags & BD_F_SB16X) {
613                /* restore possible swapped channels.
614                 * The default is to be ready for play.
615		 * XXX right now, it kills all input on overflow
616                 */
617                if (  rd && d->dbuf_out.dl == 0 ) {
618                        /* must swap channels ? */
619                        int c = d->dbuf_in.chan ;
620                        d->dbuf_in.chan = d->dbuf_out.chan;
621                        d->dbuf_out.chan = c ;
622                        reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
623                        reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
624                    printf("restored -- now dma %d:%d\n",
625                        d->dbuf_out.chan, d->dbuf_in.chan);
626                }
627            }
628	}
629	DEB( sb_cmd(d->io_base, DSP_CMD_SPKOFF) ); /* speaker off */
630	break ;
631
632    }
633    return 0 ;
634}
635
636/*
637 * The second part of the file contains all functions specific to
638 * the board and (usually) not exported to other modules.
639 */
640
641int
642sb_reset_dsp(int io_base)
643{
644    int loopc;
645
646    outb(io_base + SBDSP_RST, 3);
647    DELAY(100);
648    outb(io_base + SBDSP_RST, 0);
649    for (loopc = 0; loopc<100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++)
650	DELAY(30);
651
652    if (inb(DSP_READ) != 0xAA) {
653        DEB(printf("sb_reset_dsp 0x%x failed\n", io_base));
654	return 0;	/* Sorry */
655    }
656    return 1;
657}
658
659/*
660 * only used in sb_attach from here.
661 */
662
663static void
664sb_dsp_init(snddev_info *d, struct isa_device *dev)
665{
666    int i, x;
667    char *fmt = NULL ;
668    int	io_base = dev->id_iobase ;
669
670    d->bd_id = 0 ;
671
672    sb_reset_dsp(io_base);
673    sb_cmd(io_base, DSP_CMD_GETVER);	/* Get version */
674
675    for (i = 10000; i; i--) { /* perhaps wait longer on a fast machine ? */
676	if (inb(DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */
677	    if ( (d->bd_id & 0xff00) == 0)
678		d->bd_id = inb(DSP_READ) << 8; /* major */
679	    else {
680		d->bd_id |= inb(DSP_READ); /* minor */
681		break;
682	    }
683	} else
684	    DELAY(20);
685    }
686
687    /*
688     * now do various initializations depending on board id.
689     */
690
691    fmt = "SoundBlaster %d.%d" ; /* default */
692
693    switch ( d->bd_id >> 8 ) {
694    case 0 :
695	printf("\n\nFailed to get SB version (%x) - possible I/O conflict\n\n",
696	       inb(DSP_DATA_AVAIL));
697	d->bd_id = 0x100;
698    case 1 : /* old sound blaster has nothing... */
699	break ;
700
701    case 2 :
702	d->dbuf_in.chan = d->dbuf_out.chan ; /* half duplex */
703	d->bd_flags |= BD_F_DUP_MIDI ;
704
705	if (d->bd_id == 0x200)
706	    break ; /* no mixer on the 2.0 */
707	d->bd_flags &= ~BD_F_MIX_MASK ;
708	d->bd_flags |= BD_F_MIX_CT1335 ;
709
710	break ;
711    case 4 :
712	fmt = "SoundBlaster 16 %d.%d";
713	d->audio_fmt |= AFMT_FULLDUPLEX | AFMT_WEIRD | AFMT_S8 | AFMT_S16_LE;
714	d->bd_flags |= BD_F_SB16;
715	d->bd_flags &= ~BD_F_MIX_MASK ;
716	d->bd_flags |= BD_F_MIX_CT1745 ;
717
718	/* soft irq/dma configuration */
719	x = -1 ;
720	if (d->irq == 5) x = 2;
721	else if (d->irq == 7) x = 4;
722	else if (d->irq == 9) x = 1;
723	else if (d->irq == 10) x = 8;
724	if (x == -1)
725	    printf("<%s>%d: bad irq %d (only 5,7,9,10 allowed)\n",
726		d->name, dev->id_unit, d->irq);
727	else
728	    sb_setmixer(io_base, IRQ_NR, x);
729	if (d->dbuf_out.chan == d->dbuf_in.chan) {
730	    printf("WARNING: sb: misconfigured secondary DMA channel\n");
731	}
732	sb_setmixer(io_base, DMA_NR, (1 << d->dbuf_out.chan) | (1 << d->dbuf_in.chan));
733	break ;
734
735    case 3 :
736	d->dbuf_in.chan = d->dbuf_out.chan ; /* half duplex */
737	fmt = "SoundBlaster Pro %d.%d";
738	d->bd_flags |= BD_F_DUP_MIDI ;
739	d->bd_flags &= ~BD_F_MIX_MASK ;
740	d->bd_flags |= BD_F_MIX_CT1345 ;
741	if (d->bd_id == 0x301) {
742	    int ess_major = 0, ess_minor = 0;
743
744	    /*
745	     * Try to detect ESS chips.
746	     */
747
748	    sb_cmd(io_base, DSP_CMD_GETID);	/* Return ident. bytes. */
749
750	    for (i = 1000; i; i--) {
751		if (inb(DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */
752		    if (ess_major == 0)
753			ess_major = inb(DSP_READ);
754		    else {
755			ess_minor = inb(DSP_READ);
756			break;
757		    }
758		} else
759		    DELAY(20);
760	    }
761
762	    if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) {
763		/* the ESS488 can be treated as an SBPRO */
764		printf("ESS488 (rev %d)\n", ess_minor & 0x0f);
765		break ;
766	    }
767		else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
768			int rev = ess_minor & 0xf;
769
770			if (rev >= 8)
771				printf("ESS1868 (rev %d)\n", rev);
772			else
773				printf("ESS688 (rev %d)\n", rev);
774			d->bd_flags |= BD_F_ESS;
775			d->audio_fmt |= AFMT_S16_LE;
776
777			/* enable extended ESS mode */
778			sb_cmd(d->io_base, 0xc6);
779			break;
780	    } else {
781		printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n",
782			ess_major, ess_minor);
783		break ;
784	    }
785	}
786
787    }
788
789    snprintf(d->name, sizeof(d->name),
790	fmt, (d->bd_id >> 8) &0xff, d->bd_id & 0xff);
791
792    sb_mix_init(d);
793}
794
795static void
796sb_mix_init(snddev_info *d)
797{
798    switch (d->bd_flags & BD_F_MIX_MASK) {
799    case BD_F_MIX_CT1345 : /* SB 3.0 has 1345 mixer */
800
801	d->mix_devs = SBPRO_MIXER_DEVICES ;
802	d->mix_rec_devs = SBPRO_RECORDING_DEVICES ;
803	d->mix_recsrc = SOUND_MASK_MIC ;
804
805	sb_setmixer(d->io_base, 0, 1 ); /* reset mixer */
806	sb_setmixer(d->io_base, MIC_VOL , 0x6 ); /* mic volume max */
807	sb_setmixer(d->io_base, RECORD_SRC , 0x0 ); /* mic source */
808	sb_setmixer(d->io_base, FM_VOL , 0x0 ); /* no midi */
809	break ;
810
811    case BD_F_MIX_CT1745 : /* SB16 mixer ... */
812
813	d->mix_devs = SB16_MIXER_DEVICES ;
814	d->mix_rec_devs = SB16_RECORDING_DEVICES ;
815	d->mix_recsrc = SOUND_MASK_MIC ;
816    }
817    sb_mixer_reset(d);
818}
819
820/*
821 * Common code for the midi and pcm functions
822 *
823 * sb_cmd write a single byte to the CMD port.
824 * sb_cmd2 write a CMD + 1 byte arg
825 * sb_cmd3 write a CMD + 2 byte arg
826 * sb_get_byte returns a single byte from the DSP data port
827 *
828 * ess_write is actually sb_cmd2
829 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte
830 */
831
832int
833sb_cmd(int io_base, u_char val)
834{
835    int  i;
836
837    for (i = 0; i < 1000 ; i++) {
838	if ((inb(io_base + SBDSP_STATUS) & 0x80) == 0) {
839	    outb(io_base + SBDSP_CMD, val);
840	    return 1;
841	}
842	if (i > 10)
843	    DELAY (i > 100 ? 1000 : 10 );
844    }
845
846    printf("SoundBlaster: DSP Command(0x%02x) timeout. IRQ conflict ?\n", val);
847    return 0;
848}
849
850int
851sb_cmd3(int io_base, u_char cmd, int val)
852{
853    if (sb_cmd(io_base, cmd)) {
854	sb_cmd(io_base, val & 0xff );
855	sb_cmd(io_base, (val>>8) & 0xff );
856	return 1 ;
857    } else
858	return 0;
859}
860
861int
862sb_cmd2(int io_base, u_char cmd, int val)
863{
864    if (sb_cmd(io_base, cmd)) {
865	sb_cmd(io_base, val & 0xff );
866	return 1 ;
867    } else
868	return 0;
869}
870
871/*
872 * in the SB, there is a set of indirect "mixer" registers with
873 * address at offset 4, data at offset 5
874 */
875void
876sb_setmixer(int io_base, u_int port, u_int value)
877{
878    u_long   flags;
879
880    flags = spltty();
881    outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff));   /* Select register */
882    DELAY(10);
883    outb(io_base + SB_MIX_DATA, (u_char) (value & 0xff));
884    DELAY(10);
885    splx(flags);
886}
887
888int
889sb_getmixer(int io_base, u_int port)
890{
891    int             val;
892    u_long   flags;
893
894    flags = spltty();
895    outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff));   /* Select register */
896    DELAY(10);
897    val = inb(io_base + SB_MIX_DATA);
898    DELAY(10);
899    splx(flags);
900
901    return val;
902}
903
904u_int
905sb_get_byte(int io_base)
906{
907    int             i;
908
909    for (i = 1000; i; i--)
910	if (inb(DSP_DATA_AVAIL) & 0x80)
911	    return inb(DSP_READ);
912	else
913	    DELAY(20);
914    return 0xffff;
915}
916
917int
918ess_write(int io_base, u_char reg, int val)
919{
920    return sb_cmd2(io_base, reg, val);
921}
922
923int
924ess_read(int io_base, u_char reg)
925{
926    if (!sb_cmd(io_base, 0xc0) || !sb_cmd(io_base, reg) )
927	return 0xffff ;
928    return sb_get_byte(io_base);
929}
930
931
932/*
933 * various utility functions for the DSP
934 */
935
936/*
937 * dsp_speed updates the speed setting from the descriptor. make sure
938 * it is called at spltty().
939 * Besides, it takes care of stereo setting.
940 */
941static int
942dsp_speed(snddev_info *d)
943{
944    u_char   tconst;
945    u_long   flags;
946    int max_speed = 44100, speed = d->play_speed ;
947
948    /*
949     * special code for the SB16
950     */
951    if (d->bd_flags & BD_F_SB16) {
952	RANGE (speed, 5000, 45000);
953	d->play_speed = d->rec_speed = speed ;
954	sb_cmd(d->io_base, 0x41);
955	sb_cmd(d->io_base, d->play_speed >> 8 );
956	sb_cmd(d->io_base, d->play_speed & 0xff );
957	sb_cmd(d->io_base, 0x42);
958	sb_cmd(d->io_base, d->rec_speed >> 8 );
959	sb_cmd(d->io_base, d->rec_speed & 0xff );
960	return speed ;
961    }
962
963    /*
964     * special code for the ESS ...
965     */
966    if (d->bd_flags & BD_F_ESS) {
967	int t;
968	RANGE (speed, 5000, 49000);
969	if (speed > 22000) {
970	    t = (795500 + speed / 2) / speed;
971	    speed = (795500 + t / 2) / t ;
972	    t = (256 - t ) | 0x80 ;
973	} else {
974	    t = (397700 + speed / 2) / speed;
975	    speed = (397700 + t / 2) / t ;
976	    t = 128 - t ;
977	}
978	ess_write(d->io_base, 0xa1, t); /* set time constant */
979	d->play_speed = d->rec_speed = speed ;
980	speed = (speed * 9 ) / 20 ;
981	t = 256-7160000/(speed*82);
982	ess_write(d->io_base,0xa2,t);
983	return speed ;
984    }
985
986    /*
987     * This is code for the SB3.x and lower.
988     * Only some models can do stereo, and only if not
989     * simultaneously using midi.
990     * At the moment we do not support either...
991     */
992#if 0
993    d->flags &= ~SND_F_STEREO;
994#endif
995
996    /*
997     * here enforce speed limitations.
998     */
999    if (d->bd_id <= 0x200)
1000	max_speed = 22050; /* max 22050 on SB 1.X */
1001
1002    /*
1003     * SB models earlier than SB Pro have low limit for the
1004     * input rate. Note that this is only for input, but since
1005     * we do not support separate values for rec & play....
1006     */
1007    if (d->bd_id <= 0x200)
1008	max_speed = 13000;
1009    else if (d->bd_id < 0x300)
1010	max_speed = 15000;
1011
1012    RANGE(speed, 4000, max_speed);
1013
1014    if (d->flags & SND_F_STEREO) /* really unused right now... */
1015	speed *= 2;
1016
1017    /*
1018     * Now the speed should be valid. Compute the value to be
1019     * programmed into the board.
1020     */
1021
1022    if (speed > 22050) { /* High speed mode on 2.01/3.xx */
1023	int tmp;
1024
1025	tconst = (u_char) ((65536 - ((256000000 + speed / 2) / speed)) >> 8) ;
1026	d->bd_flags |= BD_F_HISPEED ;
1027
1028	flags = spltty();
1029	sb_cmd2(d->io_base, 0x40, tconst); /* set time constant */
1030	splx(flags);
1031
1032	tmp = 65536 - (tconst << 8);
1033	speed = (256000000 + tmp / 2) / tmp;
1034    } else {
1035	int             tmp;
1036
1037	d->bd_flags &= ~BD_F_HISPEED ;
1038	tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
1039
1040	flags = spltty();
1041	sb_cmd2(d->io_base, 0x40, tconst); /* set time constant */
1042	splx(flags);
1043
1044	tmp = 256 - tconst;
1045	speed = (1000000 + tmp / 2) / tmp;
1046    }
1047
1048    if (d->flags & SND_F_STEREO) /* really unused right now... */
1049	speed /= 2;
1050
1051    d->play_speed = d->rec_speed = speed;
1052    return speed;
1053}
1054
1055/*
1056 * mixer support, originally in sb_mixer.c
1057 */
1058
1059static void
1060sb_set_recsrc(snddev_info *d, int mask)
1061{
1062    u_char recdev ;
1063
1064    mask &= d->mix_rec_devs;
1065    switch (d->bd_flags & BD_F_MIX_MASK) {
1066    case BD_F_MIX_CT1345 :
1067	if (mask == SOUND_MASK_LINE)
1068	    recdev = 6 ;
1069	else if (mask == SOUND_MASK_CD)
1070	    recdev = 2 ;
1071	else { /* default: mic */
1072	    mask =  SOUND_MASK_MIC ;
1073	    recdev = 0 ;
1074	}
1075	sb_setmixer(d->io_base, RECORD_SRC,
1076	    recdev | (sb_getmixer(d->io_base, RECORD_SRC) & ~7 ));
1077	break ;
1078    case BD_F_MIX_CT1745 : /* sb16 */
1079	if (mask == 0)
1080	    mask = SOUND_MASK_MIC ; /* XXX For compatibility. Bug ? */
1081	recdev = 0 ;
1082	if (mask & SOUND_MASK_MIC)
1083	    recdev |= 1 ;
1084	if (mask & SOUND_MASK_CD)
1085	    recdev |= 6 ; /* l+r cd */
1086	if (mask & SOUND_MASK_LINE)
1087	    recdev |= 0x18 ; /* l+r line */
1088	if (mask & SOUND_MASK_SYNTH)
1089	    recdev |= 0x60 ; /* l+r midi */
1090	sb_setmixer(d->io_base, SB16_IMASK_L, recdev);
1091	sb_setmixer(d->io_base, SB16_IMASK_R, recdev);
1092	/*
1093	 * since the same volume controls apply to the input and
1094	 * output sections, the best approach to have a consistent
1095	 * behaviour among cards would be to disable the output path
1096	 * on devices which are used to record.
1097	 * However, since users like to have feedback, we only disable
1098	 * the mike -- permanently.
1099	 */
1100        sb_setmixer(d->io_base, SB16_OMASK, 0x1f & ~1);
1101	break ;
1102    }
1103    d->mix_recsrc = mask;
1104}
1105
1106static void
1107sb_mixer_reset(snddev_info *d)
1108{
1109    int             i;
1110
1111    for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1112	sb_mixer_set(d, i, levels[i]);
1113    if (d->bd_flags & BD_F_SB16) {
1114	sb_setmixer(d->io_base, 0x3c, 0x1f); /* make all output active */
1115	sb_setmixer(d->io_base, 0x3d, 0); /* make all inputs-l off */
1116	sb_setmixer(d->io_base, 0x3e, 0); /* make all inputs-r off */
1117    }
1118    sb_set_recsrc(d, SOUND_MASK_MIC);
1119}
1120
1121static int
1122sb_mixer_set(snddev_info *d, int dev, int value)
1123{
1124    int left = value & 0x000000ff;
1125    int right = (value & 0x0000ff00) >> 8;
1126    int regoffs;
1127    u_char   val;
1128    mixer_tab *iomap;
1129
1130#ifdef JAZZ16
1131    if (d->bd_flags & BD_F_JAZZ16 && d->bd_flags & BD_F_JAZZ16_2)
1132        return smw_mixer_set(dev, value);
1133#endif
1134
1135    if (dev == SOUND_MIXER_RECSRC) {
1136	sb_set_recsrc(d, value);
1137	return 0 ;
1138    }
1139    if (left > 100)
1140        left = 100;
1141    if (right > 100)
1142        right = 100;
1143
1144    if (dev > 31)
1145        return EINVAL ;
1146
1147    if (!(d->mix_devs & (1 << dev)))      /* Not supported */
1148        return EINVAL;
1149
1150    switch ( d->bd_flags & BD_F_MIX_MASK ) {
1151    default:
1152	/* mixer unknown, fail... */
1153	return EINVAL ;/* XXX change this */
1154    case BD_F_MIX_CT1345 :
1155	iomap = &sbpro_mix ;
1156	break;
1157    case BD_F_MIX_CT1745 :
1158	iomap = &sb16_mix ;
1159	break;
1160    /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */
1161    }
1162    regoffs = (*iomap)[dev][LEFT_CHN].regno;
1163    if (regoffs == 0)
1164        return EINVAL;
1165
1166    val = sb_getmixer(d->io_base, regoffs);
1167
1168    change_bits(iomap, &val, dev, LEFT_CHN, left);
1169
1170    d->mix_levels[dev] = left | (left << 8);
1171
1172    if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) {    /* Change register */
1173        sb_setmixer(d->io_base, regoffs, val);     /* Save the old one */
1174        regoffs = (*iomap)[dev][RIGHT_CHN].regno;
1175
1176        if (regoffs == 0)
1177            return 0 ;  /* Just left channel present */
1178
1179        val = sb_getmixer(d->io_base, regoffs);    /* Read the new one */
1180    }
1181    change_bits(iomap, &val, dev, RIGHT_CHN, right);
1182
1183    sb_setmixer(d->io_base, regoffs, val);
1184
1185    d->mix_levels[dev] = left | (right << 8);
1186    return 0 ; /* ok */
1187}
1188
1189/*
1190 * now support for some PnP boards.
1191 */
1192
1193#if NPNP > 0
1194static char *ess1868_probe(u_long csn, u_long vend_id);
1195static void ess1868_attach(u_long csn, u_long vend_id, char *name,
1196        struct isa_device *dev);
1197
1198static struct pnp_device ess1868 = {
1199        "ESS1868",
1200        ess1868_probe,
1201        ess1868_attach,
1202        &nsnd,  /* use this for all sound cards */
1203        &tty_imask      /* imask */
1204};
1205DATA_SET (pnpdevice_set, ess1868);
1206
1207static char *
1208ess1868_probe(u_long csn, u_long vend_id)
1209{
1210    /*
1211     * pnp X 1 os enable drq0 3 irq0 12 port0 0x240
1212     */
1213    if (vend_id == 0x68187316) {
1214	struct pnp_cinfo d ;
1215	read_pnp_parms ( &d , 1 ) ;
1216	if (d.enable == 0) {
1217	    printf("This is an ESS1868, but LDN 1 is disabled\n");
1218	    return NULL;
1219	}
1220        return "ESS1868" ;
1221    }
1222    return NULL ;
1223}
1224
1225static void
1226ess1868_attach(u_long csn, u_long vend_id, char *name,
1227        struct isa_device *dev)
1228{
1229    struct pnp_cinfo d ;
1230    snddev_info tmp_d ; /* patched copy of the basic snddev_info */
1231
1232    tmp_d = sb_op_desc;
1233    snddev_last_probed = &tmp_d;
1234
1235#if 0
1236    read_pnp_parms ( &d , 3 );  /* disable LDN 3 */
1237    d.port[0] = 0 ;
1238    d.enable = 0 ;
1239    write_pnp_parms ( &d , 3 );
1240
1241    read_pnp_parms ( &d , 2 ); /* disable LDN 2 */
1242    d.port[0] = 0 ;
1243    d.enable = 0 ;
1244    write_pnp_parms ( &d , 2 );
1245    read_pnp_parms ( &d , 0 ); /* read config base */
1246    tmp_d.conf_base = d.port[0];
1247    write_pnp_parms ( &d , 0 );
1248#endif
1249
1250    read_pnp_parms ( &d , 1 ) ;
1251    dev->id_iobase = d.port[0];
1252    d.port[1] = 0 ;
1253    d.port[2] = 0 ;
1254    write_pnp_parms ( &d , 1 );
1255    enable_pnp_card();
1256
1257    dev->id_drq = d.drq[0] ; /* primary dma */
1258    dev->id_irq = (1 << d.irq[0] ) ;
1259    dev->id_intr = (inthand2_t *)pcmintr ;
1260    dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */;
1261
1262#if 0
1263    snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */
1264#endif
1265    pcmattach(dev);
1266}
1267
1268/*
1269 * A driver for some SB16pnp and compatibles...
1270 *
1271 * Avance Asound 100 -- 0x01009305
1272 * Avance Logic ALS100+ -- 0x10019305
1273 * xxx               -- 0x2b008c0e
1274 *
1275 */
1276
1277static char *sb16pnp_probe(u_long csn, u_long vend_id);
1278static void sb16pnp_attach(u_long csn, u_long vend_id, char *name,
1279        struct isa_device *dev);
1280
1281static struct pnp_device sb16pnp = {
1282        "SB16pnp",
1283        sb16pnp_probe,
1284        sb16pnp_attach,
1285        &nsnd,  /* use this for all sound cards */
1286        &tty_imask      /* imask */
1287};
1288DATA_SET (pnpdevice_set, sb16pnp);
1289
1290static char *
1291sb16pnp_probe(u_long csn, u_long vend_id)
1292{
1293    char *s = NULL ;
1294
1295    /*
1296     * The SB16/AWExx cards seem to differ in the fourth byte of
1297     * the vendor id, so I have just masked it for the time being...
1298     * Reported values are:
1299     * SB16 Value PnP:	0x2b008c0e
1300     * SB AWExx PnP:	0x39008c0e 0x9d008c0e 0xc3008c0e
1301     * Vibra16X:        0xf0008c0e
1302     */
1303    if (vend_id == 0xf0008c0e)
1304	s = "Vibra16X" ;
1305    else if ( (vend_id & 0xffffff)  == (0x9d008c0e & 0xffffff) )
1306	s = "SB16 PnP";
1307    else if (vend_id == 0x01009305)
1308        s = "Avance Asound 100" ;
1309    else if (vend_id == 0x10019305)
1310        s = "Avance Logic 100+" ; /* Vibra16X-class */
1311    if (s) {
1312	struct pnp_cinfo d;
1313	read_pnp_parms(&d, 0);
1314	if (d.enable == 0) {
1315	    printf("This is a %s, but LDN 0 is disabled\n", s);
1316	    return NULL ;
1317	}
1318	return s ;
1319    }
1320    return NULL ;
1321}
1322
1323static void
1324sb16pnp_attach(u_long csn, u_long vend_id, char *name,
1325        struct isa_device *dev)
1326{
1327    struct pnp_cinfo d ;
1328    snddev_info tmp_d ; /* patched copy of the basic snddev_info */
1329
1330    tmp_d = sb_op_desc;
1331    snddev_last_probed = &tmp_d;
1332
1333    read_pnp_parms ( &d , 0 ) ;
1334    d.port[1] = 0 ; /* only the first address is used */
1335    dev->id_iobase = d.port[0];
1336    tmp_d.synth_base = d.port[2];
1337    write_pnp_parms ( &d , 0 );
1338    enable_pnp_card();
1339
1340    dev->id_drq = d.drq[0] ; /* primary dma */
1341    dev->id_irq = (1 << d.irq[0] ) ;
1342    dev->id_intr = (inthand2_t *)pcmintr ;
1343    dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ;
1344
1345    pcm_info[dev->id_unit] = tmp_d; /* pcm_info[] will be reinitialized after */
1346    snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */
1347
1348    if (vend_id == 0x10019305 || vend_id == 0xf0008c0e) {
1349	/*
1350	 * XXX please add here the vend_id for other vibra16X cards...
1351	 * And remember, must change tmp_d, not
1352	 */
1353	tmp_d.bd_flags |= BD_F_SB16X ;
1354    }
1355    pcmattach(dev);
1356}
1357#endif /* NPNP */
1358
1359#endif
1360