patch-2.3.43 linux/drivers/sound/sb_card.c
Next file: linux/drivers/sound/sonicvibes.c
Previous file: linux/drivers/sound/nm256_audio.c
Back to the patch index
Back to the overall index
- Lines: 618
- Date:
Wed Feb 9 18:48:03 2000
- Orig file:
v2.3.42/linux/drivers/sound/sb_card.c
- Orig date:
Fri Jan 7 19:13:22 2000
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
@@ -9,20 +9,25 @@
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
+ *
+ *
+ * 26th November 1999 - patched to compile without ISA PnP support in the
+ * kernel. -Daniel Stone (tamriel@ductape.net)
+ *
+ * 06-01-2000 Refined and bugfixed ISA PnP support, added
+ * CMI 8330 support - Alessandro Zummo <azummo@ita.flashnet.it>
+ *
+ *
+ * 04-02-2000 Added Soundblaster AWE 64 PnP support, isapnpjump
+ * Alessandro Zummo <azummo@ita.flashnet.it>
+ *
*/
-/* 26th Novemner 1999 - patched to compile without ISA PnP support in the
- kernel. -Daniel Stone (tamriel@ductape.net) */
-
#include <linux/config.h>
-#ifdef CONFIG_MCA
#include <linux/mca.h>
-#endif
#include <linux/module.h>
#include <linux/init.h>
-#ifdef CONFIG_ISAPNP /* Patched so it will compile withOUT ISA PnP */
#include <linux/isapnp.h>
-#endif
#include "sound_config.h"
#include "soundmodule.h"
@@ -36,10 +41,8 @@
void attach_sb_card(struct address_info *hw_config)
{
-#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
if(!sb_dsp_init(hw_config))
hw_config->slots[0] = -1;
-#endif
}
int probe_sb(struct address_info *hw_config)
@@ -91,7 +94,7 @@
hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3];
*/
- printk("SB: Reply MCA SB at slot=%d \
+ printk(KERN_INFO "sb: Reply MCA SB at slot=%d \
iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
slot+1,
hw_config->io_base, hw_config->irq,
@@ -99,12 +102,14 @@
}
else
{
- printk ("Reply SB Base I/O address disabled\n");
+ printk (KERN_INFO "sb: Reply SB Base I/O address disabled\n");
}
}
}
#endif
+ /* This is useless since is done by sb_dsp_detect - azummo*/
+
if (check_region(hw_config->io_base, 16))
{
printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
@@ -127,92 +132,403 @@
static struct address_info config;
static struct address_info config_mpu;
+struct pci_dev *sb_dev = NULL,
+ *wss_dev = NULL,
+ *jp_dev = NULL,
+ *mpu_dev = NULL,
+ *wt_dev = NULL;
/*
* Note DMA2 of -1 has the right meaning in the SB16 driver as well
- * as here. It will cause either an error if it is needed or a fallback
- * to the 8bit channel.
+ * as here. It will cause either an error if it is needed or a fallback
+ * to the 8bit channel.
*/
-int mpu_io = 0;
-int io = -1;
-int irq = -1;
-int dma = -1;
-int dma16 = -1; /* Set this for modules that need it */
-int type = 0; /* Can set this to a specific card type */
-int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */
-int trix = 0; /* Set trix=1 to load this as support for trix */
-int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */
-int support = 0; /* Set support to load this as a support module */
-int sm_games = 0; /* Mixer - see sb_mixer.c */
-int acer = 0; /* Do acer notebook init */
-
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(dma, "i");
-MODULE_PARM(dma16, "i");
-MODULE_PARM(mpu_io, "i");
-MODULE_PARM(type, "i");
-MODULE_PARM(mad16, "i");
-MODULE_PARM(support, "i");
-MODULE_PARM(trix, "i");
-MODULE_PARM(pas2, "i");
-MODULE_PARM(sm_games, "i");
-MODULE_PARM(esstype, "i");
+int mpu_io = 0;
+int io = -1;
+int irq = -1;
+int dma = -1;
+int dma16 = -1; /* Set this for modules that need it */
+int type = 0; /* Can set this to a specific card type */
+int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */
+int trix = 0; /* Set trix=1 to load this as support for trix */
+int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */
+int support = 0; /* Set support to load this as a support module */
+int sm_games = 0; /* Mixer - see sb_mixer.c */
+int acer = 0; /* Do acer notebook init */
+
+#ifdef CONFIG_ISAPNP
+int isapnp = 1;
+int isapnpjump = 0;
+#else
+int isapnp = 0;
+#endif
+
+MODULE_DESCRIPTION("Soundblaster driver");
+
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+MODULE_PARM(dma, "i");
+MODULE_PARM(dma16, "i");
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM(type, "i");
+MODULE_PARM(mad16, "i");
+MODULE_PARM(support, "i");
+MODULE_PARM(trix, "i");
+MODULE_PARM(pas2, "i");
+MODULE_PARM(sm_games, "i");
+MODULE_PARM(esstype, "i");
+MODULE_PARM(acer, "i");
+
+#ifdef CONFIG_ISAPNP
+MODULE_PARM(isapnp, "i");
+MODULE_PARM(isapnpjump, "i");
+MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled");
+MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
+#endif
+
+MODULE_PARM_DESC(io, "Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
+MODULE_PARM_DESC(irq, "IRQ (5,7,9,10)");
+MODULE_PARM_DESC(dma, "8-bit DMA channel (0,1,3)");
+MODULE_PARM_DESC(dma16, "16-bit DMA channel (5,6,7)");
+MODULE_PARM_DESC(mpu_io, "Mpu base address");
+MODULE_PARM_DESC(type, "You can set this to specific card type");
+MODULE_PARM_DESC(mad16, "Enable MAD16 support");
+MODULE_PARM_DESC(trix, "Enable Audiotrix support");
+MODULE_PARM_DESC(pas2, "Enable Pas2 support");
+MODULE_PARM_DESC(support, "Set this to load as generic support module");
+MODULE_PARM_DESC(sm_games, "Enable support for Logitech soundman games");
+MODULE_PARM_DESC(esstype, "ESS chip type");
+MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks");
void *smw_free = NULL;
#ifdef CONFIG_ISAPNP
-static struct { unsigned short vendor, function; char *name; }
+
+/* That's useful. */
+
+static int check_base(char *devname, char *resname, struct resource *res)
+{
+ if (check_region(res->start, res->end - res->start))
+ {
+ printk(KERN_ERR "sb: %s %s error, i/o at %#lx already in use\n", devname, resname, res->start);
+ return 0;
+ }
+
+ printk(KERN_INFO "sb: %s %s base located at %#lx\n", devname, resname, res->start);
+ return 1;
+}
+
+
+/* Card's specific initialization functions
+ */
+
+static struct pci_dev *sb_init_generic(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+ if((sb_dev = isapnp_find_dev(card,
+ card->vendor,
+ card->device,
+ NULL)))
+ {
+ sb_dev->prepare(sb_dev);
+ sb_dev->activate(sb_dev);
+
+ if (!sb_dev->resource[0].start)
+ return(NULL);
+
+ hw_config->io_base = sb_dev->resource[0].start;
+ hw_config->irq = sb_dev->irq_resource[0].start;
+ hw_config->dma = sb_dev->dma_resource[0].start;
+ hw_config->dma2 = sb_dev->dma_resource[1].start;
+ mpu_config->io_base = sb_dev->resource[1].start;
+ }
+ return(sb_dev);
+}
+
+static struct pci_dev *sb_init_ess(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+ if((sb_dev = isapnp_find_dev(card,
+ card->vendor,
+ card->device,
+ NULL)))
+ {
+ sb_dev->prepare(sb_dev);
+ sb_dev->activate(sb_dev);
+
+ if (!sb_dev->resource[0].start)
+ return(NULL);
+
+ hw_config->io_base = sb_dev->resource[0].start;
+ hw_config->irq = sb_dev->irq_resource[0].start;
+ hw_config->dma = sb_dev->dma_resource[0].start;
+ hw_config->dma2 = sb_dev->dma_resource[1].start;
+ mpu_config->io_base = sb_dev->resource[2].start;
+ }
+ return(sb_dev);
+}
+
+static struct pci_dev *sb_init_cmi(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+ /* What a stupid chip... where did they get all those @@@ ?*/
+
+ printk(KERN_INFO "sb: CMI8330 detected\n");
+
+ /* Soundblaster compatible logical device. */
+
+ if((sb_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+ {
+#ifdef CMI8330_DMA0BAD
+ int dmahack = 0;
+#endif
+ sb_dev->prepare(sb_dev);
+
+ /* This device doesn't work with DMA 0, so we must allocate
+ it to prevent PnP routines to assign it to the card.
+
+ I know i could have inlined the following lines, but it's cleaner
+ this way.
+ */
+
+#ifdef CMI8330_DMA0BAD
+ if(sb_dev->dma_resource[0].start == 0)
+ {
+ if(!request_dma(0, "cmi8330 dma hack"))
+ {
+ /* DMA was free, we now have it */
+ dmahack = 1;
+ }
+ }
+#endif
+
+ if(sb_dev->activate(sb_dev) >= 0)
+ {
+ hw_config->io_base = sb_dev->resource[0].start;
+ hw_config->irq = sb_dev->irq_resource[0].start;
+ hw_config->dma = sb_dev->dma_resource[0].start;
+ hw_config->dma2 = sb_dev->dma_resource[1].start;
+
+ check_base("CMI8330", "sb", &sb_dev->resource[0]);
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 sb config failed (out of resources?)\n");
+
+#ifdef CMI8330_DMA0BAD
+ if(dmahack)
+ free_dma(0);
+#endif
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 panic! sb base not found\n");
+
+ if((mpu_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+ {
+ mpu_dev->prepare(mpu_dev);
+
+ /* This disables the interrupt on this resource. Do we need it ? */
+
+ mpu_dev->irq_resource[0].flags = 0;
+
+ if(mpu_dev->activate(mpu_dev) >= 0)
+ {
+ if( check_base("CMI8330", "mpu", &mpu_dev->resource[0]) )
+ mpu_config->io_base = mpu_dev->resource[0].start;
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 mpu config failed (out of resources?)\n");
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 panic! mpu not found\n");
+
+
+ /* Gameport. */
+
+ if((jp_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('@','P','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+ {
+ jp_dev->prepare(jp_dev);
+
+ if(jp_dev->activate(jp_dev) >= 0)
+ {
+ check_base("CMI8330", "gameport", &jp_dev->resource[0]);
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 gameport config failed (out of resources?)\n");
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 panic! gameport not found\n");
+
+
+ /* OPL3 support */
+
+#if defined(CONFIG_SOUND_YM3812) || defined(CONFIG_SOUND_YM3812_MODULE)
+ if((wss_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+ {
+ wss_dev->prepare(wss_dev);
+
+ /* Let's disable IRQ and DMA for WSS device */
+
+ wss_dev->irq_resource[0].flags = 0;
+ wss_dev->dma_resource[0].flags = 0;
+
+ if(wss_dev->activate(wss_dev) >= 0)
+ {
+ check_base("CMI8330", "opl3", &wss_dev->resource[1]);
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 opl3 config failed (out of resources?)\n");
+ }
+ else
+ printk(KERN_ERR "sb: CMI8330 panic! opl3 not found\n");
+#endif
+
+ printk(KERN_INFO "sb: CMI8330 mail reports to Alessandro Zummo <azummo@ita.flashnet.it>\n");
+
+ return(sb_dev);
+}
+
+static struct pci_dev *sb_init_awe64(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+ printk(KERN_INFO "sb: SoundBlaster AWE 64 detected\n");
+
+ /* CTL0042:Audio. */
+
+ if((sb_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), NULL)))
+ {
+ sb_dev->prepare(sb_dev);
+
+ if(sb_dev->activate(sb_dev) >= 0)
+ {
+ hw_config->io_base = sb_dev->resource[0].start;
+ hw_config->irq = sb_dev->irq_resource[0].start;
+ hw_config->dma = sb_dev->dma_resource[0].start;
+ hw_config->dma2 = sb_dev->dma_resource[1].start;
+
+ mpu_config->io_base = sb_dev->resource[1].start;
+
+ check_base("AWE64", "sb", &sb_dev->resource[0]);
+ check_base("AWE64", "mpu", &sb_dev->resource[1]);
+ check_base("AWE64", "opl3", &sb_dev->resource[2]);
+ }
+ else
+ printk(KERN_ERR "sb: AWE64 sb config failed (out of resources?)\n");
+ }
+ else
+ printk(KERN_ERR "sb: AWE64 panic! sb base not found\n");
+
+
+ /* CTL7002:Game */
+
+ if((jp_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x7002), NULL)))
+ {
+ jp_dev->prepare(jp_dev);
+
+ if(jp_dev->activate(jp_dev) >= 0)
+ {
+ check_base("AWE64", "gameport", &jp_dev->resource[0]);
+ }
+ else
+ printk(KERN_ERR "sb: AWE64 gameport config failed (out of resources?)\n");
+ }
+ else
+ printk(KERN_ERR "sb: AWE64 panic! gameport not found\n");
+
+
+ /* CTL0022:WaveTable */
+
+ if((wt_dev = isapnp_find_dev(card,
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0022), NULL)))
+ {
+ wt_dev->prepare(wt_dev);
+
+ if(wt_dev->activate(wt_dev) >= 0)
+ {
+ check_base("AWE64", "wavetable", &wt_dev->resource[0]);
+ check_base("AWE64", "wavetable", &wt_dev->resource[1]);
+ check_base("AWE64", "wavetable", &wt_dev->resource[2]);
+ }
+ else
+ printk(KERN_ERR "sb: AWE64 wavetable config failed (out of resources?)\n");
+ }
+ else
+ printk(KERN_ERR "sb: AWE64 panic! wavetable not found\n");
+
+ printk(KERN_INFO "sb: AWE64 mail reports to Alessandro Zummo <azummo@ita.flashnet.it>\n");
+
+ return(sb_dev);
+}
+
+
+static struct { unsigned short vendor, function; struct pci_dev * (*initfunc)(struct pci_bus *, struct address_info *, struct address_info *); char *name; }
isapnp_sb_list[] __initdata = {
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), "Sound Blaster 16" },
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), "Sound Blaster 16" },
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), "Sound Blaster 16" },
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), "Sound Blaster 16" },
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), "Sound Blaster 16" },
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), "Sound Blaster 16" },
- {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), "Sound Blaster 16" },
- {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), "ESS 1868" },
- {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), "ESS 1868" },
- {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), "ESS 1869" },
- {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), "ESS 1878" },
- {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), "ESS 1879" },
- {0,}
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), &sb_init_generic, "Sound Blaster 16" },
+ {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x009D), &sb_init_awe64, "Sound Blaster AWE 64" },
+ {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), &sb_init_ess, "ESS 1868" },
+ {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), &sb_init_ess, "ESS 1868" },
+ {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), &sb_init_ess, "ESS 1869" },
+ {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), &sb_init_ess, "ESS 1878" },
+ {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), &sb_init_ess, "ESS 1879" },
+ {ISAPNP_VENDOR('C','M','I'), ISAPNP_FUNCTION(0x0001), &sb_init_cmi, "CMI 8330 SoundPRO" },
+ {0}
};
+/* Actually this routine will detect and configure only the first card with successful
+ initalization. isapnpjump could be used to jump to a specific entry.
+ Please always add entries at the end of the array.
+ Should this be fixed? - azummo
+*/
static int __init sb_probe_isapnp(struct address_info *hw_config, struct address_info *mpu_config) {
+
int i;
+
+ /* Count entries in isapnp_sb_list */
+ for (i = 0; isapnp_sb_list[i].vendor != 0; i++);
+
+ /* Check and adjust isapnpjump */
+ if( isapnpjump < 0 || isapnpjump > ( i - 1 ) )
+ {
+ printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to 0.\n", i-1);
+ isapnpjump = 0;
+ }
- for (i = 0; isapnp_sb_list[i].vendor != 0; i++) {
- struct pci_dev *idev = NULL;
+ for (i = isapnpjump; isapnp_sb_list[i].vendor != 0; i++) {
+ struct pci_bus *card = NULL;
- while ((idev = isapnp_find_dev(NULL,
+ while ((card = isapnp_find_card(
isapnp_sb_list[i].vendor,
isapnp_sb_list[i].function,
- idev))) {
- idev->prepare(idev);
- idev->activate(idev);
- if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
- continue;
- hw_config->io_base = idev->resource[0].start;
- hw_config->irq = idev->irq_resource[0].start;
- hw_config->dma = idev->dma_resource[0].start;
- hw_config->dma2 = idev->dma_resource[1].start;
-#ifdef CONFIG_MIDI
- if (isapnp_sb_list[i].vendor == ISAPNP_VENDOR('E','S','S'))
- mpu_config->io_base = idev->resource[2].start;
- else
- mpu_config->io_base = idev->resource[1].start;
-#endif
- break;
+ card))) {
+
+ /* You missed the init func? That's bad. */
+
+ if(isapnp_sb_list[i].initfunc)
+ {
+ struct pci_dev *idev = NULL;
+
+ /* Initialize this baby. */
+
+ if((idev = isapnp_sb_list[i].initfunc(card, hw_config, mpu_config)))
+ {
+ /* We got it. */
+
+ printk(KERN_INFO "sb: ISAPnP reports %s at i/o %#x, irq %d, dma %d, %d\n",
+ isapnp_sb_list[i].name,
+ hw_config->io_base, hw_config->irq, hw_config->dma,
+ hw_config->dma2);
+ return 0;
+ }
+ }
}
- if (!idev)
- continue;
- printk(KERN_INFO "ISAPnP reports %s at i/o %#x, irq %d, dma %d, %d\n",
- isapnp_sb_list[i].name,
- hw_config->io_base, hw_config->irq, hw_config->dma,
- hw_config->dma2);
- return 0;
}
return -ENODEV;
}
@@ -224,38 +540,52 @@
if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
{
+ /* Please remember that even with CONFIG_ISAPNP defined one should still be
+ able to disable PNP support for this single driver!
+ */
+
#ifdef CONFIG_ISAPNP
- if (sb_probe_isapnp(&config, &config_mpu)<0)
+ if (isapnp)
+ {
+ if(sb_probe_isapnp(&config, &config_mpu) < 0 )
+ {
+ printk(KERN_ERR "sb_card: No ISAPnP cards found\n");
+ return -EINVAL;
+ }
+ }
+ else
{
-#endif
+#endif
if (io == -1 || dma == -1 || irq == -1)
{
printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n");
return -EINVAL;
}
- config.io_base = io;
- config.irq = irq;
- config.dma = dma;
- config.dma2 = dma16;
- config.card_subtype = type;
-#ifdef CONFIG_MIDI
- config_mpu.io_base = mpu_io;
-#endif
+
+ config.io_base = io;
+ config.irq = irq;
+ config.dma = dma;
+ config.dma2 = dma16;
#ifdef CONFIG_ISAPNP
}
#endif
+
+ /* If this is not before the #ifdef line, there's a reason... */
+ config.card_subtype = type;
+
if (!probe_sb(&config))
return -ENODEV;
attach_sb_card(&config);
if(config.slots[0]==-1)
return -ENODEV;
-#ifdef CONFIG_MIDI
+
+ if (isapnp == 0)
+ config_mpu.io_base = mpu_io;
if (probe_sbmpu(&config_mpu))
sbmpu = 1;
if (sbmpu)
attach_sbmpu(&config_mpu);
-#endif
}
SOUND_LOCK;
return 0;
@@ -270,6 +600,12 @@
if (sbmpu)
unload_sbmpu(&config_mpu);
SOUND_LOCK_END;
+
+ if(sb_dev) sb_dev->deactivate(sb_dev);
+ if(jp_dev) jp_dev->deactivate(jp_dev);
+ if(wt_dev) wt_dev->deactivate(wt_dev);
+ if(mpu_dev) mpu_dev->deactivate(mpu_dev);
+ if(wss_dev) wss_dev->deactivate(wss_dev);
}
#else
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)