编写设备驱动程序

将用户映射与驱动程序通知关联

用户进程通过 mmap(2) 请求到设备的映射时,将会调用驱动程序的 segmap(9E) 入口点。如果驱动程序需要管理设备上下文,则在设置内存映射时,驱动程序必须使用 ddi_devmap_segmap(9F)devmap_setup(9F)。这两个函数都会调用驱动程序的 devmap(9E) 入口点,该入口点使用 devmap_devmem_setup(9F) 将设备内存与用户映射关联。有关如何映射设备内存的详细信息,请参见第 10 章

驱动程序必须向系统通知 devmap_callback_ctl(9S) 入口点才能获取对用户映射的访问通知。驱动程序通过向 devmap_devmem_setup(9F) 提供一个指向 devmap_callback_ctl(9S) 结构的指针来通知系统。devmap_callback_ctl(9S) 结构描述了一组用于上下文管理的入口点。系统通过调用这些入口点来通知设备驱动程序管理有关设备映射的事件。

系统会将每个映射与一个映射句柄关联。此句柄会传递给每个用于上下文管理的入口点。该映射句柄可用来使映射转换无效和对映射转换进行验证。如果驱动程序使映射转换无效,则会向该驱动程序通知将来对映射的任何访问。如果驱动程序对映射转换进行验证,则不再向该驱动程序通知对映射的访问。映射总是在映射转换无效的情况下创建,以便第一次访问映射时将会通知驱动程序。

以下示例说明如何使用设备上下文管理接口设置映射。


示例 11–6 支持上下文管理的 devmap(9E) 入口点

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);
}