このセクションでは、SCSI HBA ドライバによって実行される操作のエントリポイントについて説明します。
次の SCSI HBA ドライバ用のコードは、代表的なdev_ops (9S) 構造体を示しています。ドライバは、この構造体の devo_bus_ops フィールドを NULL に初期化する必要があります。SCSI HBA ドライバは、特別な目的でリーフドライバインタフェースを提供することがあり、その場合、devo_cb_ops フィールドは cb_ops(9S) 構造体を指すことがあります。この例では、リーフドライバインタフェースはエクスポートされていないため、devo_cb_ops フィールドは NULL に初期化されます。
_init(9E) 関数は、ロード可能なモジュールを初期化します。_init() は、ロード可能なモジュール内のほかのすべてのルーチンの前に呼び出されます。
SCSI HBA では、_init() 関数は、mod_install(9F) を呼び出す前に、scsi_hba_init(9F) を呼び出して、HBA ドライバの存在をフレームワークに通知する必要があります。scsi_hba__init() ルーチンがゼロ以外の値を返す場合、_init() はこの値を返します。それ以外の場合、_init() はmod_install(9F) によって返された値を返す必要があります。
ドライバは、 mod_install(9F) を呼び出す前に、必要なグローバル状態を初期化します。
mod_install() が失敗した場合、_init() 関数は割り当てられているグローバルリソースをすべて解放する必要があります。_init() は、復帰する前に scsi_hba_fini(9F) を呼び出す必要があります。
次の例では、グローバルな mutex を使用して、ドライバのすべてのインスタンスにグローバルなデータの割り当て方法を示しています。このコードでは、グローバルな mutex とソフト状態構造体の情報を宣言しています。グローバルな mutex とソフト状態は、_init() の実行中に初期化されます。
_fini(9E) 関数は、システムが SCSI HBA ドライバをアンロードしようとするときに呼び出されます。_fini() 関数は、mod_remove (9F) を呼び出して、ドライバがアンロード可能かどうかを判定する必要があります。mod_remove() が 0 を返した場合、このモジュールはアンロード可能です。HBA ドライバは、 _init(9E) で割り当てられたグローバルリソースをすべて解放する必要があります。また、HBA ドライバは、scsi_hba_fini (9F) も呼び出す必要があります。
_fini() は、mod_remove() によって返された値を返す必要があります。
Example 18–1 は、SCSI HBA 用のモジュールの初期化を示しています。
使用例 18-1 SCSI HBA 用のモジュールの初期化static struct dev_ops isp_dev_ops = {
DEVO_REV, /* devo_rev */
0, /* refcnt */
isp_getinfo, /* getinfo */
nulldev, /* identify */
nulldev, /* probe */
isp_attach, /* attach */
isp_detach, /* detach */
nodev, /* reset */
NULL, /* driver operations */
NULL, /* bus operations */
isp_power, /* power management */
isp_quiesce, /* quiesce */
};
/*
* 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);
}