This page provides an overview of device driver interfaces and all of the
Section 9 man pages (9E, 9F, 9P, and 9S). This overview is followed by an
introduction to Section 9E, the driver entry-point routines.
Section 9 provides reference information needed to write device drivers for the
illumos operating system. It describes the interfaces provided by the Device
Driver Interface and the Driver-Kernel Interface (DDI/DKI).
Software is usually considered portable if it can be adapted to run in a
different environment more cheaply than it can be rewritten. The new
environment may include a different processor, operating system, and even the
language in which the program is written, if a language translator is
available. Likewise the new environment might include multiple processors.
More often, however, software is ported between environments that share an
operating system, processor, and source language. The source code is modified
to accommodate the differences in compilers or processors or releases of the
operating system.
In the past, device drivers did not port easily for one or more of
the following reasons:
- o
- To enhance functionality, members had been added to kernel data structures
accessed by drivers, or the sizes of existing members had been
redefined.
- o
- The calling or return syntax of kernel functions had changed.
- o
- Driver developers did not use existing kernel functions where available,
or relied on undocumented side effects that were not maintained in the
next release.
- o
- Architecture-specific code had been scattered throughout the driver when
it could have been isolated.
Operating systems are periodically reissued to customers as a way
to improve performance, fix bugs, and add new features. This is probably the
most common threat to compatibility encountered by developers responsible
for maintaining software. Another common problem is upgrading hardware. As
new hardware is developed, customers occasionally decide to upgrade to
faster, more capable computers of the same family. Although they may run the
same operating system as those being replaced, architecture-specific code
may prevent the software from porting.
Although application programs have all of the porting problems mentioned,
developers attempting to port device drivers have special challenges. Before
describing the DDI/DKI, it is necessary to understand the position of device
drivers in operating systems.
Device drivers are kernel modules that control data transferred to
and received from peripheral devices but are developed independently from
the rest of the kernel. If the goal of achieving complete freedom in
modifying the kernel is to be reconciled with the goal of binary
compatibility with existing drivers, the interaction between drivers and the
kernel must be rigorously regulated. This driver/kernel service interface is
the most important of the three distinguishable interfaces for a driver,
summarized as follows:
- o
- Driver-Kernel. I/O System calls result in calls to driver entry point
routines. These make up the kernel-to-driver part of the service
interface, described in Section 9E. Drivers may call any of the functions
described in Section 9F. These are the driver-to-kernel part of the
interface.
- o
- Driver-Hardware. All drivers (except software drivers) must include code
for interrupt handling, and may also perform direct memory access (DMA).
These and other hardware-specific interactions make up the driver/hardware
interface.
- o
- Driver-Boot/Configuration Software. The interaction between the driver and
the boot and configuration software is the third interface affecting
drivers.
The primary goal of the DDI/DKI is to facilitate both source and binary
portability across successive releases of the operating systems on a
particular machine. In addition, it promotes source portability across
implementations of UNIX on different machines, and applies only to
implementations based on System V Release 4. The DDI/DKI consists of several
sections:
- o
- DDI/DKI Architecture Independent - These interfaces are supported on all
implementations of System V Release 4.
- o
- DKI-only - These interfaces are part of System V Release 4, and may not be
supported in future releases of System V. There are only two interfaces in
this class, segmap(9E) and hat_getkpfnum(9F)
- o
- illumos DDI - These interfaces specific to illumos.
- o
- illumos SPARC specific DDI - These interfaces are specific to the SPARC
processor, and may not be available on other processors supported by
illumos.
- o
- illumos x86 specific DDI - These interfaces are specific to the x86
processor, and may not be available on other processors supported by
illumos.
To achieve the goal of source and binary compatibility, the
functions, routines, and structures specified in the DDI/DKI must be used
according to these rules.
- o
- Drivers cannot access system state structures (for example, u and
sysinfo) directly.
- o
- For structures external to the driver that may be accessed directly, only
the utility functions provided in Section 9F should be used. More
generally, these functions should be used wherever possible.
- o
- The headers <sys/ddi.h> and <sys/sunddi.h> must
be the last header files included by the driver.
Section 9 is for software engineers responsible for creating, modifying, or
maintaining drivers that run on this operating system and beyond. It assumes
that the reader is familiar with system internals and the C programming
language.
The PC Card 95 Standard is listed under the
SEE ALSO heading in some Section 9 reference pages. This refers
to documentation published by the Personal Computer Memory Card International
Association (PCMCIA) and the Japan Electronic Industry Development Association
(JEIDA).
Section 9 is divided into the following subsections:
9E
Driver Entry Points - contains reference pages for all
driver entry point routines.
9F
Kernel Functions - contains reference pages for all
driver support routines.
9P
Driver Properties - contains reference pages for driver
properties.
9S
Data Structures - contains reference pages for
driver-related structures.
Sun Microsystem's implementation of the DDI/DKI was designed to provide binary
compatibility for third-party device drivers across currently supported
hardware platforms across minor releases of the operating system. However,
unforeseen technical issues may force changes to the binary interface of the
DDI/DKI. We cannot therefore promise or in any way assure that
DDI/DKI-compliant device drivers will continue to operate correctly on future
releases.
Section 9E describes the entry-point routines a developer can include in a
device driver. These are called entry-point because they provide the calling
and return syntax from the kernel into the driver. Entry-points are called,
for instance, in response to system calls, when the driver is loaded, or in
response to STREAMS events.
Kernel functions usable by the driver are described in section
9F.
In this section, reference pages contain the following
headings:
- o
- NAME describes the routine's purpose.
- o
- SYNOPSIS summarizes the routine's calling and return syntax.
- o
- INTERFACE LEVEL describes any architecture dependencies. It also
indicates whether the use of the entry point is required, optional, or
discouraged.
- o
- ARGUMENTS describes each of the routine's arguments.
- o
- DESCRIPTION provides general information about the routine.
- o
- RETURN VALUES describes each of the routine's return values.
- o
- SEE ALSO gives sources for further information.
By convention, a prefix string is added to the driver routine names. For a
driver with the prefix prefix, the driver code may contain routines
named prefixopen, prefixclose, prefixread,
prefixwrite, and so forth. All global variables associated with the
driver should also use the same prefix.
All routines and data should be declared as static.
Every driver MUST include <sys/ddi.h> and
<sys/sunddi.h>, in that order, and after all other include
files.
The following table summarizes the STREAMS driver entry points
described in this section.
Routine |
Type |
put |
DDI/DKI |
srv |
DDI/DKI |
The following table summarizes the driver entry points described
in this section.
Routine |
Type |
_fini |
illumos DDI |
_info |
illumos DDI |
_init |
illumos DDI |
aread |
illumos DDI |
attach |
illumos DDI |
awrite |
illumos DDI |
chpoll |
DDI/DKI |
close |
DDI/DKI |
detach |
illumos DDI |
devmap |
illumos DDI |
devmap_access |
illumos DDI |
devmap_contextmgt |
illumos DDI |
devmap_dup |
illumos DDI |
devmap_map |
illumos DDI |
devmap_unmap |
illumos DDI |
dump |
illumos DDI |
getinfo |
illumos DDI |
identify |
illumos DDI |
ioctl |
DDI/DKI |
ks_update |
illumos DDI |
mapdev_access |
illumos DDI |
mapdev_dup |
illumos DDI |
mapdev_free |
illumos DDI |
mmap |
DKI only |
open |
DDI/DKI |
power |
illumos DDI |
print |
DDI/DKI |
probe |
illumos DDI |
prop_op |
illumos DDI |
read |
DDI/DKI |
segmap |
DKI only |
strategy |
DDI/DKI |
tran_abort |
illumos DDI |
tran_destroy_pkt |
illumos DDI |
tran_dmafree |
illumos DDI |
tran_getcap |
illumos DDI |
tran_init_pkt |
illumos DDI |
tran_reset |
illumos DDI |
tran_reset_notify |
illumos DDI |
tran_setcap |
illumos DDI |
tran_start |
illumos DDI |
tran_sync_pkt |
illumos DDI |
tran_tgt_free |
illumos DDI |
tran_tgt_init |
illumos DDI |
tran_tgt_probe |
illumos DDI |
write |
DDI/DKI |
The following table lists the error codes returned by a driver
routine when it encounters an error. The error values are listed in
alphabetic order and are defined in sys/errno.h. In the driver
open(9E), close(9E), ioctl(9E), read(9E), and
write(9E) routines, errors are passed back to the user by calling
bioerror(9F) to set b_flags to the proper error code. In the
driver strategy(9E) routine, errors are passed back to the user by
setting the b_error member of the buf(9S) structure to the
error code. For STREAMS ioctl routines, errors should be sent
upstream in an M_IOCNAK message. For STREAMS read() and
write() routines, errors should be sent upstream in an M_ERROR
message. The driver print routine should not return an error code
because the function that it calls, cmn_err(9F), is declared as
void (no error is returned).
Error Value |
Error Description |
EAGAIN |
Kernel resources, such as the buf structure or cache memory, are not
available at this time (device may be busy, or the system resource is not
available). This is used in open, ioctl, read, write, and strategy. |
EFAULT |
An invalid address has been passed as an argument; memory addressing
error. This is used in open, close, ioctl, read, write, and strategy. |
EINTR |
Sleep interrupted by signal. This is used in open, close, ioctl, read,
write, and strategy. |
EINVAL |
An invalid argument was passed to the routine. This is used in open,
ioctl, read, write, and strategy. |
EIO |
A device error occurred; an error condition was detected in a device
status register (the I/O request was valid, but an error occurred on the
device). This is used in open, close, ioctl, read, write, and
strategy. |
ENXIO |
An attempt was made to access a device or subdevice that does not exist
(one that is not configured); an attempt was made to perform an invalid
I/O operation; an incorrect minor number was specified. This is used in
open, close, ioctl, read, write, and strategy. |
EPERM |
A process attempting an operation did not have required permission. This
is used in open, ioctl, read, write, and strategy. |
EROFS |
An attempt was made to open for writing a read-only device. This is used
in open. |
The table below cross references error values to the driver
routines from which the error values can be returned.
open |
close |
ioctl |
read, write and strategy |
EAGAIN |
EFAULT |
EAGAIN |
EAGAIN |
EFAULT |
EINTR |
EFAULT |
EFAULT |
EINTR |
EIO |
EINTR |
EINTR |
EINVAL |
ENXIO |
EINVAL |
EINVAL |
EIO |
|
EIO |
EIO |
ENXIO |
|
ENXIO |
ENXIO |
EPERM |
|
EPERM |
EROFS |