Go to main content
Oracle® Solaris 11.3 デバイスドライバの記述

印刷ビューの終了

更新: 2016 年 11 月
 
 

SCSA HBA インタフェース

SCSA HBA インタフェースには、HBA エントリポイント、HBA データ構造体、および HBA フレームワークが含まれています。

SCSA HBA エントリポイントのサマリー

SCSA では、HBA ドライバのエントリポイントを多数定義しています。次の表に、これらのエントリポイントを示します。このエントリポイントは、HBA ドライバに接続されたターゲットドライバインスタンスが構成されるときにシステムから呼び出されます。また、ターゲットドライバが SCSA 要求を出したときにも呼び出されます。詳細については、SCSA HBA ドライバのエントリポイントを参照してください。

表 16  SCSA HBA エントリポイントのサマリー
関数名
呼び出される原因となる操作
ターゲットドライバによるscsi_abort(9F) の呼び出し
システムによるバスのリセット
ターゲットドライバによるscsi_destroy_pkt(9F) の呼び出し
ターゲットドライバによるscsi_dmafree(9F) の呼び出し
ターゲットドライバによるscsi_ifgetcap(9F) の呼び出し
ターゲットドライバによるscsi_init_pkt(9F) の呼び出し
システムによるバスの休止
ターゲットドライバによる scsi_reset(9F) の呼び出し
ターゲットドライバによるscsi_reset_notify(9F) の呼び出し
ターゲットドライバによるscsi_ifsetcap(9F) の呼び出し
ターゲットドライバによるscsi_transport(9F) の呼び出し
ターゲットドライバによるscsi_sync_pkt(9F) の呼び出し
tran_tgt_free(9E)
システムによるターゲットデバイスインスタンスの切り離し
tran_tgt_init(9E)
システムによるターゲットデバイスインスタンスの接続
tran_tgt_probe(9E)
ターゲットドライバによるscsi_probe(9F) の呼び出し
システムによるバス上の動作の再開

SCSA HBA データ構造体

SCSA では、データ構造体を定義して、ターゲットドライバと HBA ドライバ間で情報交換できるようにしています。含まれているデータ構造体は次のとおりです。

scsi_hba_tran() 構造体

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 にエクスポートします。


Caution

注意  - SCSA ではトランスポート構造体を指すポインタを devinfo ノード上のドライバの非公開フィールドに保持しているため、HBA ドライバはddi_set_driver_private(9F) を使用してはいけません。ただし、HBA ドライバは、ddi_get_driver_private(9F) を使用して、トランスポート構造体を指すポインタを検出することはできます。


SCSA インタフェースでは、HBA ドライバは scsi_hba_tran 構造体を介して呼び出し可能ないくつかのエントリポイントを提供する必要があります。詳細については、SCSA HBA ドライバのエントリポイントを参照してください。

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 構造体の各フィールドについて詳しく説明します。

tran_hba_dip

HBA デバイスインスタンスの dev_info 構造体を指すポインタです。このフィールドは、scsi_hba_attach_setup(9F) 関数によって設定されます。

tran_hba_private

HBA ドライバによって保持される非公開データを指すポインタです。通常、tran_hba_private には、HBA ドライバの状態構造体を指すポインタが入ります。

tran_tgt_private

複製の使用時に 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 が参照されることがあってはなりません。詳細については、トランスポート構造体のクローニングを参照してください。

tran_sd

クローニング時に使用されるターゲットインスタンスごとのscsi_device(9S) 構造体を指すポインタです。SCSI_HBA_TRAN_CLONEscsi_hba_attach_setup(9F) に渡された場合、tran_sd はターゲットごとの scsi_device 構造体を指すように初期化されます。この初期化は、そのターゲットに代わって HBA 関数が呼び出される前に行われます。SCSI_HBA_TRAN_CLONE を指定しない場合、tran_sd は NULL となり、tran_sd が参照されることがあってはなりません。詳細については、トランスポート構造体のクローニングを参照してください。

tran_tgt_init

ターゲットデバイスインスタンスの初期化時に呼び出される HBA ドライバのエントリポイントを指すポインタです。ターゲットごとの初期化が必要ない場合、HBA は tran_tgt_init を NULL に設定しておくことができます。

tran_tgt_probe

