9.4. 汎用ドライバ(sg)

あらゆる種類の SCSI デバイスは、sg ドライバ経由でアクセスできます。つまり、 CD-ROM ドライブなら、sr と sg ドライバいずれでもアクセスできます。スキャナー のようなその他の SCSI デバイスは sg ドライバを使ってのみアクセスできます。 sg ドライバは、256 個の SCSI デバイスを認識できます。デバイスは sg ドライバ のロード後にいくつでも追加できます(ただし限度の 256 まで)。

SCSI 汎用(sg)ドライバのドキュメントはW4を参照 してください(sg_utils パッケージにも入っています)。 SCSI 規格については、W1や SCSI のプログラミングが 主題となっている書籍を参照してください。しくみを勉強したければ、 B3を参照してください。

カーネル 2.4 における sg ドライバは「バージョン 3」で、インタフェース機構の 追加と新しい ioctl() が加わりました。新規の ioctl() で一番おもしろいのは、 SG_IO で、SCSI コマンドを送り出し、その応答を待ちます。 Linux Documentation Project サイトにある www.tldp.org/HOWTO/SCSI-Generic-HOWTO/ には、sg ドライバについての完璧な解説があります。 このドキュメントの(おそらくより新しい)バージョンは、 www.torque.net/sg/p/sg_v3_ho.htmlにあります。

カーネル内で使用されている「sg」という略語には、SCSI 汎用ドライバを指す場合 と、最近の入出力デバイス(普通は DMA 対応)の多くが提供している、scatter-gather 機能を指す場合に使われています。どちらを意味するのかは、文脈次第です。 例えば、SG_GET_SG_TABLESIZE という分りにくい sg の ioctl()は、2 番目の 「SG」が scatter-gather を指しています。

sg の公開インタフェースは /usr/src/linux/include/scsi/sg.h にあります。ディストリビューションにもよりますが、これは GNU ライブラリのメンテナーが管理している /usr/include/scsi/sg.h と同じ内容かもしれませんし、違う かもしれません。この 2 つのファイルの内容が同じでなければ、前者のヘッダー ファイルを使ってください。 sg ベースでアプリケーションを書く場合は、sg の文書を見て、この問題をより 深く理解する方が良いでしょう。

sg ドライバは、現在ある SCSI デバイスすべてを登録しています(現状の最大数は、 256 個)。新しく登録する SCSI デバイスそれぞれに、次に利用可能なマイナー番号 が確保されます。少なくとも最初の内は、cat /proc/scsi/scsi で表示される中間レベルのものと同じ順番です。sg デバイスの マッピングは、cat /proc/scsi/sg/devices もしくは cat /proc/scsi/sg/device_strs でわかります。 cat /proc/scsi/scsi と sg の順序の違いが生じるのは、 低レベルのドライバが削除された時(例えば rmmod aha1542)や デバイスが remove-single-device で削除された時です。 sg ドライバは、残っている SCSI デバイスを変更すること無く、マイナー デバイス番号にマッピングし続けます。これは sg のマッピングに「欠番」を 残すことになります。 下記がその例です。

$ cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access            ANSI SCSI revision: 03
Host: scsi1 Channel: 00 Id: 02 Lun: 00
  Vendor: PIONEER  Model: DVD-ROM DVD-303  Rev: 1.10
  Type:   CD-ROM                   ANSI SCSI revision: 02
Host: scsi1 Channel: 00 Id: 06 Lun: 00
  Vendor: YAMAHA   Model: CRW4416S         Rev: 1.0g
  Type:   CD-ROM                   ANSI SCSI revision: 02

$ cat /proc/scsi/sg/device_strs 
IBM             DNES-309170W            SA30
PIONEER         DVD-ROM DVD-303         1.10
YAMAHA          CRW4416S                1.0g

$ echo "scsi remove-single-device 1 0 2 0" > /proc/scsi/scsi

$ cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access            ANSI SCSI revision: 03
Host: scsi1 Channel: 00 Id: 06 Lun: 00
  Vendor: YAMAHA   Model: CRW4416S         Rev: 1.0g
  Type:   CD-ROM                   ANSI SCSI revision: 02

$ cat /proc/scsi/sg/device_strs 
IBM             DNES-309170W            SA30
<no active device>
YAMAHA          CRW4416S                1.0g
sg ドライバが「device_strs」の出力において、残っているデバイスの並び位置を どのように管理しているかをよく見てください。Pioneer の DVD プレーヤーが削除 されると sg デバイスのマッピングには欠番ができますが、 cat /proc/scsi/scsi には現れません。この「欠番」は /dev/sg1 に該当します。

新しい sg_io_hdr インタフェースには、未転送データ量をカウントするための 「resid」というフィールドがあります。低レベルのアダプタのいくつかだけが この機能をサポートしており、その場合でのみこのフィールドに 0 以外が入ります。 このドキュメントの執筆時では、advansys、aha152x、sym53c8xx ドライバがこの機能 をサポートしています。

9.4.1. sg のブート時のパラメタ

sg ドライバは、オープンしているファイルディスクリプタそれぞれに対して、 予約済みのバッファを管理しています。 この目的は、アプリケーションのデータ転送に際してカーネルのメモリが足りなく なっても、予約バッファの大きさに達するまでは転送が失敗しないことを保証する ことです。 これは、cdrecord のような ENOMEM エラーから簡単には復旧できない(CD-R なので) アプリケーションにとっては重要です。

ブート時のパラメタに「sg_def_reserved_size」がなかったり、sg モジュールの パラメタである「def_reserved_size」がなかったりすると、sg のファイル ディスクリプタがオープンする度に、include/linux/sg.h に定義してある SG_DEF_RESERVED_SIZE をそのまま使います。

SG_DEF_RESERVED_SIZE の値は、下記のカーネルブート時のオプションで変更可能 です。

    sg_def_reserved_size=<n>

9.4.2. sg のモジュールのパラメタ

sg モジュールがロードされる時、SG_DEF_RESERVED_SIZE で定義してある値は下記 のオプションで変更できます。

    def_reserved_size=<n>

9.4.3. sg の proc インタフェース

次のファイルは誰もがすべて読み出し可能で、ASCII 形式で出力されます。 「def_reserved_size」は root が書き込み可能です。ASCII 出力は、人間と マシン両者が読める形式になっています(そのため読みやすさは犠牲に なっています)。表出力を見るには、 cat device_hdrs devices という Unix コマンドを使って ください。


/proc/scsi/sg/debug       [sg ドライバの内部状態]
/proc/scsi/sg/def_reserved_size
                          [ブート時もしくはモジュールをロードした時の
  												パラメタと同じ]
/proc/scsi/sg/devices     [数字表現のデバイスのデータテーブル]
/proc/scsi/sg/device_hdr  [sg と デバイスのカラムヘッダー]
/proc/scsi/sg/device_strs [INQUIRY からの文字列のテーブル]
/proc/scsi/sg/hosts       [ホストデータ(数字)のテーブル]
/proc/scsi/sg/host_hdr    [sg と ホストのカラムヘッダー]
/proc/scsi/sg/host_strs   [ホスト ID(文字列)のテーブル]
/proc/scsi/sg/version     [sg のバージョン番号と日付]
上記のファイルすべては root がオーナーになっていて、どのユーザも読み込み可能 です。 def_reserved_size は root が書き込み可能です。 devicesdevice_strs 各ファイル は、最初の列が /dev/sg0 に対応しており(sg のマイナー デバイス番号 0)、2 番目の列は /dev/sg1 に対応しています (以下同様)。 hostshost_strs 各ファイルは、 最初の列がホスト(アダプタ番号)の 0 に対応しています(以下同様)。 数字で書いてあるテーブルでは、見つからないデバイスやホストはその列に「-1」 という値が表示されます。文字列で書いてあるテーブルでは、見つからない デバイスもしくはホストはその列に「<no active device/host」と表示されます。