JF Linux Kernel 2.2 Documentation: /usr/src/linux/Documentation/cdrom/ide-cd

cdrom/ide-cd

IDE-CDドライバに関する文書 [プレインテキスト版]


IDE-CDドライバに関する文書
原本は scott snyder <snyder@fnald0.fnal.gov>によるものです。(1996年5月19日)
引き継いだのは: Erik Andersen <andersee@debian.org> です。
新しいメンテナは (1998年10月19日): Jens Axboe <axboe@image.dk> です。

1. はじめに
---------------

ide-cd ドライバは、IDE インタフェースに接続された全 ATAPI ver1.2から ATAPI2.6
に準拠する CDROM ドライブに対して機能します。いくつかの CDROM ベンダ(含 Mitsumi,
Sony,Creative,Aztech,Goldstar)が、ATAPI 準拠のドライバと独自のドライバの両方
を作っていることに注意してください。あなたのドライブがそういった独自のインタ
フェースを使用するのなら、このドライバは動かないでしょう。(ただし、ほかの
CDROMドライバのうちのひとつは動くかもしれません)  このドライバはパラレル
ポートに接続する `ATAPI'ドライブでは動かないでしょう。 更に IDE ポートに接続
するのにATAPIではないドライブが少なくとも1つあります。(CyCDROM CR520ie)
−このドライバはそのようなドライブに対しても動かないでしょう。(でも the 
aztcd driver を見てください)

このドライバは次のような機能を提供します:

- データトラックからの読み込みと ISO9660ファイルシステムのマウント

- オーディオトラックの演奏、広く使われている CDROM プレイヤープログラムが動くで
  しょう −私はいつも Workman を使っています

- マルチセッションサポート

- サポートしているドライブ上でのデジタルオーディオデータ直接読み込み。
  プログラム cdda2wav はこのために使われます。ですが、実際にはいくつかのドライ
  ブだけがサポートしているということに注意してください。

- ATAPI2.6に準拠している CDROM チェンジャに対して現在サポートがあります。
  この追加機能は、どのスロットが現在選択されているスロットなのかを問うファンク
  ションコールやどのスロットに CD が入っているのかを問うファンクションコールを
  含んでいます。  この機能を実証するためのサンプルプログラムはこのファイルの
  最後についています。 Sanyo の3-disk チェンジャ(標準に準拠していません)も今は
  サポートされています。
  ドライバが最初の CD をスロット#0だと考えることに注意しておいてください。


2 .インストール
---------------

0. ide-cd は、ide ディスクドライバに依存しています。 ide ドライバに関する最新の
   情報である Documentation/ide.txt を読んでください。

1. ide と ide-cd ドライバがあなたの使用しているカーネルに編集されているかどう
   かを確認してください。 カーネルの設定をしていくときに "Floppy, IDE, and other 
   block devices" というタイトルのついた節で、下記のオプションに `Y'(サポートを
   直接カーネルに組込みます) か `M'(ロードしたりアンロードしたりすることのでき
   るモジュールとしてサポートを組込みます)のどちらかを選択します:

       Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
       Include IDE/ATAPI CDROM support

   そして

       Use old disk-only driver on primary interface

   を `no' にしておいてください。

   あなたがどんなタイプの IDE インタフェースを持っているかによって、追加の構成
   オプションを指定する必要があるかも知れません。Documentation/ide.txt を読んで
   ください。

2. iso9660 ファイルシステムがカーネルに組込まれている、もしくはロード可能な
   モジュールとして使用できるようになっているかも確認しましょう。
   cat /proc/filesystems で、ファイルシステムがカーネルに認識されているかを調
   べることができます。

