编写设备驱动程序

devmap_map() 入口点

devmap(9E) 的语法如下所示:

int xxdevmap_map(devmap_cookie_t handle, dev_t dev, uint_t flags,
    offset_t offset, size_t len, void **new-devprivate);

驱动程序从其 devmap() 入口点返回并且系统已建立到设备内存的用户映射后,将会调用 devmap_map() 入口点。通过 devmap() 入口点,驱动程序可以执行其他处理操作或分配特定于映射的专用数据。例如,为了支持上下文切换,驱动程序必须分配上下文结构。然后,驱动程序必须将上下文结构与映射关联。

系统期望驱动程序在 *new-devprivate 中返回一个指向分配的专用数据的指针。驱动程序必须存储用于定义专用数据中的映射范围的 offsetlen。然后当系统调用 devmap_unmap(9E) 时,驱动程序将使用此信息来确定要取消映射的映射量。

flags 指示驱动程序是否应为映射分配专用上下文。例如,如果 flags 设置为 MAP_PRIVATE,则驱动程序可以分配用于存储设备上下文的内存区域。如果设置了 MAP_SHARED,驱动程序将返回指向共享区域的指针。

以下示例说明了 devmap() 入口点。驱动程序分配了一个新的上下文结构。然后,驱动程序便可保存通过入口点传入的相关参数。接下来,将通过分配或通过将映射附加至已经存在的共享上下文来为映射指定新的上下文。映射访问设备的最短时间间隔设置为 1 毫秒。


示例 11–1 使用 devmap() 例程

static int
int xxdevmap_map(devmap_cookie_t handle, dev_t dev, uint_t flags,
    offset_t offset, size_t len, void **new_devprivate)
{
    struct xxstate *xsp = ddi_get_soft_state(statep,
                  getminor(dev));
    struct xxctx *newctx;

    /* create a new context structure */
    newctx = kmem_alloc(sizeof (struct xxctx), KM_SLEEP);
    newctx->xsp = xsp;
    newctx->handle = handle;
    newctx->offset = offset;
    newctx->flags = flags;
    newctx->len = len;
    mutex_enter(&xsp->ctx_lock);
    if (flags & MAP_PRIVATE) {
        /* allocate a private context and initialize it */
        newctx->context = kmem_alloc(XXCTX_SIZE, KM_SLEEP);
        xxctxinit(newctx);
    } else {
        /* set a pointer to the shared context */
        newctx->context = xsp->ctx_shared;
    }
    mutex_exit(&xsp->ctx_lock);
    /* give at least 1 ms access before context switching */
    devmap_set_ctx_timeout(handle, drv_usectohz(1000));
    /* return the context structure */
    *new_devprivate = newctx;
    return(0);
}