JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Writing Device Drivers     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

Part I Designing Device Drivers for the Oracle Solaris Platform

1.  Overview of Oracle Solaris Device Drivers

2.  Oracle Solaris Kernel and Device Tree

3.  Multithreading

4.  Properties

Device Properties

Device Property Names

Creating and Updating Properties

Looking Up Properties

Changes to the driver.conf File

prop_op() Entry Point

5.  Managing Events and Queueing Tasks

6.  Driver Autoconfiguration

7.  Device Access: Programmed I/O

8.  Interrupt Handlers

9.  Direct Memory Access (DMA)

10.  Mapping Device and Kernel Memory

11.  Device Context Management

12.  Power Management

13.  Hardening Oracle Solaris Drivers

14.  Layered Driver Interface (LDI)

Part II Designing Specific Kinds of Device Drivers

15.  Drivers for Character Devices

16.  Drivers for Block Devices

17.  SCSI Target Drivers

18.  SCSI Host Bus Adapter Drivers

19.  Drivers for Network Devices

20.  USB Drivers

21.  SR-IOV Drivers

Part III Building a Device Driver

22.  Compiling, Loading, Packaging, and Testing Drivers

23.  Debugging, Testing, and Tuning Device Drivers

24.  Recommended Coding Practices

Part IV Appendixes

A.  Hardware Overview

B.  Summary of Oracle Solaris DDI/DKI Services

C.  Making a Device Driver 64-Bit Ready

D.  Console Frame Buffer Drivers

E.  pci.conf File

Index

Device Properties

Device attribute information can be represented by a name-value pair notation called a property.

For example, device registers and onboard memory can be represented by the reg property. The reg property is a software abstraction that describes device hardware registers. The value of the reg property encodes the device register address location and size. Drivers use the reg property to access device registers.

Another example is the interrupt property. An interrupt property represents the device interrupt. The value of the interrupt property encodes the device-interrupt PIN.

Five types of values can be assigned to properties:

A property that has no value is considered to be a Boolean property. A Boolean property that exists is true. A Boolean value that does not exist is false.

Device Property Names

Strictly speaking, DDI/DKI software property names have no restrictions. Certain uses are recommended, however. The IEEE 1275-1994 Standard for Boot Firmware defines properties as follows:

A property is a human readable text string consisting of from 1 to 31 printable characters. Property names cannot contain upper case characters or the characters “/”, “\”, “:”, “[“, “]” and “@”. Property names beginning with the character “+” are reserved for use by future revisions of IEEE 1275-1994.

By convention, underscores are not used in property names. Use a hyphen (-) instead. By convention, property names ending with the question mark character (?) contain values that are strings, typically TRUE or FALSE, for example auto-boot?.

For a discussion of adding properties in driver configuration files, see the driver.conf(4) man page. The pm(9P) and pm-components(9P) man pages show how properties are used in power management. Read the sd(7D) man page as an example of how properties should be documented in device driver man pages.

Creating and Updating Properties

To create a property for a driver, or to update an existing property, use an interface from the DDI driver update interfaces such as ddi_prop_update_int(9F) or ddi_prop_update_string(9F) with the appropriate property type. See Table 4-1 for a list of available property interfaces. These interfaces are typically called from the driver's attach(9E) entry point. In the following example, ddi_prop_update_string()creates a string property called pm-hardware-state with a value of needs-suspend-resume.

/* The following code is to tell cpr that this device
 * needs to be suspended and resumed.
 */
(void) ddi_prop_update_string(device, dip,
    "pm-hardware-state", "needs-suspend-resume");

In most cases, using a ddi_prop_update() routine is sufficient for updating a property. Sometimes, however, the overhead of updating a property value that is subject to frequent change can cause performance problems. See prop_op() Entry Point for a description of using a local instance of a property value to avoid using ddi_prop_update().

Looking Up Properties

A driver can request a property from its parent, which in turn can ask its parent. The driver can control whether the request can go higher than its parent.

For example, the esp driver in the following example maintains an integer property called targetx-sync-speed for each target. The x in targetx-sync-speed represents the target number. The prtconf(1M) command displays driver properties in verbose mode. The following example shows a partial listing for the esp driver.

% prtconf -v
...
       esp, instance #0
            Driver software properties:
                name <target2-sync-speed> length <4>
                    value <0x00000fa0>.
...

The following table provides a summary of the property interfaces.

Table 4-1 Property Interface Uses

Family
Property Interfaces
Description
ddi_prop_lookup
Looks up a property and returns successfully if the property exists. Fails if the property does not exist
Looks up and returns an integer property
Looks up and returns a 64-bit integer property
Looks up and returns an integer array property
Looks up and returns a 64-bit integer array property
Looks up and returns a string property
Looks up and returns a string array property
Looks up and returns a byte array property
ddi_prop_update
Updates or creates an integer property
Updates or creates a single 64-bit integer property
Updates or creates an integer array property
Updates or creates a string property
Updates or creates a string array property
Updates or creates a 64-bit integer array property
Updates or creates a byte array property
ddi_prop_remove
Removes a property
Removes all properties that are associated with a device

