Before writing a driver for hardware that runs Digital UNIX, you must be familiar with general driver concepts as well as specific tasks you need to perform to successfully code the driver. This book presumes you understand the following concepts:
The following sections review the tasks associated with writing device drivers. Writing Device Drivers: Tutorial discusses these tasks in detail.
The first task in writing a device driver is to gather pertinent information about the host system and the device for which you are writing the driver. For example, you need to:
After you gather information about the host system and the device, you are ready to design and develop the device driver. You need to specify the driver type and whether the driver you are writing will be statically or dynamically configured into the kernel. During the design of the driver, you also identify device driver entry points and describe the driver states.
Data structures are the mechanism used to pass information between the kernel and device driver interfaces. The following table summarizes data structures, which are described in Writing Device Drivers: Tutorial and Writing Device Drivers: Reference:
buf | Describes arbitrary I/O. |
bus | Represents an instance of a bus entity to which other buses or controllers are logically attached. |
cfg_attr_t | Contains information for managing the loading and unloading of drivers. |
cfg_subsys_attr_t | Contains attribute information for drivers. |
controller | Contains members that store information about hardware resources and store data for communication between the kernel and the device driver. |
controller_config | Contains information needed to create a controller structure. |
DEVGEOMST | Stores disk device geometry. |
devget | Contains information about a device. |
device | Contains information that identifies the device. There is one device data structure for each device connected to the controller. |
device_config | Contains information needed to create a device structure. |
device_info_t | Is the top-level union that stores bus- and device-type information. |
disklabel | Stores disk device label information. |
driver | Defines driver entry points and other driver-specific information. You initialize this data structure in the device driver. |
dsent | Defines a device driver's entry points and other information. |
handler_intr_info | Contains interrupt handler information. |
ihandler_t | Contains information associated with device driver interrupt handling. |
item_list | Contains hardware platform-specific information. |
lock | Contains complex lock-specific information. |
port | Contains information about a port. |
pt_tbl | Stores a disk partition map. |
sel_queue | Defines a queue of select events. |
sg_entry | Contains bus address/byte count pairs. |
slock | Contains simple lock-specific information. |
task | Contains task-specific information. |
thread | Contains kernel threads-related information. |
uio | Describes I/O, either single vector or multiple vectors. |
v1_bustype_info_t | Stores bus information. |
v1_device_info_t | Is the top-level union that stores bus- and device-type information. |
v1_devtype_info_t | Stores device-type information. |
v1_disk_dev_info_t | Stores disk information. |
v1_tape_dev_info_t | Stores tape information. |
When designing a device driver, you must decide on the technique you will use for allocating data structures. Generally, there are two techniques you can use: dynamic allocation and static allocation. Dynamic allocation is the recommended method for all new drivers; some existing drivers allocate data structures statically. If you know that the maximum number of devices is greater than five or that the driver uses numerous data structures, plan to use the dynamic allocation method. You should also use the dynamic allocation method for allocating data structures in loadable device drivers.
Whenever possible, design your device driver so that it can accommodate peripheral devices that operate on different bus architectures, different CPU architectures, and more than one CPU type within the same architecture. You need to consider the following issues to make your drivers portable across CPU architectures:
You need to consider the following issues to make your drivers portable across bus architectures:
You must consider these issues also if you have an ULTRIX device driver that
you want to port to Digital UNIX.
See
Writing Device Drivers: Tutorial
for a discussion of the additional tasks you need to perform to port an
ULTRIX device driver to Digital UNIX.
Also, see the porting chapter in
Writing Device Drivers: Tutorial
for a discussion of the issues associated with updating device drivers
written for a previous version of Digital UNIX to the current version of
the operating system.
Although existing device drivers are binary compatible with the current
version of Digital UNIX, you might want to make the changes suggested in
the porting chapter of the tutorial.
Note
See Writing Device Drivers: Tutorial for information on the CSR I/O access interfaces. These interfaces allow you to read from and write to a device's CSR addresses without directly accessing its device registers. Each of these interfaces takes an I/O handle that bus configuration code passes to the driver's probe interface.
When you are ready to write your driver, you may want to study the device driver kits delivery process and create an appropriate device driver development environment.
Writing Device Drivers: Tutorial describes the device driver kits delivery process and how to statically and dynamically configure drivers into the kernel. The tutorial discusses how to write device drivers for computer systems running Digital UNIX.
Digital recommends that you implement all new device drivers (loadable and static) to call the handler interfaces and reference the handler-specific data structures to register their device interrupt handlers. (See Writing Device Drivers: Tutorial for more information.)