3. CDROM ドライブは IDE インタフェース上のホストと接続されるでしょう。システム
   上の各インタフェースは、I/O ポートアドレスと IRQ 番号によって定義されており
   プライマリインタフェースに 0x170と14、セカンダリインタフェースに 0x1f0と15が
   標準で割り当てられています。 各インタフェースは、最高2つのデバイスを制御で
   きます。その2つは、ハードディスクドライブ、CDROM ドライブ、フロッピードライ
   ブ、テープドライブのどれかでしょう。 インタフェース上の2つのデバイスは、
   `マスタ'と`スレイブ'と呼ばれ、通常ドライブ上のジャンパを通して選択すること
   ができます。

   Linux は、次のとおりにこれらのデバイスを名づけます。プライマリ IDE インタ
   フェースのマスタとスレイブデバイスは、それぞれ `hda'と `hdb'と呼ばれます。
   セカンダリインターフェイスのドライブは、`hdc'と`hdd'と呼ばれます。(他の場所
   のインタフェースは、3番目の立場で他の文字になります −Dodumentation/ide.txt
   を読んでください)

   CDROM ドライブをドライバによって自動的に認識させたいのなら、IDE インタ
   フェースがプライマリとセカンダリのどちらのアドレスを使っているのかを確認し
   ましょう。 更に、IDEインタフェース上のデバイスが CDROM ドライブだけなら、
   ジャンパを`マスタ'にしておきましょう。  (どういうわけか、この方法でシステム
   の設定ができないとしても、おそらくまだドライバを使うことができるでしょう。
   でも起動時に余分な構成情報をカーネルに渡さなければならないかもしれません。
   もっと多くの情報を得るために Documentation/ide.txt を読んでください)

4. システムの起動しましょう。 ドライブが認識されたら、あなたはこのようなメッセ
   ージを見るでしょう。

       hdb: NEC CD-ROM DRIVE:260, ATAPI CDROM drive:

   これを確認できないようなら、次のセクション5を見てください。

5. あなたは、現実のデバイスを示すシンボリックリンク /dev/cdrom を作りたいかも
   しれません。 これはコマンドでできます。

       ln -s /dev/hdX /dev/cdrom

   Xは、あなたのドライブがどこにインストールされたかを示す文字と置き換えて
   ください。

6. `dmesg'コマンドでドライバからのあらゆるエラーメッセージを見ることができるで
   しょう。


3. 基本的な使用法
-----------------

ISO9660 CDROM は、ディスクをドライブにいれて (rootで)以下のようにタイプする
ことでマウントされます。

  mount -t iso9660 /dev/cdrom /mnt/cdrom

/dev/cdrom が実際のデバイスにリンクされていて(これの前の節のステップ5で述べまし
た)、なおかつ空であると仮定します。 あなたは、現在、/mnt/cdrom ディレクトリ下
で CDROM の内容を見ることができるでしょう。 CDROM を取り出したいなら、最初に次
のようなコマンドでディスマウントしなければいけません。

  umount /mnt/cdrom

オーディオ CD はマウントできないことに注意してください。

いくつかのディストリビューションは、CDROM ファイルシステムをシステム起動時に常
にマウントするよう /etc/fstab を組込んであります。 この方法なら CDROM のマウン
トを要求されることはありませんが、CDROM をたびたび取り替えるのなら、迷惑な設定
かもしれません。/etc/fstab から cdrom の行を消し、手動で CDROM をマウントする
ようにすれば自由になれます。もしこっちの設定があなたに合っていればですが。

マルチセッションとフォト CD のディスクは特に何もしなくても動作するでしょう。
hpcdtoppm パッケージ (ftp.gwdg.de:/pub/linux/hpcdtoppm/) は、フォト CD を読むの
に役に立つかも知れません。

オーディオ CD を演奏するためには、最初にデータ CDROM をアンマウントして取り出
さなければなりません。 CDROM プレイヤプログラムはどれでも動くでしょう。
(workman, workbone, cdplayer など) 何もなかったら、Documentation/cdrom/sbpcd
のなかの cdtester プログラムが使えるでしょう。 

いくつかのドライブでは、cdda2wav のようなプログラムを使ってデジタルオーディオを
読むことができます。 私が聞いたことのある、これをサポートするドライブはソニー
と東芝のドライブだけです。 サポートしていないドライブでこの機能を使おうとすれ
ばエラーになるでしょう。

