カーネルソースにある下記のヘッダファイルは、中間レベルに関連しています。
/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 で導入されました)。
|