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