Go to main content

man pages section 9: DDI and DKI Driver Entry Points

Exit Print View

Updated: Thursday, June 13, 2019
 
 

_fini(9E)

Name

_fini, _info, _init - loadable module configuration entry points

Synopsis

#include <sys/modctl.h>

int _fini(void)
int _info(struct modinfo *modinfop);
int _init(void)

Interface Level

Solaris DDI specific (Solaris DDI). These entry points are required to exist in a loadable module.

Parameters

modinfop

A pointer to an opaque modinfo structure.

Description

_init() initializes a loadable module, and is called as part of initial module loading. _init() may optionally perform some module initialization, and must return an appropriate error if this initialization fails. Following any initialization, _init() must call mod_install(9F). If mod_install() fails, _init() must free any resources initialized earlier. _init() must return the value returned from mod_install().

_info() returns information about a loadable module. _info() should be confined to returning the value that is returned by mod_info(9F). _info() is called as part of initial module loading, and is also called to provide information to modinfo(8).

_fini() prepares a loadable module for unloading. _fini() is called when the system wants to unload a module. If the module determines that it can be unloaded, then _fini() must call mod_remove(9F). Upon successful return from mod_remove(), global resources, such as those initialized with _init() or created via ddi_soft_state(9F) routines, should be destroyed. _fini() must return the value returned from mod_remove().

_init() is always called to initialize a module, and must return success for the module to be successfully loaded and available for use. _fini() can only be called at some point after _init() returns success, when the system tries to unload the module. Upon successful return from _fini(), no other routine in the module can be called before a subsequent _init() is called. _info() can be called before _init(), and repeatedly up until _fini() is called, to provide information to the system about the module.

Return Values

_init() must return an appropriate error if any module initialization fails, or must return the return value from mod_install(9F).

_info() must return the return value from mod_remove(9F).

_fini() can return EBUSY if the module should not be unloaded. Otherwise, _fini() must return the value that is returned by mod_remove(9F).

Examples

Example 1 Initializing and Freeing a Mutex

The following example demonstrates how to initialize and free a mutex(9F).

#include <sys/modctl.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>

static struct dev_ops  drv_ops;

/* Module linkage information for the kernel */
static struct modldrv modldrv = {
        &mod_driverops,  /* Type of module.  This one is a driver */
        "Sample Driver",
        &drv_ops         /* driver ops */
};

static struct modlinkage modlinkage = {
        MODREV_1,
        &modldrv,
        NULL
};

/* Global driver mutex */
static kmutex_t   kmutex;

int
_init(void)
{
        int     i;

        /*
         * Initialize global mutex before mod_install()'ing the driver.
         * If mod_install() fails, clean up mutex initialization.
         */
        mutex_init(&kmutex, NULL, MUTEX_DRIVER, (void *)NULL);

        if ((i = mod_install(&modlinkage)) != 0)
            mutex_destroy(&kmutex);

        return (i);
}

int
_info(struct modinfo *modinfop)
{
        return (mod_info(&modlinkage, modinfop));
}

int
_fini(void)
{
        int       i;

        /* If mod_remove() is successful, destroy the global mutex */
        if ((i = mod_remove(&modlinkage)) == 0)
            mutex_destroy(&kmutex);

        return (i);
}

See Also

add_drv(8), modinfo(8), ddi_soft_state(9F), mod_info(9F), mod_install(9F), mod_remove(9F), mutex(9F), modldrv(9S), modlinkage(9S), modlstrmod(9S)

Writing Device Drivers in Oracle Solaris 11.4

Warnings

Do not change the structures referred to by the modlinkage structure after the call to mod_install(), as the system may copy or change them.

Notes

Even though the identifiers _fini(), _info(), and _init() appear to be declared as globals, their scope is restricted by the kernel to the module that they are defined in.