devmap_contextmgt(9E) 的语法如下所示:
int xxdevmap_contextmgt(devmap_cookie_t handle, void *devprivate, offset_t offset, size_t len, uint_t type, uint_t rw);
devmap_contextmgt() 应使用当前对设备具有访问权限的映射的句柄调用 devmap_unload(9F)。此方法可使对于该映射的转换无效。通过此方法,可确保下次访问当前映射时针对该映射调用 devmap_access(9E)。对于引起访问事件发生的映射,需要验证其映射转换。相应地,驱动程序必须为进程请求访问恢复设备上下文。并且,驱动程序必须针对映射的 handle 调用 devmap_load(9F),该映射生成了对此入口点的调用。
访问已通过调用 devmap_load() 对映射转换进行验证的部分映射时不会导致调用 devmap_access()。对 devmap_unload() 的后续调用将使映射转换无效。通过此调用,可再次调用 devmap_access()。
如果 devmap_load() 或 devmap_unload() 返回错误,devmap_contextmgt() 应立即返回该错误。如果设备驱动程序在恢复设备上下文时遇到硬件故障,则应返回 -1。否则,成功处理访问请求后,devmap_contextmgt() 应返回零。如果从 devmap_contextmgt() 返回非零值,则会向进程发送 SIGBUS 或 SIGSEGV。
以下示例说明如何管理单页设备上下文。
xxctxsave() 和 xxctxrestore() 是与设备相关的上下文保存和恢复函数。xxctxsave() 从寄存器中读取数据并将数据保存在软状态结构中。xxctxrestore() 提取软状态结构中保存的数据并将数据写入设备寄存器。请注意,执行读取、写入和保存都需要使用 DDI/DKI 数据访问例程。
static int xxdevmap_contextmgt(devmap_cookie_t handle, void *devprivate, offset_t off, size_t len, uint_t type, uint_t rw) { int error; struct xxctx *ctxp = devprivate; struct xxstate *xsp = ctxp->xsp; mutex_enter(&xsp->ctx_lock); /* unload mapping for current context */ if (xsp->current_ctx != NULL) { if ((error = devmap_unload(xsp->current_ctx->handle, off, len)) != 0) { xsp->current_ctx = NULL; mutex_exit(&xsp->ctx_lock); return (error); } } /* Switch device context - device dependent */ if (xxctxsave(xsp->current_ctx, off, len) < 0) { xsp->current_ctx = NULL; mutex_exit(&xsp->ctx_lock); return (-1); } if (xxctxrestore(ctxp, off, len) < 0){ xsp->current_ctx = NULL; mutex_exit(&xsp->ctx_lock); return (-1); } xsp->current_ctx = ctxp; /* establish mapping for new context and return */ error = devmap_load(handle, off, len, type, rw); if (error) xsp->current_ctx = NULL; mutex_exit(&xsp->ctx_lock); return (error); }