Part I Designing Device Drivers for the Solaris Platform
1. Overview of Solaris Device Drivers
2. Solaris Kernel and Device Tree
5. Managing Events and Queueing Tasks
7. Device Access: Programmed I/O
10. Mapping Device and Kernel Memory
14. Layered Driver Interface (LDI)
Part II Designing Specific Kinds of Device Drivers
15. Drivers for Character Devices
18. SCSI Host Bus Adapter Drivers
19. Drivers for Network Devices
Part III Building a Device Driver
21. Compiling, Loading, Packaging, and Testing Drivers
Installing, Updating, and Removing Drivers
Copying the Driver to a Module Directory
Installing Drivers with add_drv
Stress, Performance, and Interoperability Testing
Installation and Packaging Testing
Testing Specific Types of Drivers
Asynchronous Communication Drivers
22. Debugging, Testing, and Tuning Device Drivers
23. Recommended Coding Practices
B. Summary of Solaris DDI/DKI Services
C. Making a Device Driver 64-Bit Ready
The following steps precede installation of a driver:
Compile the driver.
Create a configuration file if necessary.
Identify the driver module to the system through either of the following alternatives:
Match the driver's name to the name of the device node.
Use either add_drv(1M) or update_drv(1M) to inform the system of the module names.
The system maintains a one-to-one association between the name of the driver module and the name of the dev_info node. For example, consider a dev_info node for a device that is named mydevice. The device mydevice is handled by a driver module that is also named mydevice. The mydevice module resides in a subdirectory that is called drv, which is in the module path. The module is in drv/mydevice if you are using a 32-bit kernel. The module is in drv/sparcv9/mydevice if you are using a 64-bit SPARC kernel. The module is in drv/amd64/mydevice if you are using a 64-bit x86 kernel.
If the driver is a STREAMS network driver, then the driver name must meet the following constraints:
Only alphanumeric characters (a-z, A-Z, 0-9), plus the underscore ('_'), are allowed.
Neither the first nor the last character of the name can be a digit.
The name cannot exceed 16 characters in length. Names in the range of 3-8 characters in length are preferable.
If the driver must manage dev_info nodes with different names, the add_drv(1M) utility can create aliases. The -i flag specifies the names of other dev_info nodes that the driver handles. The update_drv command can also modify aliases for an installed device driver.
You need to compile each driver source file and link the resulting object files into a driver module. The Solaris OS is compatible with both the Sun Studio C compiler and the GNU C compiler from the Free Software Foundation, Inc. The examples in this section use the Sun Studio C compiler unless otherwise noted. For information on the Sun Studio C compiler, see the Sun Studio 12: C User’s Guide and the Sun Studio Documentation on the Sun Developer Network web site. For more information on compile and link options, see the Sun Studio Man Pages. The GNU C compiler is supplied in the /usr/sfw directory. For information on the GNU C compiler, see http://gcc.gnu.org/ or check the man pages in /usr/sfw/man.
The example below shows a driver that is called xx with two C source files. A driver module that is called xx is generated. The driver that is created in this example is for a 32-bit kernel. You must use ld -r even if your driver has only one object module.
% cc -D_KERNEL -c xx1.c % cc -D_KERNEL -c xx2.c % ld -r -o xx xx1.o xx2.o
The _KERNEL symbol must be defined to indicate that this code defines a kernel module. No other symbols should be defined, except for driver private symbols. The DEBUG symbol can be defined to enable any calls to ASSERT(9F).
If you are compiling for a 64-bit SPARC architecture using Sun Studio 9, Sun Studio 10, or Sun Studio 11, use the -xarch=v9 option:
% cc -D_KERNEL -xarch=v9 -c xx.c
If you are compiling for a 64-bit SPARC architecture using Sun Studio 12, use the -m64 option:
% cc -D_KERNEL -m64 -c xx.c
If you are compiling for a 64-bit x86 architecture using Sun Studio 10 or Sun Studio 11, use both the -xarch=amd64 option and the -xmodel=kernel option:
% cc -D_KERNEL -xarch=amd64 -xmodel=kernel -c xx.c
If you are compiling for a 64-bit x86 architecture using Sun Studio 12, use the -m64 option, the -xarch=sse2a option, and the -xmodel=kernel option:
% cc -D_KERNEL -m64 -xarch=sse2a -xmodel=kernel -c xx.c
Note - Sun Studio 9 does not support 64-bit x86 architectures. Use Sun Studio 10, Sun Studio 11, or Sun Studio 12 to compile and debug drivers for 64-bit x86 architectures.
After the driver is stable, you might want to add optimization flags to build a production quality driver. See the cc(1) man page in Sun Studio Man Pages for specific information on optimizations in the Sun Studio C compiler.
Global variables should be treated as volatile in device drivers. The volatile tag is discussed in greater detail in Declaring a Variable Volatile. Use of the flag depends on the platform. See the man pages.
If the driver module depends on symbols exported by another kernel module, the dependency can be specified by the -dy and -N options of the loader, ld(1). If the driver depends on a symbol exported by misc/mySymbol, the example below should be used to create the driver binary.
% ld -dy -r -o xx xx1.o xx2.o -N misc/mySymbol
If a device is non-self-identifying, the kernel requires a hardware configuration file for that device. If the driver is called xx, the hardware configuration file for the driver should be called xx.conf. See the driver.conf(4), pseudo(4), sbus(4), scsi_free_consistent_buf(9F), and update_drv(1M) man pages for more information on hardware configuration files.
Arbitrary properties can be defined in hardware configuration files. Entries in the configuration file are in the form property=value, where property is the property name and value is its initial value. The configuration file approach enables devices to be configured by changing the property values.