File: /usr/src/linux/drivers/sound/sb_card.c

1     /*
2      * sound/sb_card.c
3      *
4      * Detection routine for the Sound Blaster cards.
5      *
6      *
7      * Copyright (C) by Hannu Savolainen 1993-1997
8      *
9      * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10      * Version 2 (June 1991). See the "COPYING" file distributed with this software
11      * for more info.
12      *
13      * 26-11-1999 Patched to compile without ISA PnP support in the
14      * kernel - Daniel Stone (tamriel@ductape.net) 
15      *
16      * 06-01-2000 Refined and bugfixed ISA PnP support, added
17      *  CMI 8330 support - Alessandro Zummo <azummo@ita.flashnet.it>
18      *
19      * 18-01-2000 Separated sb_card and sb_common
20      *  Jeff Garzik <jgarzik@mandrakesoft.com>
21      *
22      * 04-02-2000 Added Soundblaster AWE 64 PnP support, isapnpjump
23      *  Alessandro Zummo <azummo@ita.flashnet.it>
24      *
25      * 11-02-2000 Added Soundblaster AWE 32 PnP support, refined PnP code
26      *  Alessandro Zummo <azummo@ita.flashnet.it>
27      *
28      * 13-02-2000 Hopefully fixed awe/sb16 related bugs, code cleanup
29      *  Alessandro Zummo <azummo@ita.flashnet.it>
30      *
31      * 13-03-2000 Added some more cards, thanks to Torsten Werner.
32      *  Removed joystick and wavetable code, there are better places for them.
33      *  Code cleanup plus some fixes. 
34      *  Alessandro Zummo <azummo@ita.flashnet.it>
35      * 
36      * 26-03-2000 Fixed acer, esstype and sm_games module options.
37      *  Alessandro Zummo <azummo@ita.flashnet.it>
38      *
39      * 12-04-2000 ISAPnP cleanup, reorg, fixes, and multiple card support.
40      *  Thanks to Gaël Quéri and Alessandro Zummo for testing and fixes.
41      *  Paul E. Laufer <pelaufer@csupomona.edu>
42      *
43      * 06-05-2000 added another card. Daniel M. Newman <dmnewman@pobox.com>
44      *
45      * 25-05-2000 Added Creative SB AWE64 Gold (CTL00B2). 
46      * 	Pål-Kristian Engstad <engstad@att.net>
47      *
48      * 12-08-2000 Added Creative SB32 PnP (CTL009F).
49      * 	Kasatenko Ivan Alex. <skywriter@rnc.ru>
50      *
51      * 21-09-2000 Got rid of attach_sbmpu
52      * 	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
53      *
54      * 28-10-2000 Added pnplegacy support
55      * 	Daniel Church <dchurch@mbhs.edu>
56      */
57     
58     #include <linux/config.h>
59     #include <linux/mca.h>
60     #include <linux/module.h>
61     #include <linux/init.h>
62     #include <linux/isapnp.h>
63     
64     #include "sound_config.h"
65     
66     #include "sb_mixer.h"
67     #include "sb.h"
68     
69     #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
70     #define SB_CARDS_MAX 5
71     #else
72     #define SB_CARDS_MAX 1
73     #endif
74     
75     static int sbmpu[SB_CARDS_MAX] = {0};
76     static int sb_cards_num = 0;
77     
78     extern void *smw_free;
79     
80     /*
81      *    Note DMA2 of -1 has the right meaning in the SB16 driver as well
82      *    as here. It will cause either an error if it is needed or a fallback
83      *    to the 8bit channel.
84      */
85     
86     static int __initdata mpu_io	= 0;
87     static int __initdata io	= -1;
88     static int __initdata irq	= -1;
89     static int __initdata dma	= -1;
90     static int __initdata dma16	= -1;   /* Set this for modules that need it */
91     static int __initdata type	= 0;    /* Can set this to a specific card type */
92     static int __initdata esstype   = 0;	/* ESS chip type */
93     static int __initdata acer 	= 0;	/* Do acer notebook init? */
94     static int __initdata sm_games 	= 0;	/* Logitech soundman games? */
95     
96     static void __init attach_sb_card(struct address_info *hw_config)
97     {
98     	if(!sb_dsp_init(hw_config, THIS_MODULE))
99     		hw_config->slots[0] = -1;
100     }
101     
102     static int __init probe_sb(struct address_info *hw_config)
103     {
104     	struct sb_module_options sbmo;
105     
106     	if (hw_config->io_base == -1 || hw_config->dma == -1 || hw_config->irq == -1)
107     	{
108     		printk(KERN_ERR "sb: I/O, IRQ, and DMA are mandatory\n");
109     		return -EINVAL;
110     	}
111     
112     #ifdef CONFIG_MCA
113     	/* MCA code added by ZP Gu (zpg@castle.net) */
114     	if (MCA_bus) {               /* no multiple REPLY card probing */
115     		int slot;
116     		u8 pos2, pos3, pos4;
117     
118     		slot = mca_find_adapter( 0x5138, 0 );
119     		if( slot == MCA_NOTFOUND ) 
120     		{
121     			slot = mca_find_adapter( 0x5137, 0 );
122     
123     			if (slot != MCA_NOTFOUND)
124     				mca_set_adapter_name( slot, "REPLY SB16 & SCSI Adapter" );
125     		}
126     		else
127     		{
128     			mca_set_adapter_name( slot, "REPLY SB16 Adapter" );
129     		}
130     
131     		if (slot != MCA_NOTFOUND) 
132     		{
133     			mca_mark_as_used(slot);
134     			pos2 = mca_read_stored_pos( slot, 2 );
135     			pos3 = mca_read_stored_pos( slot, 3 );
136     			pos4 = mca_read_stored_pos( slot, 4 );
137     
138     			if (pos2 & 0x4) 
139     			{
140     				/* enabled? */
141     				static unsigned short irq[] = { 0, 5, 7, 10 };
142     				/*
143     				static unsigned short midiaddr[] = {0, 0x330, 0, 0x300 };
144            				*/
145     
146     				hw_config->io_base = 0x220 + 0x20 * (pos2 >> 6);
147     				hw_config->irq = irq[(pos4 >> 5) & 0x3];
148     				hw_config->dma = pos3 & 0xf;
149     				/* Reply ADF wrong on High DMA, pos[1] should start w/ 00 */
150     				hw_config->dma2 = (pos3 >> 4) & 0x3;
151     				if (hw_config->dma2 == 0)
152     					hw_config->dma2 = hw_config->dma;
153     				else
154     					hw_config->dma2 += 4;
155     				/*
156     					hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3];
157     				*/
158     	
159     				printk(KERN_INFO "sb: Reply MCA SB at slot=%d \
160     iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
161     						slot+1,
162     				        	hw_config->io_base, hw_config->irq,
163     	        				hw_config->dma, hw_config->dma2);
164     			}
165     			else
166     			{
167     				printk (KERN_INFO "sb: Reply SB Base I/O address disabled\n");
168     			}
169     		}
170     	}
171     #endif
172     
173     	/* Setup extra module options */
174     
175     	sbmo.acer 	= acer;
176     	sbmo.sm_games	= sm_games;
177     	sbmo.esstype	= esstype;
178     
179     	return sb_dsp_detect(hw_config, 0, 0, &sbmo);
180     }
181     
182     static void __exit unload_sb(struct address_info *hw_config, int card)
183     {
184     	if(hw_config->slots[0]!=-1)
185     		sb_dsp_unload(hw_config, sbmpu[card]);
186     }
187     
188     static struct address_info cfg[SB_CARDS_MAX];
189     static struct address_info cfg_mpu[SB_CARDS_MAX];
190     
191     struct pci_dev 	*sb_dev[SB_CARDS_MAX] 	= {NULL}, 
192     		*mpu_dev[SB_CARDS_MAX]	= {NULL},
193     		*opl_dev[SB_CARDS_MAX]	= {NULL};
194     
195     
196     #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
197     static int isapnp	= 1;
198     static int isapnpjump	= 0;
199     static int multiple	= 1;
200     static int pnplegacy	= 0;
201     static int reverse	= 0;
202     static int uart401	= 0;
203     
204     static int audio_activated[SB_CARDS_MAX] = {0};
205     static int mpu_activated[SB_CARDS_MAX]   = {0};
206     static int opl_activated[SB_CARDS_MAX]   = {0};
207     #else
208     static int isapnp	= 0;
209     static int multiple	= 0;
210     static int pnplegacy	= 0;
211     #endif
212     
213     MODULE_DESCRIPTION("Soundblaster driver");
214     
215     MODULE_PARM(io,		"i");
216     MODULE_PARM(irq,	"i");
217     MODULE_PARM(dma,	"i");
218     MODULE_PARM(dma16,	"i");
219     MODULE_PARM(mpu_io,	"i");
220     MODULE_PARM(type,	"i");
221     MODULE_PARM(sm_games,	"i");
222     MODULE_PARM(esstype,	"i");
223     MODULE_PARM(acer,	"i");
224     
225     #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
226     MODULE_PARM(isapnp,	"i");
227     MODULE_PARM(isapnpjump,	"i");
228     MODULE_PARM(multiple,	"i");
229     MODULE_PARM(pnplegacy,	"i");
230     MODULE_PARM(reverse,	"i");
231     MODULE_PARM(uart401,	"i");
232     MODULE_PARM_DESC(isapnp,	"When set to 0, Plug & Play support will be disabled");
233     MODULE_PARM_DESC(isapnpjump,	"Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
234     MODULE_PARM_DESC(multiple,	"When set to 0, will not search for multiple cards");
235     MODULE_PARM_DESC(pnplegacy,	"When set to 1, will search for a legacy SB card along with any PnP cards.");
236     MODULE_PARM_DESC(reverse,	"When set to 1, will reverse ISAPnP search order");
237     MODULE_PARM_DESC(uart401,	"When set to 1, will attempt to detect and enable the mpu on some clones");
238     #endif
239     
240     MODULE_PARM_DESC(io,		"Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
241     MODULE_PARM_DESC(irq,		"IRQ (5,7,9,10)");
242     MODULE_PARM_DESC(dma,		"8-bit DMA channel (0,1,3)");
243     MODULE_PARM_DESC(dma16,		"16-bit DMA channel (5,6,7)");
244     MODULE_PARM_DESC(mpu_io,	"Mpu base address");
245     MODULE_PARM_DESC(type,		"You can set this to specific card type");
246     MODULE_PARM_DESC(sm_games,	"Enable support for Logitech soundman games");
247     MODULE_PARM_DESC(esstype,	"ESS chip type");
248     MODULE_PARM_DESC(acer,		"Set this to detect cards in some ACER notebooks");
249     
250     #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
251     
252     /* Please add new entries at the end of the table */
253     static struct {
254     	char *name; 
255     	unsigned short	card_vendor, card_device, 
256     			audio_vendor, audio_function,
257     			mpu_vendor, mpu_function,
258     			opl_vendor, opl_function;
259     	short dma, dma2, mpu_io, mpu_irq; /* see sb_init() */
260     } sb_isapnp_list[] __initdata = {
261     	{"Sound Blaster 16", 
262     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
263     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
264     		0,0,0,0,
265     		0,1,1,-1},
266     	{"Sound Blaster 16",
267     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
268     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
269     		0,0,0,0,
270     		0,1,1,-1},
271     	{"Sound Blaster 16", 
272     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
273     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
274     		0,0,0,0,
275     		0,1,1,-1},
276     	{"Sound Blaster 16", 
277     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
278     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
279     		0,0,0,0,
280     		0,1,1,-1},
281     	{"Sound Blaster 16", 
282     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
283     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
284     		0,0,0,0,
285     		0,1,1,-1},
286     	{"Sound Blaster 16", 
287     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
288     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
289     		0,0,0,0,
290     		0,1,1,-1},
291     	{"Sound Blaster 16",
292     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
293     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
294     		0,0,0,0,
295     		0,1,1,-1},
296     	{"Sound Blaster 16", 
297     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
298     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
299     		0,0,0,0,
300     		0,1,1,-1},
301     	{"Sound Blaster 16", 
302     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
303     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
304     		0,0,0,0,
305     		0,1,1,-1},
306     	{"Sound Blaster 16", 
307     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
308     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
309     		0,0,0,0,
310     		0,1,1,-1},
311     	{"Sound Blaster 16", 
312     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), 
313     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
314     		0,0,0,0,
315     		0,1,1,-1},
316     	{"Sound Blaster 16", 
317     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
318     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
319     		0,0,0,0,
320     		0,1,1,-1},
321     	{"Sound Blaster 16", 
322     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
323     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
324     		0,0,0,0,
325     		0,1,1,-1},
326     	{"Sound Blaster Vibra16S", 
327     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
328     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
329     		0,0,0,0,
330     		0,1,1,-1},
331     	{"Sound Blaster Vibra16C", 
332     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
333     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
334     		0,0,0,0,
335     		0,1,1,-1},
336     	{"Sound Blaster Vibra16CL", 
337     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
338     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
339     		0,0,0,0,
340     		0,1,1,-1},
341     	{"Sound Blaster Vibra16X", 
342     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
343     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
344     		0,0,0,0,
345     		0,1,1,-1},
346     	{"Sound Blaster AWE 32", 
347     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
348     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
349     		0,0,0,0,
350     		0,1,1,-1},
351     	{"Sound Blaster AWE 32",
352     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
353     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
354     		0,0,0,0,
355     		0,1,1,-1},
356     	{"Sound Blaster AWE 32",
357     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
358     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
359     		0,0,0,0,
360     		0,1,1,-1},
361     	{"Sound Blaster AWE 32",
362     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
363     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
364     		0,0,0,0,
365     		0,1,1,-1},
366             {"Sound Blaster AWE 32",
367     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
368     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
369     		0,0,0,0,
370     		0,1,1,-1},
371     	{"Sound Blaster AWE 32",
372     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
373     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
374     		0,0,0,0,
375     		0,1,1,-1},
376     	{"Sound Blaster AWE 32",
377     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
378     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
379     		0,0,0,0,
380     		0,1,1,-1},
381     	{"Sound Blaster AWE 32",
382     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
383     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
384     		0,0,0,0,
385     		0,1,1,-1},
386     	{"Sound Blaster AWE 32",
387     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
388     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
389     		0,0,0,0,
390     		0,1,1,-1},
391     	{"Sound Blaster AWE 32",
392     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
393     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
394     		0,0,0,0,
395     		0,1,1,-1},
396     	{"Creative SB32 PnP",
397     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
398     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
399     		0,0,0,0,
400     		0,1,1,-1},
401     	{"Sound Blaster AWE 64",
402     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
403     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
404     		0,0,0,0,
405     		0,1,1,-1},
406     	{"Sound Blaster AWE 64 Gold",
407     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
408     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
409     		0,0,0,0,
410     		0,1,1,-1},
411     	{"Sound Blaster AWE 64 Gold",
412     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
413     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
414     		0,0,0,0,
415     		0,1,1,-1},
416     	{"Sound Blaster AWE 64",
417     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
418     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
419     		0,0,0,0,
420     		0,1,1,-1},
421     	{"Sound Blaster AWE 64",
422     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
423     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
424     		0,0,0,0,
425     		0,1,1,-1},
426     	{"Sound Blaster AWE 64",
427     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
428     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
429     		0,0,0,0,
430     		0,1,1,-1},
431     	{"Sound Blaster AWE 64",
432     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
433     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
434     		0,0,0,0,
435     		0,1,1,-1},
436     	{"Sound Blaster AWE 64",
437     		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
438     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
439     		0,0,0,0,
440     		0,1,1,-1},
441     	{"ESS 1688",
442     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
443     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
444     		0,0,0,0,
445     		0,1,2,-1},
446     	{"ESS 1868",
447     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
448     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
449     		0,0,0,0,
450     		0,1,2,-1},
451     	{"ESS 1868",
452     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
453     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
454     		0,0,0,0,
455     		0,1,2,-1},
456     	{"ESS 1869 PnP AudioDrive", 
457     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
458     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
459     		0,0,0,0,
460     		0,1,2,-1},
461     	{"ESS 1869",
462     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
463     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
464     		0,0,0,0,
465     		0,1,2,-1},
466     	{"ESS 1878",
467     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
468     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
469     		0,0,0,0,
470     		0,1,2,-1},
471     	{"ESS 1879",
472     		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
473     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
474     		0,0,0,0,
475     		0,1,2,-1},
476     	{"CMI 8330 SoundPRO",
477     		ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
478     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
479     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
480     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
481     		0,1,0,-1},
482     	{"Diamond DT0197H",
483     		ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
484     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
485     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
486     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
487     		0,-1,0,0},
488     	{"ALS007",
489     		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
490     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
491     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
492     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
493     		0,-1,0,0},
494     	{"ALS100",
495     		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
496     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
497     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
498     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
499     		1,0,0,0},
500     	{"ALS110",
501     		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
502     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001),
503     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001),
504     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
505     		1,0,0,0},
506     	{"ALS120",
507     		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
508     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
509     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
510     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
511     		1,0,0,0},
512     	{"ALS200",
513     		ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
514     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020),
515     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020),
516     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
517     		1,0,0,0},
518     	{"RTL3000",
519     		ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
520     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
521     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
522     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
523     		1,0,0,0},
524     	{0}
525     };
526     
527     static struct isapnp_device_id id_table[] __devinitdata = {
528     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
529     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
530     
531     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
532     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
533     
534     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
535     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
536     
537     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
538     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
539     
540     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
541     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
542     
543     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
544     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
545     
546     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
547     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
548     
549     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
550     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
551     
552     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
553     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
554     
555     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
556     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
557     
558     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), 
559     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
560     
561     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
562     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
563     
564     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
565     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
566     
567     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
568     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
569     
570     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
571     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
572     
573     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
574     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
575     
576     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
577     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), 0 },
578     
579     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
580     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
581     
582     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
583     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
584     
585     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
586     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
587     
588     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
589     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
590     
591     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
592     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
593     
594     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
595     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
596     
597     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
598     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
599     
600     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
601     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
602     
603     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
604     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
605     
606     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
607     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
608     
609     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
610     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
611     
612     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
613     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
614     
615     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
616     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
617     
618     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
619     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
620     
621     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
622     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
623     
624     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
625     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
626     
627     	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
628     		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
629     
630     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
631     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), 0 },
632     
633     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
634     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), 0 },
635     
636     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
637     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), 0 },
638     
639     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
640     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
641     
642     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
643     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
644     
645     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
646     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), 0 },
647     
648     	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
649     		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), 0 },
650     
651     	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
652     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
653     
654     	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
655     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
656     
657     	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
658     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
659     
660     	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
661     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
662     
663     	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
664     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
665     
666     	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
667     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
668     
669     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
670     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
671     
672     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
673     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
674     
675     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
676     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
677     
678     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
679     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
680     
681     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
682     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
683     
684     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
685     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
686     
687     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
688     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001), 0 },
689     
690     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
691     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001), 0 },
692     
693     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
694     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
695     
696     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
697     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
698     
699     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
700     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
701     
702     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
703     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
704     
705     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
706     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020), 0 },
707     
708     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
709     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020), 0 },
710     
711     	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
712     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
713     
714     	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
715     		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
716     
717     	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
718     		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
719     
720     	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
721     		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
722     	{0}
723     };
724     
725     MODULE_DEVICE_TABLE(isapnp, id_table);
726     
727     static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
728     {
729     	int err;
730     
731     	/* Device already active? Let's use it */
732     	if(dev->active)
733     		return(dev);
734     	
735     	if((err = dev->activate(dev)) < 0) {
736     		printk(KERN_ERR "sb: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
737     
738     		dev->deactivate(dev);
739     
740     		return(NULL);
741     	}
742     	return(dev);
743     }
744     
745     static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_config, struct address_info *mpu_config, int slot, int card)
746     {
747     
748     	/* Configure Audio device */
749     	if((sb_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].audio_vendor, sb_isapnp_list[slot].audio_function, NULL)))
750     	{
751     		int ret;
752     		ret = sb_dev[card]->prepare(sb_dev[card]);
753     		/* If device is active, assume configured with /proc/isapnp
754     		 * and use anyway. Some other way to check this? */
755     		if(ret && ret != -EBUSY) {
756     			printk(KERN_ERR "sb: ISAPnP found device that could not be autoconfigured.\n");
757     			return(NULL);
758     		}
759     		if(ret == -EBUSY)
760     			audio_activated[card] = 1;
761     		
762     		if((sb_dev[card] = activate_dev(sb_isapnp_list[slot].name, "sb", sb_dev[card])))
763     		{
764     			hw_config->io_base 	= sb_dev[card]->resource[0].start;
765     			hw_config->irq 		= sb_dev[card]->irq_resource[0].start;
766     			hw_config->dma 		= sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma].start;
767     			if(sb_isapnp_list[slot].dma2 != -1)
768     				hw_config->dma2 = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma2].start;
769     			else
770     				hw_config->dma2 = -1;
771     		} else
772     			return(NULL);
773     	} else
774     		return(NULL);
775     
776     	/* Cards with separate OPL3 device (ALS, CMI, etc.)
777     	 * This is just to activate the device so the OPL module can use it */
778     	if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
779     		if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
780     			int ret = opl_dev[card]->prepare(opl_dev[card]);
781     			/* If device is active, assume configured with
782     			 * /proc/isapnp and use anyway */
783     			if(ret && ret != -EBUSY) {
784     				printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n");
785     				return(sb_dev[card]);
786     			}
787     			if(ret == -EBUSY)
788     				opl_activated[card] = 1;
789     
790     			/* Some have irq and dma for opl. the opl3 driver wont
791     			 * use 'em so don't configure 'em and hope it works -PEL */
792     			opl_dev[card]->irq_resource[0].flags = 0;
793     			opl_dev[card]->dma_resource[0].flags = 0;
794     
795     			opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
796     		} else
797     			printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
798     	}
799     
800     	/* Cards with MPU as part of Audio device (CTL and ESS) */
801     	if(!sb_isapnp_list[slot].mpu_vendor) {
802     		mpu_config->io_base	= sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
803     		return(sb_dev[card]);
804     	}
805     	
806     	/* Cards with separate MPU device (ALS, CMI, etc.) */
807     	if(!uart401)
808     		return(sb_dev[card]);
809     	if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL)))
810     	{
811     		int ret = mpu_dev[card]->prepare(mpu_dev[card]);
812     		/* If device is active, assume configured with /proc/isapnp
813     		 * and use anyway */
814     		if(ret && ret != -EBUSY) {
815     			printk(KERN_ERR "sb: MPU device could not be autoconfigured.\n");
816     			return(sb_dev[card]);
817     		}
818     		if(ret == -EBUSY)
819     			mpu_activated[card] = 1;
820     		
821     		/* Some cards ask for irq but don't need them - azummo */
822     		if(sb_isapnp_list[slot].mpu_irq == -1)
823     			mpu_dev[card]->irq_resource[0].flags = 0;
824     		
825     		if((mpu_dev[card] = activate_dev(sb_isapnp_list[slot].name, "mpu", mpu_dev[card]))) {
826     			mpu_config->io_base = mpu_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
827     			if(sb_isapnp_list[slot].mpu_irq != -1)
828     				mpu_config->irq = mpu_dev[card]->irq_resource[sb_isapnp_list[slot].mpu_irq].start;
829     		}
830     	}
831     	else
832     		printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
833     	
834     	return(sb_dev[card]);
835     }
836     
837     static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, int slot, int card)
838     {
839     	char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name;
840     
841     	printk(KERN_INFO "sb: %s detected\n", busname); 
842     
843     	/* Initialize this baby. */
844     
845     	if(sb_init(bus, hw_config, mpu_config, slot, card)) {
846     		/* We got it. */
847     		
848     		printk(KERN_NOTICE "sb: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
849     		       busname,
850     		       hw_config->io_base, hw_config->irq, hw_config->dma,
851     		       hw_config->dma2);
852     		return 1;
853     	}
854     	else
855     		printk(KERN_INFO "sb: Failed to initialize %s\n", busname);
856     
857     	return 0;
858     }
859     
860     static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
861     {
862     	static int first = 1;
863     	int i;
864     
865     	/* Count entries in sb_isapnp_list */
866     	for (i = 0; sb_isapnp_list[i].card_vendor != 0; i++);
867     	i--;
868     
869     	/* Check and adjust isapnpjump */
870     	if( isapnpjump < 0 || isapnpjump > i) {
871     		isapnpjump = reverse ? i : 0;
872     		printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump);
873     	}
874     
875     	if(!first || !reverse)
876     		i = isapnpjump;
877     	first = 0;
878     	while(sb_isapnp_list[i].card_vendor != 0) {
879     		static struct pci_bus *bus = NULL;
880     
881     		while ((bus = isapnp_find_card(
882     				sb_isapnp_list[i].card_vendor,
883     				sb_isapnp_list[i].card_device,
884     				bus))) {
885     	
886     			if(sb_isapnp_init(hw_config, mpu_config, bus, i, card)) {
887     				isapnpjump = i; /* start next search from here */
888     				return 0;
889     			}
890     		}
891     		i += reverse ? -1 : 1;
892     	}
893     
894     	return -ENODEV;
895     }
896     #endif
897     
898     static int __init init_sb(void)
899     {
900     	int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1;
901     
902     	printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
903     	
904     	for(card = 0; card < max; card++, sb_cards_num++) {
905     #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
906     		/* Please remember that even with CONFIG_ISAPNP defined one
907     		 * should still be able to disable PNP support for this 
908     		 * single driver! */
909     		if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
910     			if(!sb_cards_num) {
911     				/* Found no ISAPnP cards, so check for a non-pnp
912     				 * card and set the detection loop for 1 cycle
913     				 */
914     				printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
915     				isapnp = 0;
916     				max = 1;
917     			} else
918     				/* found all the ISAPnP cards so exit the
919     				 * detection loop. */
920     				break;
921     		}
922     #endif
923     
924     		if(!isapnp || (pnplegacy&&card==0)) {
925     			cfg[card].io_base	= io;
926     			cfg[card].irq		= irq;
927     			cfg[card].dma		= dma;
928     			cfg[card].dma2		= dma16;
929     		}
930     
931     		cfg[card].card_subtype = type;
932     
933     		if (!probe_sb(&cfg[card])) {
934     			/* if one or more cards already registered, don't
935     			 * return an error but print a warning. Note, this
936     			 * should never really happen unless the hardware
937     			 * or ISAPnP screwed up. */
938     			if (sb_cards_num) {
939     				printk(KERN_WARNING "sb.c: There was a " 
940     				  "problem probing one of your SoundBlaster " 
941     				  "ISAPnP soundcards. Continuing.\n");
942     				card--;
943     				sb_cards_num--;
944     				continue;
945     			} else if(pnplegacy && isapnp) {
946     				printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " 
947     				  "found.  Continuing with PnP detection.\n");
948     				pnplegacy=0;
949     				card--;
950     				continue;
951     			} else
952     				return -ENODEV;
953     		}
954     		attach_sb_card(&cfg[card]);
955     
956     		if(cfg[card].slots[0]==-1) {
957     			if(card==0 && pnplegacy && isapnp) {
958     				printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " 
959     				  "found.  Continuing with PnP detection.\n");
960     				pnplegacy=0;
961     				card--;
962     				continue;
963     			} else
964     				return -ENODEV;
965     		}
966     		
967     		if (!isapnp||(pnplegacy&&card==0))
968     			cfg_mpu[card].io_base = mpu_io;
969     		if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE))
970     			sbmpu[card] = 1;
971     	}
972     
973     	if(isapnp)
974     		printk(KERN_NOTICE "sb: %d Soundblaster PnP card(s) found.\n", sb_cards_num);
975     
976     	return 0;
977     }
978     
979     static void __exit cleanup_sb(void)
980     {
981     	int i;
982     	
983     	if (smw_free) {
984     		vfree(smw_free);
985     		smw_free = NULL;
986     	}
987     
988     	for(i = 0; i < sb_cards_num; i++) {
989     		unload_sb(&cfg[i], i);
990     		if (sbmpu[i])
991     			unload_sbmpu(&cfg_mpu[i]);
992     
993     #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
994     		if(!audio_activated[i] && sb_dev[i])
995     			sb_dev[i]->deactivate(sb_dev[i]);
996     		if(!mpu_activated[i] && mpu_dev[i])
997     			mpu_dev[i]->deactivate(mpu_dev[i]);
998     		if(!opl_activated[i] && opl_dev[i])
999     			opl_dev[i]->deactivate(opl_dev[i]);
1000     #endif
1001     	}
1002     }
1003     
1004     module_init(init_sb);
1005     module_exit(cleanup_sb);
1006     
1007     #ifndef MODULE
1008     static int __init setup_sb(char *str)
1009     {
1010     	/* io, irq, dma, dma2 - just the basics */
1011     	int ints[5];
1012     	
1013     	str = get_options(str, ARRAY_SIZE(ints), ints);
1014     	
1015     	io	= ints[1];
1016     	irq	= ints[2];
1017     	dma	= ints[3];
1018     	dma16	= ints[4];
1019     
1020     	return 1;
1021     }
1022     __setup("sb=", setup_sb);
1023     #endif
1024