スポンサーリンク

CAM_CDBPARSE(3) FreeBSD ライブラリ関数マニュアル CAM_CDBPARSE(3)

名称

csio_build, csio_build_visit, csio_decode, csio_decode_visit, buff_decode, buff_decode_visit, csio_encode, csio_encode_visit, buff_encode_visit − CAM ユーザライブラリ SCSI バッファパーズルーチン

ライブラリ

Common Access Method User Library (libcam, −lcam)

書式

#include <stdio.h>
#include <camlib.h>

int

       csio_build(struct ccb_scsiio *csio, u_int8_t *data_ptr,u_int32_t dxfer_len, u_int32_t flags, int retry_count,int timeout, char *cmd_spec, ...);
int

csio_build_visit(struct ccb_scsiio *csio, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t flags, int retry_count, int timeout, char *cmd_spec, int (*arg_get)(void *hook, char *field_name), void *gethook);

int
csio_decode
(struct ccb_scsiio *csio, char *fmt, ...);

int
csio_decode_visit
(struct ccb_scsiio *csio, char *fmt, void (*arg_put)(void *hook, int letter, void *val, int count, char *name), void *puthook);

int
buff_decode
(u_int8_t *buff, size_t len, char *fmt, ...);

int
buff_decode_visit
(u_int8_t *buff, size_t len, char *fmt, void (*arg_put)(void *, int, void *, int, char *), void *puthook);

int
csio_encode
(struct ccb_scsiio *csio, char *fmt, ...);

int
csio_encode_visit
(struct ccb_scsiio *csio, char *fmt, int (*arg_get)(void *hook, char *field_name), void *gethook);

int
buff_encode_visit
(u_int8_t *buff, size_t len, char *fmt, int (*arg_get)(void *hook, char *field_name), void *gethook);

解説

CAM バッファ /CDB エンコードおよびデコードルーチンは、古い FreeBSD SCSI レイヤの、類似した名前の scsireq_* 関数で書かれたユーザランド SCSI アプリ ケーションに対し、比較的簡単に新しいインタフェースへの移行できる道筋を提 供します。

これらの関数は、新しいアプリケーションで使っても構いませんが、ユーザは、 cam(3) ライブラリに組み入れられた関数を構築する各種 SCSI CCB 構築関数を使 用する方が簡単だということに気づくでしょう ( たとえば、 cam_fill_csio(), scsi_start_stop(), csi_read_write() です)。

csio_build() は、変数引数リストに提供された情報をもとにして ccb_scsiio 構 造体を構築します。この関数は、この関数に渡される NULL の data_ptrt 引数を 整然と処理します。

dxfer_len は、データフェーズの長さです。データ転送の方向は flags 引数に よって決まります。

data_ptr は、 SCSI データフェーズの間に使用されるデータバッファです。問題 の SCSI コマンドについてデータが転送されない場合は、これを NULL に設定す る必要があります。コマンドについて転送するデータがある場合は、このバッ ファは少なくとも dxfer_len の長さでなければなりません。

flags は ⟨cam/cam_ccb.h⟩ に定義されたフラグでなければなりません。

