Linux における SCSI プログラミン グ sg3-utils ソースコード解読
SCSI 規格の規定 大まかに以下の 3 層に分かれる – 物理層 – プロトコル層 – コマンド・セット 共通コマンド プロトコル ダイレクト・アクセス シーケンシャル・アクセス メディアチェンジャー パラレル SCSI シリアル SCSI ファイバーチャネル 物理・電気層 コネクタ ケーブル シングル・エンドディファレンシャル
Linux での SCSI 制御 大まかに以下の 3 層に分かれる – 「高」レベルレイヤが SCSI 規格のコマンド・ セットの部分に接している – 「低」レベルレイヤがプロトコル層や物理・電 気層に接している – 「中間」レベルは「高」レベルと「低」レベル に共通のサービス層を提供する アプリケーションレベルの開発ではこれらの「高」レ ベルレイヤのドライバを用いて開発を行う。 「高」レベル 「中間」レベル SG (汎用ドライバ ) 「低」レベル ST ( テープドライバ ) SR(CDROM 等ドライバ ) SD( ディスクドライバ )
Linux での SCSI プログラミング SD( ディスクドライバ ) ・ SR(CDROM または DVD ドライバ ) ・ ST( テープドライバ ) での開 発 – 開発が可能であればこれらのドライバを使って開 発したほうが楽。 以下の場合は SG ドライバを使って開発 – 細かい SCSI 制御が必要な場合。 – 上記以外の種類の SCSI 機器を制御しなければいけ ないとき。 ( 例:テープライブラリ )
SG ドライバを用いたのプログ ラム開発の手法 最小限必要な include ファイル –/usr/include/scsi/scsi.h SCSI コマンドやステータス・バイト ( コマンド の返り値 ) 等を定義 –/usr/include/scsi/sg.h SG デバイスとアクセスするための ioctl システ ムコールの引数を定義
プログラム開発の大まかな開 発手順 SG デバイスを open(2) を O_RDWR の flag を付 けて開く。 –(Read only のデバイスでも O_RDWR を付ける ) sg_io_hdr 構造体を初期化して ioctl システム コールを呼び出す。 SG デバイスを close する。 エラーが発生したときの具体的内容は sg_io_hdr 構造体に保持されているので、エ ラー発生時には sg_io_hdr 構造体の中身を見 て処理をする。
少し楽に開発するには このままではエラー処理が大変面倒 sg3-utils のソースコードにある以下のファイ ルを用いると開発が楽になる。 –sg_linux.inc.h sg.h と scsi.h が /usr/include/scsi ディレクトリに無い場合 でもコンパイル出来るようにする為のラッパーファイル –sg_io_linux.h ・ sg_io_linux.c SCSI コマンド実行後の返り値 エラー発生時のエラー処理をするための関数等を定義し たファイル (Linux 依存 ) –sg_lib.h ・ sg_lib.c CDB( 後で説明 ) で定義されている情報を処理するコマン ド SCSI コマンドやステータス・バイトの定義 SCSI コマンドで入出力に使われるメモリを処理するコマ ンド SCSI 処理でエラーが発生したときに出力される Sense Data を処理するコマンド等を定義したファイル (Linux 非 依存 )
更に楽にするには 殆ど SCSI コマンドを呼び出すだけ Linux 以外の OS にも移植出来るように なる。 –sg_pt.h ・ sg_pt_linux.c sg_pt.h はさまざまな OS で同じ関数名で呼び出 すためのインクルードファイル sg_pt_linx.c(sg_pt_freebsd.c ・ sg_pt_solaris.c ・ sg_pt_osf1.c ・ sg_pt_win32.c) はその実際の処理の記述したファイル。 –sg_cmds.h sg_cmds_basic および sg_cmds_extra の両方の インクルードファイルを呼び出すファイル
更に楽にするには ( 続き) –sg_cmds_basic.h ・ sg_cmds_basic.c SCSI コマンドの中で比較的良く使われるコマ ンドおよびファイルのオープン・クローズ・エ ラー出力処理を定義したファイル –sg_cmds_extra.h ・ sg_cmds_extra.c SCSI コマンドの中で比較的使われる頻度が少 ないコマンドを定義したファイル
sg_io_hdr_t で設定するデータ 1) CDB(Command Descriptor Block ) – イニシエータ (SCSI ボード ) からターゲット (SCSI 機器 ) に操作要求を伝えるためのコマ ンド情報を示す。大体 6 ・ 10 ・ 12 バイトの 大きさ。必ず先頭バイトがオペレーション コード最終バイトがコントール・バイトと なる。 – サポートする SCSI コマンドは SCSI 機器毎 で異なる。詳しくはそれぞれの SCSI 機器 のハードウェアマニュアルを参照する。
sg_io_hdr_t で設定するデータ 1 ) CDB( 続き ) – コマンドの先頭アドレスとコマンドの長さ を sg_io_hdr_t の以下のメンバに設定 cmd_len –CDB を保持する配列の長さ cmdp –CDB を保持する配列を指すポインタ
sg_io_hdr_t で設定するデータ 2 ) SCSI コマンドで受け渡しするメモリ上の データ –SCSI コマンドでデータを送るとき 送るデータ内容の配列を設定する。 –SCSI コマンドでデータを受け取るとき 受け取るデータの配列を初期化しておく。 – どちらもデータの先頭アドレスとデータの長さを sg_io_hdr_t のメンバに設定する。 –SCSI コマンドでデータを受け取とったときの配列 の長さは CDB のデータとして返される。
sg_io_hdr_t で設定するデータ 2 ) SCSI コマンドで受け渡しするメモリ上の データ –dxfer_direction SCSI コマンドを使って遣取りをするデータの流れる方向 SG_DXFER_NONE データのやり取りをしない SG_DXFER_TO_DEV イニシエータ → ターゲット SG_DXVER_FROM_DEV ターゲット → イニシエータ SG_DXFER_TO_FROM_DEV ターゲット ←→ イニシエータ
sg_io_hdr_t で設定するデータ 2 ) SCSI コマンドで受け渡しするメモリ上の データ –SG_DXFER_TO_DEV mode select (6) mode select (10) log select set target port group send diagnostic set identifying information format unit reassign blocks persistent reserve out write long(10) write long(16) verify (10) write buffer
sg_io_hdr_t で設定するデータ 2 ) SCSI コマンドで受け渡しするメモリ上の データ –SG_DXFER_FROM_DEV inquiry read capacity (16) read capacity (10) mode sense (6) mode sense (10) request sense report luns log sense report target port group receive diagnostic results read defect (10) read media serial number report identifying information get configuration persistent reservation in read long (10) read long (16) read buffer
sg_io_hdr_t で設定するデータ 3 ) Sense Data –SCSI コマンドがエラーを起こしたときに 機器の」メモリに保存されたエラー情報 発生時に自動的に sg_io_hdr_t のメンバにコ ピーされる。 – 先頭アドレスとデータの長さは sg_io_hdr_t のメンバにあらかじめ設定しておく
ioctl の返り値 ステータス・バイトの値を返す。 値の定義は scsi.h の中で定義されている。