Writing Device Drivers

Development Environment

DDI/DKI

The device driver interface/driver-kernel interface (DDI/DKI) is a new name for the routines formerly called "kernel support routines" in the SunOS 4.1 Writing Device Drivers manual, and for the "well-known" entry points in the SunOS 4.1 cdevsw and bdevsw structures. The intent is to specify a set of interfaces for drivers that provide a binary and source code interface. If a driver uses only kernel routines and structures described in Section 9 of the Solaris 2.6 Reference Manual, it is called Solaris 7 DDI/DKI-compliant. A Solaris 7 DDI/DKI-compliant driver is likely to be binary compatible across Sun Solaris platforms with the same processor, and binary compatible with future releases of Solaris on platforms the driver works on.

Avoid Using Non-DDI/DKI Interfaces

Many architecture-specific features have been hidden from driver writers behind DDI/DKI interfaces. Specific examples are elements of the dev_info structure, user structure, proc structure, and page tables. If the driver has been using unadvertised interfaces, it must be changed to use DDI/DKI interfaces that provide the required functionality. If the driver continues to use unadvertised interfaces, it loses all the source and binary compatibility features of the DDI/DKI. For example, previous releases had an undocumented routine called as_fault( ) that could be used to lock down user pages in memory. This routine still exists, but is not part of the DDI/DKI, so it should not be used. The only documented way to lock down user memory is to use physio(9F).

Do not use any undocumented fields of structures. Documented fields are in Section 9S of the Solaris 2.6 Reference Manual. Do not use fields, structures, variables, or macros just because they are in a header file.

Dynamically allocate structures whenever possible. If buf(9S) structure is needed, do not declare one. Instead, declare a pointer to one, and call getrbuf(9F) to allocate it.


Note -

Even using kmem_alloc(sizeof(struct buf)) is not allowed, because the size of a buf(9S) structure might change in future releases.


UNIX System V Release 4

The SunOS 5.7 system is the Sun version of AT&T's System V Release 4 (SVR4). The system administration model is different from those in previous SunOS releases, which were more like 4.3 BSD. Differences important to device driver writers are:

For general SVR4 system administration information, see the Solaris Transition Guide.

Development Tools

The only compiler that should be used to compile SunOS 5.7 device drivers is the unbundled Sun C compiler, Sun WorkShop Compiler C 4.2. See Chapter 15, Loading and Unloading Drivers for information on how to compile and load a driver. Note that the compiler's bin directory (possibly /opt/SUNWspro/bin) and the supporting tools directory (/usr/ccs/bin) should be prepended to the PATH. When compiling a driver, use the -Xt and -D_KERNEL options.

When building a loadable driver module from the object modules, use ld(1) with the -r flag.

Debugging Tools

adb(1), kadb(1M), and crash(1M) are essentially the same as they were in the SunOS 4.1 system, though there are new macros. To debug a live kernel, use /dev/ksyms (see ksyms(7)) instead of the kernel name (which used to be /vmunix):

# adb -k /dev/ksyms /dev/mem

See "Debugging Tools" for more information.

ANSI C Features

The unbundled Sun C compiler is now ANSI C compliant. Two important ANSI C features device driver writers should use are the volatile keyword and function prototyping.

volatile

volatile is an ANSI C keyword that is used to prevent the optimizer from removing what it thinks are unnecessary accesses to objects. As an example, if the device has a control register that requires two consecutive writes to get it to take action, the optimizer could decide that the first write is unnecessary since the value is unused if there is no intervening read access.

If a device driver does not use the DDI data access functions to access device registers, device registers should be declared volatile. However, if the DDI data access functions are used to access device registers, it is not necessary to use volatile.


Note -

It is not an error to declare a variable volatile unnecessarily, but it might impact performance.


Function Prototypes

ANSI C provides function prototypes. This allows the compiler to check the type and number of arguments to functions, and avoids default argument promotions. To prototype functions, declare the type and name of each function in the function definition. Then provide a prototype declaration (including at least the types) before the function is called.

Prototypes are provided for most DDI/DKI functions, so many potentially fatal errors are now caught at compile time.

Header Files

For Solaris 7 DDI/DKI compliance, drivers are allowed to include only the kernel header files listed in the synopsis sections of Section 9 of the Solaris 2.6 Reference Manual. All allowed kernel header files are now located in the /usr/include/sys directory.

New header files all drivers must include are <sys/ddi.h> and <sys/sunddi.h>. These two headers must appear last in the list of kernel header include files.