Whenever possible, use 64-bit versions of int property interfaces such as ddi_prop_update_int64(9F) instead of 32-bit versions such as ddi_prop_update_int(9F)).

Changes to the driver.conf File

When a system running the Oracle Solaris OS is upgraded, new versions of drivers may be installed. During the upgrade process, the driver.conf file is also updated on the system. The driver.conf file is customized by both the vendor and the system administrator. During a system upgrade, the system's previous configuration should continue to work with the new drivers, the vendor's driver.conf file and with the administrator's driver.conf file.

In the Oracle Solaris 11 release, driver writers have an option to provide a separate driver.conf file that will contain the vendor provided driver data. The new driver.conf file is stored in the /etc/driver/drv directory. This enables the system to retain any administrative changes made to the file. If a driver is found in both the configuration files, the system will merge the files and present a file with the combined properties. The format of the vendor's driver.conf file is the same as the administrator's driver configuration file.

The vendor and administrative configuration data can now be made available to the driver explicitly via new interfaces. This enables the driver writer to encode any merge logic directly in the driver rather than in the class action scripts or the pre–install scripts and post–install scripts. The customizations made to the administrative file are preserved and the driver can decide on the relevance of the new values to the old values.

In order for a driver to ensure that the above model works well, the driver developer should consider the following:

Example 4-1 Driver Check for Locally Configured Timeout Value

     * Has the timeout been locally configured using the
+     * prior option of timeout in units of seconds?
+     */
+    if (ddi_prop_lookup_int(DDI_DEV_T_ANY, dip,
+        DDI_PROP_ADMIN, "timeout",&ivalues,&n) ==
+        DDI_PROP_SUCCESS) {
+        if (n != 1) {
+            ddi_prop_free(ivalues);
+            return (EINVAL);
+        }
+        /* yes - convert our working timeout accordingly */
+        dip->ms_timeout = 1000 * ivalues[0];
+        /* record the new parameter setting for confirmation */
+        (void) ddi_prop_update_int(DDI_DEV_T_NONE,
+            dip, "ms-timeout", dip->ms_timeout);
+        ddi_prop_free(ivalues);
+    }

The prtconf(1M) command displays the driver properties and the new -u option can be used to display the original property value and the changed property value.

prop_op() Entry Point

The prop_op(9E) entry point is generally required for reporting device properties or driver properties to the system. If the driver does not need to create or manage its own properties, then the ddi_prop_op(9F) function can be used for this entry point.

ddi_prop_op(9F) can be used as the prop_op(9E) entry point for a device driver when ddi_prop_op() is defined in the driver's cb_ops(9S) structure. ddi_prop_op() enables a leaf device to search for and obtain property values from the device's property list.

If the driver has to maintain a property whose value changes frequently, you should define a driver-specific prop_op() routine within the cb_ops structure instead of calling ddi_prop_op(). This technique avoids the inefficiency of using ddi_prop_update() repeatedly. The driver should then maintain a copy of the property value either within its soft-state structure or in a driver variable.

The prop_op(9E) entry point reports the values of specific driver properties and device properties to the system. In many cases, the ddi_prop_op(9F) routine can be used as the driver's prop_op() entry point in the cb_ops(9S) structure. ddi_prop_op() performs all of the required processing. ddi_prop_op() is sufficient for drivers that do not require special processing when handling device property requests.

However, sometimes the driver must provide a prop_op() entry point. For example, if a driver maintains a property whose value changes frequently, updating the property with ddi_prop_update(9F) for each change is not efficient. Instead, the driver should maintain a shadow copy of the property in the instance's soft state. The driver would then update the shadow copy when the value changes without using any of the ddi_prop_update() routines. The prop_op() entry point must intercept requests for this property and use one of the ddi_prop_update() routines to update the value of the property before passing the request to ddi_prop_op() to process the property request.

In the following example, prop_op() intercepts requests for the temperature property. The driver updates a variable in the state structure whenever the property changes. However, the property is updated only when a request is made. The driver then uses ddi_prop_op() to process the property request. If the property request is not specific to a device, the driver does not intercept the request. This situation is indicated when the value of the dev parameter is equal to DDI_DEV_T_ANY, the wildcard device number.

Example 4-2 prop_op() Routine

static int
xx_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
    int flags, char *name, caddr_t valuep, int *lengthp)
{
        minor_t instance;
        struct xxstate *xsp;
        if (dev != DDI_DEV_T_ANY) {
                return (ddi_prop_op(dev, dip, prop_op, flags, name,
                    valuep, lengthp));
        }

        instance = getminor(dev);
        xsp = ddi_get_soft_state(statep, instance);
        if (xsp == NULL)
                return (DDI_PROP_NOTFOUND);
        if (strcmp(name, "temperature") == 0) {
                ddi_prop_update_int(dev, dip, name, temperature);
        }

        /* other cases */    
}