4 * Detection routine for the Sound Blaster cards.
7 * Copyright (C) by Hannu Savolainen 1993-1997
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
13 * 26-11-1999 Patched to compile without ISA PnP support in the
14 * kernel - Daniel Stone (tamriel@ductape.net)
16 * 06-01-2000 Refined and bugfixed ISA PnP support, added
17 * CMI 8330 support - Alessandro Zummo <azummo@ita.flashnet.it>
19 * 18-01-2000 Separated sb_card and sb_common
20 * Jeff Garzik <jgarzik@pobox.com>
22 * 04-02-2000 Added Soundblaster AWE 64 PnP support, isapnpjump
23 * Alessandro Zummo <azummo@ita.flashnet.it>
25 * 11-02-2000 Added Soundblaster AWE 32 PnP support, refined PnP code
26 * Alessandro Zummo <azummo@ita.flashnet.it>
28 * 13-02-2000 Hopefully fixed awe/sb16 related bugs, code cleanup
29 * Alessandro Zummo <azummo@ita.flashnet.it>
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>
36 * 26-03-2000 Fixed acer, esstype and sm_games module options.
37 * Alessandro Zummo <azummo@ita.flashnet.it>
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>
43 * 06-05-2000 added another card. Daniel M. Newman <dmnewman@pobox.com>
45 * 25-05-2000 Added Creative SB AWE64 Gold (CTL00B2).
46 * Pål-Kristian Engstad <engstad@att.net>
48 * 12-08-2000 Added Creative SB32 PnP (CTL009F).
49 * Kasatenko Ivan Alex. <skywriter@rnc.ru>
51 * 21-09-2000 Got rid of attach_sbmpu
52 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
54 * 28-10-2000 Added pnplegacy support
55 * Daniel Church <dchurch@mbhs.edu>
57 * 01-10-2001 Added a new flavor of Creative SB AWE64 PnP (CTL00E9).
58 * Jerome Cornet <jcornet@free.fr>
61 #include <linux/config.h>
62 #include <linux/mca.h>
63 #include <linux/module.h>
64 #include <linux/init.h>
65 #include <linux/isapnp.h>
67 #include "sound_config.h"
72 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
73 #define SB_CARDS_MAX 5
75 #define SB_CARDS_MAX 1
78 static int sbmpu[SB_CARDS_MAX] = {0};
79 static int sb_cards_num = 0;
81 extern void *smw_free;
84 * Note DMA2 of -1 has the right meaning in the SB16 driver as well
85 * as here. It will cause either an error if it is needed or a fallback
86 * to the 8bit channel.
89 static int __initdata mpu_io = 0;
90 static int __initdata io = -1;
91 static int __initdata irq = -1;
92 static int __initdata dma = -1;
93 static int __initdata dma16 = -1; /* Set this for modules that need it */
94 static int __initdata type = 0; /* Can set this to a specific card type */
95 static int __initdata esstype = 0; /* ESS chip type */
96 static int __initdata acer = 0; /* Do acer notebook init? */
97 static int __initdata sm_games = 0; /* Logitech soundman games? */
99 static void __init attach_sb_card(struct address_info *hw_config)
101 if(!sb_dsp_init(hw_config, THIS_MODULE))
102 hw_config->slots[0] = -1;
105 static int __init probe_sb(struct address_info *hw_config)
107 struct sb_module_options sbmo;
109 if (hw_config->io_base == -1 || hw_config->dma == -1 || hw_config->irq == -1)
111 printk(KERN_ERR "sb: I/O, IRQ, and DMA are mandatory\n");
116 /* MCA code added by ZP Gu (zpg@castle.net) */
117 if (MCA_bus) { /* no multiple REPLY card probing */
121 slot = mca_find_adapter( 0x5138, 0 );
122 if( slot == MCA_NOTFOUND )
124 slot = mca_find_adapter( 0x5137, 0 );
126 if (slot != MCA_NOTFOUND)
127 mca_set_adapter_name( slot, "REPLY SB16 & SCSI Adapter" );
131 mca_set_adapter_name( slot, "REPLY SB16 Adapter" );
134 if (slot != MCA_NOTFOUND)
136 mca_mark_as_used(slot);
137 pos2 = mca_read_stored_pos( slot, 2 );
138 pos3 = mca_read_stored_pos( slot, 3 );
139 pos4 = mca_read_stored_pos( slot, 4 );
144 static unsigned short irq[] = { 0, 5, 7, 10 };
146 static unsigned short midiaddr[] = {0, 0x330, 0, 0x300 };
149 hw_config->io_base = 0x220 + 0x20 * (pos2 >> 6);
150 hw_config->irq = irq[(pos4 >> 5) & 0x3];
151 hw_config->dma = pos3 & 0xf;
152 /* Reply ADF wrong on High DMA, pos[1] should start w/ 00 */
153 hw_config->dma2 = (pos3 >> 4) & 0x3;
154 if (hw_config->dma2 == 0)
155 hw_config->dma2 = hw_config->dma;
157 hw_config->dma2 += 4;
159 hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3];
162 printk(KERN_INFO "sb: Reply MCA SB at slot=%d \
163 iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
165 hw_config->io_base, hw_config->irq,
166 hw_config->dma, hw_config->dma2);
170 printk (KERN_INFO "sb: Reply SB Base I/O address disabled\n");
176 /* Setup extra module options */
179 sbmo.sm_games = sm_games;
180 sbmo.esstype = esstype;
182 return sb_dsp_detect(hw_config, 0, 0, &sbmo);
185 static void __exit unload_sb(struct address_info *hw_config, int card)
187 if(hw_config->slots[0]!=-1)
188 sb_dsp_unload(hw_config, sbmpu[card]);
191 static struct address_info cfg[SB_CARDS_MAX];
192 static struct address_info cfg_mpu[SB_CARDS_MAX];
194 struct pci_dev *sb_dev[SB_CARDS_MAX] = {NULL},
195 *mpu_dev[SB_CARDS_MAX] = {NULL},
196 *opl_dev[SB_CARDS_MAX] = {NULL};
199 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
200 static int isapnp = 1;
201 static int isapnpjump = 0;
202 static int multiple = 1;
203 static int pnplegacy = 0;
204 static int reverse = 0;
205 static int uart401 = 0;
207 static int audio_activated[SB_CARDS_MAX] = {0};
208 static int mpu_activated[SB_CARDS_MAX] = {0};
209 static int opl_activated[SB_CARDS_MAX] = {0};
211 static int isapnp = 0;
212 static int multiple = 0;
213 static int pnplegacy = 0;
216 MODULE_DESCRIPTION("Soundblaster driver");
217 MODULE_LICENSE("GPL");
219 MODULE_PARM(io, "i");
220 MODULE_PARM(irq, "i");
221 MODULE_PARM(dma, "i");
222 MODULE_PARM(dma16, "i");
223 MODULE_PARM(mpu_io, "i");
224 MODULE_PARM(type, "i");
225 MODULE_PARM(sm_games, "i");
226 MODULE_PARM(esstype, "i");
227 MODULE_PARM(acer, "i");
229 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
230 MODULE_PARM(isapnp, "i");
231 MODULE_PARM(isapnpjump, "i");
232 MODULE_PARM(multiple, "i");
233 MODULE_PARM(pnplegacy, "i");
234 MODULE_PARM(reverse, "i");
235 MODULE_PARM(uart401, "i");
236 MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled");
237 MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
238 MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");
239 MODULE_PARM_DESC(pnplegacy, "When set to 1, will search for a legacy SB card along with any PnP cards.");
240 MODULE_PARM_DESC(reverse, "When set to 1, will reverse ISAPnP search order");
241 MODULE_PARM_DESC(uart401, "When set to 1, will attempt to detect and enable the mpu on some clones");
244 MODULE_PARM_DESC(io, "Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
245 MODULE_PARM_DESC(irq, "IRQ (5,7,9,10)");
246 MODULE_PARM_DESC(dma, "8-bit DMA channel (0,1,3)");
247 MODULE_PARM_DESC(dma16, "16-bit DMA channel (5,6,7)");
248 MODULE_PARM_DESC(mpu_io, "Mpu base address");
249 MODULE_PARM_DESC(type, "You can set this to specific card type");
250 MODULE_PARM_DESC(sm_games, "Enable support for Logitech soundman games");
251 MODULE_PARM_DESC(esstype, "ESS chip type");
252 MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks");
254 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
256 /* Please add new entries at the end of the table */
259 unsigned short card_vendor, card_device,
260 audio_vendor, audio_function,
261 mpu_vendor, mpu_function,
262 opl_vendor, opl_function;
263 short dma, dma2, mpu_io, mpu_irq; /* see sb_init() */
264 } sb_isapnp_list[] __initdata = {
266 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
267 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
271 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
272 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
276 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026),
277 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
281 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027),
282 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
286 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028),
287 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
291 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029),
292 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
296 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
297 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
301 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b),
302 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
306 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c),
307 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
311 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c),
312 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
316 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed),
317 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
321 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086),
322 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
326 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086),
327 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
330 {"Sound Blaster Vibra16S",
331 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051),
332 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
335 {"Sound Blaster Vibra16C",
336 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070),
337 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
340 {"Sound Blaster Vibra16CL",
341 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080),
342 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
345 {"Sound Blaster Vibra16X",
346 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0),
347 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
350 {"Sound Blaster AWE 32",
351 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039),
352 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
355 {"Sound Blaster AWE 32",
356 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
357 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
360 {"Sound Blaster AWE 32",
361 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
362 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
365 {"Sound Blaster AWE 32",
366 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
367 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
370 {"Sound Blaster AWE 32",
371 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
372 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
375 {"Sound Blaster AWE 32",
376 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0046),
377 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
380 {"Sound Blaster AWE 32",
381 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
382 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
385 {"Sound Blaster AWE 32",
386 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048),
387 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
390 {"Sound Blaster AWE 32",
391 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054),
392 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
395 {"Sound Blaster AWE 32",
396 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C),
397 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
400 {"Creative SB32 PnP",
401 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
402 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
405 {"Sound Blaster AWE 64",
406 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D),
407 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
410 {"Sound Blaster AWE 64 Gold",
411 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E),
412 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
415 {"Sound Blaster AWE 64 Gold",
416 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
417 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
420 {"Sound Blaster AWE 64",
421 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1),
422 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
425 {"Sound Blaster AWE 64",
426 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3),
427 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
430 {"Sound Blaster AWE 64",
431 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5),
432 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
435 {"Sound Blaster AWE 64",
436 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7),
437 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
440 {"Sound Blaster AWE 64",
441 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4),
442 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
445 {"Sound Blaster AWE 64",
446 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9),
447 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
451 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968),
452 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
456 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868),
457 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
461 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868),
462 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
465 {"ESS 1869 PnP AudioDrive",
466 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003),
467 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
471 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869),
472 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
476 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878),
477 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
481 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879),
482 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
485 {"CMI 8330 SoundPRO",
486 ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
487 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
488 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
489 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
492 ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688),
493 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
494 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
495 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
498 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
499 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
500 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
501 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
504 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001),
505 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
506 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
507 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
510 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
511 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001),
512 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001),
513 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
516 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
517 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
518 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
519 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
522 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
523 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020),
524 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020),
525 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
528 ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
529 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
530 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
531 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
536 static struct isapnp_device_id id_table[] __devinitdata = {
537 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
538 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
540 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
541 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
543 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026),
544 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
546 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027),
547 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
549 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028),
550 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
552 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029),
553 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
555 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
556 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
558 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b),
559 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
561 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c),
562 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
564 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c),
565 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
567 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed),
568 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
570 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086),
571 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
573 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086),
574 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
576 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051),
577 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
579 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070),
580 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
582 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080),
583 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
585 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0),
586 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), 0 },
588 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039),
589 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
591 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
592 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
594 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
595 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
597 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
598 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
600 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
601 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
603 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048),
604 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
606 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054),
607 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
609 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C),
610 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
612 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
613 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
615 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D),
616 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
618 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E),
619 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
621 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
622 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
624 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1),
625 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
627 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3),
628 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
630 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5),
631 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
633 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7),
634 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
636 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4),
637 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
639 { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9),
640 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
642 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968),
643 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), 0 },
645 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868),
646 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), 0 },
648 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868),
649 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), 0 },
651 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003),
652 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
654 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869),
655 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
657 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878),
658 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), 0 },
660 { ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879),
661 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), 0 },
663 { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
664 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
666 { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
667 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
669 { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
670 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
672 { ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688),
673 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
675 { ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688),
676 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
678 { ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688),
679 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
681 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
682 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
684 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
685 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
687 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
688 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
690 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001),
691 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
693 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001),
694 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
696 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001),
697 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
699 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
700 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001), 0 },
702 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
703 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001), 0 },
705 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
706 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
708 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
709 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
711 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
712 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
714 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
715 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
717 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
718 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020), 0 },
720 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
721 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020), 0 },
723 { ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
724 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
726 { ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
727 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
729 { ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
730 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
732 { ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
733 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
737 MODULE_DEVICE_TABLE(isapnp, id_table);
739 static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
743 /* Device already active? Let's use it */
747 if((err = dev->activate(dev)) < 0) {
748 printk(KERN_ERR "sb: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
750 dev->deactivate(dev);
757 static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_config, struct address_info *mpu_config, int slot, int card)
760 /* Configure Audio device */
761 if((sb_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].audio_vendor, sb_isapnp_list[slot].audio_function, NULL)))
764 ret = sb_dev[card]->prepare(sb_dev[card]);
765 /* If device is active, assume configured with /proc/isapnp
766 * and use anyway. Some other way to check this? */
767 if(ret && ret != -EBUSY) {
768 printk(KERN_ERR "sb: ISAPnP found device that could not be autoconfigured.\n");
772 audio_activated[card] = 1;
774 if((sb_dev[card] = activate_dev(sb_isapnp_list[slot].name, "sb", sb_dev[card])))
776 hw_config->io_base = sb_dev[card]->resource[0].start;
777 hw_config->irq = sb_dev[card]->irq_resource[0].start;
778 hw_config->dma = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma].start;
779 if(sb_isapnp_list[slot].dma2 != -1)
780 hw_config->dma2 = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma2].start;
782 hw_config->dma2 = -1;
788 /* Cards with separate OPL3 device (ALS, CMI, etc.)
789 * This is just to activate the device so the OPL module can use it */
790 if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
791 if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
792 int ret = opl_dev[card]->prepare(opl_dev[card]);
793 /* If device is active, assume configured with
794 * /proc/isapnp and use anyway */
795 if(ret && ret != -EBUSY) {
796 printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n");
797 return(sb_dev[card]);
800 opl_activated[card] = 1;
802 /* Some have irq and dma for opl. the opl3 driver wont
803 * use 'em so don't configure 'em and hope it works -PEL */
804 opl_dev[card]->irq_resource[0].flags = 0;
805 opl_dev[card]->dma_resource[0].flags = 0;
807 opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
809 printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
812 /* Cards with MPU as part of Audio device (CTL and ESS) */
813 if(!sb_isapnp_list[slot].mpu_vendor) {
814 mpu_config->io_base = sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
815 return(sb_dev[card]);
818 /* Cards with separate MPU device (ALS, CMI, etc.) */
820 return(sb_dev[card]);
821 if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL)))
823 int ret = mpu_dev[card]->prepare(mpu_dev[card]);
824 /* If device is active, assume configured with /proc/isapnp
826 if(ret && ret != -EBUSY) {
827 printk(KERN_ERR "sb: MPU device could not be autoconfigured.\n");
828 return(sb_dev[card]);
831 mpu_activated[card] = 1;
833 /* Some cards ask for irq but don't need them - azummo */
834 if(sb_isapnp_list[slot].mpu_irq == -1)
835 mpu_dev[card]->irq_resource[0].flags = 0;
837 if((mpu_dev[card] = activate_dev(sb_isapnp_list[slot].name, "mpu", mpu_dev[card]))) {
838 mpu_config->io_base = mpu_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
839 if(sb_isapnp_list[slot].mpu_irq != -1)
840 mpu_config->irq = mpu_dev[card]->irq_resource[sb_isapnp_list[slot].mpu_irq].start;
844 printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
846 return(sb_dev[card]);
849 static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, int slot, int card)
851 char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name;
853 printk(KERN_INFO "sb: %s detected\n", busname);
855 /* Initialize this baby. */
857 if(sb_init(bus, hw_config, mpu_config, slot, card)) {
860 printk(KERN_NOTICE "sb: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
862 hw_config->io_base, hw_config->irq, hw_config->dma,
867 printk(KERN_INFO "sb: Failed to initialize %s\n", busname);
872 static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
874 static int first = 1;
877 /* Count entries in sb_isapnp_list */
878 for (i = 0; sb_isapnp_list[i].card_vendor != 0; i++);
881 /* Check and adjust isapnpjump */
882 if( isapnpjump < 0 || isapnpjump > i) {
883 isapnpjump = reverse ? i : 0;
884 printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump);
887 if(!first || !reverse)
890 while(sb_isapnp_list[i].card_vendor != 0) {
891 static struct pci_bus *bus = NULL;
893 while ((bus = isapnp_find_card(
894 sb_isapnp_list[i].card_vendor,
895 sb_isapnp_list[i].card_device,
898 if(sb_isapnp_init(hw_config, mpu_config, bus, i, card)) {
899 isapnpjump = i; /* start next search from here */
903 i += reverse ? -1 : 1;
910 static int __init init_sb(void)
912 int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1;
914 printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
916 for(card = 0; card < max; card++, sb_cards_num++) {
917 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
918 /* Please remember that even with CONFIG_ISAPNP defined one
919 * should still be able to disable PNP support for this
921 if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
923 /* Found no ISAPnP cards, so check for a non-pnp
924 * card and set the detection loop for 1 cycle
926 printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
930 /* found all the ISAPnP cards so exit the
936 if(!isapnp || (pnplegacy&&card==0)) {
937 cfg[card].io_base = io;
940 cfg[card].dma2 = dma16;
943 cfg[card].card_subtype = type;
945 if (!probe_sb(&cfg[card])) {
946 /* if one or more cards already registered, don't
947 * return an error but print a warning. Note, this
948 * should never really happen unless the hardware
949 * or ISAPnP screwed up. */
951 printk(KERN_WARNING "sb.c: There was a " \
952 "problem probing one of your SoundBlaster " \
953 "ISAPnP soundcards. Continuing.\n");
957 } else if(pnplegacy && isapnp) {
958 printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \
959 "found. Continuing with PnP detection.\n");
966 attach_sb_card(&cfg[card]);
968 if(cfg[card].slots[0]==-1) {
969 if(card==0 && pnplegacy && isapnp) {
970 printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \
971 "found. Continuing with PnP detection.\n");
979 if (!isapnp||(pnplegacy&&card==0))
980 cfg_mpu[card].io_base = mpu_io;
981 if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE))
986 printk(KERN_NOTICE "sb: %d Soundblaster PnP card(s) found.\n", sb_cards_num);
991 static void __exit cleanup_sb(void)
1000 for(i = 0; i < sb_cards_num; i++) {
1001 unload_sb(&cfg[i], i);
1003 unload_sbmpu(&cfg_mpu[i]);
1005 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
1006 if(!audio_activated[i] && sb_dev[i])
1007 sb_dev[i]->deactivate(sb_dev[i]);
1008 if(!mpu_activated[i] && mpu_dev[i])
1009 mpu_dev[i]->deactivate(mpu_dev[i]);
1010 if(!opl_activated[i] && opl_dev[i])
1011 opl_dev[i]->deactivate(opl_dev[i]);
1016 module_init(init_sb);
1017 module_exit(cleanup_sb);
1020 static int __init setup_sb(char *str)
1022 /* io, irq, dma, dma2 - just the basics */
1025 str = get_options(str, ARRAY_SIZE(ints), ints);
1034 __setup("sb=", setup_sb);