SCSA では、データ構造体を定義して、ターゲットドライバと HBA ドライバ間で情報交換できるようにしています。含まれているデータ構造体は次のとおりです。
HBA ドライバの各インスタンスでは、attach(9E) エントリポイントでscsi_hba_tran_alloc(9F) 関数を使用してscsi_hba_tran(9S) 構造体を割り当てる必要があります。scsi_hba_tran_alloc() 関数は、scsi_hba_tran 構造体を初期化します。HBA ドライバは、HBA ドライバ内のエントリポイントを指すように、トランスポート構造体にある特定のベクトルを初期化する必要があります。scsi_hba_tran 構造体が初期化されたあとで、HBA ドライバはscsi_hba_attach_setup(9F) 関数を呼び出して、このトランスポート構造体を SCSA にエクスポートします。
![]() | 注意 - SCSA ではトランスポート構造体を指すポインタを devinfo ノード上のドライバの非公開フィールドに保持しているため、HBA ドライバはddi_set_driver_private(9F) を使用してはいけません。ただし、HBA ドライバは、 ddi_get_driver_private(9F) を使用して、トランスポート構造体を指すポインタを検出することはできます。 |
SCSA インタフェースでは、HBA ドライバは scsi_hba_tran 構造体を介して呼び出し可能ないくつかのエントリポイントを提供する必要があります。詳細については、Entry Points for SCSA HBA Driversを参照してください。
scsi_hba_tran 構造体には、次のフィールドがあります。
struct scsi_hba_tran { dev_info_t *tran_hba_dip; /* HBAs dev_info pointer */ void *tran_hba_private; /* HBA softstate */ void *tran_tgt_private; /* HBA target private pointer */ struct scsi_device *tran_sd; /* scsi_device */ int (*tran_tgt_init)(); /* Transport target */ /* Initialization */ int (*tran_tgt_probe)(); /* Transport target probe */ void (*tran_tgt_free)(); /* Transport target free */ int (*tran_start)(); /* Transport start */ int (*tran_reset)(); /* Transport reset */ int (*tran_abort)(); /* Transport abort */ int (*tran_getcap)(); /* Capability retrieval */ int (*tran_setcap)(); /* Capability establishment */ struct scsi_pkt *(*tran_init_pkt)(); /* Packet and DMA allocation */ void (*tran_destroy_pkt)(); /* Packet and DMA */ /* Deallocation */ void (*tran_dmafree)(); /* DMA deallocation */ void (*tran_sync_pkt)(); /* Sync DMA */ void (*tran_reset_notify)(); /* Bus reset notification */ int (*tran_bus_reset)(); /* Reset bus only */ int (*tran_quiesce)(); /* Quiesce a bus */ int (*tran_unquiesce)(); /* Unquiesce a bus */ int tran_interconnect_type; /* transport interconnect */ };
次に、scsi_hba_tran 構造体の各フィールドについて詳しく説明します。
HBA デバイスインスタンスの dev_info 構造体を指すポインタです。このフィールドは、 scsi_hba_attach_setup(9F) 関数によって設定されます。
HBA ドライバによって保持される非公開データを指すポインタです。通常、tran_hba_private には、HBA ドライバの状態構造体を指すポインタが入ります。
複製の使用時に HBA ドライバによって保持される非公開データを指すポインタです。scsi_hba_attach_setup(9F) の呼び出し時に SCSI_HBA_TRAN_CLONE を指定することにより、scsi_hba_tran(9S) 構造体が 1 つのターゲットにつき一度だけクローニングされます。この方法により、HBA はtran_tgt_init (9E) エントリポイントでターゲットインスタンスごとのデータ構造体を指すようにこのフィールドを初期化できます。SCSI_HBA_TRAN_CLONE を指定しない場合、tran_tgt_private は NULL となり、tran_tgt_private が参照されることがあってはなりません。詳細については、Transport Structure Cloningを参照してください。
クローニング時に使用されるターゲットインスタンスごとのscsi_device (9S) 構造体を指すポインタです。SCSI_HBA_TRAN_CLONE が scsi_hba_attach_setup(9F) に渡された場合、tran_sd はターゲットごとの scsi_device 構造体を指すように初期化されます。この初期化は、そのターゲットに代わって HBA 関数が呼び出される前に行われます。SCSI_HBA_TRAN_CLONE を指定しない場合、tran_sd は NULL となり、tran_sd が参照されることがあってはなりません。詳細については、Transport Structure Cloningを参照してください。
ターゲットデバイスインスタンスの初期化時に呼び出される HBA ドライバのエントリポイントを指すポインタです。ターゲットごとの初期化が必要ない場合、HBA は tran_tgt_init を NULL に設定しておくことができます。
ターゲットドライバインスタンスがscsi_probe (9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。このルーチンは、ターゲットデバイスの存在を調べるために呼び出されます。この HBA にターゲットのプローブカスタマイズが必要ない場合、HBA は tran_tgt_probe を scsi_hba_probe(9F) に設定します。
ターゲットデバイスのインスタンスが破棄されるときに呼び出される HBA ドライバのエントリポイントを指すポインタです。ターゲットごとの解放が必要ない場合、HBA は tran_tgt_free を NULL に設定しておくことができます。
ターゲットドライバが scsi_transport(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバが scsi_reset(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバが scsi_abort(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバが scsi_ifgetcap(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバが scsi_ifsetcap(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバがscsi_init_pkt(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバがscsi_destroy_pkt (9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバが scsi_dmafree(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバが scsi_sync_pkt(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットドライバがtran_reset_notify (9E) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。
ターゲットをリセットしないで SCSI バスをリセットする関数エントリです。
未処理のコマンドが完了するのを待ち、発行されたすべての入出力要求をブロックする (またはキューに入れる) 関数エントリです。
入出力動作が SCSI バス上で再開できるようにする関数エントリです。
services.h ヘッダーファイルに定義されたとおりにトランスポートの相互接続タイプを示す整数値です。
scsi_address(9S) 構造体は、ターゲットドライバのインスタンスによって割り当てられ、トランスポートされる各 SCSI コマンドのトランスポートとアドレス指定の情報を提供します。
scsi_address 構造体には、次のフィールドがあります。
struct scsi_address { struct scsi_hba_tran *a_hba_tran; /* Transport vectors */ ushort_t a_target; /* Target identifier */ uchar_t a_lun; /* LUN on that target */ uchar_t a_sublun; /* Sub LUN on that LUN */ /* Not used */ };
HBA ドライバによって割り当てられ、初期化された scsi_hba_tran (9S) 構造体を指すポインタです。scsi_hba_attach_setup(9F) のフラグとして SCSI_HBA_TRAN_CLONE を指定した場合、a_hba_tran はその構造体のコピーを指します。
SCSI バス上の SCSI ターゲットを識別します。
SCSI ターゲット上の SCSI 論理ユニットを識別します。
HBA フレームワークでは、ターゲットデバイスのインスタンスごとにscsi_device(9S) 構造体を割り当て、初期化します。この割り当てと初期化は、フレームワークで HBA ドライバのtran_tgt_init (9E) エントリポイントを呼び出す前に行われます。この構造体には、一般的な情報とデバイス固有の情報を含む情報領域を指すポインタなど、各 SCSI 論理ユニットに関する情報が格納されます。システムに接続されているターゲットデバイスインスタンスごとに 1 つの scsi_device(9S) 構造体が存在します。
ターゲットごとの初期化が正常に行われると、HBA フレームワークはddi_set_driver_private(9F) を使用して、ターゲットドライバのインスタンスごとの非公開データがscsi_device(9S) 構造体を指すように設定します。初期化が正常に行われるのは、tran_tgt_init() が成功を返した場合またはベクトルが null の場合です。
scsi_device(9S) 構造体には、次のフィールドがあります。
struct scsi_device { struct scsi_address sd_address; /* routing information */ dev_info_t *sd_dev; /* device dev_info node */ kmutex_t sd_mutex; /* mutex used by device */ void *sd_reserved; struct scsi_inquiry *sd_inq; struct scsi_extended_sense *sd_sense; caddr_t sd_private; /* for driver's use */ };
ここでは:
SCSI リソースの割り当てのためのルーチンに渡されるデータ構造体です。
ターゲットの dev_info 構造体を指すポインタです。
ターゲットドライバが使用する mutex です。この mutex は、HBA フレームワークによって初期化されます。ターゲットドライバは、この mutex をデバイスごとの mutex として使用できます。この mutex は、scsi_transport (9F) またはscsi_poll (9F) への呼び出しの前後にわたって保持してはいけません。mutex の詳細については、Chapter 3, Multithreadingを参照してください。
ターゲットデバイスの SCSI 照会データへのポインタです。scsi_probe(9F) ルーチンは、バッファーを割り当て、そのバッファーを満たして、このフィールドに追加します。
デバイスから送られた要求検知データを収めるバッファーを指すポインタです。ターゲットドライバは、このバッファーそのものを割り当てて管理する必要があります。詳細については、attach() Entry Point に記載されたターゲットドライバのattach(9E) ルーチンを参照してください。
ターゲットドライバが使用するポインタフィールドです。このフィールドは、ターゲットドライバの非公開の状態構造体を指すポインタの格納によく使われます。
SCSI コマンドを実行するには、ターゲットドライバはまずそのコマンドに scsi_pkt(9S) 構造体を割り当てる必要があります。次に、そのターゲットドライバ専用の非公開データ領域の大きさ、コマンドのステータス、およびコマンドの長さを指定する必要があります。HBA ドライバは、tran_init_pkt(9E) エントリポイントでパケット割り当てを実装します。また、HBA ドライバは、その tran_destroy_pkt(9E) エントリポイントでパケットの解放を行う必要があります。詳細については、scsi_pkt Structure (Target Drivers)を参照してください。
scsi_pkt(9S) 構造体には、次のフィールドがあります。
struct scsi_pkt { opaque_t pkt_ha_private; /* private data for host adapter */ struct scsi_address pkt_address; /* destination address */ opaque_t pkt_private; /* private data for target driver */ void (*pkt_comp)(struct scsi_pkt *); /* completion routine */ uint_t pkt_flags; /* flags */ int pkt_time; /* time allotted to complete command */ uchar_t *pkt_scbp; /* pointer to status block */ uchar_t *pkt_cdbp; /* pointer to command block */ ssize_t pkt_resid; /* data bytes not transferred */ uint_t pkt_state; /* state of command */ uint_t pkt_statistics; /* statistics */ uchar_t pkt_reason; /* reason completion called */ };
ここでは:
コマンドごとの HBA ドライバの非公開データを指すポインタです。
このコマンドのアドレス情報を提供するscsi_address (9S) 構造体を指すポインタです。
パケットごとのターゲットドライバの非公開データを指すポインタです。
トランスポート層でこのコマンドが実行されたときに HBA ドライバによって呼び出されるターゲットドライバ完了ルーチンを指すポインタです。
コマンドのフラグです。
コマンドの完了タイムアウトを秒単位で指定します。
コマンドのステータス完了ブロックを指すポインタです。
コマンドのコマンド記述子ブロック (CDB) を指すポインタです。
コマンドが完了したときに転送されなかったデータバイト数です。このフィールドを使用すると、リソースが割り当てられなかったデータの量も指定できます。HBA は、トランスポート時にこのフィールドを変更する必要があります。
コマンドの状態です。HBA は、トランスポート時にこのフィールドを変更する必要があります。
トランスポート層に存在している間に、コマンドが検出したイベントの履歴を提供します。HBA は、トランスポート時にこのフィールドを変更する必要があります。
コマンド完了の理由です。HBA は、トランスポート時にこのフィールドを変更する必要があります。