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

ドキュメントの情報

はじめに

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

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

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

3.  マルチスレッド

4.  プロパティー

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

6.  ドライバの自動構成

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

8.  割り込みハンドラ

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

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

メモリーマッピングの概要

マッピングのエクスポート

segmap(9E) エントリポイント

devmap(9E) エントリポイント

ユーザーマッピングへのデバイスメモリーの関連付け

ユーザーマッピングへのカーネルメモリーの関連付け

ユーザーアクセス用カーネルメモリーの割り当て

アプリケーションへのカーネルメモリーのエクスポート

ユーザーアクセス用にエクスポートされたカーネルメモリーの解放

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

12.  電源管理

13.  Oracle Solaris ドライバの強化

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

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

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

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

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

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

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

20.  USB ドライバ

21.  SR-IOV ドライバ

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

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

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

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

パート IV 付録

A.  ハードウェアの概要

B.  Oracle Solaris DDI/DKI サービスのサマリー

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

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

E.  pci.conf ファイル

索引

ドキュメントの品質向上のためのご意見をください
簡潔すぎた
読みづらかった、または難し過ぎた
重要な情報が欠けていた
内容が間違っていた
翻訳版が必要
その他
Your rating has been updated
貴重なご意見を有り難うございました!

あなたの貴重なご意見はより良いドキュメント作成の手助けとなります 内容の品質向上と追加コメントのためのアンケートに参加されますか?

マッピングのエクスポート

このセクションでは、segmap(9E) および devmap(9E) エントリポイントの使用方法について説明します。

segmap(9E) エントリポイント

segmap(9E) エントリポイントは、mmap(2) システムコールからリクエストされたメモリーマッピングを設定する役割を担います。多くのメモリーマッピングデバイスに対応するドライバは、独自の segmap(9E) ルーチンを定義する代わりに、ddi_devmap_segmap(9F) をエントリポイントとして使用します。ドライバは、segmap() エントリポイントを提供することにより、マッピング作成の前後で一般的なタスクを処理できます。たとえば、ドライバ内でマッピング許可を確認し、非公開のマッピングリソースを割り当てることができます。また、ドライバ内でマッピングを調整し、ページ境界割り当てされていないデバイスバッファーに対応させることもできます。segmap() エントリポイントは、戻り値を返す前に ddi_devmap_segmap(9F) 関数を呼び出す必要があります。ddi_devmap_segmap() 関数は、ドライバの devmap(9E) エントリポイントを呼び出すことで実際のマッピングを実行します。

segmap() 関数の構文は次のとおりです。

int segmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp,
     off_t len, unsigned int prot, unsigned int maxprot,
     unsigned int flags, cred_t *credp);

各表記の意味は次のとおりです。

dev

マップするメモリーを含むデバイス。

off

マッピングの開始位置となる、デバイスメモリー内のオフセット。

asp

デバイスメモリーのマッピング先となるアドレス空間へのポインタ。

この引数には、例 10-1 に示した struct as *例 10-2 に示した ddi_as_handle_t のどちらを指定してもかまいません。これは、ddidevmap.h に次の宣言が含まれているからです。

typedef struct as *ddi_as_handle_t
addrp

デバイスメモリーのマッピング先となる、アドレス空間内のアドレスへのポインタ。

len

マップするメモリーの長さ (バイト)。

prot

保護を指定するビットフィールド。指定可能な設定は、PROT_READ、PROT_WRITE、PROT_EXEC、PROT_USER、および PROT_ALL です。詳細はマニュアルページを参照してください。

maxprot

試みられたマッピングで使用可能な最大の保護フラグ。ユーザーが特殊ファイルを読み取り専用で開いた場合には、PROT_WRITE ビットをマスキングして除外できます。

flags

マッピングのタイプを示すフラグ。指定可能な値は MAP_SHARED と MAP_PRIVATE です。

credp

ユーザー資格構造体へのポインタ。

次の例のドライバは、書き込み専用マッピングを許可するフレームバッファーを制御しています。このドライバは、アプリケーションが読み取りアクセス権の取得を試みた場合に EINVAL を返し、続いて ddi_devmap_segmap(9F) を呼び出してユーザーマッピングを設定します。

例 10-1 segmap(9E) ルーチン

static int
xxsegmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp,
    off_t len, unsigned int prot, unsigned int maxprot,
    unsigned int flags, cred_t *credp)
{
    if (prot & PROT_READ)
        return (EINVAL);
    return (ddi_devmap_segmap(dev, off, as, addrp,
        len, prot, maxprot, flags, cred));
}

