linux-old/drivers/sound/sb_card.c
<<
>>
Prefs
   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@pobox.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 * 01-10-2001 Added a new flavor of Creative SB AWE64 PnP (CTL00E9).
  58 *      Jerome Cornet <jcornet@free.fr>
  59 */
  60
  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>
  66
  67#include "sound_config.h"
  68
  69#include "sb_mixer.h"
  70#include "sb.h"
  71
  72#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
  73#define SB_CARDS_MAX 5
  74#else
  75#define SB_CARDS_MAX 1
  76#endif
  77
  78static int sbmpu[SB_CARDS_MAX] = {0};
  79static int sb_cards_num = 0;
  80
  81extern void *smw_free;
  82
  83/*
  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.
  87 */
  88
  89static int __initdata mpu_io    = 0;
  90static int __initdata io        = -1;
  91static int __initdata irq       = -1;
  92static int __initdata dma       = -1;
  93static int __initdata dma16     = -1;   /* Set this for modules that need it */
  94static int __initdata type      = 0;    /* Can set this to a specific card type */
  95static int __initdata esstype   = 0;    /* ESS chip type */
  96static int __initdata acer      = 0;    /* Do acer notebook init? */
  97static int __initdata sm_games  = 0;    /* Logitech soundman games? */
  98
  99static void __init attach_sb_card(struct address_info *hw_config)
 100{
 101        if(!sb_dsp_init(hw_config, THIS_MODULE))
 102                hw_config->slots[0] = -1;
 103}
 104
 105static int __init probe_sb(struct address_info *hw_config)
 106{
 107        struct sb_module_options sbmo;
 108
 109        if (hw_config->io_base == -1 || hw_config->dma == -1 || hw_config->irq == -1)
 110        {
 111                printk(KERN_ERR "sb: I/O, IRQ, and DMA are mandatory\n");
 112                return -EINVAL;
 113        }
 114
 115#ifdef CONFIG_MCA
 116        /* MCA code added by ZP Gu (zpg@castle.net) */
 117        if (MCA_bus) {               /* no multiple REPLY card probing */
 118                int slot;
 119                u8 pos2, pos3, pos4;
 120
 121                slot = mca_find_adapter( 0x5138, 0 );
 122                if( slot == MCA_NOTFOUND ) 
 123                {
 124                        slot = mca_find_adapter( 0x5137, 0 );
 125
 126                        if (slot != MCA_NOTFOUND)
 127                                mca_set_adapter_name( slot, "REPLY SB16 & SCSI Adapter" );
 128                }
 129                else
 130                {
 131                        mca_set_adapter_name( slot, "REPLY SB16 Adapter" );
 132                }
 133
 134                if (slot != MCA_NOTFOUND) 
 135                {
 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 );
 140
 141                        if (pos2 & 0x4) 
 142                        {
 143                                /* enabled? */
 144                                static unsigned short irq[] = { 0, 5, 7, 10 };
 145                                /*
 146                                static unsigned short midiaddr[] = {0, 0x330, 0, 0x300 };
 147                                */
 148
 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;
 156                                else
 157                                        hw_config->dma2 += 4;
 158                                /*
 159                                        hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3];
 160                                */
 161        
 162                                printk(KERN_INFO "sb: Reply MCA SB at slot=%d \
 163iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
 164                                                slot+1,
 165                                                hw_config->io_base, hw_config->irq,
 166                                                hw_config->dma, hw_config->dma2);
 167                        }
 168                        else
 169                        {
 170                                printk (KERN_INFO "sb: Reply SB Base I/O address disabled\n");
 171                        }
 172                }
 173        }
 174#endif
 175
 176        /* Setup extra module options */
 177
 178        sbmo.acer       = acer;
 179        sbmo.sm_games   = sm_games;
 180        sbmo.esstype    = esstype;
 181
 182        return sb_dsp_detect(hw_config, 0, 0, &sbmo);
 183}
 184
 185static void __exit unload_sb(struct address_info *hw_config, int card)
 186{
 187        if(hw_config->slots[0]!=-1)
 188                sb_dsp_unload(hw_config, sbmpu[card]);
 189}
 190
 191static struct address_info cfg[SB_CARDS_MAX];
 192static struct address_info cfg_mpu[SB_CARDS_MAX];
 193
 194struct pci_dev  *sb_dev[SB_CARDS_MAX]   = {NULL}, 
 195                *mpu_dev[SB_CARDS_MAX]  = {NULL},
 196                *opl_dev[SB_CARDS_MAX]  = {NULL};
 197
 198
 199#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
 200static int isapnp       = 1;
 201static int isapnpjump   = 0;
 202static int multiple     = 1;
 203static int pnplegacy    = 0;
 204static int reverse      = 0;
 205static int uart401      = 0;
 206
 207static int audio_activated[SB_CARDS_MAX] = {0};
 208static int mpu_activated[SB_CARDS_MAX]   = {0};
 209static int opl_activated[SB_CARDS_MAX]   = {0};
 210#else
 211static int isapnp       = 0;
 212static int multiple     = 0;
 213static int pnplegacy    = 0;
 214#endif
 215
 216MODULE_DESCRIPTION("Soundblaster driver");
 217MODULE_LICENSE("GPL");
 218
 219MODULE_PARM(io,         "i");
 220MODULE_PARM(irq,        "i");
 221MODULE_PARM(dma,        "i");
 222MODULE_PARM(dma16,      "i");
 223MODULE_PARM(mpu_io,     "i");
 224MODULE_PARM(type,       "i");
 225MODULE_PARM(sm_games,   "i");
 226MODULE_PARM(esstype,    "i");
 227MODULE_PARM(acer,       "i");
 228
 229#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
 230MODULE_PARM(isapnp,     "i");
 231MODULE_PARM(isapnpjump, "i");
 232MODULE_PARM(multiple,   "i");
 233MODULE_PARM(pnplegacy,  "i");
 234MODULE_PARM(reverse,    "i");
 235MODULE_PARM(uart401,    "i");
 236MODULE_PARM_DESC(isapnp,        "When set to 0, Plug & Play support will be disabled");
 237MODULE_PARM_DESC(isapnpjump,    "Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
 238MODULE_PARM_DESC(multiple,      "When set to 0, will not search for multiple cards");
 239MODULE_PARM_DESC(pnplegacy,     "When set to 1, will search for a legacy SB card along with any PnP cards.");
 240MODULE_PARM_DESC(reverse,       "When set to 1, will reverse ISAPnP search order");
 241MODULE_PARM_DESC(uart401,       "When set to 1, will attempt to detect and enable the mpu on some clones");
 242#endif
 243
 244MODULE_PARM_DESC(io,            "Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
 245MODULE_PARM_DESC(irq,           "IRQ (5,7,9,10)");
 246MODULE_PARM_DESC(dma,           "8-bit DMA channel (0,1,3)");
 247MODULE_PARM_DESC(dma16,         "16-bit DMA channel (5,6,7)");
 248MODULE_PARM_DESC(mpu_io,        "Mpu base address");
 249MODULE_PARM_DESC(type,          "You can set this to specific card type");
 250MODULE_PARM_DESC(sm_games,      "Enable support for Logitech soundman games");
 251MODULE_PARM_DESC(esstype,       "ESS chip type");
 252MODULE_PARM_DESC(acer,          "Set this to detect cards in some ACER notebooks");
 253
 254#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
 255
 256/* Please add new entries at the end of the table */
 257static struct {
 258        char *name; 
 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 = {
 265        {"Sound Blaster 16", 
 266                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
 267                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 268                0,0,0,0,
 269                0,1,1,-1},
 270        {"Sound Blaster 16",
 271                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
 272                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 273                0,0,0,0,
 274                0,1,1,-1},
 275        {"Sound Blaster 16", 
 276                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
 277                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 278                0,0,0,0,
 279                0,1,1,-1},
 280        {"Sound Blaster 16", 
 281                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
 282                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 283                0,0,0,0,
 284                0,1,1,-1},
 285        {"Sound Blaster 16", 
 286                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
 287                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 288                0,0,0,0,
 289                0,1,1,-1},
 290        {"Sound Blaster 16", 
 291                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
 292                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 293                0,0,0,0,
 294                0,1,1,-1},
 295        {"Sound Blaster 16",
 296                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
 297                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 298                0,0,0,0,
 299                0,1,1,-1},
 300        {"Sound Blaster 16", 
 301                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
 302                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 303                0,0,0,0,
 304                0,1,1,-1},
 305        {"Sound Blaster 16", 
 306                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
 307                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 308                0,0,0,0,
 309                0,1,1,-1},
 310        {"Sound Blaster 16", 
 311                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
 312                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 313                0,0,0,0,
 314                0,1,1,-1},
 315        {"Sound Blaster 16", 
 316                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), 
 317                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
 318                0,0,0,0,
 319                0,1,1,-1},
 320        {"Sound Blaster 16", 
 321                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
 322                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
 323                0,0,0,0,
 324                0,1,1,-1},
 325        {"Sound Blaster 16", 
 326                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
 327                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
 328                0,0,0,0,
 329                0,1,1,-1},
 330        {"Sound Blaster Vibra16S", 
 331                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
 332                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
 333                0,0,0,0,
 334                0,1,1,-1},
 335        {"Sound Blaster Vibra16C", 
 336                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
 337                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
 338                0,0,0,0,
 339                0,1,1,-1},
 340        {"Sound Blaster Vibra16CL", 
 341                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
 342                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
 343                0,0,0,0,
 344                0,1,1,-1},
 345        {"Sound Blaster Vibra16X", 
 346                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
 347                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
 348                0,0,0,0,
 349                0,1,1,-1},
 350        {"Sound Blaster AWE 32", 
 351                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
 352                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 353                0,0,0,0,
 354                0,1,1,-1},
 355        {"Sound Blaster AWE 32",
 356                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
 357                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 358                0,0,0,0,
 359                0,1,1,-1},
 360        {"Sound Blaster AWE 32",
 361                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
 362                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 363                0,0,0,0,
 364                0,1,1,-1},
 365        {"Sound Blaster AWE 32",
 366                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
 367                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 368                0,0,0,0,
 369                0,1,1,-1},
 370        {"Sound Blaster AWE 32",
 371                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
 372                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 373                0,0,0,0,
 374                0,1,1,-1},
 375        {"Sound Blaster AWE 32",
 376                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0046),
 377                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 378                0,0,0,0,
 379                0,1,1,-1},
 380        {"Sound Blaster AWE 32",
 381                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
 382                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 383                0,0,0,0,
 384                0,1,1,-1},
 385        {"Sound Blaster AWE 32",
 386                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
 387                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 388                0,0,0,0,
 389                0,1,1,-1},
 390        {"Sound Blaster AWE 32",
 391                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
 392                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 393                0,0,0,0,
 394                0,1,1,-1},
 395        {"Sound Blaster AWE 32",
 396                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
 397                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
 398                0,0,0,0,
 399                0,1,1,-1},
 400        {"Creative SB32 PnP",
 401                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
 402                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
 403                0,0,0,0,
 404                0,1,1,-1},
 405        {"Sound Blaster AWE 64",
 406                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
 407                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
 408                0,0,0,0,
 409                0,1,1,-1},
 410        {"Sound Blaster AWE 64 Gold",
 411                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
 412                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
 413                0,0,0,0,
 414                0,1,1,-1},
 415        {"Sound Blaster AWE 64 Gold",
 416                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
 417                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
 418                0,0,0,0,
 419                0,1,1,-1},
 420        {"Sound Blaster AWE 64",
 421                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
 422                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
 423                0,0,0,0,
 424                0,1,1,-1},
 425        {"Sound Blaster AWE 64",
 426                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
 427                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
 428                0,0,0,0,
 429                0,1,1,-1},
 430        {"Sound Blaster AWE 64",
 431                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
 432                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
 433                0,0,0,0,
 434                0,1,1,-1},
 435        {"Sound Blaster AWE 64",
 436                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
 437                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
 438                0,0,0,0,
 439                0,1,1,-1},
 440        {"Sound Blaster AWE 64",
 441                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
 442                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
 443                0,0,0,0,
 444                0,1,1,-1},
 445        {"Sound Blaster AWE 64",
 446                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9), 
 447                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
 448                0,0,0,0,
 449                0,1,1,-1},
 450        {"ESS 1688",
 451                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
 452                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
 453                0,0,0,0,
 454                0,1,2,-1},
 455        {"ESS 1868",
 456                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
 457                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
 458                0,0,0,0,
 459                0,1,2,-1},
 460        {"ESS 1868",
 461                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
 462                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
 463                0,0,0,0,
 464                0,1,2,-1},
 465        {"ESS 1869 PnP AudioDrive", 
 466                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
 467                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
 468                0,0,0,0,
 469                0,1,2,-1},
 470        {"ESS 1869",
 471                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
 472                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
 473                0,0,0,0,
 474                0,1,2,-1},
 475        {"ESS 1878",
 476                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
 477                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
 478                0,0,0,0,
 479                0,1,2,-1},
 480        {"ESS 1879",
 481                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
 482                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
 483                0,0,0,0,
 484                0,1,2,-1},
 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),
 490                0,1,0,-1},
 491        {"Diamond DT0197H",
 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),
 496                0,-1,0,0},
 497        {"ALS007",
 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),
 502                0,-1,0,0},
 503        {"ALS100",
 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),
 508                1,0,0,0},
 509        {"ALS110",
 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),
 514                1,0,0,0},
 515        {"ALS120",
 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),
 520                1,0,0,0},
 521        {"ALS200",
 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),
 526                1,0,0,0},
 527        {"RTL3000",
 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),
 532                1,0,0,0},
 533        {0}
 534};
 535
 536static 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 },
 539
 540        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
 541                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 542
 543        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
 544                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 545
 546        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
 547                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 548
 549        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
 550                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 551
 552        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
 553                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 554
 555        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
 556                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 557
 558        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
 559                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 560
 561        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
 562                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 563
 564        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), 
 565                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 566
 567        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), 
 568                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
 569
 570        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
 571                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
 572
 573        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 
 574                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
 575
 576        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
 577                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
 578
 579        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
 580                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
 581
 582        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
 583                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
 584
 585        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
 586                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), 0 },
 587
 588        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
 589                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 590
 591        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
 592                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 593
 594        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
 595                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 596
 597        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
 598                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 599
 600        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
 601                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 602
 603        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
 604                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 605
 606        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
 607                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 608
 609        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
 610                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
 611
 612        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
 613                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
 614
 615        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
 616                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
 617
 618        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
 619                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
 620
 621        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
 622                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
 623
 624        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
 625                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
 626
 627        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
 628                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
 629
 630        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
 631                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
 632
 633        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
 634                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
 635
 636        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
 637                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
 638
 639        {       ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9),
 640                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
 641
 642        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
 643                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), 0 },
 644
 645        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
 646                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), 0 },
 647
 648        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
 649                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), 0 },
 650
 651        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
 652                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
 653
 654        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
 655                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
 656
 657        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
 658                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), 0 },
 659
 660        {       ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
 661                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), 0 },
 662
 663        {       ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
 664                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
 665
 666        {       ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
 667                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 668
 669        {       ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
 670                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
 671
 672        {       ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
 673                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
 674
 675        {       ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
 676                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
 677
 678        {       ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
 679                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 680
 681        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
 682                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
 683
 684        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
 685                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
 686
 687        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
 688                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 689
 690        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
 691                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
 692
 693        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
 694                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
 695
 696        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
 697                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 698
 699        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
 700                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001), 0 },
 701
 702        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
 703                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001), 0 },
 704
 705        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
 706                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 707
 708        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
 709                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
 710
 711        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
 712                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
 713
 714        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
 715                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 716
 717        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
 718                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020), 0 },
 719
 720        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
 721                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020), 0 },
 722
 723        {       ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
 724                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 725
 726        {       ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
 727                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
 728
 729        {       ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
 730                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
 731
 732        {       ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
 733                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
 734        {0}
 735};
 736
 737MODULE_DEVICE_TABLE(isapnp, id_table);
 738
 739static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
 740{
 741        int err;
 742
 743        /* Device already active? Let's use it */
 744        if(dev->active)
 745                return(dev);
 746        
 747        if((err = dev->activate(dev)) < 0) {
 748                printk(KERN_ERR "sb: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
 749
 750                dev->deactivate(dev);
 751
 752                return(NULL);
 753        }
 754        return(dev);
 755}
 756
 757static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_config, struct address_info *mpu_config, int slot, int card)
 758{
 759
 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)))
 762        {
 763                int ret;
 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");
 769                        return(NULL);
 770                }
 771                if(ret == -EBUSY)
 772                        audio_activated[card] = 1;
 773                
 774                if((sb_dev[card] = activate_dev(sb_isapnp_list[slot].name, "sb", sb_dev[card])))
 775                {
 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;
 781                        else
 782                                hw_config->dma2 = -1;
 783                } else
 784                        return(NULL);
 785        } else
 786                return(NULL);
 787
 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]);
 798                        }
 799                        if(ret == -EBUSY)
 800                                opl_activated[card] = 1;
 801
 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;
 806
 807                        opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
 808                } else
 809                        printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
 810        }
 811
 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]);
 816        }
 817        
 818        /* Cards with separate MPU device (ALS, CMI, etc.) */
 819        if(!uart401)
 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)))
 822        {
 823                int ret = mpu_dev[card]->prepare(mpu_dev[card]);
 824                /* If device is active, assume configured with /proc/isapnp
 825                 * and use anyway */
 826                if(ret && ret != -EBUSY) {
 827                        printk(KERN_ERR "sb: MPU device could not be autoconfigured.\n");
 828                        return(sb_dev[card]);
 829                }
 830                if(ret == -EBUSY)
 831                        mpu_activated[card] = 1;
 832                
 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;
 836                
 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;
 841                }
 842        }
 843        else
 844                printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
 845        
 846        return(sb_dev[card]);
 847}
 848
 849static int __init sb_isapnp_init(struct address_info *hw_config, struct address_info *mpu_config, struct pci_bus *bus, int slot, int card)
 850{
 851        char *busname = bus->name[0] ? bus->name : sb_isapnp_list[slot].name;
 852
 853        printk(KERN_INFO "sb: %s detected\n", busname); 
 854
 855        /* Initialize this baby. */
 856
 857        if(sb_init(bus, hw_config, mpu_config, slot, card)) {
 858                /* We got it. */
 859                
 860                printk(KERN_NOTICE "sb: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
 861                       busname,
 862                       hw_config->io_base, hw_config->irq, hw_config->dma,
 863                       hw_config->dma2);
 864                return 1;
 865        }
 866        else
 867                printk(KERN_INFO "sb: Failed to initialize %s\n", busname);
 868
 869        return 0;
 870}
 871
 872static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
 873{
 874        static int first = 1;
 875        int i;
 876
 877        /* Count entries in sb_isapnp_list */
 878        for (i = 0; sb_isapnp_list[i].card_vendor != 0; i++);
 879        i--;
 880
 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);
 885        }
 886
 887        if(!first || !reverse)
 888                i = isapnpjump;
 889        first = 0;
 890        while(sb_isapnp_list[i].card_vendor != 0) {
 891                static struct pci_bus *bus = NULL;
 892
 893                while ((bus = isapnp_find_card(
 894                                sb_isapnp_list[i].card_vendor,
 895                                sb_isapnp_list[i].card_device,
 896                                bus))) {
 897        
 898                        if(sb_isapnp_init(hw_config, mpu_config, bus, i, card)) {
 899                                isapnpjump = i; /* start next search from here */
 900                                return 0;
 901                        }
 902                }
 903                i += reverse ? -1 : 1;
 904        }
 905
 906        return -ENODEV;
 907}
 908#endif
 909
 910static int __init init_sb(void)
 911{
 912        int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1;
 913
 914        printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 915        
 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 
 920                 * single driver! */
 921                if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
 922                        if(!sb_cards_num) {
 923                                /* Found no ISAPnP cards, so check for a non-pnp
 924                                 * card and set the detection loop for 1 cycle
 925                                 */
 926                                printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
 927                                isapnp = 0;
 928                                max = 1;
 929                        } else
 930                                /* found all the ISAPnP cards so exit the
 931                                 * detection loop. */
 932                                break;
 933                }
 934#endif
 935
 936                if(!isapnp || (pnplegacy&&card==0)) {
 937                        cfg[card].io_base       = io;
 938                        cfg[card].irq           = irq;
 939                        cfg[card].dma           = dma;
 940                        cfg[card].dma2          = dma16;
 941                }
 942
 943                cfg[card].card_subtype = type;
 944
 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. */
 950                        if (sb_cards_num) {
 951                                printk(KERN_WARNING "sb.c: There was a " \
 952                                  "problem probing one of your SoundBlaster " \
 953                                  "ISAPnP soundcards. Continuing.\n");
 954                                card--;
 955                                sb_cards_num--;
 956                                continue;
 957                        } else if(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                attach_sb_card(&cfg[card]);
 967
 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");
 972                                pnplegacy=0;
 973                                card--;
 974                                continue;
 975                        } else
 976                                return -ENODEV;
 977                }
 978                
 979                if (!isapnp||(pnplegacy&&card==0))
 980                        cfg_mpu[card].io_base = mpu_io;
 981                if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE))
 982                        sbmpu[card] = 1;
 983        }
 984
 985        if(isapnp)
 986                printk(KERN_NOTICE "sb: %d Soundblaster PnP card(s) found.\n", sb_cards_num);
 987
 988        return 0;
 989}
 990
 991static void __exit cleanup_sb(void)
 992{
 993        int i;
 994        
 995        if (smw_free) {
 996                vfree(smw_free);
 997                smw_free = NULL;
 998        }
 999
1000        for(i = 0; i < sb_cards_num; i++) {
1001                unload_sb(&cfg[i], i);
1002                if (sbmpu[i])
1003                        unload_sbmpu(&cfg_mpu[i]);
1004
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]);
1012#endif
1013        }
1014}
1015
1016module_init(init_sb);
1017module_exit(cleanup_sb);
1018
1019#ifndef MODULE
1020static int __init setup_sb(char *str)
1021{
1022        /* io, irq, dma, dma2 - just the basics */
1023        int ints[5];
1024        
1025        str = get_options(str, ARRAY_SIZE(ints), ints);
1026        
1027        io      = ints[1];
1028        irq     = ints[2];
1029        dma     = ints[3];
1030        dma16   = ints[4];
1031
1032        return 1;
1033}
1034__setup("sb=", setup_sb);
1035#endif
1036