サポートされたチェンジャでは、チェンジャスロット間の切り替えに、`cdchange'
プログラム(このファイルの最後についています)を使うことができます。 これを試す
前にドライブをアンマウントしなければならないことに注意してください。 そのプロ
グラムは、2つの引数をとります: CDROM デバイスと変更したいスロット番号です。
スロット番号が -1なら、そのドライブはアンロードされます。


4. コンパイルオプション
----------------------

ドライバをコンパイルするときに設定できる2〜3の追加オプションがあります。 
ほとんどの人はこれらのどれにもわざわざ関わる必要はありません −完璧を期す
るためにここで簡単にリストしておきます。 コンパイルオプションは 
`define <option> 1'という書き方で、ide-cd.c の最初に書き足すと使えるように
なります。 これらのオプションすべては、デフォルトでは無効になっています。

VERBOSE_IDE_CD_ERRORS
  これを設定すると、ATAPI エラーコードは原文のままの記述に変換されるでしょう。
  更に、エラーを引き起こしたコマンドでダンプが作られます。 (やや長い)エラー
  記述のテーブルによってメモリが使われるのを防ぐためにデフォルトではオフに
  なっています。

STANDARD_ATAPI
  これを設定すると、ATAPI 仕様をきちんと実装していないドライブを扱うために必要
  なコードが無効にされるでしょう。 あなたのドライブが ATAPI をきちんと実装して
  いることを知っているなら、少しだけ小さなカーネルにするためにオンにすることが
  できます。

NO_DOOR_LOCKING
  これを設定すると、ドライバは絶対にドライブのドアをロックしようとしないでしょ
  う。

CDROM_NBLOCKS_BUFFER
  これは、CDROMREADAUDIO ioctl のために使用されるバッファのサイズを設定します。
  デフォルトは 8です。

TEST
  これは、任意のパケットコマンドを実行可能にするユーザモードプログラムを使用
  可能にする追加 ioctl を使用可能にします。 詳細はソースを見てください。
  自分で何をしているのかを理解していない限り、これは放っておくべきでしょう。


5. 一般的な問題
------------------

この節では、ドライバを使おうとしているときに遭遇する一般的な問題と解決策につい
て論じます。 あなたが問題にぶつかっているなら、基本的なIDEサポートコードについ
ての現在の情報を得るために Documentation/ide.txt の見直しもした方がいいでしょ
う。これらの項目のうちのいくつかは、ドライバの初期バージョンにだけ適用されます
が、完璧を期するためにここに書いておきます。

ほとんどの場合、ドライバからのあらゆるエラーのための`dmesg'をチェックした方が
いいでしょう。

a. 起動時にドライブが検出されません。

   - configration instructions aboveとDocumentation/ide.txt の中を見直し、
     ハードウェアがどのように構成されているかを調べましょう。

   - ドライブが IDE インタフェース上の唯一のデバイスで、もし可能なら、ジャンパ
     はマスタにするべきでしょう。

   - IDE インタフェースが 0x170 と 0x1f0 の標準のアドレスでないなら、lilo オプ
     ションを使って、ドライバに明示的に知らせてやる必要があるでしょう。 
     Documentation/ide.txt を読んでください。 (この特徴は、カーネルバージョン
     1.3.30あたりで加えられました)

   - ドライブが自動で認識されなかったら、`hdX=cdrom'という形式の lilo オプショ
     ンの使用によって、ドライブの存在をドライバに教えることができます。 X はド
     ライブのインストールされているドライブの文字と一致します。 ドライブの存在
     をドライバに教えて、ブートメッセージに次のようなものが出たら注意して下さ
     い。

       hdX: ATAPI cdrom (?)

     これはドライバがドライブを首尾よく検出したことを意味するのでは*ありません*
     − それどころか、ドライバがドライブを検出しなかったのに、ドライブがあると
     ドライバに教えたために、ドライブがあるだろうと推測していることを意味して
     います。 あなたが実際に、実在しないか対応していない I/O アドレスをドライブ
     に定義しようとしているのなら、おそらく 0xff のエラーが出るでしょう。

   - いくつかの IDE アダプタは、きちんと機能する前に標準的でない初期化シーケン
     スを要求します。 (これがその場合なら、おそらくそのコントローラにあった個
     別の MS-DOS ドライバがあるでしょう) サウンドカード上の IDE インタフェース
     は、よくこのカテゴリに分類されます。 

     特別な初期化が必要ないくつかのインタフェースへのサポートは、カーネル1.3.x
     以降で提供されています。 それらを動かすためにカーネルにオプションを追加し
     てやる必要があるかもしれません −Documentation/ide.txtを読んでください。

     インタフェースに対してサポートが使えないとしても、次の手続きで動くように
     できるかもしれません。 最初に MS-DOS を起動し、適切なドライバをロードして
     ください。 それから、linux をウォームブートします。(つまり電源を落とさずに)
     これで動くなら、MS-DOS の autoexec から loadlin を実行することで自動化で
     きます。

