Writing Device Drivers

Associating User Mappings With Driver Notifications

When a user process requests a mapping to a device with mmap(2), the driver`s segmap(9E) entry point is called. The driver must use ddi_devmap_segmap(9F) or devmap_setup(9F) when setting up the memory mapping if the driver needs to manage device contexts. Both functions call the driver's devmap(9E) entry point, which uses devmap_devmem_setup(9F) to associate the device memory with the user mapping. See Chapter 10, Mapping Device and Kernel Memory for details on how to map device memory.

The driver must inform the system of the devmap_callback_ctl(9S) entry points to get notifications of accesses to the user mapping. The driver informs the system by providing a pointer to a devmap_callback_ctl(9S) structure to devmap_devmem_setup(9F). A devmap_callback_ctl(9S) structure describes a set of entry points for context management. These entry points are called by the system to notify a device driver to manage events on the device mappings.

The system associates each mapping with a mapping handle. This handle is passed to each of the entry points for context management. The mapping handle can be used to invalidate and validate the mapping translations. If the driver invalidates the mapping translations, the driver will be notified of any future access to the mapping. If the driver validates the mapping translations, the driver will no longer be notified of accesses to the mapping. Mappings are always created with the mapping translations invalidated so that the driver will be notified on first access to the mapping.

The following example shows how to set up a mapping using the device context management interfaces.


Example 11–6 devmap(9E) Entry Point With Context Management Support

static struct devmap_callback_ctl xx_callback_ctl = {
    DEVMAP_OPS_REV, xxdevmap_map, xxdevmap_access,
    xxdevmap_dup, xxdevmap_unmap
};

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;
    uint_t rnumber;
    int    error;
    
    /* Setup data access attribute structure */
    struct ddi_device_acc_attr xx_acc_attr = {
        DDI_DEVICE_ATTR_V0,
        DDI_NEVERSWAP_ACC,
        DDI_STRICTORDER_ACC
    };
    xsp = ddi_get_soft_state(statep, getminor(dev));
    if (xsp == NULL)
        return (ENXIO);
    len = ptob(btopr(len));
    rnumber = 0;
    /* Set up the device mapping */
    error = devmap_devmem_setup(handle, xsp->dip, &xx_callback_ctl,
        rnumber, off, len, PROT_ALL, 0, &xx_acc_attr);
    *maplen = len;
    return (error);
}