CD(4)

名称
cd - SCSI CD-ROM ドライバ

書式
device cd device cd1 at scbus0 target 4 lun 0 options CHANGER_MIN_BUSY_SECONDS=3 options CHANGER_MAX_BUSY_SECONDS=11

解説
cd ドライバは、 SCSI CD-ROM (コンパクトディスク-読み出し専用メモリ) ドライブをサポートします。 通常ディスクと同じように見せるために、 cd ドライバは、 CD-ROM 全体をカバーする 1 つのパーティションからなる パーティションテーブルを合成します。 このパーティションテーブルを disklabel(8) を用いて修正することは可能ですが、 その修正は CD-ROM をアンマウントするまでの間のみ有効です。 一般的に、このインタフェースは wd(4) や da(4) で述べられているものと同様です。

SCSI アダプタがブート中にプローブされる際、 SCSI バス上のデバイスが走査されます。 見つかったデバイスのうち、 タイプ CDROM (タイプ 5) あるいは WORM (タイプ 4) と応答したものは cd ドライバにアタッチされます。 FreeBSD 2.1 以前のバージョンでは、 最初に見つかったデバイスは cd0 としてアタッチされ、その次が cd1 のようになっていました。 FreeBSD 2.1 からは、デバイスが何番の cd ユニットとなるべきか指定できます。 カーネル設定の詳細については scsi(4) を参照して下さい。

システムユーティリティ disklabel(8) を用いて、合成されたディスクラベル構造体を読み出せます。 この構造体には、必要となる CD-ROM のサイズに関する正しい値が含まれます。

カーネル設定
システム設定に関わらず、任意の数の CD-ROM デバイスをシステムにアタッチできます。 全てのリソースは動的にアロケートされます。

IOCTL
SCSI CD-ROM ドライブに適用される以下の ioctl(2) 呼び出しが、ヘッダファイル <sys/cdio.h> と <sys/disklabel.h> で定義されています。

DIOCGDINFO
DIOCSDINFO
    (struct disklabel) 当該ドライブに対するディスクラベルのカーネル内コピーを読み書きします。 ディスクラベルは scsi inquiry コマンドから読み取った情報で初期化されます。 その値はブート時に表示されたものと同一のはずです。 この構造体は disklabel(5) で定義されています。
CDIOCCAPABILITY
    (struct ioc_capability) 当該ドライブがサポートしている機能に関する情報を取り出します。 情報は以下の構造体で返されます。

        struct ioc_capability {
        	u_long	play_function;
        #define CDDOPLAYTRK	0x00000001
        	/* tracks/index 指定で再生可能 */
        #define	CDDOPLAYMSF	0x00000002
        	/* msf (分秒フレーム) 指定で再生可能 */
        #define	CDDOPLAYBLOCKS	0x00000004
        	/* ブロック指定で再生可能 */
        #define	CDDOPAUSE	0x00000100
        	/* 出力を一時停止可能 */
        #define	CDDORESUME	0x00000200
        	/* 出力を再開可能 */
        #define	CDDORESET	0x00000400
        	/* ドライブを完全にリセット可能 */
        #define	CDDOSTART	0x00000800
        	/* オーディオ開始可能 */
        #define CDDOSTOP	0x00001000
        	/* オーディオ停止可能 */
        #define CDDOPITCH	0x00002000
        	/* オーディオピッチ調整可能 */
        	u_long	routing_function;
        #define CDREADVOLUME	0x00000001
        	/* ボリューム設定の読み出し可能 */
        #define CDSETVOLUME	0x00000002
        	/* ボリュームの設定可能 */
        #define	CDSETMONO	0x00000100
        	/* 出力をモノラルに設定可能 */
        #define CDSETSTEREO	0x00000200
        	/* 出力をステレオに設定可能 (デフォルト) */
        #define	CDSETLEFT	0x00000400
        	/* 出力を左のみに設定可能 */
        #define	CDSETRIGHT	0x00000800
        	/* 出力を右のみに設定可能 */
        #define	CDSETMUTE	0x00001000
        	/* 出力のミュート可能 */
        #define CDSETPATCH	0x00008000
        	/* ダイレクトルーティング制御可能 */
        	u_long	special_function;
        #define	CDDOEJECT	0x00000001
        	/* トレーのオープン可能 */
        #define	CDDOCLOSE	0x00000002
        	/* トレーのクローズ可能 */
        #define	CDDOLOCK	0x00000004
        	/* トレーのロック可能 */
        #define CDREADHEADER	0x00000100
        	/* 目次の読み出し可能 */
        #define	CDREADENTRIES	0x00000200
        	/* 目次エントリの読み出し可能 */
        #define	CDREADSUBQ	0x00000200
        	/* サブチャネル情報の読み出し可能 */
        #define CDREADRW	0x00000400
        	/* サブコード R-W の読み出し可能 */
        #define	CDHASDEBUG	0x00004000
        	/* トレーがダイナミックデバッグ機能を持つ */
        };

