Writing Device Drivers for Oracle® Solaris 11.2

Exit Print View

Updated: September 2014
 
 

Firmware Compatibility

For devices to function properly, the firmware of the device must be compatible with the device driver. You must check the firmware compatibility before installing or upgrading the device driver. The implementation of a device driver must ensure that a device driver is not installed or upgraded if the compatible firmware is not available.


Note -  If you use IPS to package the driver, you can notify the user of any firmware incompatibility before the driver packet is downloaded to the system. For more information, see Driver Packaging.

A good device driver design is to encapsulate the firmware in one or more ELF (executable linkable format) modules and use the attach() function to manage the firmware version. To encapsulate a firmware in an ELF module, use the elfwrap(1) command. The firmware ELF modules are linked with a module linkage stub as a misc module. Firmware modules exist in the /kernel/misc directory.

The following flow chart shows the approach to manage the firmware version in the attach() function of the device driver.

Figure 1-1  Managing Firmware Version in the attach() Function

image:Managing Firmware Version in the attach() Function

For more information, see the attach (9E) , ddi_modopen (9F) , ddi_modsym (9F) , and ddi_modclose (9F) man pages.


Note -  Some of the devices such as mwl, uath, and hwarc do not contain nonvolatile memory. In such devices, the device driver loads the firmware without checking for any conditions.

A generic pseudo code of the attach() function that checks for the firmware version is as follows:

static int xxxx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
        .....
    ddi_modhandle_t modfn;
    int errno;
    uint32_t *fwvp;
       .....
    long fw_version;
    .....

    /* Check if firmware update is disabled. 
    *  If firmware update is disabled, return.
    *  The setting is stored in a config file.
    */
    if(dip->firmware_disable_update){
        return (0);  
    }

    /* Get the current firmware version. */
    fw_version = xxxx_get_firmware_version(dip,...);
   
     /* Check if the firmware version is correct and if force update is disabled. */
     if(fw_version == REQUIRED_FIRMWARE_VERSION){
        if(dip->firmware_force_update == 0){
        return (0);   
    }
        /* Even though the firmware version matches, update is forced. */
    }


    /* Open the firmware file by using ddi_modopen. */
    modfn = ddi_modopen(FIRMWARE_FILENAME, KRTLD_MODE_FIRST, &errno);
    if (errno){
    /* handle error */
    }

    /* locate the firmware */
    fwvp = ddi_modsym(modfn, FIRMWARE_VERSION_NAME, &errno);
    if (errno){
            /* handle error */
          (void) ddi_modclose(modfn);
    }
 
    /* Check if the firmware version in the module is correct. */
    if (*fwvp != REQUIRED_FIRMWARE_VERSION){
        if(dip->firmware_force_update == 0){
       
            /* close the firmware module file */
            (void) ddi_modclose(modfn);   
        return (0);   
    }
        /* Even tough the firmware version in the module does not match, 
         * update is forced.
         */
     }   
 
    /* Update the firmware. */
        xxx_update_firmware(dip,....);

    /* Close the FIRMWARE file */
    (void) ddi_modclose(modfn);
   
      .....
    // resume attach
}