b. タイムアウト/IRQ エラー。

   - いつもタイムアウトエラーになるのなら、ホストに対するドライブからの割り込
     みができていません。

   - IRQの問題でもブートの途中で `IRQ probe failed (<n>)'というメッセージが表
     示されるかも知れません。 <n>がゼロなら、システムが(あらゆる実行可能なIRQ
     上で)割込みを予定していたのに、割込みを見つけられなかったことを意味しま
     す。 <n>が負の数なら、システムが CDROM ドライブから1つだけの割込みを予定し
     ていたのに、複数の IRQ ライン上で割込みを見つけたことを意味します。

   - IDE インタフェースの IRQ 番号がドライバの予定しているものと一致しているか
     を確認するために、ハードウェア構成を再度点検してください。 (通常の割当は、14
     はプライマリ(0x170)インタフェース、それから15がセカンダリ(0x1f0)インタ
     フェースとなっています) 同時に、使おうとしている IRQ と衝突するほかの
     ハードウェアがないかを確認してください。 システムの BIOS セットアップも調べ
     てみてください −いくつかのセットアップは個々のIRQレベルを無効にすることが
     できますし、デフォルトで IRQ15が無効にされて出荷されたシステムの報告があり
     ました。

   - 割込みのセットアップに関するハードウェアの問題があったとしても、多くの
     MS-DOS CDROM ドライバがまだ動くことに注意してください −それらは、明らかに
     割込みを使いません。

   - Pioneer DR-A24X を持っているなら、起動時に "irq timeout: status=0x50 { 
     DriveReady SeekComplete }"というような不快なエラーメッセージが出る*でしょ
     う*。Pioneer DR-A24X CDROM ドライブは、最近かなりポピュラーです。 不幸にも      これらのドライブは、標準
の Linux ATA ディスクドライブの検出を行うときに、
     非常に混乱するようです。 あなたがこれらのドライブの1つを持っているなら、
     lilo.conf に `append="hdX=noprobe hdX=cdrom"'と書き加え、lilo を動かすこと
     によって、CDROM ドライブを混乱させるATAの検出を回避することができます。
     (ここでも X はドライブのインストールされているところの文字に一致します)

c. システムのハングアップ

   - CDROM にアクセスしようとしたときにシステムがロックしてしまうとすると、最も
     ありうる原因は、多重インタフェース上での同時トランザクションを適切に扱え
     ないバキーな IDE アダプタの使用でしょう。 最も悪名高いのは CMD640B チップ
     です。 この問題はブート時の `serialize'オプションを指定していることによっ
     て発生します。 最近のカーネルは、ほとんどの場合、自動的にこれの必要性を検
     出できるでしょうが、しかし検出することがきわめて簡単というわけではありませ
     ん。 `serialize'オプションと CMD640B についてのもっと多くの情報を得るため
     に Documentation/ide.txt を読んでください。

   - 多くの MS-DOS の CDROM ドライバはそのようなバギーなハードウェアで動くこと
     に注意してください。なぜならそれらはほかのディスクの動きに CDROM の操作を
     重複してみようとしないからです。

