Constructor

The real constructor of PCI drivers is probe callback. The probe callback and other component-constructors which are called from probe callback should be defined with __devinit prefix. You cannot use __init prefix for them, because any PCI device could be a hotplug device.

In the probe callback, the following scheme is often used.

1) Check and increment the device index.

  static int dev;
  ....
  if (dev >= SNDRV_CARDS)
          return -ENODEV;
  if (!enable[dev]) {
          dev++;
          return -ENOENT;
  }
            

where enable[dev] is the module option.

At each time probe callback is called, check the availability of the device. If not available, simply increment the device index and returns. dev will be incremented also later (step 7).

2) Create a card instance

  struct snd_card *card;
  ....
  card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
            

The detail will be explained in the section Management of Cards and Components.

3) Create a main component

In this part, the PCI resources are allocated.

  struct mychip *chip;
  ....
  if ((err = snd_mychip_create(card, pci, &chip)) < 0) {
          snd_card_free(card);
          return err;
  }
            

The detail will be explained in the section PCI Resource Managements.

4) Set the driver ID and name strings.

  strcpy(card->driver, "My Chip");
  strcpy(card->shortname, "My Own Chip 123");
  sprintf(card->longname, "%s at 0x%lx irq %i",
          card->shortname, chip->ioport, chip->irq);
            

The driver field holds the minimal ID string of the chip. This is referred by alsa-lib's configurator, so keep it simple but unique. Even the same driver can have different driver IDs to distinguish the functionality of each chip type.

The shortname field is a string shown as more verbose name. The longname field contains the information which is shown in /proc/asound/cards.

5) Create other components, such as mixer, MIDI, etc.

Here you define the basic components such as PCM, mixer (e.g. AC97), MIDI (e.g. MPU-401), and other interfaces. Also, if you want a proc file, define it here, too.

6) Register the card instance.

  if ((err = snd_card_register(card)) < 0) {
          snd_card_free(card);
          return err;
  }
            

Will be explained in the section Management of Cards and Components, too.

7) Set the PCI driver data and return zero.

        pci_set_drvdata(pci, card);
        dev++;
        return 0;
            

In the above, the card record is stored. This pointer is referred in the remove callback and power-management callbacks, too.