JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Writing Device Drivers
search filter icon
search icon

Document Information


Part I Designing Device Drivers for the Solaris Platform

1.  Overview of Solaris Device Drivers

2.  Solaris Kernel and Device Tree

3.  Multithreading

4.  Properties

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

Memory Mapping Overview

Exporting the Mapping

The segmap(9E) Entry Point

The devmap(9E) Entry Point

Associating Device Memory With User Mappings

Associating Kernel Memory With User Mappings

Allocating Kernel Memory for User Access

Exporting Kernel Memory to Applications

Freeing Kernel Memory Exported for User Access

11.  Device Context Management

12.  Power Management

13.  Hardening 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

Part III Building a Device Driver

21.  Compiling, Loading, Packaging, and Testing Drivers

22.  Debugging, Testing, and Tuning Device Drivers

23.  Recommended Coding Practices

Part IV Appendixes

A.  Hardware Overview

B.  Summary of Solaris DDI/DKI Services

C.  Making a Device Driver 64-Bit Ready

D.  Console Frame Buffer Drivers


Associating Device Memory With User Mappings

Call devmap_devmem_setup(9F) from the driver's devmap(9E) entry point to export device memory to user applications.

The devmap_devmem_setup(9F) function has the following syntax:

int devmap_devmem_setup(devmap_cookie_t handle, dev_info_t *dip,
    struct devmap_callback_ctl *callbackops, uint_t rnumber, 
    offset_t roff, size_t len, uint_t maxprot, uint_t flags, 
    ddi_device_acc_attr_t *accattrp);



Opaque device-mapping handle that the system uses to identify the mapping.


Pointer to the device's dev_info structure.


Pointer to a devmap_callback_ctl(9S) structure that enables the driver to be notified of user events on the mapping.


Index number to the register address space set.


Offset into the device memory.


Length in bytes that is exported.


Allows the driver to specify different protections for different regions within the exported device memory.


Must be set to DEVMAP_DEFAULTS.


Pointer to a ddi_device_acc_attr(9S) structure.

The roff and len arguments describe a range within the device memory specified by the register set rnumber. The register specifications that are referred to by rnumber are described by the reg property. For devices with only one register set, pass zero for rnumber. The range is defined by roff and len. The range is made accessible to the user's application mapping at the offset that is passed in by the devmap(9E) entry point. Usually the driver passes the devmap(9E) offset directly to devmap_devmem_setup(9F). The return address of mmap(2) then maps to the beginning address of the register set.

The maxprot argument enables the driver to specify different protections for different regions within the exported device memory. For example, to disallow write access for a region, set only PROT_READ and PROT_USER for that region.

The following example shows how to export device memory to an application. The driver first determines whether the requested mapping falls within the device memory region. The size of the device memory is determined using ddi_dev_regsize(9F). The length of the mapping is rounded up to a multiple of a page size using ptob(9F) and btopr(9F). Then devmap_devmem_setup(9F) is called to export the device memory to the application.

Example 10-3 Using the devmap_devmem_setup() Routine

static int
xxdevmap(dev_t dev, devmap_cookie_t handle, offset_t off, size_t len,
    size_t *maplen, uint_t model)
    struct xxstate *xsp;
    int    error, rnumber;
    off_t regsize;
    /* Set up data access attribute structure */
    struct ddi_device_acc_attr xx_acc_attr = {
    xsp = ddi_get_soft_state(statep, getminor(dev));
    if (xsp == NULL)
        return (-1);
    /* use register set 0 */
    rnumber = 0;
    /* get size of register set */
    if (ddi_dev_regsize(xsp->dip, rnumber, &regsize) != DDI_SUCCESS)
        return (-1);
    /* round up len to a multiple of a page size */
       len = ptob(btopr(len));
    if (off + len > regsize)
        return (-1);
    /* Set up the device mapping */
    error = devmap_devmem_setup(handle, xsp->dip, NULL, rnumber, 
    off, len, PROT_ALL, DEVMAP_DEFAULTS, &xx_acc_attr);
    /* acknowledge the entire range */
    *maplen = len;
    return (error);