次の例は、レジスタ空間内でページ境界割り当てされていないバッファーを持つデバイスの処理方法を示したものです。この例では、バッファーの先頭に対応するアドレスが mmap(2) から返されるように、オフセット 0x800 から始まるバッファーをマップしています。devmap_devmem_setup(9F) 関数は、ページの全体をマップし、マッピングがページ境界割り当てされるように要求したあと、ページの先頭のアドレスを返します。このアドレスが segmap(9E) をパススルーしたり、segmap() エントリポイントが未定義の場合には、バッファーの先頭に対応するアドレスではなくページの先頭に対応するアドレスが mmap() から返されます。この例では、結果として返されるアドレスが目的とするバッファーの先頭位置になるように、devmap_devmem_setup からの戻り値であるページ境界割り当てされたアドレスに、バッファーのオフセットが加算されています。

例 10-2 mmap() 呼び出しから返されるアドレスを segmap() 関数を使用して変更する

#define    BUFFER_OFFSET 0x800

int
xx_segmap(dev_t dev, off_t off, ddi_as_handle_t as, caddr_t *addrp, off_t len,
    uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
{
        int rval;
        unsigned long pagemask = ptob(1L) - 1L;

        if ((rval = ddi_devmap_segmap(dev, off, as, addrp, len, prot, maxprot,
            flags, credp)) == DDI_SUCCESS) {
                /*
                 * The address returned by ddi_devmap_segmap is the start of the page
                 * that contains the buffer.  Add the offset of the buffer to get the
                 * final address.
                 */
                *addrp += BUFFER_OFFSET & pagemask);
        }
        return (rval);
}

devmap(9E) エントリポイント

devmap(9E) エントリポイントは、ddi_devmap_segmap(9F) エントリポイントの内側にある segmap(9E) 関数から呼び出されます。

devmap(9E) エントリポイントは、mmap(2) システムコールの結果として呼び出されます。devmap(9E) 関数は、デバイスメモリーまたはカーネルメモリーをユーザーアプリケーションにエクスポートするために呼び出されます。devmap() 関数は次の操作のために使用されます。

devmap() 関数の構文は次のとおりです。

int devmap(dev_t dev, devmap_cookie_t handle, offset_t off,
     size_t len, size_t *maplen, uint_t model);

各表記の意味は次のとおりです。

dev

マップするメモリーを含むデバイス。

handle

システムがデバイス内またはカーネル内の連続するメモリーへのマッピングを記述するために作成して使用するデバイスマッピングハンドル。

off

アプリケーションマッピング内の論理オフセット。ドライバはこのオフセットを、デバイスメモリーまたはカーネルメモリー内の対応するオフセットに変換する必要があります。

len

マップするメモリーの長さ (バイト)。

maplen

ドライバが、異なるカーネルメモリー領域または物理的に不連続な複数のメモリー領域を、連続する 1 つのユーザーアプリケーションマッピングに関連付けることを可能にします。

model

現在のスレッドのデータモデルタイプ。

システムは、1 つの mmap(2) システムコールで複数のマッピングハンドルを作成します。たとえば、マッピングには、物理的に不連続なメモリー領域が複数含まれる可能性があります。

最初、パラメータ offlen を指定して devmap(9E) が呼び出されます。これらのパラメータは、アプリケーションから mmap(2) に渡されます。devmap(9E) は、*maplen を、off から連続するメモリー領域の末尾までの長さに設定します。*maplen の値は、ページサイズの倍数に切り上げる必要があります。 *maplen の値は、元のマッピング長 len よりも小さい値に設定してもかまいません。そうした場合、システムは、新しいマッピングハンドルと調整後の off および len パラメータを使用しながら、最初のマッピング長に達するまで devmap(9E) を繰り返し呼び出します。

ドライバが複数のアプリケーションデータモデルをサポートする場合は、ddi_model_convert_from(9F)model を渡す必要があります。ddi_model_convert_from() 関数は、現在のスレッドとデバイスドライバとの間にデータモデルの不一致が存在しているかどうかを判定します。ユーザースレッドが異なるデータモデルをサポートしている場合、デバイスドライバは、データ構造体の構造を調整したあとでその構造体をユーザースレッドにエクスポートしなければならない可能性があります。詳細については、付録 C 64 ビットデバイスドライバの準備のページを参照してください。

devmap(9E) エントリポイントは、論理オフセット off がドライバからエクスポートされるメモリーの範囲外である場合には -1 を返す必要があります。