Discover resources (addresses and IRQ numbers) provided by the device
Allocate these resources
Communicate with the device
+ Disable the device
Most of these topics are covered by the following sections, for the rest
look at <linux/pci.h>, it's hopefully well commented.
Most drivers don't need to use the driver_data field. Best practice
for use of driver_data is to use it as an index into a static list of
-equivalant device types, not to use it as a pointer.
+equivalent device types, not to use it as a pointer.
Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}
to have probe() called for every PCI device known to the system.
Users need pass only as many fields as necessary; vendor, device,
subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF),
class and classmask fields default to 0, and driver_data defaults to
-0UL. Device drivers must call
- pci_dynids_set_use_driver_data(pci_driver *, 1)
-in order for the driver_data field to get passed to the driver.
-Otherwise, only a 0 is passed in that field.
+0UL. Device drivers must initialize use_driver_data in the dynids struct
+in their pci_driver struct prior to calling pci_register_driver in order
+for the driver_data field to get passed to the driver. Otherwise, only a
+0 is passed in that field.
When the driver exits, it just calls pci_unregister_driver() and the PCI layer
automatically calls the remove hook for all devices handled by the driver.
Searching by vendor and device ID:
struct pci_dev *dev = NULL;
- while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
+ while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
configure_device(dev);
Searching by class ID (iterate in a similar way):
- pci_find_class(CLASS_ID, dev)
+ pci_get_class(CLASS_ID, dev)
Searching by both vendor/device and subsystem vendor/device ID:
- pci_find_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+ pci_get_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
You can use the constant PCI_ANY_ID as a wildcard replacement for
VENDOR_ID or DEVICE_ID. This allows searching for any device from a
specific vendor, for example.
-Note that these functions are not hotplug-safe. Their hotplug-safe
-replacements are pci_get_device(), pci_get_class() and pci_get_subsys().
-They increment the reference count on the pci_dev that they return.
-You must eventually (possibly at module unload) decrement the reference
-count on these devices by calling pci_dev_put().
+ These functions are hotplug-safe. They increment the reference count on
+the pci_dev that they return. You must eventually (possibly at module unload)
+decrement the reference count on these devices by calling pci_dev_put().
-3. Enabling devices
-~~~~~~~~~~~~~~~~~~~
+3. Enabling and disabling devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before you do anything with the device you've found, you need to enable
it by calling pci_enable_device() which enables I/O and memory regions of
the device, allocates an IRQ if necessary, assigns missing resources if
Make sure to check the return value of pci_set_mwi(), not all architectures
may support Memory-Write-Invalidate.
+ If your driver decides to stop using the device (e.g., there was an
+error while setting it up or the driver module is being unloaded), it
+should call pci_disable_device() to deallocate any IRQ resources, disable
+PCI bus-mastering, etc. You should not do anything with the device after
+calling pci_disable_device().
+
4. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can use pci_(read|write)_config_(byte|word|dword) to access the config
to be handled by platform and generic code, not individual drivers.
-8. Obsolete functions
+8. Vendor and device identifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For the future, let's avoid adding device ids to include/linux/pci_ids.h.
+
+PCI_VENDOR_ID_xxx for vendors, and a hex constant for device ids.
+
+Rationale: PCI_VENDOR_ID_xxx constants are re-used, but device ids are not.
+ Further, device ids are arbitrary hex numbers, normally used only in a
+ single location, the pci_device_id table.
+
+9. Obsolete functions
~~~~~~~~~~~~~~~~~~~~~
There are several functions which you might come across when trying to
port an old driver to the new PCI interface. They are no longer present
in the kernel as they aren't compatible with hotplug or PCI domains or
having sane locking.
-pcibios_present() and Since ages, you don't need to test presence
-pci_present() of PCI subsystem when trying to talk to it.
- If it's not there, the list of PCI devices
- is empty and all functions for searching for
- devices just return NULL.
-pcibios_(read|write)_* Superseded by their pci_(read|write)_*
- counterparts.
-pcibios_find_* Superseded by their pci_find_* counterparts.
-pci_for_each_dev() Superseded by pci_find_device()
-pci_for_each_dev_reverse() Superseded by pci_find_device_reverse()
-pci_for_each_bus() Superseded by pci_find_next_bus()
pci_find_device() Superseded by pci_get_device()
pci_find_subsys() Superseded by pci_get_subsys()
-pcibios_find_class() Superseded by pci_find_class()
-pci_(read|write)_*_nodev() Superseded by pci_bus_(read|write)_*()
+pci_find_slot() Superseded by pci_get_slot()