ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 10 8/11 Information Library (日本語) |
デバイス属性情報は、プロパティーと呼ばれる名前-値ペアの表記で表すことができます。
たとえば、デバイスレジスタとオンボードメモリーは reg プロパティーで表すことができます。reg プロパティーは、デバイスハードウェアレジスタを記述するソフトウェアの抽象化です。reg プロパティーの値により、デバイスレジスタのアドレス位置とサイズがエンコードされます。ドライバは、reg プロパティーを使用してデバイスレジスタにアクセスします。
別の例として interrupt プロパティーがあります。interrupt プロパティーは、デバイス割り込みを表します。interrupt プロパティーの値により、デバイス割り込み PIN がエンコードされます。
プロパティーには次の 5 つの型の値を割り当てることができます。
バイト配列 – 任意の長さの一連のバイト
整数プロパティー – 整数値
整数配列プロパティー – 整数の配列
文字列プロパティー – null で終わる文字列
文字列配列プロパティー – null で終わる文字列のリスト
値を持たないプロパティーは、boolean プロパティーとみなされます。boolean プロパティーが存在する場合は真 (true) です。boolean プロパティーが存在しない場合は偽 (false) です。
厳密に言えば、DDI/DKI ソフトウェアのプロパティー名には制限がありません。ただし、推奨される使い方がいくつかあります。IEEE 1275-1994「Standard for Boot Firmware」では、プロパティーは次のように定義されています。
プロパティーとは、1 から 31 文字までのプリント可能文字で構成される、人間が読めるテキスト文字列のことです。プロパティー名には、大文字や「/」、「\」、「:」、「[」、「]」、「@」の文字を含めることはできません。「+」文字で始まるプロパティー名は、将来のバージョンの IEEE 1275-1994 用に予約されています。
通常、下線はプロパティー名に使用しません。代わりにハイフン (-) を使用します。通常、疑問符 (?) で終わるプロパティー名には、文字列の値 (一般には TRUE または FALSE) を指定します (例: auto-boot?)。
定義済みのプロパティー名は、IEEE 1275 ワーキンググループの出版物に記載されています。これらの資料の入手方法については、http://playground.sun.com/1275/ を参照してください。ドライバ設定ファイルへのプロパティーの追加については、driver.conf(4) のマニュアルページを参照してください。pm(9P) と pm-components(9P) のマニュアルページには、電源管理におけるプロパティーの使用方法が記載されています。デバイスドライバのマニュアルページにプロパティーがどのように文書化されているかの例として、sd(7D) のマニュアルページをお読みください。
ドライバのプロパティーを作成したり、既存のプロパティーを更新したりするには、適切なプロパティー型を持つ DDI ドライバ更新インタフェース (ddi_prop_update_int(9F) や ddi_prop_update_string(9F) など) の 1 つを使用します。使用できるプロパティーインタフェースの一覧については、表 4-1 を参照してください。これらのインタフェースは通常、ドライバの attach(9E) エントリポイントから呼び出されます。次の例では、ddi_prop_update_string() は、needs-suspend-resume という値を使って pm-hardware-state という文字列プロパティーを作成します。
/* The following code is to tell cpr that this device * needs to be suspended and resumed. */ (void) ddi_prop_update_string(device, dip, "pm-hardware-state", "needs-suspend-resume");
ほとんどの場合、プロパティーの更新には ddi_prop_update() ルーチンを使用すれば十分です。ただし、頻繁に値が変わるプロパティーの場合は更新によるオーバーヘッドが原因で、パフォーマンスに関する問題が発生することがあります。ddi_prop_update() の使用を避けるためにプロパティー値のローカルインスタンスを使用する方法については、「prop_op() エントリポイント」を参照してください。
ドライバは、その親にプロパティーを要求できます。そしてその親は、さらにその親に要求できます。ドライバは、要求をその親よりも上位に対して行えるかどうかを制御できます。
たとえば、次の例の esp ドライバは、ターゲットごとに targetx-sync-speed という整数プロパティーを保持します。targetx-sync-speed 内の x はターゲット番号を表します。prtconf(1M) コマンドは、ドライバのプロパティーを冗長モードで表示します。次の例は、esp ドライバの部分的なリストを示しています。
% prtconf -v ... esp, instance #0 Driver software properties: name <target2-sync-speed> length <4> value <0x00000fa0>. ...
次の表で、プロパティーインタフェースについて簡単に説明します。
表 4-1 プロパティーインタフェースの使い方
|
int プロパティーインタフェースを使用するときは、できるだけ ddi_prop_update_int(9F) などの 32 ビットバージョンではなく、ddi_prop_update_int64(9F) などの 64 ビットバージョンを使用してください。
prop_op(9E) エントリポイントは通常、デバイスプロパティーまたはドライバプロパティーの値をシステムに報告するために必要です。ドライバが専用のプロパティーを作成または管理する必要がない場合は、ddi_prop_op(9F) 関数をこのエントリポイントに使用できます。
ddi_prop_op() がデバイスドライバの cb_ops(9S) 構造体で定義されている場合は、ddi_prop_op(9F) をそのドライバの prop_op(9E) エントリポイントとして使用できます。ddi_prop_op() を使用すると、リーフデバイスでプロパティー値を検索して、それをデバイスのプロパティーリストから取得できます。
頻繁に値が変わるプロパティーをドライバで保持する必要がある場合は、ddi_prop_op() を呼び出すのではなく、cb_ops 構造体の中にドライバ固有の prop_op() ルーチンを定義します。この手法により、ddi_prop_update() を繰り返し使用するという非効率性を解消できます。ドライバは、そのソフト状態構造体の中またはドライバ変数でプロパティー値のコピーを保持します。
prop_op(9E) エントリポイントは、特定のドライバプロパティーやデバイスプロパティーの値をシステムに報告します。多くの場合、ddi_prop_op(9F) ルーチンは、cb_ops(9S) 構造体でドライバの prop_op() エントリポイントとして使用できます。ddi_prop_op() は、必要なすべての処理を実行します。デバイスプロパティー要求の処理時に特別な処理を必要としないドライバには、ddi_prop_op() で十分です。
ただし、ドライバが prop_op() エントリポイントを提供することが必要な場合があります。たとえば、頻繁に値が変わるプロパティーをドライバで保持する場合、変更のたびに ddi_prop_update(9F) を使用してプロパティーを更新することは効率的ではありません。代わりに、ドライバはインスタンスのソフト状態によってプロパティーのシャドウコピーを保持します。ドライバは、プロパティーの値が変わると、ddi_prop_update() ルーチンを一切使わずにシャドウコピーを更新します。prop_op() エントリポイントは、ddi_prop_op() に要求を渡してプロパティー要求を処理する前に、このプロパティーの要求を遮断し、いずれかの ddi_prop_update() ルーチンを使用してプロパティーの値を更新する必要があります。
次の例では、prop_op() は temperature プロパティーの要求を遮断しています。ドライバは、プロパティーが変わるたびに状態構造体で変数を更新します。ただし、プロパティーが更新されるのは、要求が出されたときだけです。その際、ドライバは ddi_prop_op() を使用してプロパティー要求を処理します。プロパティー要求がデバイスに固有のものでない場合、ドライバはその要求を遮断しません。このような状況は、dev パラメータの値が DDI_DEV_T_ANY (ワイルドカードのデバイス番号) である場合に示されます。
例 4-1 prop_op() ルーチン
static int xx_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags, char *name, caddr_t valuep, int *lengthp) { minor_t instance; struct xxstate *xsp; if (dev != DDI_DEV_T_ANY) { return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp)); } instance = getminor(dev); xsp = ddi_get_soft_state(statep, instance); if (xsp == NULL) return (DDI_PROP_NOTFOUND); if (strcmp(name, "temperature") == 0) { ddi_prop_update_int(dev, dip, name, temperature); } /* other cases */ }