d. CDROM をマウントすることができません。

   - マウントしようとしてエラーがでたら、`dmesg'をチェックするのと、ドライバや
     ファイルシステムから具体的なエラーがでているかどうかを見ることが助けにな
     るかもしれません。

   - ドライブの中に CDROM が入っていることとその CDROM が ISO9660 ディスクであ
     ることを確認してください。 オーディオ CD をマウントすることはできません。

   - ドライブに入っている CDROM に対してアンマウントし、こんな感じで試してみて
     ください。

       cat /dev/cdrom | od | more

     ダンプを見ることができたら、ドライブとドライバはたぶんちゃんと動いていま
     す。 問題はファイルシステムレベルです。(つまり、CDROM が ISO9660 じゃない
     か、ファイルシステム構造にエラーがあります)

   - `not a block device'エラーがでたら、デバイスの特別なファイルの定義が正し
     いかをチェックしてください。 次のとおりであるべきです :

       brw-rw---- 1 root disk  3,  0 Nov 11 18:48 /dev/hda 
       brw-rw---- 1 root disk  3, 64 Nov 11 18:48 /dev/hdb 
       brw-rw---- 1 root disk 22,  0 Nov 11 18:48 /dev/hdc 
       brw-rw---- 1 root disk 22, 64 Nov 11 18:48 /dev/hdd

      Slackware の初期リリースのいくつかは、これらを間違って定義していました。
     もし間違っていたら、スクリプトの scripts/MAKEDEV.ide を実行することで作り
     直すことができます。 (最初に chmod で、そのスクリプトを実行可能にしなけれ
     ばならないかも知れません)

     /dev/cdrom のシンボリックリンクを使っているのなら、それが正しいデバイス
     ファイルを指し示しているかどうかチェックしてください。 だれかが デバイス
     `hd1a'や`hd1b'について話しているのを聞いたとしたら、これらは現在 hdc と 
     hdd と呼ばれているものの昔の名前です。 その名前は時代遅れでしょう。

   - マウントが iso9660 ファイルシステムを利用できないと不平を言っていて、あな
     たもそれを知っている(/proc/filesustems をチェックしてください)のなら、おそ
     らくマウントの新しいバージョンが必要です。 初期バージョンは、いつも意味の
     あるエラーメッセージを出すとは限りません。


e. ディレクトリリスティングが予告されずに切り捨てられ、`dmesg'がドライバからの
   メッセージを `buffer botch'に出します。

   - カーネル1.2.xのドライバのバージョンにこれを引き起こすと思われるバグがあり
     ました。 それは 1.3.0で修正されました。 もしアップグレードできないなら、
     マウントのときに2048のブロックサイズを指定することで、おそらく問題を回避
     することができます。 (この場合、CDROM からバイナリを直接実行することができ
     ないだろうことに注意してください)

     もしこの問題をカーネル1.3.0以降で見かけたら、バグとして報告してください。


f. データの破損

   - でたらめなデータの破損が、Hitachi CDR-7730 CDROM でときおり見られました。
     もしデータの破損をぶつかっているなら、"hdx=slow"をコマンドラインパラメータ
     として使うことで、システムパフォーマンスの低下の変わりに、問題を回避でき
     るかも知れません。


6. cdchange.c
-------------

/*
 * cdchange.c [-v] <device> [<slot>]
 *
 * これはチェンジャの指定されたスロットから CDROM を読み込み、チェンジャの状態
 * に関する情報を表示します。 このプログラムを使う前にドライブをアンマウント
 * した方がいいでしょう。
 *
 * チャンジャの情報は -v フラグを指定するかスロットを指定しないかでも表示され
 * ます。
 *
 * Gerhard  Zuber <zuber@berlin.snafu.de>のオリジナルコードが元になっています。
 * チャンジャの状態情報と新しい均一な CDROM ドライバインタフェースのための
 * 書き換えは Erik Andersen <andersee@debian.org>です。
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>


int
main (int argc, char **argv)
{
	char *program;
	char *device;
	int fd;           /* file descriptor for CD-ROM device */
	int status;       /* return status for system calls */
	int verbose = 0;
	int slot=-1, x_slot;
	int total_slots_available;

	program = argv[0];

	++argv;
	--argc;

	if (argc < 1 || argc > 3) {
		fprintf (stderr, "usage: %s [-v] <device> [<slot>]\n",
			 program);
		fprintf (stderr, "       Slots are numbered 1 -- n.\n");
		exit (1);
	}
 
       if (strcmp (argv[0], "-v") == 0) {
                verbose = 1;
                ++argv;
                --argc;
        }
 
	device = argv[0];
 
	if (argc == 2)
		slot = atoi (argv[1]) - 1;

	/* open device */ 
	fd = open(device, O_RDONLY | O_NONBLOCK);
	if (fd < 0) {
		fprintf (stderr, "%s: open failed for `%s': %s\n",
			 program, device, strerror (errno));
		exit (1);
	}

	/* Check CD player status */ 
	total_slots_available = ioctl (fd, CDROM_CHANGER_NSLOTS);
	if (total_slots_available <= 1 ) {
		fprintf (stderr, "%s: Device `%s' is not an ATAPI "
			"compliant CD changer.\n", program, device);
		exit (1);
	}

	if (slot >= 0) {
		if (slot >= total_slots_available) {
			fprintf (stderr, "Bad slot number.  "
				 "Should be 1 -- %d.\n",
				 total_slots_available);
			exit (1);
		}

		/* load */ 
		slot=ioctl (fd, CDROM_SELECT_DISC, slot);
		if (slot<0) {
			fflush(stdout);
				perror ("CDROM_SELECT_DISC ");
			exit(1);
		}
	}

	if (slot < 0 || verbose) {

		status=ioctl (fd, CDROM_SELECT_DISC, CDSL_CURRENT);
		if (status<0) {
			fflush(stdout);
			perror (" CDROM_SELECT_DISC");
			exit(1);
		}
		slot=status;

		printf ("Current slot: %d\n", slot+1);
		printf ("Total slots available: %d\n",
			total_slots_available);

		printf ("Drive status: ");
                status = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
                if (status<0) {
                  perror(" CDROM_DRIVE_STATUS");
                } else switch(status) {
		case CDS_DISC_OK:
			printf ("Ready.\n");
			break;
		case CDS_TRAY_OPEN:
			printf ("Tray Open.\n");
			break;
		case CDS_DRIVE_NOT_READY:
			printf ("Drive Not Ready.\n");
			break;
		default:
			printf ("This Should not happen!\n");
			break;
		}

		for (x_slot=0; x_slot<total_slots_available; x_slot++) {
			printf ("Slot %2d: ", x_slot+1);
             		status = ioctl (fd, CDROM_DRIVE_STATUS, x_slot);
             		if (status<0) {
             		     perror(" CDROM_DRIVE_STATUS");
             		} else switch(status) {
			case CDS_DISC_OK:
				printf ("Disc present.");
				break;
			case CDS_NO_DISC: 
				printf ("Empty slot.");
				break;
			case CDS_TRAY_OPEN:
				printf ("CD-ROM tray open.\n");
				break;
			case CDS_DRIVE_NOT_READY:
				printf ("CD-ROM drive not ready.\n");
				break;
			case CDS_NO_INFO:
				printf ("No Information available.");
				break;
			default:
				printf ("This Should not happen!\n");
				break;
			}
		  if (slot == x_slot) {
                  status = ioctl (fd, CDROM_DISC_STATUS);
                  if (status<0) {
			perror(" CDROM_DISC_STATUS");
                  }
		  switch (status) {
			case CDS_AUDIO:
				printf ("\tAudio disc.\t");
				break;
			case CDS_DATA_1:
			case CDS_DATA_2:
				printf ("\tData disc type %d.\t", status-CDS_DATA_1+1);
				break;
			case CDS_XA_2_1:
			case CDS_XA_2_2:
				printf ("\tXA data disc type %d.\t", status-CDS_XA_2_1+1);
				break;
			default:
				printf ("\tUnknown disc type 0x%x!\t", status);
				break;
			}
			}
                  	status = ioctl (fd, CDROM_MEDIA_CHANGED, x_slot);
                  	if (status<0) {
				perror(" CDROM_MEDIA_CHANGED");
                  	}
		  	switch (status) {
			case 1:
				printf ("Changed.\n");
				break;
			default:
				printf ("\n");
				break;
			}
		}
	}

	/* close device */
	status = close (fd);
	if (status != 0) {
		fprintf (stderr, "%s: close failed for `%s': %s\n",
			 program, device, strerror (errno));
		exit (1);
	}
 
	exit (0);
}

Linux カーネル 2.2 付属文書一覧へ戻る