/* 共通の CCB ヘッダ */
/* CAM CCB フラグ */
typedef enum {
     CAM_CDB_POINTER       = 0x00000001,/* CDB フィールドはポインタである */
     CAM_QUEUE_ENABLE      = 0x00000002,/* SIM 待ち行列処置は有効である */
     CAM_CDB_LINKED        = 0x00000004,/* CCB はリンクした CDB を含む */
     CAM_SCATTER_VALID     = 0x00000010,/* 分散/収集リストは有効である */
     CAM_DIS_AUTOSENSE     = 0x00000020,/* 自動探知機能を無効にする */
     CAM_DIR_RESV          = 0x00000000,/* データ方向 (00:予約済み) */
     CAM_DIR_IN            = 0x00000040,/* データ方向 (01:DATA IN) */
     CAM_DIR_OUT           = 0x00000080,/* データ方向 (10:DATA OUT) */
     CAM_DIR_NONE          = 0x000000C0,/* データ方向 (11:データなし) */
     CAM_DIR_MASK          = 0x000000C0,/* データ方向マスク */
     CAM_SOFT_RST_OP       = 0x00000100,/* 代わりにソフトリセットを使用する */
     CAM_ENG_SYNC          = 0x00000200,/* 完了時に剰余バイトをフラッシュする */
     CAM_DEV_QFRZDIS       = 0x00000400,/* DEV Q 凍結を無効にする */
     CAM_DEV_QFREEZE       = 0x00000800,/* 実行時に DEV Q を凍結する */
     CAM_HIGH_POWER        = 0x00001000,/* コマンドは大量の能力を得る */
     CAM_SENSE_PTR         = 0x00002000,/* センスデータはポインタである */
     CAM_SENSE_PHYS        = 0x00004000,/* センスポインタは物理的なアドレス */
     CAM_TAG_ACTION_VALID  = 0x00008000,/* この ccb 内ではタグ処置を使用する */
     CAM_PASS_ERR_RECOVER  = 0x00010000,/* 受け渡しドライバエラー。回復 */
     CAM_DIS_DISCONNECT    = 0x00020000,/* 切断を無効にする */
     CAM_SG_LIST_PHYS      = 0x00040000,/* SG リストに物理アドレスがある */
     CAM_MSG_BUF_PHYS      = 0x00080000,/* メッセージバッファ ptr が物理的である */
     CAM_SNS_BUF_PHYS      = 0x00100000,/* 自動探知データ ptr が物理的である */
     CAM_DATA_PHYS         = 0x00200000,/* SG/バッファデータ ptr が物理的である */
     CAM_CDB_PHYS          = 0x00400000,/* CDBポインタが物理的である */
     CAM_ENG_SGLIST        = 0x00800000,/* SG リストは HBA エンジン用である */

/* フェーズ認識モードフラグ */
     CAM_DIS_AUTOSRP       = 0x01000000,/* 自動保存/復元ポインタを無効にする */
     CAM_DIS_AUTODISC      = 0x02000000,/* 自動切断を無効にする */
     CAM_TGT_CCB_AVAIL     = 0x04000000,/* ターゲットの CCB が利用可能 */
     CAM_TGT_PHASE_MODE    = 0x08000000,/* SIM がフェーズモードで実行される */
     CAM_MSGB_VALID        = 0x20000000,/* メッセージバッファが有効 */
     CAM_STATUS_VALID      = 0x40000000,/* ステータスバッファが有効 */
     CAM_DATAB_VALID       = 0x80000000,/* データバッファが有効 */

/* ホストターゲットモードフラグ */
     CAM_TERM_IO           = 0x20000000,/* 入出力メッセージ補充を終了 */
     CAM_DISCONNECT        = 0x40000000,/* 切断は必須である */
     CAM_SEND_STATUS       = 0x80000000,/* データフェーズの後にステータスを送信 */
} ccb_flags;

複数のフラグを指定する場合、OR (論理和) を取る必要があります。どの CCB フ ラグを使用することもできます。以降の重要ないくつかのフラグについては特に 説明しておく価値があります。

       CAM_DIR_IN

問題の操作が読み取り操作であることを示します。すな わち、データは SCSI デバイスからユーザ指定バッファ に読み取られています。

CAM_DIR_OUT
操作が書き込み操作であることを示します。すなわち、 データはユーザ指定バッファからデバイスに書き込まれ ています。

CAM_DIR_NONE
このコマンドについて転送されるデータはないことを示 します。

CAM_DEV_QFRZDIS
デバイス待ち行列の、エラー回復メカニズムとしての凍 結を無効にします。

CAM_PASS_ERR_RECOVER
pass(4) ドライバにエラー回復を有効にするように通知 します。デフォルトではエラー回復を実行されません。 すなわち、このフラグがない場合は再試行カウントは意 味を持ちません。

CAM_DATA_PHYS
data_ptr
に入っているアドレスが、仮想アドレスではな く物理アドレスであることを示します。

