JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
デバイスドライバの記述     Oracle Solaris 10 8/11 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

パート I Solaris プラットフォーム用デバイスドライバの設計

1.  Solaris デバイスドライバの概要

2.  Solaris カーネルとデバイスツリー

3.  マルチスレッド

4.  プロパティー

デバイスプロパティー

デバイスプロパティー名

プロパティーの作成と更新

プロパティーの検索

prop_op() エントリポイント

5.  イベントの管理とタスクのキュー

6.  ドライバの自動設定

7.  デバイスアクセス: プログラム式入出力

8.  割り込みハンドラ

9.  ダイレクトメモリーアクセス (DMA)

10.  デバイスメモリーおよびカーネルメモリーのマッピング

11.  デバイスコンテキスト管理

12.  電源管理

13.  Solaris ドライバの強化

14.  階層化ドライバインタフェース (LDI)

パート II 特定の種類のデバイスドライバの設計

15.  文字デバイスのドライバ

16.  ブロックデバイスのドライバ

17.  SCSI ターゲットドライバ

18.  SCSI ホストバスアダプタドライバ

19.  ネットワークデバイスのドライバ

20.  USB ドライバ

パート III デバイスドライバの構築

21.  ドライバのコンパイル、ロード、パッケージ化、およびテスト

22.  デバイスドライバのデバッグ、テスト、およびチューニング

23.  推奨されるコーティング方法

パート IV 付録

A.  ハードウェアの概要

B.  Solaris DDI/DKI サービスの概要

C.  64 ビットデバイスドライバの準備

D.  コンソールフレームバッファードライバ

索引

デバイスプロパティー

デバイス属性情報は、プロパティーと呼ばれる名前-値ペアの表記で表すことができます。

たとえば、デバイスレジスタとオンボードメモリーは reg プロパティーで表すことができます。reg プロパティーは、デバイスハードウェアレジスタを記述するソフトウェアの抽象化です。reg プロパティーの値により、デバイスレジスタのアドレス位置とサイズがエンコードされます。ドライバは、reg プロパティーを使用してデバイスレジスタにアクセスします。

別の例として interrupt プロパティーがあります。interrupt プロパティーは、デバイス割り込みを表します。interrupt プロパティーの値により、デバイス割り込み PIN がエンコードされます。

プロパティーには次の 5 つの型の値を割り当てることができます。

値を持たないプロパティーは、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 プロパティーインタフェースの使い方

ファミリ
プロパティーインタフェース
説明
ddi_prop_lookup
プロパティーを検索し、そのプロパティーが存在する場合は正常に復帰します。プロパティーが存在しない場合は失敗します。
整数プロパティーを検索し、それを返します。
64 ビットの整数プロパティーを検索し、それを返します。
整数配列プロパティーを検索し、それを返します。
64 ビットの整数配列プロパティーを検索し、それを返します。
文字列プロパティーを検索し、それを返します。
文字列配列プロパティーを検索し、それを返します。
バイト配列プロパティーを検索し、それを返します。
ddi_prop_update
整数プロパティーを更新または作成します。
単一の 64 ビットの整数プロパティーを更新または作成します。
整数配列プロパティーを更新または作成します。
文字列プロパティーを更新または作成します。
文字列配列プロパティーを更新または作成します。
64 ビットの整数配列プロパティーを更新または作成します。
バイト配列プロパティーを更新または作成します。
ddi_prop_remove
プロパティーを削除します。
デバイスに関連付けられているすべてのプロパティーを削除します。

int プロパティーインタフェースを使用するときは、できるだけ ddi_prop_update_int(9F) などの 32 ビットバージョンではなく、ddi_prop_update_int64(9F) などの 64 ビットバージョンを使用してください。

prop_op() エントリポイント

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 */    
}