如果系统准备尝试卸载 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);
}