retry_count は、問題のコマンドを何回再試行するかをカーネルに通知します。 pass(4) ドライバが CAM_PASS_ERR_RECOVER フラグによって回復を有効にするよ う指示されていない限り、再試行カウントは無視されます。

timeout は、指定のコマンドが完了するまでどのくらい待機するかをカーネルに 通知します。時間が切れ、しかもコマンドが完了していないと、 CCB は、該当す るエラーステータスでカーネルから帰ります。

cmd_specis は SCSI CDB を構築するのに使用される CDB 形式指示子です。この テキストストリングは、フィールド指示子のリストで構成されます。フィールド 指示子は、各 CDB フィールド用の値 (値を変数引数リスト内の次の引数から取る べきことを示すことも含む)、フィールドの幅 (ビット単位またはバイト単位)、 およびオプションの名前を指定します。スペースは無視され、シャープ記号 (’#’) は、現在の行の末尾で終了するコメントの先頭を示します。

オプションの名前は、フィールド指定子の最初の部分であり、中括弧で囲まれま す。次の例で中括弧で囲まれたテキストは名前です。 {PS} v:b1 {Reserved} 0:b1 {Page Code} v:b6 # Mode select page

このフィールド指定子には、3 つのフィールドがあります。 1 ビットのフィール ドが 2 つと 6 ビットのフィールドが 1 つです。 2 番めの 1 ビットフィールド は定数値 0 であり、最初の 1 ビットフィールドと 6 ビットフィールドは、変数 引数リストから取られます。複数バイトのフィールドは SCSI のバイト順序で CDB 内にスワップされ、スペースは無視されます。

フィールドが 16 進数値または文字 v のとき ( たとえば、 1A または v) 、 1 バイト値が CDB 中の次の未使用バイトにコピーされます。文字 v が使用されて いるとき、次の整数引数が変数引数リストから取られ、その値が使用されます。

定数の 16 進数値にフィールド幅の指定子、または文字 v にフィールド幅指定子 フィールドが続いたもの ( たとえば、 3:4, 3:b4, 3:i3, v:i3) は、指定のビッ トまたはバイト幅のフィールドを指定します。定数値、または (V 指定子の場合) 可変引数リストの次の整数値が、 CDB の次の未使用ビットまたはバイトにコピー されます。

10 進数または文字 b に 10 進数フィールド幅が続いたものは、その幅のビット フィールドを示します。ビットフィールドは、可能な限り緊密にパックされ、上 位ビットで開始し (SCSI 仕様と同じものを読み取られるようにです ) 、 1 バイ トが完全に一杯になるときはいつでも、または i フィールドが検出されたとき は、 CDB の新しいバイトが開始されます。

文字 i の後に 1, 2, 3, または 4 が続いたフィールド幅指示子は、 SCSI バイ ト順 (MSB が先頭) にスワップしなければならない 1, 2, 3, または 4 バイトの 整数値を示します。

v フィールド指示子については、次の整数引数が、変数引数リストから取られ、 その値が SCSI 順にスワップするのに使用されます。

csio_build_visit() は csio_build() と動作が類似していますが、 cmd_spec 内 の変数引数に置き換わる値が、 stdarg(3) によってではなく、 csio_build_visit() に渡される arg_get() 関数によって取り出される点が異な ります。 arg_get() 関数は次の 2 つの引数を取ります。

gethook
は関数呼び出しのたびに arg_get() 関数に渡されます。これによっ て、 arg_get() 関数は、グローバル変数または静的変数を使用せず に、間の呼び出しの間に状態のいくらかを保持することができま す。

field_name
は、 fmt がある場合はそれによって与えられる名前です。

csio_decode() は、 SCSI 転送のフェーズでデータの情報をデコードするのに使 用されます。

デコードは、 csio_build() のコマンド指示子処理に類似していますが、 csio->data_ptr によって指されるデータからデータを取り出す点が異なります。 stdarg リストは、整数値ではなく整数を指すポインタです。シークフィールドタ イプと抑制修飾子が追加されます。 * 抑制修飾子 ( たとえば、 *i3 または *b4) は、フィールドからの割り当てを抑制し、データ内のバイトまたはビットを スキップするのに使用できます。これにより arg リスト内のダミー変数にコピー する必要がなくなります。

シークフィールドタイプ s によって、データをスキップできます。これは、’+’ 符号の存在の有無に基づき、データ内の絶対位置 (s3) または相対位置 (s+3) を 探します。シーク値は v として指定することができ、引数リストの次の整数値が シーク値として使用されます。

csio_decode_visit() は、 csio_decode() と同じように動作しますが、デコード したバッファの内容を可変長引数に配置する代わりに、デコードしたバッファの 内容は、渡された arg_put() 関数を通じてユーザに返される点が異なります。 arg_put() 関数は、次のいくつかの引数を取ります。

hook
"hook" は、 arg_put() 関数が呼び出しの間で状態を保存できるように するメカニズムです。

letter
関数に渡される引数の形式を記述する文字です。

val
関数に渡される値を指す void ポインタです。

count
arg_put
() 関数に渡される値のサイズです。引数のフォーマットにより 大きさの単位が決まります。

name
フィールドのテキスト記述です。ただし fmt 内にそれが準備されている 場合です。

buff_decode() は、 csio_decode() について前述した方式を使用して任意のデー タバッファをデコードします。

buff_decode_visit() は、 csio_decode_visit() について前述した方式を使用し て任意のデータバッファをデコードします。

csio_encode() は、 csio_build() について前述した方式を使用して、 ccb_scsiio の構造 data_ptr 部分 (CDB ではない ) をエンコードします。

csio_encode_visit() は、 csio_build_visit() について前述した方式を使用し て、 ccb_scsiio 構造の data_ptr 部分 (CDB ではない ) をエンコードします。

buff_encode_visit() は、 csio_build_visit() について前述した方式を使用し て、任意のデータポインタをエンコードします。

戻り値

csio_build(), csio_build_visit(), csio_encode(), csio_encode_visit() およ び buff_encode_visit() は、処理済みのフィールドの数を返します。

csio_decode(), csio_decode_visit(), buff_decode() および buff_decode_visit() は、実行された割り当ての数を返します。

関連項目

cam(3), pass(4), camcontrol(8)

歴史

これらの関数の CAM バージョンは、古い FreeBSD の SCSI レイヤ用に実現され た類似の関数を基礎にしています。 SCSI の古いコード内のエンコード/デコード 関数は Peter Dufault が作成したものです。

多数のシステムに、ユーザ空間で SCSI コマンドをユーザが構築できる、これと 匹敵するインタフェースがあります。

古い scsireq データ構造は、SGI の /dev/scsi データ構造とほとんど同じでし た。作者の名前を知っている人はここに連絡してください。 Peter Dufault は、 1989 年の『Sun Expert』誌で、最初にこれについて読みました。

新しい CCB データ構造は、 CAM-2 および CAM-3 仕様に由来しています。

Peter Dufault は、 386BSD で SGI のインタフェースのクローンを実現しまし た。これがオリジナルの FreeBSD SCSI ライブラリと関連カーネル ioctl に至る ものになりました。互換性の必要がある場合は、dufault@hda.com に連絡してく ださい。

作者

Kenneth Merry が、これらのエンコードおよびデコードの関数の CAM バージョン を実現しました。この現在の作業は、Peter Dufault による以前の作業を基礎に しています。

バグ

CDB および SCSI CCB のデータバッファ部分の両方をエンコードする関数はおそ らく必要でしょう。 camcontrol(8) で任意のコマンド実行コードを実現している 間に私はこの必要性に気づきましたが、そのような関数を実現する時間がまだあ りません。

CCB フラグの説明には本当はここに属さないものがあります。それらは一般の CCB マニュアルページに属します。そのマニュアルページはまだ書かれていない ので、ここでの短い説明で間に合わせざるを得ません。

FreeBSD 10.0 October 13, 1998 FreeBSD 10.0

スポンサーリンク