如果系统准备尝试卸载 SCSI HBA 驱动程序,则会调用 _fini(9E) 函数。 _fini() 函数必须调用 mod_remove(9F) 来确定是否可以卸载该驱动程序。如果 mod_remove() 返回 0,则可以卸载该模块。HBA 驱动程序必须取消分配 _init(9E) 中分配的所有全局资源。HBA 驱动程序还必须调用 scsi_hba_fini(9F)。
_fini() 必须返回 mod_remove() 所返回的值。
除非 mod_remove(9F) 返回 0,否则 HBA 驱动程序决不能释放任何资源或调用 scsi_hba_fini(9F)。
示例 18–1 说明了 SCSI HBA 的模块初始化。
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); }