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);
where:
- handle
Opaque device-mapping handle that the system uses to identify the mapping.
- dip
Pointer to the device's dev_info structure.
- callbackops
Pointer to a devmap_callback_ctl(9S) structure that enables the driver to be notified of user events on the mapping.
- rnumber
Index number to the register address space set.
- roff
Offset into the device memory.
- len
Length in bytes that is exported.
- maxprot
Allows the driver to specify different protections for different regions within the exported device memory.
- flags
Must be set to DEVMAP_DEFAULTS.
- accattrp
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 = {
DDI_DEVICE_ATTR_V0,
DDI_NEVERSWAP_ACC,
DDI_STRICTORDER_ACC
};
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, ®size) != 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);
}