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