Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
15.  SCSI Host Bus Adapter Drivers HBA Driver Dependency and Configuration Issues Declarations and Structures Per-Command Structure  Previous   Contents   Next 
   
 

Module Initialization Entry Points

Drivers for different types of devices have different sets of entry points, depending on the operations they perform. Some operations, however, are common to all drivers, such as the as _init(9E), _info(9E), and _fini(9E) entry points for module initialization. This section describes only those entry points associated with operations performed by SCSI HBA drivers.

The following code for a SCSI HBA driver illustrates a representative dev_ops(9S) structure. The driver must initialize the devo_bus_ops field in this structure to NULL. A SCSI HBA driver can provide leaf driver interfaces for special purposes, in which case the devo_cb_ops field might point to a cb_ops(9S) structure. In this example, no leaf driver interfaces are exported, so the devo_cb_ops field is initialized to NULL.

_init() Entry Point (SCSI HBA Drivers)

The _init(9E) function initializes a loadable module and is called before any other routine in the loadable module.

In a SCSI HBA, the _init() function must call scsi_hba_init(9F) to inform the framework of the existence of the HBA driver before calling mod_install(9F). If scsi_hba__init() returns a nonzero value,_init() should return this value. Otherwise, _init() must return the value returned by mod_install(9F).

The driver should initialize any required global state before calling mod_install(9F).

If mod_install() fails, the _init() function must free any global resources allocated and must call scsi_hba_fini(9F) before returning.

Example 15-1 uses a global mutex to show how to allocate data that is global to all instances of a driver. The code declares global mutex and soft-state structure information. The global mutex and soft state are initialized during _init().

_fini() Entry Point (SCSI HBA Drivers)

The _fini(9E) function is called when the system is about to try to unload the SCSI HBA driver. The _fini() function must call mod_remove(9F) to determine if the driver can be unloaded. If mod_remove() returns 0, the module can be unloaded, and the HBA driver must deallocate any global resources allocated in _init(9E) and must call scsi_hba_fini(9F).

_fini() must return the value returned by mod_remove().


Note - The HBA driver must not free any resources or call scsi_hba_fini(9F) unless mod_remove(9F) returns 0.


Example 15-1 shows SCSI HBA module initialization.


Example 15-1 SCSI HBA Module Initialization

static struct dev_ops isp_dev_ops = {
        DEVO_REV,           /* devo_rev */
        0,                  /* refcnt  */
        isp_getinfo,        /* getinfo */
        nulldev,            /* probe */
        isp_attach,         /* attach */
        isp_detach,         /* detach */
        nodev,              /* reset */
        NULL,               /* driver operations */
        NULL,               /* bus operations */
        isp_power,          /* power management */
};

/*
 * Local static data
 */
static kmutex_t          isp_global_mutex;
static void              *isp_state;

int
_init(void)
{
        int     err;
    
        if ((err = ddi_soft_state_init(&isp_state,
            sizeof (struct isp), 0)) != 0) {
                return (err);
        }
        if ((err = scsi_hba_init(&modlinkage)) == 0) {
                mutex_init(&isp_global_mutex, "isp global mutex",
                MUTEX_DRIVER, NULL);
                if ((err = mod_install(&modlinkage)) != 0) {
                    mutex_destroy(&isp_global_mutex);
                    scsi_hba_fini(&modlinkage);
                    ddi_soft_state_fini(&isp_state);    
                }
        }
        return (err);
}

int
_fini(void)
{
        int     err;
    
        if ((err = mod_remove(&modlinkage)) == 0) {
                mutex_destroy(&isp_global_mutex);
                scsi_hba_fini(&modlinkage);
                ddi_soft_state_fini(&isp_state);
        }
        return (err);
}

Autoconfiguration Entry Points

Associated with each device driver is a dev_ops(9S) structure, which allows the kernel to locate the autoconfiguration entry points of the driver. A complete description of these autoconfiguration routines is given in Chapter 5, Driver Autoconfiguration. This section describes only those entry points associated with operations performed by SCSI HBA drivers. These include attach(9E) and detach(9E).

attach() Entry Point (SCSI HBA Drivers)

The attach(9E) entry point for a SCSI HBA driver must perform a number of tasks to configure and attach an instance of the driver for the device. For a typical driver of real devices, the following operating system and hardware concerns must be addressed:

  • Soft-state structure

  • DMA

  • Transport structure

  • Attaching an HBA driver

  • Register mapping

  • Interrupt specification

  • Interrupt handling

  • Create power manageable components

  • Report attachment status

 
 
 
  Previous   Contents   Next