Table of Contents
In this section, we'll complete the chip-specific constructor, destructor and PCI entries. Example code is shown first, below.
Example 4.1. PCI Resource Management Example
struct mychip {
struct snd_card *card;
struct pci_dev *pci;
unsigned long port;
int irq;
};
static int snd_mychip_free(struct mychip *chip)
{
/* disable hardware here if any */
.... /* (not implemented in this document) */
/* release the irq */
if (chip->irq >= 0)
free_irq(chip->irq, chip);
/* release the I/O ports & memory */
pci_release_regions(chip->pci);
/* disable the PCI entry */
pci_disable_device(chip->pci);
/* release the data */
kfree(chip);
return 0;
}
/* chip-specific constructor */
static int snd_mychip_create(struct snd_card *card,
struct pci_dev *pci,
struct mychip **rchip)
{
struct mychip *chip;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_mychip_dev_free,
};
*rchip = NULL;
/* initialize the PCI entry */
err = pci_enable_device(pci);
if (err < 0)
return err;
/* check PCI availability (28bit DMA) */
if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
/* initialize the stuff */
chip->card = card;
chip->pci = pci;
chip->irq = -1;
/* (1) PCI resource allocation */
err = pci_request_regions(pci, "My Chip");
if (err < 0) {
kfree(chip);
pci_disable_device(pci);
return err;
}
chip->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_mychip_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
/* (2) initialization of the chip hardware */
.... /* (not implemented in this document) */
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
snd_mychip_free(chip);
return err;
}
*rchip = chip;
return 0;
}
/* PCI IDs */
static struct pci_device_id snd_mychip_ids[] = {
{ PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
....
{ 0, }
};
MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
/* pci_driver definition */
static struct pci_driver driver = {
.name = KBUILD_MODNAME,
.id_table = snd_mychip_ids,
.probe = snd_mychip_probe,
.remove = snd_mychip_remove,
};
/* module initialization */
static int __init alsa_card_mychip_init(void)
{
return pci_register_driver(&driver);
}
/* module clean up */
static void __exit alsa_card_mychip_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_mychip_init)
module_exit(alsa_card_mychip_exit)
EXPORT_NO_SYMBOLS; /* for old kernels only */