ターゲットドライバインスタンスがscsi_probe(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。このルーチンは、ターゲットデバイスの存在を調べるために呼び出されます。この HBA にターゲットのプローブカスタマイズが必要ない場合、HBA は tran_tgt_probe をscsi_hba_probe(9F) に設定します。

tran_tgt_free

ターゲットデバイスのインスタンスが破棄されるときに呼び出される HBA ドライバのエントリポイントを指すポインタです。ターゲットごとの解放が必要ない場合、HBA は tran_tgt_free を NULL に設定しておくことができます。

tran_start

ターゲットドライバがscsi_transport(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_reset

ターゲットドライバがscsi_reset(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_abort

ターゲットドライバがscsi_abort(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_getcap

ターゲットドライバがscsi_ifgetcap(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_setcap

ターゲットドライバがscsi_ifsetcap(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_init_pkt

ターゲットドライバがscsi_init_pkt(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_destroy_pkt

ターゲットドライバがscsi_destroy_pkt(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_dmafree

ターゲットドライバがscsi_dmafree(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_sync_pkt

ターゲットドライバがscsi_sync_pkt(9F) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_reset_notify

ターゲットドライバがtran_reset_notify(9E) を呼び出したときに呼び出される HBA ドライバのエントリポイントを指すポインタです。

tran_bus_reset

ターゲットをリセットしないで SCSI バスをリセットする関数エントリです。

tran_quiesce

未処理のコマンドが完了するのを待ち、発行されたすべての入出力要求をブロックする (またはキューに入れる) 関数エントリです。

tran_unquiesce

入出力動作が SCSI バス上で再開できるようにする関数エントリです。

tran_interconnect_type

services.h ヘッダーファイルに定義されたとおりにトランスポートの相互接続タイプを示す整数値です。

scsi_address 構造体

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 */
};
a_hba_tran

HBA ドライバによって割り当てられ、初期化された scsi_hba_tran(9S) 構造体を指すポインタです。scsi_hba_attach_setup(9F) のフラグとして SCSI_HBA_TRAN_CLONE を指定した場合、a_hba_tran はその構造体のコピーを指します。

a_target

SCSI バス上の SCSI ターゲットを識別します。

a_lun

SCSI ターゲット上の SCSI 論理ユニットを識別します。

scsi_device 構造体

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 */
};

ここでは:

sd_address

SCSI リソースの割り当てのためのルーチンに渡されるデータ構造体です。

sd_dev

ターゲットの dev_info 構造体を指すポインタです。

sd_mutex

ターゲットドライバが使用する mutex です。この mutex は、HBA フレームワークによって初期化されます。ターゲットドライバは、この mutex をデバイスごとの mutex として使用できます。この mutex は、scsi_transport(9F) またはscsi_poll(9F) への呼び出しの前後にわたって保持してはいけません。mutex の詳細については、マルチスレッドを参照してください。

sd_inq

ターゲットデバイスの SCSI 照会データへのポインタです。scsi_probe(9F) ルーチンは、バッファーを割り当て、そのバッファーを満たして、このフィールドに追加します。

sd_sense

デバイスから送られた要求検知データを収めるバッファーを指すポインタです。ターゲットドライバは、このバッファーそのものを割り当てて管理する必要があります。詳細については、attach エントリポイント に記載されたターゲットドライバのattach(9E) ルーチンを参照してください。

sd_private

ターゲットドライバが使用するポインタフィールドです。このフィールドは、ターゲットドライバの非公開の状態構造体を指すポインタの格納によく使われます。

scsi_pkt 構造体 (HBA)

SCSI コマンドを実行するには、ターゲットドライバはまずそのコマンドにscsi_pkt(9S) 構造体を割り当てる必要があります。次に、そのターゲットドライバ専用の非公開データ領域の大きさ、コマンドのステータス、およびコマンドの長さを指定する必要があります。HBA ドライバは、tran_init_pkt(9E) エントリポイントでパケット割り当てを実装します。また、HBA ドライバは、そのtran_destroy_pkt(9E) エントリポイントでパケットの解放を行う必要があります。詳細については、scsi_pkt 構造体 (ターゲットドライバ)を参照してください。

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 */
};

ここでは:

pkt_ha_private

コマンドごとの HBA ドライバの非公開データを指すポインタです。

pkt_address

このコマンドのアドレス情報を提供するscsi_address(9S) 構造体を指すポインタです。

pkt_private

パケットごとのターゲットドライバの非公開データを指すポインタです。

pkt_comp

トランスポート層でこのコマンドが実行されたときに HBA ドライバによって呼び出されるターゲットドライバ完了ルーチンを指すポインタです。

pkt_flags

コマンドのフラグです。

pkt_time

コマンドの完了タイムアウトを秒単位で指定します。

pkt_scbp

コマンドのステータス完了ブロックを指すポインタです。

pkt_cdbp

コマンドのコマンド記述子ブロック (CDB) を指すポインタです。

pkt_resid

コマンドが完了したときに転送されなかったデータバイト数です。このフィールドを使用すると、リソースが割り当てられなかったデータの量も指定できます。HBA は、トランスポート時にこのフィールドを変更する必要があります。

pkt_state

コマンドの状態です。HBA は、トランスポート時にこのフィールドを変更する必要があります。

pkt_statistics

トランスポート層に存在している間に、コマンドが検出したイベントの履歴を提供します。HBA は、トランスポート時にこのフィールドを変更する必要があります。

pkt_reason

コマンド完了の理由です。HBA は、トランスポート時にこのフィールドを変更する必要があります。

ターゲットインスタンスごとのデータ

HBA ドライバは、attach(9E) の実行中にscsi_hba_tran(9S) 構造体を割り当てる必要があります。次に、HBA ドライバは、HBA ドライバの必須のエントリポイントを指すように、このトランスポート構造体にあるベクトルを初期化する必要があります。その後、この scsi_hba_tran 構造体は scsi_hba_attach_setup(9F) に渡されます。

scsi_hba_tran 構造体には tran_hba_private フィールドがあり、HBA ドライバのインスタンスごとの状態を参照するために使用できます。

scsi_address(9S) 構造体には、scsi_hba_tran 構造体を指すポインタが含まれています。また、scsi_address 構造体には、特定のターゲットデバイスのターゲット (a_target) と論理ユニット (a_lun) のアドレスもあります。HBA ドライバの各エントリポイントには、scsi_address 構造体を指すポインタが直接渡されるか、scsi_device(9S) 構造体を経由して間接的に渡されます。その結果、HBA ドライバは自身の状態を参照できます。HBA ドライバは、アドレス指定されているターゲットデバイスを識別することもできます。

次の図は、トランスポート操作のための HBA データ構造体を示しています。

図 18  HBA トランスポート構造体

image:図では、HBA トランスポート層に含まれる構造体の関係を示しています。

トランスポート構造体のクローニング

HBA ドライバがscsi_hba_tran(9S) 構造体でターゲットごとの非公開データを保持する必要がある場合は、クローニングが役立つことがあります。クローニングは、scsi_address(9S) 構造体で提供されるアドレスよりも複雑なアドレスを保持する目的にも使用できます。

クローニングプロセスでも、HBA ドライバはattach(9E) の実行時に scsi_hba_tran 構造体を割り当てる必要があります。また、HBA ドライバの tran_hba_private ソフト状態ポインタとエントリポイントベクトルを初期化する必要もあります。違いが生じるのは、フレームワークがターゲットドライバのインスタンスを HBA ドライバに接続開始するときです。HBA ドライバのtran_tgt_init(9E) エントリポイントを呼び出す前に、フレームワークでは HBA のそのインスタンスに関連付けられている scsi_hba_tran 構造体をクローニングします。その結果、特定のターゲットデバイスインスタンスに割り当てられ、初期化された各 scsi_address 構造体は、scsi_hba_tran 構造体のターゲットインスタンスごとのコピーを指します。scsi_address 構造体は、attach() の実行時に HBA ドライバによって割り当てられた scsi_hba_tran 構造体を指しません。

複製の指定時には、HBA ドライバは 2 つの重要なポインタを使用できます。これらのポインタは、scsi_hba_tran 構造体に含まれています。最初のポインタは tran_tgt_private フィールドであり、ドライバがターゲットごとの HBA 非公開データを指すために使用できます。tran_tgt_private ポインタは、HBA ドライバが a_targeta_lun で提供されるアドレスよりも複雑なアドレスを保持する必要がある場合などに役立ちます。2 番目のポインタは tran_sd フィールドであり、これは特定のターゲットデバイスを参照するscsi_device(9S) 構造体を指すポインタです。

複製の指定時は、HBA ドライバはターゲットごとのデータを割り当て、初期化する必要があります。次に、HBA ドライバは、そのtran_tgt_init(9E) エントリポイントの実行中にこのデータを指すように tran_tgt_private フィールドを初期化する必要があります。HBA ドライバは、その tran_tgt_free(9E) エントリポイントの実行中に、このターゲットごとのデータを解放する必要があります。

複製時にフレームワークでは、HBA ドライバの tran_tgt_init() エントリポイントが呼び出される前に、scsi_device 構造体を指すように tran_sd フィールドを初期化します。ドライバがクローニングを要求するときは、SCSI_HBA_TRAN_CLONE フラグをscsi_hba_attach_setup(9F) に渡します。次の図は、トランスポート操作を複製するための HBA データ構造体を示しています。

図 19  トランスポート操作のクローニング

image:図は、複製された HBA 構造体の例を示しています。

SCSA HBA 関数

SCSA では、いくつかの関数も提供しています。これらの関数は次の表に一覧表示されており、HBA ドライバで使用されます。

表 17  SCSA HBA 関数
関数名
呼び出し元のドライバエントリポイント