The sections that make up a Digital UNIX device driver differ, depending on whether the driver is a block, character, or network driver. Figure 3-1 shows the sections that a character device driver can contain and the possible sections that a block device driver can contain. Device drivers do not have to use all of the sections shown in the figure, and more complex drivers can use additional sections. Both character and block device drivers can contain:
The block device driver can also contain a strategy section, a psize section, and a dump section.
The character device driver contains the following sections not contained in a block device driver:
Writing Device Drivers: Tutorial discusses each of the driver sections. The remainder of this chapter describes the differences in the following driver sections as they relate to PCI bus device drivers: include files and autoconfiguration support (specifically, the xxprobe and xxslave interfaces).
Data structures and constant values are defined in header files that you include in the include files section of the single binary driver source code. The number and types of header files you specify in the include files section vary, depending on such things as what structures, constants, and kernel interfaces your device driver references. You need to be familiar with:
These files are described in Writing Device Drivers: Tutorial. Only drivers that run on a PCI bus use the following header file:
#include <io/dec/pci/pci.h>
When Digital UNIX starts up, the kernel determines what devices are connected to the computer. After finding a device, the kernel initializes it so that the device can be used at a later time. The probe interface determines if a particular device is present and the attach interface initializes the device. If the device is a disk controller, the slave interface determines if any slave device attached to the controller is present. The autoconfiguration support section of a PCI bus device driver contains the code that implements these interfaces. Both character and block device drivers contain an autoconfiguration support section.
Writing Device Drivers: Tutorial discusses each of these interfaces.
The remainder of this section describes the features of the xxprobe and xxslave interfaces that support PCI bus devices. For convenience in referring to the names of the driver interfaces, the chapter uses the prefix xx. For example, xxprobe refers to a probe interface for some xx device.
The arguments passed to the driver's probe interface depend upon the type of I/O bus on which the driver operates. You set up a PCI device driver's probe interface as follows:
xxprobe(slot_cnfg_p, ctlr) struct pci_config_hdr *slot_cnfg_p; [1] struct controller *ctlr; [2] { /* Variable and structure declarations */
.
.
.
/* Code to perform necessary checks */
.
.
.
The PCI bus code calls the xxprobe interface for each device on the PCI bus for which it finds a matching PCI_Option entry in the /etc/sysconfigtab database file. For a statically configured driver, this happens during autoconfiguration at system startup. For dynamically configured drivers, it happens when the driver calls the configure_driver interface.
The driver's xxprobe interface performs tasks necessary to determine if the device exists and is functional on a given system. These tasks include the following:
Checks a device control status register (CSR) to determine whether the physical device is present. If the device is not present, the device is not initialized and not available for use.
In single binary device drivers, the xxprobe or xxattach interface registers and enables a device's interrupt handler by calling handler_add and handler_enable.
The xxprobe interface of single binary drivers may obtain handles that map the base of PCI memory, I/O, and configuration address space from the pci_config_hdr data structure and store them for later use.
The xxprobe interface returns a nonzero value if the probe operation is successful. It returns the value zero (0) to indicate that the driver did not complete the probe operation.
A device driver's xxslave interface is called only for a controller that has devices in the topology list. This interface is called once for each device in the list. You (or the system manager) specify the attachments of these slave devices in the driver's xxconfigure routine by calling the create_device_struct and configure_driver interfaces.
Note
It is common for a device's xxslave interface to be called for a controller it is not attached to. This is because the create_device_struct interface does not know which driver controls the devices it sees.
The following code fragment shows how to set up a slave interface for a driver that operates on the PCI bus:
xxslave(device, slot_cnfg_p) struct device *device; [1] pci_config_hdr *slot_cnfg_p; [2] { /* Variable and structure declarations */
.
.
.
/* Code to check that the device is valid */
.
.
.