Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
9.  Power Management Device Power Management Model Device Power Management Interfaces Device Power State Transitions  Previous   Contents   Next 
   
 

power() Entry Point

The power management framework uses the power(9E) entry point.

The syntax for power(9E) is:

    int power(dev_info_t *dip, int component, int level);

The system calls the power(9E) entry point (either directly or as a result of a call to pm_raise_power(9F) or pm_lower_power(9F)) when it determines that a component's current power level needs to be changed. The action taken by this entry point is device driver specific. In the example of the SCSI target disk driver mentioned previously, setting the power level to 0 results in sending a SCSI command to spin down the disk, while setting the power level to the full power level results in sending a SCSI command to spin up the disk.

If a power transition will cause the device to lose state, then the driver must ensure that any necessary state is saved in memory so that it can be restored when it is needed again. If a power transition will require that saved state be restored before the device can be used again, then the driver must restore that state. The framework makes no assumptions about what power transactions cause the loss of or require the restoration of state for automatically power-manage devices. Example 9-4 shows a sample power(9E) routine.


Example 9-4 power(9E) Routine for Single-Component Device

int
xxpower(dev_info_t *dip, int component, int level)
{
        struct xxstate *xsp;
        int instance;

        instance = ddi_get_instance(dip);
        xsp = ddi_get_soft_state(statep, instance);
        /*
         * Make sure the request is valid
         */
        if (!xx_valid_power_level(component, level))
                return (DDI_FAILURE);
        mutex_enter(&xsp->mu);
        /*
         * If the device is busy, don't lower its power level
         */
        if (xsp->xx_busy[component] &&
            xsp->xx_power_level[component] > level) {
                mutex_exit(&xsp->mu);
                return (DDI_FAILURE);
        }

        if (xsp->xx_power_level[component] != level) {
                /*
                 * device- and component-specific setting of power level
                 * goes here
                 */
                ...
                xsp->xx_power_level[component] = level;
        }
        mutex_exit(&xsp->mu);
        return (DDI_SUCCESS);
}

Example 9-5 is a power(9E) routine for a device with two components, where component 0 must be on when component 1 is on.


Example 9-5 power(9E) Routine for Multiple Component Device

int
xxpower(dev_info_t *dip, int component, int level)
{
        struct xxstate *xsp;
        int instance;

        instance = ddi_get_instance(dip);
        xsp = ddi_get_soft_state(statep, instance);
        /*
         * Make sure the request is valid
         */
        if (!xx_valid_power_level(component, level))
                return (DDI_FAILURE);
        mutex_enter(&xsp->mu);
        /*
         * If the device is busy, don't lower its power level
         */
        if (xsp->xx_busy[component] &&
            xsp->xx_power_level[component] > level) {
                mutex_exit(&xsp->mu);
                return (DDI_FAILURE);
        }

        /*
         * This code implements inter-component dependencies:
         * If we are bringing up component 1 and component 0 
         * is off, we must bring component 0 up first, and if
         * we are asked to shut down component 0 while component
         * 1 is up we must refuse
         */
        if (component == 1 && level > 0 && xsp->xx_power_level[0] == 0) {
                xsp->xx_busy[0]++;
                if (pm_busy_component(dip, 0) != DDI_SUCCESS) {
                        /*
                         * This can only happen if the args to 
                         * pm_busy_component()
                         * are wrong, or pm-components property was not
                         * exported by the driver.
                         */
                        xsp->xx_busy[0]--;
                        mutex_exit(&xsp->mu);
                        cmn_err(CE_WARN, "xxpower pm_busy_component() 
                            failed");
                        return (DDI_FAILURE);
                }
                mutex_exit(&xsp->mu);
                if (pm_raise_power(dip, 0, XX_FULL_POWER_0) != DDI_SUCCESS)
                        return (DDI_FAILURE);
                mutex_enter(&xsp->mu);
        }
        if (component == 0 && level == 0 && xsp->xx_power_level[1] != 0) {
                mutex_exit(&xsp->mu);
                return (DDI_FAILURE);
        }
        if (xsp->xx_power_level[component] != level) {
                /*
                 * device- and component-specific setting of power level
                 * goes here
                 */
                ...
                xsp->xx_power_level[component] = level;
        }
        mutex_exit(&xsp->mu);
        return (DDI_SUCCESS);
}

 
 
 
  Previous   Contents   Next