~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/sound/sb_card.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 Vibra16S", 
302                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
303                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
304                 0,0,0,0,
305                 0,1,1,-1},
306         {"Sound Blaster Vibra16C", 
307                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
308                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
309                 0,0,0,0,
310                 0,1,1,-1},
311         {"Sound Blaster Vibra16CL", 
312                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
313                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
314                 0,0,0,0,
315                 0,1,1,-1},
316         {"Sound Blaster Vibra16X", 
317                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
318                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
319                 0,0,0,0,
320                 0,1,1,-1},
321         {"Sound Blaster AWE 32", 
322                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
323                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
324                 0,0,0,0,
325                 0,1,1,-1},
326         {"Sound Blaster AWE 32",
327                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
328                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
329                 0,0,0,0,
330                 0,1,1,-1},
331         {"Sound Blaster AWE 32",
332                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
333                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
334                 0,0,0,0,
335                 0,1,1,-1},
336         {"Sound Blaster AWE 32",
337                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
338                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
339                 0,0,0,0,
340                 0,1,1,-1},
341         {"Sound Blaster AWE 32",
342                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
343                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
344                 0,0,0,0,
345                 0,1,1,-1},
346         {"Sound Blaster AWE 32",
347                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
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(0x009C), 
353                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
354                 0,0,0,0,
355                 0,1,1,-1},
356         {"Creative SB32 PnP",
357                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
358                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
359                 0,0,0,0,
360                 0,1,1,-1},
361         {"Sound Blaster AWE 64",
362                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
363                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
364                 0,0,0,0,
365                 0,1,1,-1},
366         {"Sound Blaster AWE 64 Gold",
367                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
368                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
369                 0,0,0,0,
370                 0,1,1,-1},
371         {"Sound Blaster AWE 64 Gold",
372                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
373                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
374                 0,0,0,0,
375                 0,1,1,-1},
376         {"Sound Blaster AWE 64",
377                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
378                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
379                 0,0,0,0,
380                 0,1,1,-1},
381         {"Sound Blaster AWE 64",
382                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
383                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
384                 0,0,0,0,
385                 0,1,1,-1},
386         {"Sound Blaster AWE 64",
387                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
388                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
389                 0,0,0,0,
390                 0,1,1,-1},
391         {"Sound Blaster AWE 64",
392                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
393                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
394                 0,0,0,0,
395                 0,1,1,-1},
396         {"Sound Blaster AWE 64",
397                 ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
398                 ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
399                 0,0,0,0,
400                 0,1,1,-1},
401         {"ESS 1688",
402                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
403                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
404                 0,0,0,0,
405                 0,1,2,-1},
406         {"ESS 1868",
407                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
408                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
409                 0,0,0,0,
410                 0,1,2,-1},
411         {"ESS 1868",
412                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
413                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
414                 0,0,0,0,
415                 0,1,2,-1},
416         {"ESS 1869 PnP AudioDrive", 
417                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
418                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
419                 0,0,0,0,
420                 0,1,2,-1},
421         {"ESS 1869",
422                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
423                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
424                 0,0,0,0,
425                 0,1,2,-1},
426         {"ESS 1878",
427                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
428                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
429                 0,0,0,0,
430                 0,1,2,-1},
431         {"ESS 1879",
432                 ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
433                 ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
434                 0,0,0,0,
435                 0,1,2,-1},
436         {"CMI 8330 SoundPRO",
437                 ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
438                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
439                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
440                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
441                 0,1,0,-1},
442         {"Diamond DT0197H",
443                 ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
444                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
445                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
446                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
447                 0,-1,0,0},
448         {"ALS007",
449                 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
450                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
451                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
452                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
453                 0,-1,0,0},
454         {"ALS100",
455                 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
456                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
457                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
458                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
459                 1,0,0,0},
460         {"ALS110",
461                 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
462                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001),
463                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001),
464                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
465                 1,0,0,0},
466         {"ALS120",
467                 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
468                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
469                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
470                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
471                 1,0,0,0},
472         {"ALS200",
473                 ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
474                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020),
475                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020),
476                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
477                 1,0,0,0},
478         {"RTL3000",
479                 ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
480                 ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
481                 ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
482                 ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
483                 1,0,0,0},
484         {0}
485 };
486 
487 static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
488 {
489         int err;
490 
491         /* Device already active? Let's use it */
492         if(dev->active)
493                 return(dev);
494         
495         if((err = dev->activate(dev)) < 0) {
496                 printk(KERN_ERR "sb: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
497 
498                 dev->deactivate(dev);
499 
500                 return(NULL);
501         }
502         return(dev);
503 }
504 
505 static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_config, struct address_info *mpu_config, int slot, int card)
506 {
507 
508         /* Configure Audio device */
509         if((sb_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].audio_vendor, sb_isapnp_list[slot].audio_function, NULL)))
510         {
511                 int ret;
512                 ret = sb_dev[card]->prepare(sb_dev[card]);
513                 /* If device is active, assume configured with /proc/isapnp
514                  * and use anyway. Some other way to check this? */
515                 if(ret && ret != -EBUSY) {
516                         printk(KERN_ERR "sb: ISAPnP found device that could not be autoconfigured.\n");
517                         return(NULL);
518                 }
519                 if(ret == -EBUSY)
520                         audio_activated[card] = 1;
521                 
522                 if((sb_dev[card] = activate_dev(sb_isapnp_list[slot].name, "sb", sb_dev[card])))
523                 {
524                         hw_config->io_base      = sb_dev[card]->resource[0].start;
525                         hw_config->irq          = sb_dev[card]->irq_resource[0].start;
526                         hw_config->dma          = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma].start;
527                         if(sb_isapnp_list[slot].dma2 != -1)
528                                 hw_config->dma2 = sb_dev[card]->dma_resource[sb_isapnp_list[slot].dma2].start;
529                         else
530                                 hw_config->dma2 = -1;
531                 } else
532                         return(NULL);
533         } else
534                 return(NULL);
535 
536         /* Cards with separate OPL3 device (ALS, CMI, etc.)
537          * This is just to activate the device so the OPL module can use it */
538         if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
539                 if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
540                         int ret = opl_dev[card]->prepare(opl_dev[card]);
541                         /* If device is active, assume configured with
542                          * /proc/isapnp and use anyway */
543                         if(ret && ret != -EBUSY) {
544                                 printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n");
545                                 return(sb_dev[card]);
546                         }
547                         if(ret == -EBUSY)
548                                 opl_activated[card] = 1;
549 
550                         /* Some have irq and dma for opl. the opl3 driver wont
551                          * use 'em so don't configure 'em and hope it works -PEL */
552                         opl_dev[card]->irq_resource[0].flags = 0;
553                         opl_dev[card]->dma_resource[0].flags = 0;
554 
555                         opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
556                 } else
557                         printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
558         }
559 
560         /* Cards with MPU as part of Audio device (CTL and ESS) */
561         if(!sb_isapnp_list[slot].mpu_vendor) {
562                 mpu_config->io_base     = sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
563                 return(sb_dev[card]);
564         }
565         
566         /* Cards with separate MPU device (ALS, CMI, etc.) */
567         if(!uart401)
568                 return(sb_dev[card]);
569         if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL)))
570         {
571                 int ret = mpu_dev[card]->prepare(mpu_dev[card]);
572                 /* If device is active, assume configured with /proc/isapnp
573                  * and use anyway */
574                 if(ret && ret != -EBUSY) {
575                         printk(KERN_ERR "sb: MPU device could not be autoconfigured.\n");
576                         return(sb_dev[card]);
577                 }
578                 if(ret == -EBUSY)
579                         mpu_activated[card] = 1;
580                 
581                 /* Some cards ask for irq but don't need them - azummo */
582                 if(sb_isapnp_list[slot].mpu_irq == -1)
583                         mpu_dev[card]->irq_resource[0].flags = 0;
584                 
585                 if((mpu_dev[card] = activate_dev(sb_isapnp_list[slot].name, "mpu", mpu_dev[card]))) {
586                         mpu_config->io_base = mpu_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
587                         if(sb_isapnp_list[slot].mpu_irq != -1)
588                                 mpu_config->irq = mpu_dev[card]->irq_resource[sb_isapnp_list[slot].mpu_irq].start;
589                 }
590         }
591         else
592                 printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
593         
594         return(sb_dev[card]);
595 }
596 
597 static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, int slot, int card)
598 {
599         char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name;
600 
601         printk(KERN_INFO "sb: %s detected\n", busname); 
602 
603         /* Initialize this baby. */
604 
605         if(sb_init(bus, hw_config, mpu_config, slot, card)) {
606                 /* We got it. */
607                 
608                 printk(KERN_NOTICE "sb: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
609                        busname,
610                        hw_config->io_base, hw_config->irq, hw_config->dma,
611                        hw_config->dma2);
612                 return 1;
613         }
614         else
615                 printk(KERN_INFO "sb: Failed to initialize %s\n", busname);
616 
617         return 0;
618 }
619 
620 static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
621 {
622         static int first = 1;
623         int i;
624 
625         /* Count entries in sb_isapnp_list */
626         for (i = 0; sb_isapnp_list[i].card_vendor != 0; i++);
627         i--;
628 
629         /* Check and adjust isapnpjump */
630         if( isapnpjump < 0 || isapnpjump > i) {
631                 isapnpjump = reverse ? i : 0;
632                 printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump);
633         }
634 
635         if(!first || !reverse)
636                 i = isapnpjump;
637         first = 0;
638         while(sb_isapnp_list[i].card_vendor != 0) {
639                 static struct pci_bus *bus = NULL;
640 
641                 while ((bus = isapnp_find_card(
642                                 sb_isapnp_list[i].card_vendor,
643                                 sb_isapnp_list[i].card_device,
644                                 bus))) {
645         
646                         if(sb_isapnp_init(hw_config, mpu_config, bus, i, card)) {
647                                 isapnpjump = i; /* start next search from here */
648                                 return 0;
649                         }
650                 }
651                 i += reverse ? -1 : 1;
652         }
653 
654         return -ENODEV;
655 }
656 #endif
657 
658 static int __init init_sb(void)
659 {
660         int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1;
661 
662         printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
663         
664         for(card = 0; card < max; card++, sb_cards_num++) {
665 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
666                 /* Please remember that even with CONFIG_ISAPNP defined one
667                  * should still be able to disable PNP support for this 
668                  * single driver! */
669                 if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
670                         if(!sb_cards_num) {
671                                 /* Found no ISAPnP cards, so check for a non-pnp
672                                  * card and set the detection loop for 1 cycle
673                                  */
674                                 printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
675                                 isapnp = 0;
676                                 max = 1;
677                         } else
678                                 /* found all the ISAPnP cards so exit the
679                                  * detection loop. */
680                                 break;
681                 }
682 #endif
683 
684                 if(!isapnp || (pnplegacy&&card==0)) {
685                         cfg[card].io_base       = io;
686                         cfg[card].irq           = irq;
687                         cfg[card].dma           = dma;
688                         cfg[card].dma2          = dma16;
689                 }
690 
691                 cfg[card].card_subtype = type;
692 
693                 if (!probe_sb(&cfg[card])) {
694                         /* if one or more cards already registered, don't
695                          * return an error but print a warning. Note, this
696                          * should never really happen unless the hardware
697                          * or ISAPnP screwed up. */
698                         if (sb_cards_num) {
699                                 printk(KERN_WARNING "sb.c: There was a " \
700                                   "problem probing one of your SoundBlaster " \
701                                   "ISAPnP soundcards. Continuing.\n");
702                                 card--;
703                                 sb_cards_num--;
704                                 continue;
705                         } else if(pnplegacy && isapnp) {
706                                 printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \
707                                   "found.  Continuing with PnP detection.\n");
708                                 pnplegacy=0;
709                                 card--;
710                                 continue;
711                         } else
712                                 return -ENODEV;
713                 }
714                 attach_sb_card(&cfg[card]);
715 
716                 if(cfg[card].slots[0]==-1) {
717                         if(card==0 && pnplegacy && isapnp) {
718                                 printk(KERN_NOTICE "sb: No legacy SoundBlaster cards " \
719                                   "found.  Continuing with PnP detection.\n");
720                                 pnplegacy=0;
721                                 card--;
722                                 continue;
723                         } else
724                                 return -ENODEV;
725                 }
726                 
727                 if (!isapnp||(pnplegacy&&card==0))
728                         cfg_mpu[card].io_base = mpu_io;
729                 if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE))
730                         sbmpu[card] = 1;
731         }
732 
733         if(isapnp)
734                 printk(KERN_NOTICE "sb: %d Soundblaster PnP card(s) found.\n", sb_cards_num);
735 
736         return 0;
737 }
738 
739 static void __exit cleanup_sb(void)
740 {
741         int i;
742         
743         if (smw_free) {
744                 vfree(smw_free);
745                 smw_free = NULL;
746         }
747 
748         for(i = 0; i < sb_cards_num; i++) {
749                 unload_sb(&cfg[i], i);
750                 if (sbmpu[i])
751                         unload_sbmpu(&cfg_mpu[i]);
752 
753 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
754                 if(!audio_activated[i] && sb_dev[i])
755                         sb_dev[i]->deactivate(sb_dev[i]);
756                 if(!mpu_activated[i] && mpu_dev[i])
757                         mpu_dev[i]->deactivate(mpu_dev[i]);
758                 if(!opl_activated[i] && opl_dev[i])
759                         opl_dev[i]->deactivate(opl_dev[i]);
760 #endif
761         }
762 }
763 
764 module_init(init_sb);
765 module_exit(cleanup_sb);
766 
767 #ifndef MODULE
768 static int __init setup_sb(char *str)
769 {
770         /* io, irq, dma, dma2 - just the basics */
771         int ints[5];
772         
773         str = get_options(str, ARRAY_SIZE(ints), ints);
774         
775         io      = ints[1];
776         irq     = ints[2];
777         dma     = ints[3];
778         dma16   = ints[4];
779 
780         return 1;
781 }
782 __setup("sb=", setup_sb);
783 #endif
784 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.