CDIOCPLAYTRACKS
    (struct ioc_play_track) 指定されたトラックアドレスおよび長さに基づいてオーディオの再生を開始します。 この構造体は以下のように定義されます:

        struct ioc_play_track
        {
        	u_char	start_track;
        	u_char	start_index;
        	u_char	end_track;
        	u_char	end_index;
        };

CDIOCPLAYBLOCKS
    (struct ioc_play_blocks) 指定されたブロックアドレスおよび長さに基づいてオーディオの再生を開始します。 この構造体は以下のように定義されます:

        struct ioc_play_blocks
        {
        	int	blk;
        	int	len;
        };

CDIOCPLAYMSF
    (struct ioc_play_msf) 指定された「分-秒-フレーム」と長さに基づいてオーディオの再生を開始します。 この構造体は以下のように定義されます:

        struct ioc_play_msf
        {
        	u_char	start_m;
        	u_char	start_s;
        	u_char	start_f;
        	u_char	end_m;
        	u_char	end_s;
        	u_char	end_f;
        };

CDIOCREADSUBCHANNEL
    (struct ioc_read_subchannel) この構造体で指定されたロケーションのサブチャネルから情報を読み出します。

        struct ioc_read_subchannel {
        	u_char address_format;
        #define CD_LBA_FORMAT	1
        #define CD_MSF_FORMAT	2
        	u_char data_format;
        #define CD_SUBQ_DATA		0
        #define CD_CURRENT_POSITION	1
        #define CD_MEDIA_CATALOG	2
        #define CD_TRACK_INFO		3
        	u_char track;
        	int	data_len;
        	struct  cd_sub_channel_info *data;
        };

CDIOREADTOCHEADER
    (struct ioc_toc_header) マウントされた CD-ROM の目次に関する情報のサマリを返します。 この情報は以下の構造体に格納して返されます。

        struct ioc_toc_header {
        	u_short len;
        	u_char  starting_track;
        	u_char  ending_track;
        };

CDIOREADTOCENTRYS
    (struct ioc_read_toc_entry) 指定された目次エントリからの情報を返します。 (そう、このコマンド名のスペルは間違っています。) 引数の構造体は以下のようになります:

        struct ioc_read_toc_entry {
        	u_char	address_format;
        	u_char	starting_track;
        	u_short	data_len;
        	struct  cd_toc_entry *data;
        };

    要求データは、 data が指す大きさ data_len の領域に格納されます。
CDIOCSETPATCH
    (struct ioc_patch) 様々なオーディオチャネルを様々な出力チャネルに割り当てます。 引数の構造体は次のように定義されます:

        struct ioc_patch {
        	u_char	patch[4];
        	/* 各チャネルに対し 1 要素が対応 */
        };

CDIOCGETVOL
CDIOCSETVOL
    (struct ioc_vol) 出力チャネルのボリューム設定に関する情報を取得 (あるいは設定) します。 引数の構造体は次のとおりです:

        struct	ioc_vol
        {
        	u_char	vol[4];
        	/* 各チャネルに対し 1 要素が対応 */
        };

CDIOCSETMONO
    全ての出力チャネルを全ての入力チャネルに割り当てます。
CDIOCSETSTEREO
    左入力チャネルを左出力チャネルに、右入力チャネルを右出力チャネルに、 それぞれ割り当てます。
CDIOCSETMUTE
    ボリューム設定を変更せずに出力をミュートします。
CDIOCSETLEFT
CDIOCSETRIGHT
    両方の出力チャネルを左 (または右) 入力チャネルに割り当てます。
CDIOCSETDEBUG
CDIOCCLRDEBUG
    対応するデバイスに対するデバッグ機能をオン (またはオフ) にします。
CDIOCPAUSE
CDIOCRESUME
    オーディオ再生を一時停止 (または再開) します。 読み出しヘッドの位置はリセットしません。
CDIOCRESET
    ドライブをリセットします。
CDIOCSTART
CDIOCSTOP
    ドライブに対し、 CD-ROM の回転開始 (または停止) を指示します。
CDIOCALLOW
CDIOCPREVENT
    ドライブに対し、 CD-ROM ディスクの手動による取り出しを許可 (または禁止) します。 この機能をサポートしないドライブがあります。
CDIOCEJECT
    CD-ROM を取り出します。
CDIOCCLOSE
    ドライブに対し、ドアを閉じメディアをロードするよう指示します。 この機能をサポートしないドライブがあります。
CDIOCPITCH
    (struct ioc_pitch) この機能をサポートするドライブに対し、 オーディオを通常より早い速度ないし遅い速度で再生するよう指示します。 speed の値が -32767 から -1 までの間なら遅い速度で再生します。 値が 0 なら通常速度です。値が 1 から 32767 の場合は早い速度で再生します。 分解能が 16 ビット未満のドライブの場合、エラーを出さず、 単に下位ビットが無視されます。 この構造体は次のように定義されます:

        struct	ioc_pitch
        {
        	short	speed;
        };

注意
cd ドライバで制御されているドライブ中の CD-ROM が入れ換えられた場合、 メディア交換操作によってカーネル内のディスクラベルと関連情報が 無効化されます。 データ破損を避けるため、当該デバイスを参照するオープンファイル デスクリプタがなくなるまで、当該デバイスに対するアクセスは全て破棄されます。 この間、新たなオープン操作は全て拒否されます。 当該デバイスを参照するオープンファイルデスクリプタがなくなると、 後続の最初のオープン操作により、当該ドライブに対する新しい パラメータ一式 (ディスクラベルを含む) がロードされます。

cd ドライバ中のオーディオコードは SCSI-2 標準のオーディオコマンドのみサポートします。 多くの CD-ROM 製造業者はこの標準規格に従っていないため、 オーディオが動作しない CD-ROM ドライブが数多く存在します。 より一般的な「ダメな」 CD-ROM ドライブをサポートする作業も計画されていますが、 まだ実行に移されていません。

チェンジャ操作
このドライバは LUN ベースの CD チェンジャのサポートを内蔵しています。 LUN ベースの CD チェンジャとは、2 つ以上の CD を保持できるが、 CD 再生機構を一組しか持たないドライブです。 このドライブ内の各 CD は、 SCSI バス上の別々の論理ユニットとして現れます。 この cd ドライバは自動的に LUN ベースのチェンジャを認識し、 内部のスケジューラを通してチェンジャに対するコマンドを送り出します。 このスケジューラは、チェンジャ中の異なる LUN に同時にコマンドを送ることで 引き起こされる、チェンジャの「スラッシング」を防ぎます。

スケジューラは、ドライバが特定の LUN で消費するタイムクァンタムの 最小値と最大値を管理します。 最小値とは、たとえその LUN に処理中の I/O がない場合でも、 その LUN で費すことが保証されている最小時間量です。 最大値とは、他の LUN に処理中の I/O がある場合に、 ある LUN でチェンジャが費す最大時間量です。 他の LUN に処理中の I/O がない場合は、 ドライバはある LUN に対するアクセスに上限を設けません。

最小および最大タイムクァンタムはカーネルオプションや sysctl 変数を 通じて変更できます。カーネルオプションは以下の通り:
options CHANGER_MIN_BUSY_SECONDS=3
options CHANGER_MAX_BUSY_SECONDS=11

sysctl 変数は以下の通り:

kern.cam.cd.changer.min_busy_seconds
kern.cam.cd.changer.max_busy_seconds

ユーザは、sysctl 変数を通じて最小および最大タイムアウトを試し、 自分のチェンジャに最適な値を見つけるとよいでしょう。 一旦、自分のチェンジャに対する最適タイムアウトが決まれば、 それをカーネル設定ファイルに記述できます。

自分のシステムに LUN ベースのチェンジャが存在すれば、 ブートプロセスが進むに従って、そのチェンジャの様々な LUN に対する プローブメッセージが表示されることに気づくでしょう。 これは正常であり、チェンジャのスケジューリングコードによって引き起こされます。

関連ファイル
/dev/cd[0-9][a-h]
    ブロックモード CD-ROM デバイス
/dev/rcd[0-9][a-h]
    raw モード CD-ROM デバイス

診断
ありません。

関連項目
scsi(4), da(4), disklabel(5), disklabel(8), cd(9)

バグ
ioctl() に対する 3 番目の引数に用いられる構造体の名前は適当ではありません。 また、 ioctl() コマンドの中にはスペルミスがいくつも残っています。

現在のところ、異なる CD チェンジャに対して異なる最小および最大 タイムアウト値を設定する機構はありません。 カーネルオプションあるいは sysctl 変数で設定したタイムアウト値は システムにある LUN ベースの CD チェンジャ全てに適用されます。 このようなサポートを実装することは可能ですが、 少なくとも sysctl による実装はあまりエレガントではありません。 というのは、現在の sysctl コードではコンパイル後のノード追加を 取り扱うことができないためです。 それゆえ、動的に大きさを決定する sysctl 変数を用意し、 ユーザレベルのユーティリティを用いてタイムアウト値を取得ないし設定する ことになるでしょう。 カーネル設定ファイル中で、異なる CD デバイスに対して 別々のタイムアウトを指定できるようにするには、 config(8) を修正し、 固定的に記述した cd デバイスに 2 つのタイムアウト値をサポートするようにしなければ ならないかもしれません。

歴史
本 cd ドライバは、Julian Ellischer が記述し 386BSD 0.1 に登場した cd ドライバをベースにしています。 cd ドライバの CAM バージョンは Kenneth Merry が記述し、 FreeBSD 3.0 で最初に登場しました。