CAM(3)

名称
cam_open_device, cam_open_spec_device, cam_open_btl, cam_open_pass, cam_close_device, cam_close_spec_device, cam_getccb, cam_send_ccb, cam_freeccb, cam_path_string, cam_device_dup, cam_device_copy, cam_get_device - CAM ユーザライブラリ

ライブラリ
libcam

書式
#include <stdio.h> #include <camlib.h> struct cam_device * cam_open_device(const char *path, int flags) struct cam_device * cam_open_spec_device(const char *dev_name, int unit, int flags, struct cam_device *device) struct cam_device * cam_open_btl(path_id_t path_id, target_id_t target_id, lun_id_t target_lun, int flags, struct cam_device *device) struct cam_device * cam_open_pass(const char *path, int flags, struct cam_device *device) void cam_close_device(struct cam_device *dev) void cam_close_spec_device(struct cam_device *dev) union ccb * cam_getccb(struct cam_device *dev) int cam_send_ccb(struct cam_device *device, union ccb *ccb) void cam_freeccb(union ccb *ccb) char * cam_path_string(struct cam_device *dev, char *str, int len) struct cam_device * cam_device_dup(struct cam_device *device) void cam_device_copy(struct cam_device *src, struct cam_device *dst) int cam_get_device(const char *path, char *dev_name, int devnamelen, int *unit)

解説
CAM ライブラリは、 CAM システムでのプログラミングを補助するよう 設計されたいくつかの関数で構成されています。 このマニュアルページは、 ライブラリ関数の基本セットについて説明してあります。 次にリストする マニュアルページにさらに多くの関数が記載してあります。

多数の CAM ライブラリ関数が cam_device 構造体を使用します。

    struct cam_device {
    	char		device_path[MAXPATHLEN+1];/*
    						   * ユーザが指定した
    						   * デバイスのパス名。
    						   * ユーザがデバイス名
    						   * とユニット番号を
    						   * 別々に記述すると
    						   * これは NULL に
    						   * なることがあります。
    						   */
    	char		given_dev_name[DEV_IDLEN+1];/*
    						     * ユーザが指定した
    						     * デバイス名。
    						     */
    	u_int32_t	given_unit_number;	    /*
    						     * ユーザが指定した
    						     * ユニット番号。
    						     */
    	char		device_name[DEV_IDLEN+1];/*
    						  * デバイス名。
    						  * たとえば 'pass'
    						  */
    	u_int32_t	dev_unit_num;	/* この特定のデバイスに
    					 * 対応する通過デバイスの
    					 * ユニット番号。
    					 */
    	char		sim_name[SIM_IDLEN+1];/*
    					       * コントローラ名。
    					       * たとえば 'ahc'
    					       */
    	u_int32_t	sim_unit_number; /* コントローラユニット番号 */
    	u_int32_t	bus_id;		 /* コントローラバス番号 */
    	lun_id_t	target_lun;	 /* 論理ユニット番号 */
    	target_id_t	target_id;	 /* ターゲット ID */
    	path_id_t	path_id;	 /* システム SCSI バス番号 */
    	u_int16_t	pd_type;	 /* 周辺装置のタイプ */
    	struct scsi_inquiry_data inq_data;  /* SCSI 照会データ */
    	u_int8_t	serial_num[252]; /* デバイスシリアル番号 */
    	u_int8_t	serial_num_len;  /* シリアル番号の長さ */
    	u_int8_t	sync_period;	 /* 調整された同期周期 */
    	u_int8_t	sync_offset;     /* 調整された同期オフセット */
    	u_int8_t	bus_width;	 /* 調整されたバス幅 */
    	int		fd;		 /* デバイスのファイル記述子 */
    };

cam_open_device() は、引数として、開こうとしているデバイスを記述する文字列、 および open(2) に渡すのに適切な flags を取ります。 渡される「パス」は、 実際には、開くデバイス名とユニット番号が入った任意のタイプの 文字列です。 文字列は cam_get_device() によって解釈されて、 デバイス名とユニット番号になります。デバイス名とユニット番号が 決定されると、ルックアップが実行されて、指定のデバイスに対応する通過 デバイスを決定します。 cam_open_device() は使用法はかなり簡単ですが、 現実には一般的な使用に適していません。動作が必ずしも 決定的ではないからです。新しいアプリケーションを作成しているプログラマは、 以下に説明する他のオープンルーチンの 1 つを使用するようにしてください。

cam_open_spec_device() は、渡されたデバイス名とユニット番号に対応する pass(4) デバイスを開きます。 flags は、 open(2) に渡すのに適切なフラグである 必要があります。 device 引数はオプションです。 ユーザは、 cam_device 構造体に 割り振り済みの空間を指定できます。 device 引数が NULL の場合、 cam_open_spec_device() は、 malloc(3) を使用して cam_device 構造体用の空間を 割り振ります。

