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 EISA/ISA bus device drivers: include file 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 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:
Writing Device Drivers: Tutorial describes these files. EISA/ISA bus device drivers use the following file in addition to the previously mentioned files:
#include <io/dec/eisa/eisa.h>
The eisa.h file contains definitions specific to EISA/ISA buses.
You must also be familiar with the following name_data.c files:
The eisa_option_data.c file contains the array (table) of eisa_option structures, which store information about a specific EISA option. Each structure contains such information as the option board's product ID and the name of the controlling device driver. Digital initilizes the array of eisa_option structures with its own EISA bus option product information. Third-party device driver writers can directly edit the eisa_option array with their EISA bus option product information; or, they can use the mkdata utility to automatically add product entries to a copy of the eisa_option array. Chapter 8 discusses the mkdata utility.
The isa_option_data.c file contains the array (table) of eisa_option structures, which store information about a specific ISA option. The isa_option_data.c file defines the table as follows: struct eisa_option isa_option []. Each structure contains such information as the option board's product ID and the name of the controlling device driver. In the case of the ISA bus, the option board's product ID is not used. Digital initializes the array of isa_option structures with its own ISA bus option product information. Third-party device driver writers can directly edit the isa_option array with their ISA bus option product information; or, they can use the mkdata utility to automatically add product entries to a copy of the isa_option array. Chapter 8 discusses the mkdata utility.
When Digital UNIX boots, the kernel determines what EISA/ISA bus devices are connected to the computer. After finding an EISA/ISA bus device, the EISA/ISA bus configuration code initializes it based on the data supplied in the device's configuration file. The probe interface determines if a particular EISA/ISA bus device is present and the attach interface initializes the device. If the device is a disk controller, the slave interface determines if the device is present.
The Autoconfiguration Support Section of an EISA/ISA bus device driver contains the code that implements these interfaces and the section applies to both character and block device drivers. The section can contain:
Writing Device Drivers: Tutorial discusses each of these interfaces.
The following sections describe the xxprobe and xxslave interfaces as they apply to EISA/ISA bus device drivers. 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.
An EISA/ISA bus device driver's xxprobe interface performs the tasks necessary to determine if the device exists and is functional on a given system. At system startup time, the EISA bus configuration code reads the configuration information saved by the EISA configuration utility (ECU) and performs checks to determine if the device is present before calling xxprobe for statically configured drivers. The EISA bus configuration code calls the xxprobe interface for each device that is defined according to specific rules discussed in Chapter 6.
The ISA bus configuration code reads the data saved by the console firmware's isacfg utility and attempts to match the data to a configured device driver. The matching occurs by using the ISACFG handle and the strings stored in the function member of the isa_option data table that resides in /usr/sys/data/isa_option_data.c.
EISA bus devices must have an ID register that the EISA bus configuration code can use to ensure that the device is present on the system before calling the driver's probe interface. ISA bus devices have no such requirement. Thus drivers for ISA bus devices, whether on either the EISA or ISA bus, should attempt to determine the actual presence of the device in the probe interface probe routine. The methodology to accomplish this is unique to each device. Some predictable device register manipulation is one such method.
The xxprobe interface typically checks some 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 previous versions of the operating system, you defined the device interrupt handlers for static device drivers in the system configuration file or the stanza.static file fragment. At system configuration time, the config program registered the defined device interrupt handlers. For this version of Digital UNIX, Digital recommends that you register the device interrupt handlers for static device drivers in the same way that you register them for loadable device drivers: by calling the handler_add and handler_enable interfaces.
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.
The arguments you pass to the probe interface differ according to the bus on which the driver operates. The following code fragment shows you how to set up a probe interface for a driver that operates on an EISA or ISA bus:
xxprobe(bus_io_handle, ctlr) io_handle_t bus_io_handle; [1] struct controller *ctlr; [2] { /* Variable and structure declarations */
.
.
.
/* Code to perform necessary checks */
.
.
.
Device drivers pass the I/O handle to the following categories of interfaces, which are discussed in Writing Device Drivers: Tutorial. These interfaces can process the I/O handle to access the bus address space they need.
The read_io_port and write_io_port interfaces allow device drivers to read from and write to device registers. Using these interfaces to read data from and write data to a device register makes the device driver more portable across different bus architectures, different CPU architectures, and different CPU types within the same CPU architecture.
The
io_copyin,
io_copyio,
io_copyout,
and
io_zero
interfaces allow device drivers to perform I/O
copy operations.
Using these interfaces to perform the copy operation makes the device
driver more portable across different CPU architectures and different
CPU types within the same architecture.
Section 7.3 shows how the /dev/envram device driver uses the read_io_port and write_io_port interfaces to construct driver-specific interfaces to accomplish the tasks of reading from and writing to the device registers of an EISA bus nonvolatile random-access memory (NVRAM) expansion board. (The /dev/envram driver does not currently accommodate devices that operate on the ISA bus.)
The /dev/envram device driver example described in Chapter 7 uses the io_copyin, io_copyout, and io_zero interfaces. [Return to example]
Section 7.6.1 shows the probe interface for the /dev/envram device driver.
A device driver's xxslave interface is called only for a controller that has slave devices connected to it. This interface is called once for each slave attached to the controller. You (or the system manager) specify the attachments of these slave devices as follows:
The following code fragment shows you how to set up a slave interface for a driver that operates on an EISA or ISA bus:
xxslave(device, bus_io_handle) struct device *device; [1] io_handle_t bus_io_handle; [2] { /* Variable and structure declarations */
.
.
.
/* Code to check that the device is valid */
.
.
.
Device drivers pass the I/O handle to the following categories of interfaces, which are discussed in Writing Device Drivers: Tutorial. These interfaces can process the I/O handle to access the bus address space they need.
The read_io_port and write_io_port interfaces allow device drivers to read from and write to device registers. Using these interfaces to read data from and write data to a device register makes the device driver more portable across different bus architectures, different CPU architectures, and different CPU types within the same CPU architecture.
The io_copyin, io_copyio, io_copyout, and io_zero interfaces allow device drivers to perform I/O copy operations. Using these interfaces to perform the copy operation makes the device driver more portable across different CPU architectures and different CPU types within the same architecture.