ChorusOS 4.0 Device Driver Framework Guide

Write the Unload Function

drv_unload is called by the driver registry module (more precisely, by the svDriverUnregister routine) when an application wishes to unload the driver component from the system. The drv_unload routine is called in the context of the DKI thread.

This makes it possible to invoke directly the bus/nexus and DKI services allowed in the DKI thread context only. The purpose of drv_unload is to check that the driver component is not currently in use. On success, drv_unload returns K_OK , otherwise K_EBUSY is returned.

The drv_unload routine is optional. If drv_unload is not provided, the driver code cannot be unloaded. drv_unload is a global, per driver component routine. Therefore, to implement unloading, the driver should handle a list of driver instances. When drv_unload is called, the driver should go through the list, and for each driver instance, check whether the driver instance is currently in use.


Note -

Once the check is positive (a given instance is not used), the driver instance must become invisible for potential clients. In other words, if drv_unload returns K_OK , all previously created driver instances (if any) must be deleted and all previously allocated system resources (if any) must be released.


If drv_unload returns K_EBUSY, the driver component will not be unloaded. In this case, the driver component state must not be changed by drv_unload.

The drv_unload routine of a bus/nexus driver typically takes the following actions:

  1. Checks that the driver component is not in use.drv_unload iterates through the driver instances list and, for each driver instance, checks whether a connection is opened to the driver instance.

    Once a driver instance with an open connection is found, the iteration is aborted and K_EBUSY is returned. Otherwise, drv_unload proceeds to step 2.

  2. Releases resources associated to the driver component.drv_unload iterates through the driver instances list and, for each driver instance, releases all system resources associated to the instance ( io_unmap , mem_unmap , ...) and, finally, closes the connection to the parent bus. Once the iteration is finished, drv_unload returns K_OK.

Note that drv_unload runs in the DKI thread context.

This guarantees stability of the driver instances and open connections during the drv_unload execution. Indeed, a new driver instance may be created only by the drv_init routine and a new parent-to-child connection may be opened only by the drv_init or drv_probe routines.

Both drv_init and drv_probe are invoked in the DKI thread context. Thus, drv_init and drv_probe are serialized with drv_unload by the DKI thread.

On the other hand, if a bus/nexus driver supports hot-pluggable devices, it is up to the bus/nexus driver to implement a synchronization mechanism with a hot-plug insertion interrupt which may occur during the driver unloading.

In the following example, the W83C553_DRV_UNLOAD compilation flag is used to allow downsizing of the driver component, at compile time, if the unload mechanism is not needed.

    /*
     * Unload the W83C553 driver.
     * This routine is called by the driver registry when an application
     * wishes to unload the driver component.
     */
    static KnError
drv_unload ()
{
        /*
         * The driver unloading is an optional feature.
         * In case when such a feature is not supported, drv_unload()
         * just returns K_EBUSY preventing the driver component to be
         * unloaded.
         */
#if defined(W83C553_DRV_UNLOAD)
    W83c553Data*  udev;
        /*
         * Go through the driver instances list and check if it is unused
         * i.e. if the list of connected devices is empty.
         */
    udev = w83c553Devs;
    while (udev && (udev->dev == NULL)) {
        udev = udev->next;
    }
        /*
         * If all driver instances are unused, we invoke shutdown()
         * to shutdown each instance.
         */
    if (!udev) {
        while (w83c553Devs) {
            shutdown(w83c553Devs);
        }
        return K_OK;
    }
        /*
         * If there is a driver instance in use, we cannot unload the
         * driver, and return K_EBUSY.
         */
#endif

    return K_EBUSY;
}