Device Driver Tutorial

Devices as Files

In UNIX, almost everything can be treated as a file. UNIX user applications access devices as if the devices were files. Files that represent devices are called special files or device nodes. Device special files are divided into two classes: block devices and character devices. See Character and Block Devices for more information.

Every I/O service request initially refers to a named file. Most I/O operations that read or write data perform equally well on ordinary or special files. For example, the same read(2) system call reads bytes from a file created with a text editor and reads bytes from a terminal device.

Control signals also are handled as files. Use the ioctl(9E) function to manipulate control signals.

Devices Directories

The Oracle Solaris OS includes both /dev and /devices directories for device drivers. Almost all the drivers in the /dev directory are links to the /devices directory. The /dev directory is UNIX standard. The /devices directory is specific to the Oracle Solaris OS.

By convention, file names in the /dev directory are more readable. For example, the /dev directory might contain files with names such as kdb and mouse that are links to files such as /devices/pseudo/conskbd@0:kbd and /devices/pseudo/consms@0:mouse. The prtconf(1M) command shows device names that are very similar to the file names in the /devices directory. In the following example, only selected output of the command is shown.


% prtconf -P
        conskbd, instance #0
        consms, instance #0

Entries in the /dev directory that are not links to the /devices directory are device nodes or special files created by mknod(1M) or mknod(2). These are zero-length files that just have a major number and minor number attached to them. Linking to the physical name of the device in the /devices directory is preferred to using mknod(1M).

Prior to the Oracle Solaris 10 OS, /devices was an on-disk filesystem composed of subdirectories and files. Beginning with the Oracle Solaris 10 OS, /devices is a virtual filesystem that creates these subdirectories and special files on demand.

For more information about the devices file system, see the devfs(7FS) man page.

Device Tree

The device files in the /devices directory are also called the device tree.

The device tree shows relationships among devices. In the device tree, a directory represents a nexus device. A nexus is a device that can be a parent of other devices. In the following example, pci@1f,0 is a nexus device. Only selected output from the command is shown.


# ls -l /devices
drwxr-xr-x   4 root     sys          512 date time pci@1f,0/
crw-------   1 root     sys      111,255 date time pci@1f,0:devctl

You can use prtconf(1M) or prtpicl(1M) to see a graphic representation of the device tree. See Overview of the Device Tree in Writing Device Drivers for more information about the device tree.

Character and Block Devices

A file in the device tree that is not a directory represents either a character device or a block device.

A block device can contain addressable, reusable data. An example of a block device is a file system. Any device can be a character device. Most block devices also have character interfaces. Disks have both block and character interfaces. In your /devices/pseudo directory, you might find devices such as the following:

brw-r-----   1 root     sys       85,  0 Nov  3 09:43 md@0:0,0,blk
crw-r-----   1 root     sys       85,  0 Nov  3 09:43 md@0:0,0,raw
brw-r-----   1 root     sys       85,  1 Nov  3 09:43 md@0:0,1,blk
crw-r-----   1 root     sys       85,  1 Nov  3 09:43 md@0:0,1,raw
brw-r-----   1 root     sys       85,  2 Nov  3 09:43 md@0:0,2,blk
crw-r-----   1 root     sys       85,  2 Nov  3 09:43 md@0:0,2,raw

Block devices have a b as the first character of their file mode. Character devices have a c as the first character of their file mode. In this example, the block devices have blk in their names and the character devices have raw in their names.

The md(7D) device is a metadevice that provides disk services. The block devices access the disk using the system's normal buffering mechanism. The character devices provide for direct transmission between the disk and the user's read or write buffer.

Device Names

This section shows a complex device name and explains the meaning of each part of the name in /dev and also in /devices. The following example is the name of a disk slice:


/dev/dsk/c0t0d0s7 -> ../../devices/pci@1c,600000/scsi@2/sd@0,0:h

First, examine the name of the file in the /dev directory. These names are managed by the devfsadmd(1M) daemon.

c0

Controller 0

t0

Target 0. On SCSI controllers, this value is the disk number.

d0

SCSI LUN. This value indicates a virtual partitioning of a target or single physical device.

s7

Slice 7 on the target 0 disk.

For the same device, compare the name of the file in the /devices directory. These names show the physical structure and real device names. Note that some of the components of the device name in the /devices directory are subdirectories.

pci@1c,600000

PCI bus at address 1c,600000. These addresses are meaningful only to the parent device.

scsi@2

SCSI controller at address 2 on the PCI bus at address 1c,600000. This name corresponds to the c0 in /dev/dsk/c0t0d0s7.

sd@0,0

SCSI disk at address 0,0 on the SCSI controller at address 2. This name represents target 0, LUN 0 and corresponds to the t0d0 in /dev/dsk/c0t0d0s7. The sd name and driver can also apply to IDE CD-ROM devices.

sd@0,0:h

Minor node h on the SCSI disk at address 0,0. This name corresponds to the s7 in /dev/dsk/c0t0d0s7.

Device Numbers

A device number identifies a particular device and minor node in the device tree. The dev_t parameter that is required in many DDI/DKI routines is this device number.

Each device has a major number and a minor number. A device number is a major,minor pair. A long file listing shows the device number in the column where file sizes are usually listed. In the following example, the device number is 86,255. The device major number is 86, and the device minor number is 255.


% ls -l /devices/pci@0,0:devctl
crw-------   1 root     sys       86,255 date time /devices/pci@0,0:devctl

In the Oracle Solaris OS, the major number is chosen for you when you install the driver so that it will not conflict with any other major number. The kernel uses the major number to associate the I/O request with the correct driver code. The kernel uses this association to decide which driver to execute when the user reads or writes the device file. All devices and their major numbers are listed in the file /etc/name_to_major.


% grep 86 /etc/name_to_major
pci 86

The minor number is assigned in the driver. The minor number must map each driver to a specific device instance. Minor numbers usually refer to sub-devices. For example, a disk driver might communicate with a hardware controller device that has several disk drives attached. Minor nodes do not necessarily have a physical representation.

The following example shows instances 0, 1, and 2 of the md device. The numbers 0, 1, and 2 are the minor numbers.

brw-r-----   1 root     sys       85,  0 Nov  3 09:43 md@0:0,0,blk
crw-r-----   1 root     sys       85,  0 Nov  3 09:43 md@0:0,0,raw
brw-r-----   1 root     sys       85,  1 Nov  3 09:43 md@0:0,1,blk
crw-r-----   1 root     sys       85,  1 Nov  3 09:43 md@0:0,1,raw
brw-r-----   1 root     sys       85,  2 Nov  3 09:43 md@0:0,2,blk
crw-r-----   1 root     sys       85,  2 Nov  3 09:43 md@0:0,2,raw

In the name sd@0,0:h,, h represents a minor node. When the driver receives a request for minor node h, the driver actually receives a corresponding minor number. The driver for the sd node interprets that minor number to be a particular section of disk, such as slice 7 mounted on /export.

Chapter 2, Template Driver Example shows how to use the ddi_get_instance(9F) routine in your driver to get an instance number for the device you are driving.