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