summaryrefslogtreecommitdiffstats
path: root/Documentation/pci.txt
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
commit529c593ece216e4aaffd36bd940cb94f1fa63129 (patch)
tree78f1c0b805f5656aa7b0417a043c5346f700a2cf /Documentation/pci.txt
parent0bd079751d25808d1972baee5c4eaa1db2227257 (diff)
Merge with 2.3.43. I did ignore all modifications to the qlogicisp.c
driver due to the Origin A64 hacks.
Diffstat (limited to 'Documentation/pci.txt')
-rw-r--r--Documentation/pci.txt178
1 files changed, 139 insertions, 39 deletions
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index e74477fd4..d1211c512 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -1,52 +1,130 @@
- Few Notes About The PCI Subsystem
+ How To Write Linux PCI Drivers
- or
-
- "What should you avoid when writing PCI drivers"
-
- by Martin Mares <mj@suse.cz> on 21-Nov-1999
+ by Martin Mares <mj@suse.cz> on 07-Feb-2000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The world of PCI is vast and it's full of (mostly unpleasant) surprises.
+Different PCI devices have different requirements and different bugs --
+because of this, the PCI support layer in Linux kernel is not as trivial
+as one would wish. This short pamphlet tries to help all potential driver
+authors to find their way through the deep forests of PCI handling.
+
0. Structure of PCI drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Aa typical PCI device driver needs to perform the following actions:
-
- 1. Find PCI devices it's able to handle
- 2. Enable them
- 3. Access their configuration space
- 4. Discover addresses and IRQ numbers
-
-1. How to find PCI devices
-~~~~~~~~~~~~~~~~~~~~~~~~~~
- In case your driver wants to search for all devices with given vendor/device
-ID, it should use:
-
- struct pci_dev *dev = NULL;
- while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
- configure_device(dev);
-
- For class-based search, use pci_find_class(CLASS_ID, dev).
-
- If you need to match by subsystem vendor/device ID, use
-pci_find_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+There exist two kinds of PCI drivers: new-style ones (which leave most of
+probing for devices to the PCI layer and support online insertion and removal
+of devices [thus supporting PCI, hot-pluggable PCI and CardBus in single
+driver]) and old-style ones which just do all the probing themselves. Unless
+you have a very good reason to do so, please don't use the old way of probing
+in any new code. After the driver finds the devices it wishes to operate
+on (either the old or the new way), it needs to perform the following steps:
+
+ Enable the device
+ Access device configuration space
+ Discover resources (addresses and IRQ numbers) provided by the device
+ Allocate these resources
+ Communicate with 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.
+
+If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
+the functions described below are defined as inline functions either completely
+empty or just returning an appropriate error codes to avoid lots of ifdefs
+in the drivers.
+
+
+1. New-style drivers
+~~~~~~~~~~~~~~~~~~~~
+The new-style drivers just call pci_register_driver during their initialization
+with a pointer to a structure describing the driver (struct pci_driver) which
+contains:
+
+ name Name of the driver
+ id_table Pointer to table of device ID's the driver is
+ interested in
+ probe Pointer to a probing function which gets called (during
+ execution of pci_register_driver for already existing
+ devices or later if a new device gets inserted) for all
+ PCI devices which match the ID table and are not handled
+ by the other drivers yet. This function gets passed a pointer
+ to the pci_dev structure representing the device and also
+ which entry in the ID table did the device match. It returns
+ zero when the driver has accepted the device or an error
+ code (negative number) otherwise. This function always gets
+ called from process context, so it can sleep.
+ remove Pointer to a function which gets called whenever a device
+ being handled by this driver is removed (either during
+ deregistration of the driver or when it's manually pulled
+ out of a hot-pluggable slot). This function can be called
+ from interrupt context.
+ suspend, Power management hooks (currently used only for CardBus
+ resume cards) -- called when the device goes to sleep or is
+ resumed.
+
+The ID table is an array of struct pci_device_id ending with a all-zero entry.
+Each entry consists of:
+
+ vendor, device Vendor and device ID to match (or PCI_ANY_ID)
+ subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
+ subdevice
+ class, Device class to match. The class_mask tells which bits
+ class_mask of the class are honored during the comparison.
+ driver_data Data private to the driver.
+
+When the driver exits, it just calls pci_deregister_driver() and the PCI layer
+automatically calls the remove hook for all devices handled by the driver.
+
+Please mark the initialization and cleanup functions where appropriate
+(the corresponding macros are defined in <linux/init.h>):
+
+ __init Initialization code. Thrown away after the driver
+ initializes.
+ __exit Exit code. Ignored for non-modular drivers.
+ __devinit Device initialization code. Identical to __init if
+ the kernel is not compiled with CONFIG_HOTPLUG, normal
+ function otherwise.
+ __devexit The same for __exit.
+
+
+2. How to find PCI devices manually (the old style)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+PCI drivers not using the pci_register_driver() interface search
+for PCI devices manually using the following constructs:
+
+Searching by vendor and device ID:
+
+ struct pci_dev *dev = NULL;
+ while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
+ configure_device(dev);
+
+Searching by class ID (iterate in a similar way):
+
+ pci_find_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).
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.
- In case you want to do some complex matching, you can walk the list of all
-known PCI devices:
+ In case you need to decide according to some more complex criteria,
+you can walk the list of all known PCI devices yourself:
+
+ struct pci_dev *dev;
+ pci_for_each_dev(dev) {
+ ... do anything you want with dev ...
+ }
- struct pci_dev *dev;
- pci_for_each_dev(dev) {
- ... do anything you want with dev ...
- }
+For compatibility with device ordering in older kernels, you can also
+use pci_for_each_dev_reverse(dev) for walking the list in the opposite
+direction.
- The `struct pci_dev *' pointer serves as an identification of a PCI device
-and is passed to all other functions operating on PCI devices.
-2. Enabling devices
+3. Enabling 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
@@ -57,7 +135,8 @@ if it was in suspended state. Please note that this function can fail.
which enables the bus master bit in PCI_COMMAND register and also fixes
the latency timer value if it's set to something bogus by the BIOS.
-3. How to access PCI config space
+
+4. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can use pci_(read|write)_config_(byte|word|dword) to access the config
space of a device represented by struct pci_dev *. All these functions return 0
@@ -72,7 +151,8 @@ use symbolic names of locations and bits declared in <linux/pci.h>.
pci_find_capability() for the particular capability and it will find the
corresponding register block for you.
-4. Addresses and interrupts
+
+5. Addresses and interrupts
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Memory and port addresses and interrupt numbers should NOT be read from the
config space. You should use the values in the pci_dev structure as they might
@@ -86,13 +166,33 @@ for memory regions to make sure nobody else is using the same device.
All interrupt handlers should be registered with SA_SHIRQ and use the devid
to map IRQs to devices (remember that all PCI interrupts are shared).
-5. Other interesting functions
+
+6. Other interesting functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pci_find_slot() Find pci_dev corresponding to given bus and
slot numbers.
pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
+pci_find_capability() Find specified capability in device's capability
+ list.
+
+
+7. Miscellaneous hints
+~~~~~~~~~~~~~~~~~~~~~~
+When displaying PCI slot names to the user (for example when a driver wants
+to tell the user what card has it found), please use pci_dev->slot_name
+for this purpose.
+
+Always refer to the PCI devices by a pointer to the pci_dev structure.
+All PCI layer functions use this identification and it's the only
+reasonable one. Don't use bus/slot/function numbers except for very
+special purposes -- on systems with multiple primary buses their semantics
+can be pretty complex.
+
+If you're going to use PCI bus mastering DMA, take a look at
+Documentation/DMA-mapping.txt.
+
-6. Obsolete functions
+8. Obsolete functions
~~~~~~~~~~~~~~~~~~~~~
There are several functions kept only for compatibility with old drivers
not updated to the new PCI interface. Please don't use them in new code.