Writing Device Drivers

Mapping Device Memory

Some devices, such as frame buffers, have memory that is directly accessible to user threads by way of memory mapping. Drivers for these devices typically do not support the read(9E) and write(9E) interfaces. Instead, these drivers support memory mapping with the devmap(9E) entry point. A typical example is a frame buffer driver that implements the devmap(9E) entry point to allow the frame buffer to be mapped in a user thread.

segmap() Entry Point

int xxsegmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp,
     off_t len, unsigned int prot, unsigned int maxprot,
     unsigned int flags, cred_t *credp);

segmap(9E) is the entry point responsible for actually setting up a memory mapping requested by the system on behalf of an mmap(2) system call. Drivers for many memory-mapped devices will use ddi_devmap_segmap(9F) as the entry point rather than defining their own segmap(9E) routine.

If a driver wants to check mapping permissions or allocate private mapping resources before setting up the mapping, the driver can provide its own segmap(9E) entry point. segmap(9E) must call devmap_setup(9F) before returning.

In Example 10–10, the driver controls a frame buffer that allows write-only mappings. The driver returns EINVAL if the application tries to gain read access and then calls devmap_setup(9F) to set up the user mapping.


Example 10–10 segmap(9E) Routine

static int
xxsegmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp,
    off_t len, unsigned int prot, unsigned int maxprot,
    unsigned int flags, cred_t *credp)
{
        if (prot & PROT_READ)
                return (EINVAL);
        return (devmap_setup(dev, (offset_t)off, as, addrp,
            (size_t)len, prot, maxprot, flags, cred));
} 

devmap() Entry Point

int xxdevmap(dev_t dev, devmap_cookie_t handle, offset_t off,
     size_t len, size_t *maplen, uint_t model);

This entry point is called to export device memory or kernel memory to user applications. devmap(9E) is called from devmap_setup(9F) inside segmap(9E) or on behalf of ddi_devmap_segmap(9F). See Chapter 12, Mapping Device and Kernel Memory and Chapter 13, Device Context Management for details.