Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 6: Device Drivers


Registering Drivers


PCI drivers can be registered by means ofpci_register_driver. The function is quite primitive. Its
prime task is to fill a few remaining fields of apci_deviceinstance to which relevant functions have
already been assigned. This instance is passed to the generic device layer usingdriver_register,whose
mode of operation was discussed above.

More interesting than the registration process is the filling of thepci_devicestructure in the individual
drivers as this involves not only defining the above functions that define the interfaces between the driver
and the generic kernel code but also creating a list of all devices whose (sub)device and (sub)vendor IDs
indicate that they are suitable for the driver.

As already noted above, thepci_device_iddata structure whose definition is given below has a decisive
role to play in this context.

<mod_devicetable.h>
struct pci_device_id {
__u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
__u32 subvendor, subdevice; /* Subsystem ID’s or PCI_ANY_ID */
__u32 class, class_mask; /* (class,subclass,prog-if) triplet */
unsigned long driver_data; /* Data private to the driver */
};

You are familiar with the elements of this structure from the description of the PCI configuration space.
By defining specific constants, a driver is ableto refer to a particular chipset/device;class_maskalso
allows classes to be filtered by reference to a bitmask.

In many cases, it is neither necessary nor desirable to describejust onedevice. If a large number of com-
patible devices is supported, this would quickly result in endless declaration lists in the driver sources;
these would be difficult to read and would have the tangible disadvantage that a compatible device may
not be found simply because it is not included in the list of supported devices. The kernel therefore pro-
vides the wildcard constantPCI_ANY_IDthat matches any identifier of a PCI device. Let us look at how
this is used in the following example for the eepro100 driver (a widely used network card chipset from
Intel):

drivers/net/e100/e100_main.c
#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
static struct pci_device_id e100_id_table[] = {
INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
INTEL_8255X_ETHERNET_DEVICE(0x1032, 3),
INTEL_8255X_ETHERNET_DEVICE(0x1033, 3),
...
INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7),
{0,}
};

Each macro expansion ofINTEL_8255X_ETHERNET_DEVICEgenerates an entry in the table. The individual
elements of the entry are given in the sequence in which they are declared inpci_device_id.
Free download pdf