// component-destructor // (see "Management of Cards and Components") static int snd_vortex_dev_free(struct snd_device *device) { vortex_t *vortex = device->device_data; vortex_gameport_unregister(vortex); vortex_core_shutdown(vortex); // Take down PCI interface. free_irq(vortex->irq, vortex); iounmap(vortex->mmio); pci_release_regions(vortex->pci_dev); pci_disable_device(vortex->pci_dev); kfree(vortex); return 0; }
// component-destructor // (see "Management of Cards and Components") static int snd_vortex_dev_free(snd_device_t * device) { vortex_t *vortex = device->device_data; vortex_gameport_unregister(vortex); vortex_core_shutdown(vortex); // Take down PCI interface. synchronize_irq(vortex->irq); free_irq(vortex->irq, vortex); pci_release_regions(vortex->pci_dev); pci_disable_device(vortex->pci_dev); kfree(vortex); return 0; }
// chip-specific constructor // (see "Management of Cards and Components") static int __devinit snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip) { vortex_t *chip; int err; static snd_device_ops_t ops = { .dev_free = snd_vortex_dev_free, }; *rchip = NULL; // check PCI availability (DMA). if ((err = pci_enable_device(pci)) < 0) return err; if (!pci_dma_supported(pci, VORTEX_DMA_MASK)) { printk(KERN_ERR "error to set DMA mask\n"); return -ENXIO; } pci_set_dma_mask(pci, VORTEX_DMA_MASK); chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->card = card; // initialize the stuff chip->pci_dev = pci; chip->io = pci_resource_start(pci, 0); chip->vendor = pci->vendor; chip->device = pci->device; chip->card = card; chip->irq = -1; // (1) PCI resource allocation // Get MMIO area // if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0) goto regions_out; chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), pci_resource_len(pci, 0)); if (!chip->mmio) { printk(KERN_ERR "MMIO area remap failed.\n"); err = -ENOMEM; goto ioremap_out; } /* Init audio core. * This must be done before we do request_irq otherwise we can get spurious * interupts that we do not handle properly and make a mess of things */ if ((err = vortex_core_init(chip)) != 0) { printk(KERN_ERR "hw core init failed\n"); goto core_out; } if ((err = request_irq(pci->irq, vortex_interrupt, SA_INTERRUPT | SA_SHIRQ, CARD_NAME_SHORT, chip)) != 0) { printk(KERN_ERR "cannot grab irq\n"); goto irq_out; } chip->irq = pci->irq; pci_set_master(pci); // End of PCI setup. // Register alsa root device. if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { goto alloc_out; } *rchip = chip; return 0; alloc_out: synchronize_irq(chip->irq); free_irq(chip->irq, chip); irq_out: vortex_core_shutdown(chip); core_out: iounmap(chip->mmio); ioremap_out: pci_release_regions(chip->pci_dev); regions_out: pci_disable_device(chip->pci_dev); //FIXME: this not the right place to unregister the gameport vortex_gameport_unregister(chip); return err; }
// chip-specific constructor // (see "Management of Cards and Components") static int snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) { vortex_t *chip; int err; static struct snd_device_ops ops = { .dev_free = snd_vortex_dev_free, }; *rchip = NULL; // check PCI availability (DMA). if ((err = pci_enable_device(pci)) < 0) return err; if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { pr_err( "error to set DMA mask\n"); pci_disable_device(pci); return -ENXIO; } chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) { pci_disable_device(pci); return -ENOMEM; } chip->card = card; // initialize the stuff chip->pci_dev = pci; chip->io = pci_resource_start(pci, 0); chip->vendor = pci->vendor; chip->device = pci->device; chip->card = card; chip->irq = -1; // (1) PCI resource allocation // Get MMIO area // if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0) goto regions_out; chip->mmio = pci_ioremap_bar(pci, 0); if (!chip->mmio) { pr_err( "MMIO area remap failed.\n"); err = -ENOMEM; goto ioremap_out; } /* Init audio core. * This must be done before we do request_irq otherwise we can get spurious * interrupts that we do not handle properly and make a mess of things */ if ((err = vortex_core_init(chip)) != 0) { pr_err( "hw core init failed\n"); goto core_out; } if ((err = request_irq(pci->irq, vortex_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) != 0) { pr_err( "cannot grab irq\n"); goto irq_out; } chip->irq = pci->irq; pci_set_master(pci); // End of PCI setup. // Register alsa root device. if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { goto alloc_out; } *rchip = chip; return 0; alloc_out: free_irq(chip->irq, chip); irq_out: vortex_core_shutdown(chip); core_out: iounmap(chip->mmio); ioremap_out: pci_release_regions(chip->pci_dev); regions_out: pci_disable_device(chip->pci_dev); //FIXME: this not the right place to unregister the gameport vortex_gameport_unregister(chip); kfree(chip); return err; }