Writing Device Drivers

devmap_contextmgt() Entry Point

The syntax for devmap_contextmgt(9E) is as follows:

int xxdevmap_contextmgt(devmap_cookie_t handle, void *devprivate,
    offset_t offset, size_t len, uint_t type, uint_t rw);

devmap_contextmgt() should call devmap_unload(9F) with the handle of the mapping that currently has access to the device. This approach invalidates the translations for that mapping. The approach ensures that a call to devmap_access(9E) occurs for the current mapping the next time the mapping is accessed. The mapping translations for the mapping that caused the access event to occur need to be validated. Accordingly, the driver must restore the device context for the process requesting access. Furthermore, the driver must call devmap_load(9F) on the handle of the mapping that generated the call to this entry point.

Accesses to portions of mappings that have had their mapping translations validated by a call to devmap_load() do not generate a call to devmap_access(). A subsequent call to devmap_unload() invalidates the mapping translations. This call enables devmap_access() to be called again.

If either devmap_load() or devmap_unload() returns an error, devmap_contextmgt() should immediately return that error. If the device driver encounters a hardware failure while restoring a device context, a -1 should be returned. Otherwise, after successfully handling the access request, devmap_contextmgt() should return zero. A return of other than zero from devmap_contextmgt() causes a SIGBUS or SIGSEGV to be sent to the process.

The following example shows how to manage a one-page device context.


Note –

xxctxsave() and xxctxrestore() are device-dependent context save and restore functions. xxctxsave() reads data from the registers and saves the data in the soft state structure. xxctxrestore() takes data that is saved in the soft state structure and writes the data to device registers. Note that the read, write, and save are all performed with the DDI/DKI data access routines.



Example 11–3 Using the devmap_contextmgt() Routine

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