cam_open_btl() は、 cam_open_spec_device() に類似していますが、引数として、 デバイス名とユニット番号の代わりに SCSI バス、ターゲット、および論理 ユニットを取る点が異なります。 path_id 引数は、 SCSI バス番号の CAM の 同等のものです。これはシステム内の論理バス番号を表します。 flags は、 open(2) に渡すのに適切なフラグである必要があります。 cam_open_spec_device() と同じように、 device 引数はオプションです。

cam_open_pass() は、引数として、開く pass(4) デバイスの path を取ります。 変換もルックアップも行われないので、 渡されるパスは CAM pass(4) デバイスの パスでなければなりません。 flags は、 open(2) に渡すのに適したフラグである 必要があります。 device 引数は、ユーザが CAM ライブラリに cam_device 構造体用の空間を割り振りさせたい場合は、 cam_open_spec_device() および cam_open_btl() と同じように、 NULL である必要があります。 cam_close_device() は、上記の open() 呼び出しの 1 つが割り振った cam_device 構造体を解放し、通過デバイスへのファイル記述子を閉じます。 ユーザが cam_device 構造体用の空間を割り振っている場合は、このルーチンを呼び 出してはなりません。 代わりに、ユーザは cam_close_spec_device() を呼び出すべきです。

cam_close_spec_device() は、上記の open() ルーチンの 1 つで開かれた ファイル記述子を閉じるだけです。この関数は、 cam_device が CAM ライブラリ ではなく、呼び出し元によって割り振られたときに呼び出す必要があります。

cam_getccb() は、 malloc(3) を使用して CCB を割り振り、 cam_device 構造の値を使用して CCB ヘッダ内にフィールドを設定します。

cam_send_ccb() は、指定の ccb を、 cam_device 構造体内で記述された device に 送信します。

cam_freeccb() は、 cam_getccb() が割り振った CCB を解放します。

cam_path_string() は、引数として、 cam_device 構造体、および長さが len のストリングを取ります。 この関数は、カーネルが使用するのと類似した、コロンで 終了する印刷接頭語ストリングを作成します。 たとえば、"(cd0:ahc1:0:4:0): " です。 cam_path_string() は、多くとも len-1 キャラクタを str に設定します。 len 番めのキャラクタは、終了を示す ‘\0’ です。

cam_device_dup() は、 strdup(3) と同じように方法で動作します。 cam_device 構造体用に空間を割り当て、渡された device 構造体の内容を、新たに割り振られた 構造体にコピーします。

cam_device_copy() は src 構造体を dst にコピーします。

cam_get_device() は、デバイス名にユニット番号が続いたストリングの入った path 引数を取ります。次に、ストリングをデバイス名とユニット名に分解し、 それぞれ dev_name と unit に戻します。 cam_get_device() は、少なくとも次の 形式のストリングを処理できます。

/dev/foo0a
/dev/foo1s2c
foo0
foo0a
nfoo0

cam_get_device() は、 cam_open_device() に類似した機能を準備する必要がある アプリケーション用の便利な関数として備えられています。プログラマは、 可能であれば、デバイス名とユニット番号を得るもっと決定的な方式を 使用することをお勧めします。

戻り値
cam_open_device() 、 cam_open_spec_device() 、 cam_open_btl() 、および cam_open_pass() は、 cam_device 構造を指すポインタを返します。または、 エラーがあった場合は NULL を返します。

cam_getccb() は、割り振り済みで部分的に初期化済みの CCB を返します。また、 CCB の割り振りが処理失敗した場合は NULL を返します。

cam_send_ccb() は、エラーが発生した場合、値 -1 を返し、 errno がエラーを 示すように設定されます。

cam_path_string() は、便宜として記入された印刷接頭語を返します。これは、 cam_path_string() に渡されるのと同じ str です。

cam_device_dup() は、渡された device のコピーを返します。または、エラーが 発生した場合は NULL を返します。

cam_get_device() は、処理成功の場合は 0 を返し、 処理失敗を示す場合は -1 を返します。

ここで説明した基本 CAM ライブラリ関数の 1 つから エラーが返された場合は、 エラーの理由が一般にグローバルストリング cam_errbuf に印刷されます。 これの長さは CAM_ERRBUF_SIZE キャラクタです。

関連項目
cam_cdbparse(3), pass(4), camcontrol(8)

歴史
CAM ライブラリは最初に FreeBSD 3.0 で現れました。

作者
Kenneth Merry <ken@FreeBSD.org>

バグ
cam_open_device() は、渡された path が何かへの symlink であるかどうか チェックしません。渡された path が実際の pass(4) デバイスであるかどうかも チェックしません。前のチェックを実現するのはかなり簡単でしょうが、後の チェックを実行するためには、 pass(4) デバイスとしてデバイスノードを識別する 決定的な方法が必要でしょう。

おそらく関数には名前が不適切なものや、名前が不十分なものがあります。