📄 sb16.c
字号:
static void snd_sb16_free(snd_card_t *card){ struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data; if (acard == NULL) return; if (acard->fm_res) { release_resource(acard->fm_res); kfree_nocheck(acard->fm_res); }}static int __init snd_sb16_probe(int dev, struct pnp_card_link *pcard, const struct pnp_card_device_id *pid){ static int possible_irqs[] = {5, 9, 10, 7, -1}; static int possible_dmas8[] = {1, 3, 0, -1}; static int possible_dmas16[] = {5, 6, 7, -1}; int xirq, xdma8, xdma16; sb_t *chip; snd_card_t *card; struct snd_card_sb16 *acard; opl3_t *opl3; snd_hwdep_t *synth = NULL;#ifdef CONFIG_SND_SB16_CSP snd_hwdep_t *xcsp = NULL;#endif unsigned long flags; int err; card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_card_sb16)); if (card == NULL) return -ENOMEM; acard = (struct snd_card_sb16 *) card->private_data; card->private_free = snd_sb16_free;#ifdef CONFIG_PNP if (isapnp[dev]) { if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) { snd_card_free(card); return err; } snd_card_set_dev(card, &pcard->card->dev); }#endif xirq = irq[dev]; xdma8 = dma8[dev]; xdma16 = dma16[dev];#ifdef CONFIG_PNP if (!isapnp[dev]) {#endif if (xirq == SNDRV_AUTO_IRQ) { if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { snd_card_free(card); snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); return -EBUSY; } } if (xdma8 == SNDRV_AUTO_DMA) { if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) { snd_card_free(card); snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n"); return -EBUSY; } } if (xdma16 == SNDRV_AUTO_DMA) { if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) { snd_card_free(card); snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n"); return -EBUSY; } } /* non-PnP FM port address is hardwired with base port address */ fm_port[dev] = port[dev]; /* block the 0x388 port to avoid PnP conflicts */ acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");#ifdef SNDRV_SBAWE_EMU8000 /* non-PnP AWE port address is hardwired with base port address */ awe_port[dev] = port[dev] + 0x400;#endif#ifdef CONFIG_PNP }#endif if ((err = snd_sbdsp_create(card, port[dev], xirq, snd_sb16dsp_interrupt, xdma8, xdma16, SB_HW_AUTO, &chip)) < 0) { snd_card_free(card); return err; } if (chip->hardware != SB_HW_16) { snd_card_free(card); snd_printdd("SB 16 chip was not detected at 0x%lx\n", port[dev]); return -ENODEV; } chip->mpu_port = mpu_port[dev];#ifdef CONFIG_PNP if (!isapnp[dev] && (err = snd_sb16dsp_configure(chip)) < 0) {#else if ((err = snd_sb16dsp_configure(chip)) < 0) {#endif snd_card_free(card); return -ENXIO; } if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) { snd_card_free(card); return -ENXIO; } strcpy(card->driver,#ifdef SNDRV_SBAWE_EMU8000 awe_port[dev] > 0 ? "SB AWE" :#endif "SB16"); strcpy(card->shortname, chip->name); sprintf(card->longname, "%s at 0x%lx, irq %i, dma ", chip->name, chip->port, xirq); if (xdma8 >= 0) sprintf(card->longname + strlen(card->longname), "%d", xdma8); if (xdma16 >= 0) sprintf(card->longname + strlen(card->longname), "%s%d", xdma8 >= 0 ? "&" : "", xdma16); if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, chip->mpu_port, 0, xirq, 0, &chip->rmidi)) < 0) { snd_card_free(card); return -ENXIO; } chip->rmidi_callback = snd_mpu401_uart_interrupt; }#ifdef SNDRV_SBAWE_EMU8000 if (awe_port[dev] == SNDRV_AUTO_PORT) awe_port[dev] = 0; /* disable */#endif if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_OPL3, acard->fm_res != NULL || fm_port[dev] == port[dev], &opl3) < 0) { snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", fm_port[dev], fm_port[dev] + 2); } else {#ifdef SNDRV_SBAWE_EMU8000 int seqdev = awe_port[dev] > 0 ? 2 : 1;#else int seqdev = 1;#endif if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) { snd_card_free(card); return -ENXIO; } } } if ((err = snd_sbmixer_new(chip)) < 0) { snd_card_free(card); return -ENXIO; }#ifdef CONFIG_SND_SB16_CSP /* CSP chip on SB16ASP/AWE32 */ if ((chip->hardware == SB_HW_16) && csp[dev]) { snd_sb_csp_new(chip, synth != NULL ? 1 : 0, &xcsp); if (xcsp) { chip->csp = xcsp->private_data; chip->hardware = SB_HW_16CSP; } else { snd_printk(KERN_INFO PFX "warning - CSP chip not detected on soundcard #%i\n", dev + 1); } }#endif#ifdef SNDRV_SBAWE_EMU8000 if (awe_port[dev] > 0) { if (snd_emu8000_new(card, 1, awe_port[dev], seq_ports[dev], NULL) < 0) { snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); snd_card_free(card); return -ENXIO; } }#endif /* setup Mic AGC */ spin_lock_irqsave(&chip->mixer_lock, flags); snd_sbmixer_write(chip, SB_DSP4_MIC_AGC, (snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) | (mic_agc[dev] ? 0x00 : 0x01)); spin_unlock_irqrestore(&chip->mixer_lock, flags); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } if (pcard) pnp_set_card_drvdata(pcard, card); else snd_sb16_legacy[dev] = card; return 0;}static int __init snd_sb16_probe_legacy_port(unsigned long xport){ static int dev; int res; for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT) continue;#ifdef CONFIG_PNP if (isapnp[dev]) continue;#endif port[dev] = xport; res = snd_sb16_probe(dev, NULL, NULL); if (res < 0) port[dev] = SNDRV_AUTO_PORT; return res; } return -ENODEV;}#ifdef CONFIG_PNPstatic int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card, const struct pnp_card_device_id *id){ static int dev; int res; for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev] || !isapnp[dev]) continue; res = snd_sb16_probe(dev, card, id); if (res < 0) return res; dev++; return 0; } return -ENODEV;}static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard){ snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard); snd_card_disconnect(card); snd_card_free_in_thread(card);}static struct pnp_card_driver sb16_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, .name = "sb16", .id_table = snd_sb16_pnpids, .probe = snd_sb16_pnp_detect, .remove = __devexit_p(snd_sb16_pnp_remove),};#endif /* CONFIG_PNP */static int __init alsa_card_sb16_init(void){ int dev, cards = 0, i; static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1}; /* legacy non-auto cards at first */ for (dev = 0; dev < SNDRV_CARDS; dev++) { if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT) continue;#ifdef CONFIG_PNP if (isapnp[dev]) continue;#endif if (!snd_sb16_probe(dev, NULL, NULL)) { cards++; continue; }#ifdef MODULE snd_printk(KERN_ERR "Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]);#endif } /* legacy auto configured cards */ i = snd_legacy_auto_probe(possible_ports, snd_sb16_probe_legacy_port); if (i > 0) cards += i;#ifdef CONFIG_PNP /* PnP cards at last */ i = pnp_register_card_driver(&sb16_pnpc_driver); if (i >0) cards += i;#endif if (!cards) {#ifdef CONFIG_PNP pnp_unregister_card_driver(&sb16_pnpc_driver);#endif#ifdef MODULE snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");#ifdef SNDRV_SBAWE_EMU8000 snd_printk(KERN_ERR "In case, if you have non-AWE card, try snd-sb16 module\n");#else snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");#endif#endif return -ENODEV; } return 0;}static void __exit alsa_card_sb16_exit(void){ int dev;#ifdef CONFIG_PNP /* PnP cards first */ pnp_unregister_card_driver(&sb16_pnpc_driver);#endif for (dev = 0; dev < SNDRV_CARDS; dev++) snd_card_free(snd_sb16_legacy[dev]);}module_init(alsa_card_sb16_init)module_exit(alsa_card_sb16_exit)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -