カーネルソースにある下記のヘッダファイルは、中間レベルに関連しています。
/usr/src/linux/include/scsi/scsi.h /usr/src/linux/include/scsi/scsi_ioctl.h |
これらのファイルは、アプリケーションから用いるためのものです(__KERNEL__ 条件 内部のコンパイルブロック以外の部分)。これらは /usr/include/scsi ディレクトリ にもありますが、そちらは glibc ライブラリとともにメンテナンスされており、 カーネルのバージョンに追随していないので、信じない方が賢明です。 Linux システムでは、 /usr/include/linuxがカーネルソースの include 領域 にシンボリックリンクされています(普通は、 /usr/src/linux/include/linux)。このシンボリックリンク を使うと、#include <linux/../scsi/scsi_ioctl.h> という技によって、 正確なscsi_ioctl.hをインクルードできます。
この /usr/src/linux/drivers/scsi/scsi.h は、SCSI サブ システムの鍵となる内部ヘッダーファイルです。同名の(ただし、別ディレクトリに 存在する)ファイル名があり、それはこのセクションの最初で注目したファイルである という点だけ指摘しておきます。これはときどき混乱の原因になります。
中間レベルのファイル drivers/scsi/scsi_scan.c には、 既知の SCSI デバイスの多くが特徴ある記述方法で載って います。(これは「ブラックリスト」として知られていましたが、あまりに断定的と みなされていました)。この配列の名前は「デバイスリスト」です。 次のようにいろいろな値があります。
BLIST_NOLUN LUN の 0 だけを検査する
BLIST_FORCELUN 8 つすべての LUN を強制的に検査
BLIST_BORKEN 低レベルのドライバに 故障フラグを渡す
BLIST_KEY ロックを外すドライバに即効果が出る MODE SENSE (pc=0x2e)を送る
BLIST_SINGLELUN は、一度に 1 つの LUN にしか入出力を許可 しない
BLIST_NOTQ タグキューを無効
BLIST_SPARSELUN LUN が見つからなくても動き続ける
BLIST_MAX5LUN LUN を探るのを最大 5 まで
BLIST_ISDISK INQUIRY タイプを強制的にディスク (直接アクセス)に
BLIST_ISROM INQUIRY タイプを 強制的に ROM に
ありません。
次のファイルを見てください。
/usr/src/linux/include/scsi/scsi.h |
include/scsi/scsi.h で定義してある SCSI の状態定数は、SCSI 規格で定義 してある値に比べて、1 ビット右にシフトしている点に注意してください。
scsi.h 定数 値 SCSI 2 規格の値 ---------------------------------------------------- CHECK_CONDITION 0x1 0x2 CHECK_GOOD 0x2 0x4 BUSY 0x4 0x8 .... |
ioctl()の概要は下記の通りです。
SCSI_IOCTL_SEND_COMMAND このインタフェースは旧方式です。かわりに汎用 SCSI(sg)インタフェース を利用してください。汎用 SCSI(sg)インタフェースを使った方が、デバイス をより柔軟に扱えます。 これまで触れて来ませんでしたが、構造体は下記のようになります。 struct sdata { unsigned int inlen; [i] デバイスに書き込んだデータ長 unsigned int outlen; [i] デバイスから読み込んだデータ長 unsigned char cmd[x]; [i] SCSI コマンド(6 <= x <= 16) [o] デバイスから読み込んだデータはここから開始 [o] エラー時には、センスバッファはここから開始 unsigned char wdata[y]; [i] デバイスに書き込んだデータはここから開始 }; 注意: ・SCSI コマンド長は、コマンドの最初のバイトでわかります。これを上書き する方法はありません。 ・データ転送は、PAGE_SIZE(i386 で 4 K、alpha で 8 K)に制限されます。 ・(x + y)の長さは、エラーが起こった時にセンスバッファ用に、 最低 OMAX_SB_LEN バイトなければなりません。センスバッファは OMAX_SB_LEN (16)バイトに縮められているので、古いコードでも支障はでません。 ・Unix でエラーが発生した場合(例えば ENOMEM)、ユーザは負の返り値と 「errno」にある Unix のエラーコードを受け取ります。 SCSI コマンドが成功すると 0 が返ります。正の数を受け取ると、それは SCSI のエラーコードの集まりになっています(4 バイトが int ひとつにまとめ られている)。下位バイトが SCSI の状態を表しています。詳しい情報は drivers/scsi/scsi.h ファイルを見てください。 SCSI_IOCTL_GET_IDLUN この ioctl は 3 番目の引数として「struct scsi_idlun」オブジェクト へのポインタをとります。「struct scsi_idlun」の定義は、<scsi/scsi.h> にあります。これには、そのデバイスの SCSI ホスト、チャネル、デバイス ID、 LUN データが入っています。 あいにく、ヘッダファイルは構造体を「#ifdef __KERNEL__」ブロックで 「隠して」います。これを利用するには、構造体をユーザのプログラムにコピー しなければなりません。 このようになります。 typedef struct my_scsi_idlun { int four_in_one; /* 4 つの独立したバイトを 1 つの int にまとめてある */ int host_unique_id; /* 同じメーカー製カードと区別 */ } My_scsi_idlun; 「four_in_one」は、下記のように構成されています。 (scsi_device_id | (lun << 8) | (channel << 16) | (host << 24)) これら 4 つの部分はそれぞれ 1 バイトである(でマスクしてある)ことが 前提になっています。 SCSI_IOCTL_GET_BUS_NUMBER Linux カーネル 2.2 以前では、この ioctl にはホスト番号が必要でした。 Linux カーネル 2.3 開発版になって、SCSI_IOCTL_GET_IDLUN ioctl が変更に なり、この情報が入るようになりました。したがって、この ioctl は下位互換性 のためにだけ必要です。 SCSI_IOCTL_TAGGED_ENABLE おそらく、中間レベルが以前扱っていた時の名残りです。現状この機能は、 低レベルのドライバが制御しています。無視するのが一番です。 SCSI_IOCTL_TAGGED_DISABLE SCSI_IOCTL_TAGGED_ENABLE のコメントを見てください。 SCSI_IOCTL_PROBE_HOST この ioctl は 3 番目の引数に下記のような共用体へのポインタを要求します。 union probe_host { unsigned int length; /* [i] ASCII 文字列出力の最大長 */ char str[length]; /* [o] 注意。'\0' を加える必要があるかも しれない */ }; デバイスの fd に対応したホストは、ホストに依存した情報の文字列か、 それがなければホストの名前が与えられた構造体に出力されます。出力は与えられた 構造体の先頭から出力が行われることに注意してください(入力の length は上書き される)。「注意」出力文字列が length に切り詰められた場合は、末尾に「\0」を 加える必要があるかもしれません。返り値が 1 の場合はホストが存在することを 表し、0 の場合はホストが存在しないことを表します(どのような場合?)。負の値 はエラーを意味します。 SCSI_IOCTL_DOORLOCK SCSI_IOCTL_DOORUNLOCK SCSI_IOCTL_TEST_UNIT_READY ユニット(デバイス)が準備できていれば 0 が返り、準備ができていなければ 正の値が返り、OS のエラーが発生した場合は負の値が返ります。 SCSI_IOCTL_START_UNIT SCSI_IOCTL_STOP_UNIT SCSI_EMULATED_HOST {SG_EMULATED_HOST <new>と同じ} SCSI_IOCTL_GET_PCI 低レベル(アダプタ)に対応したPCI のスロット名(pci_dev::slot_name)のうち、 現在デバイスを制御しているものを表示します。最大 8 文字が「引数」で指定 された場所に出力されます。現在のデバイスが PCI デバイスによって制御されて いなければ、errno に ENXIO が設定されます。(この ioctl()は、Linux カーネル 2.4.4 で導入されました)。 |