int detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
Before the system sets component 0 (entire device) to power level 0, it calls the driver's detach(9E) entry point with a detach command of DDI_PM_SUSPEND to allow the driver to save all hardware state to memory.
If the device is busy and has outstanding operations, it should fail the detach(9E) call. The framework will try again later after the device has been idle for its threshold time. Otherwise, the driver must arrange to block all subsequent accesses to the hardware until the device has been resumed (which the driver can initiate by calling ddi_dev_is_needed(9F)), and save all hardware state to memory.
Example 8-2 shows an example of a detach(9E) routine with DDI_PM_SUSPEND implemented.
int xxdetach(devinfo_t *dip, ddi_detach_cmd_t cmd) { struct xxstate *xsp; int instance; instance = ddi_get_instance(dip); xsp = ddi_get_soft_state(statep, instance); switch (cmd) { case DDI_DETACH: see chapter 5, Autoconfiguration, for discussion case DDI_SUSPEND: see Example 8-4 case DDI_PM_SUSPEND: /* * We won't be called with DDI_PM_SUSPEND when already called * with DDI_SUSPEND. */ mutex_enter(&xsp->mu); if (xsp->xx_busy) { mutex_exit(&xsp->mu); return(DDI_FAILURE); } xsp->xx_pm_suspended = 1; Save device register contents into xsp->xx_device_state this section is optional, only needed if the driver maintains a running timeout (but be sure to drop the mutex in any case) /* cancel timeouts */ if (xsp->xx_timeout_id) { timeout_id_t temp_timeout_id = xsp->xx_timeout_id; xsp->xx_timeout_id = 0; mutex_exit(&xsp->mu); untimeout(temp_timeout_id); } else { mutex_exit(&xsp->mu); } return(DDI_SUCCESS); default: return(DDI_FAILURE); } }