Autoconfiguration is a process that determines what hardware actually exists during the current instance of the running kernel. Writing Device Drivers: Tutorial discusses the events that occur during device autoconfiguration. This chapter discusses the following topics related to device configuration on the PCI bus:
Console power-on self-test code configures devices according to PCI Local Bus Specification Revision 2.1. Digital UNIX PCI bus configuration code reads these values from the PCI device's configuration space header, creates a pci_config_hdr data structure, and transfers the values to it. For those registers in the configuration space header that contain base address registers, the PCI bus configuration code maps them to I/O handles before moving them to the pci_config_hdr data structure.
Multifunction devices are configured and viewed as multiple standalone devices that are plugged into a slot. For example, the PPB front end of a quad-Ethernet module is viewed as four separate Ethernet devices, each of which has its own pci_config_hdr structure.
The Digital UNIX operating system provides a flexible method of associating a PCI bus device with its device driver, thus facilitating the configuration of a wide variety of devices, especially those with problematic IDs.
By default, PCI bus configuration code matches a device it encounters on a PCI bus with its driver by using the device's vendor ID and device ID. However, it may sometimes be necessary to use other fields to better match a device driver to a hardware interface implementation. Some examples of such devices include the following:
To allow PCI bus configuration code to more accurately match a device to its driver, you can indicate that a specific set of IDs be involved in the match. If you set the appropriate flag attribute, such as Vid_Mo_Flag or Did_Mo_Flag in the device's PCI_Option sysconfigtab entry, the bus configuration code uses the corresponding attributes in the PCI_Option entry to identify the driver. Table 5-1 shows the flags that involve other attributes in matching.
Flag | Attribute |
Vid_Mo_Flag | Vendor_Id |
Did_Mo_Flag | Device_Id |
Rev_Mo_Flag | Rev |
Base_Mo_Flag | Base |
Sub_Mo_Flag | Sub |
Pif_Mo_Flag | Pif |
Sub_Vid_Mo_Flags | Sub_Vid |
Sub_Did_Mo_Flags | Sub_Did |
The following list records, in order of precedence, all legal combinations of IDs and indicates the sequence in which the PCI bus configuration code considers each ID (when more than one flag is set) in its search for a driver. Note that dashes (---) represent a match-on flag that is set to 0.
Digital's PCI-to-PCI Bridge (PPB) product adheres to both the PCI to PCI Bridge Architecture Specification and PCI Local Bus Specification Revision 2.1. Digital UNIX PCI bus support code uses the data structures and bus interfaces discussed in this manual to configure the PPB.
Before deciding whether your device driver should support the PPB, consider the following resource issues:
Whenever possible, your driver should use memory-mapped register space rather than I/O-mapped register space to avoid any limitations with the base-system configuration.
The layout of the device-specific portion of the PPB device's pci_config_hdr data structure differs from that depicted (in Table 4-1) for devices that employ a HDR_LAYOUT_V2 hdr_type, although the predefined portion of the header is identical. Table 5-2 shows the contents of the pci_config_hdr data structure for a device with a a Type 1 header (that is, a hdr_type of HDR_MULTI_FCN).
Member Name | Data Type |
vendor_id | u_short |
device_id | u_short |
command | u_short |
status | u_short |
rev_id | u_char |
class_code | struct class_code |
cache_line_size | u_char |
latency_timer | u_char |
hdr_type | u_char |
bist | u_char |
bar0 | io_handle_t |
bar1 | io_handle_t |
ppb_pri_bus_num | u_char |
ppb_sec_bus_num | u_char |
ppb_sub_bus_num | u_char |
ppb_sec_max_lat | u_char |
ppb_io_base | u_char |
ppb_io_limit | u_char |
ppb_sec_status | u_short |
ppb_mem_base | u_short |
ppb_mem_limit | u_short |
ppb_premem_base | u_short |
ppb_premem_limit | u_short |
ppb_premem_base_upper | u_int |
ppb_premem_limit_upper | u_int |
ppb_io_base_upper | u_short |
ppb_io_limit_upper | u_short |
ppb_exp_rom_bar | io_handle_t |
intr_line | u_char |
intr_pin | u_char |
ppb_bridge_ctl | u_short |
A discussion of the purpose of the PPB configuration registers, and an explanation of how the PPB works, is beyond the scope of this book. You can find a description in PCI to PCI Bridge Architecture Specification.
By definition of the PCI Local Bus Specification Revision 2.1, PCI bus interrupts are shareable. Therefore, you should write a PCI device driver to support shared interrupts as follows:
The INTR_SERVICED status indicates to the interrupt dispatcher that the interrupt has been handled and that the dispatcher should stop looking for a handler. The INTR_NOT_SERVICED status causes the dispatcher to continue looking for an interrupt service routine attached to this interrupt line to handle the interrupt.
In Digital UNIX, if a PCI device shares an interrupt with another PCI device, all drivers sharing the interrupt signal must be shared-interrupt capable (SHARED_INTR_CAPABLE) to be configured into the operating system.