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)

DMA モデル

デバイス DMA の種類

バスマスター DMA

サードパーティー DMA

ファーストパーティー DMA

ホストプラットフォームの DMA の種類

DMA ソフトウェアコンポーネント: ハンドル、ウィンドウ、cookie

DMA 操作

バスマスター DMA 転送の実行

ファーストパーティー DMA 転送の実行

サードパーティー DMA 転送の実行

DMA 属性

ddi_dma_attr 構造体

SBus の例

ISA バスの例

DMA 資源の管理

オブジェクトのロック

DMA ハンドルの割り当て

DMA 資源の割り当て

デバイスレジスタ構造体

DMA コールバックの例

最大バーストサイズの決定

プライベート DMA バッファーの割り当て

資源割り当てエラーの処理

DMA エンジンのプログラミング

DMA 資源の解放

DMA ハンドルの解放

DMA コールバックの取り消し

メモリーオブジェクトの同期

キャッシュ

ddi_dma_sync() 関数

DMA ウィンドウ

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

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
貴重なご意見を有り難うございました!

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

DMA ウィンドウ

オブジェクトが DMA エンジンの制限内に収まらない大きさの場合は、その転送をより小さい一連の転送に分ける必要があります。ドライバは転送そのものを分割できます。別の方法として、ドライバはシステムがオブジェクトの一部にだけ資源を割り当てられるようにすることができます。その結果、一連の DMA ウィンドウが作成されます。システムが資源を割り当てられるようにすることが推奨される解決方法です。ドライバが資源を管理するよりも効果的に資源を管理できるからです。

DMA ウィンドウには 2 つの属性があります。offset 属性はオブジェクトの先頭から測定されます。length 属性は、割り当てられるメモリーのバイト数です。部分的な割り当てが行われたあと、offset で始まる length バイトの範囲だけに資源が割り当てられています。

DMA ウィンドウを要求するには、ddi_dma_buf_bind_handle(9F) または ddi_dma_addr_bind_handle(9F) のパラメータとして DDI_DMA_PARTIAL フラグを指定します。ウィンドウを作成できる場合は、どちらの関数も DDI_DMA_PARTIAL_MAP を返します。ただし、システムがオブジェクト全体に資源を割り当てることがあります。この場合は DDI_DMA_MAPPED が返されます。ドライバは、戻り値を調べて、DMA ウィンドウが使用されているかどうかを判断します。次の例を参照してください。

例 9-7 DMA ウィンドウの設定

static int
xxstart (caddr_t arg)
{
    struct xxstate *xsp = (struct xxstate *)arg;
    struct device_reg *regp = xsp->reg;
    ddi_dma_cookie_t cookie;
    int status;
    mutex_enter(&xsp->mu);
    if (xsp->busy) {
        /* transfer in progress */
        mutex_exit(&xsp->mu);
        return (DDI_DMA_CALLBACK_RUNOUT);
    }
    xsp->busy = 1;
    mutex_exit(&xsp->mu);
    if ( /* transfer is a read */) {
        flags = DDI_DMA_READ;
    } else {
        flags = DDI_DMA_WRITE;
    }
    flags |= DDI_DMA_PARTIAL;
    status = ddi_dma_buf_bind_handle(xsp->handle, xsp->bp,
        flags, xxstart, (caddr_t)xsp, &cookie, &ccount);
    if (status != DDI_DMA_MAPPED &&
        status != DDI_DMA_PARTIAL_MAP)
        return (DDI_DMA_CALLBACK_RUNOUT);
    if (status == DDI_DMA_PARTIAL_MAP) {
        ddi_dma_numwin(xsp->handle, &xsp->nwin);
        xsp->partial = 1;
        xsp->windex = 0;
    } else {
        xsp->partial = 0;
    }
    /* Program the DMA engine. */
    return (DDI_DMA_CALLBACK_DONE);
}

2 つの関数が DMA ウィンドウで動作します。最初の関数 ddi_dma_numwin(9F) は、特定の DMA オブジェクト用の DMA ウィンドウの数を返します。もう 1 つの関数 ddi_dma_getwin(9F) は、オブジェクト内での再配置、つまりシステム資源の再割り当てを許可します。ddi_dma_getwin() 関数は、現在のウィンドウをオブジェクト内の新しいウィンドウにシフトします。ddi_dma_getwin() はシステム資源を新しいウィンドウに再割り当てするので、以前のウィンドウは無効になります。


注意

注意 - 現在のウィンドウへの転送が完了する前に、ddi_dma_getwin() の呼び出しを使って DMA ウィンドウを移動しないでください。現在のウィンドウへの転送が完了するまで待ってください。このタイミングで割り込みが発生します。次に、データの破壊を避けるために ddi_dma_getwin() を呼び出してください。


Example 9–8() に示すように、例 9-8 関数は通常、割り込みルーチンから呼び出されます。最初の DMA 転送は、ドライバの呼び出しによって開始されます。それ以降の転送は、割り込みルーチンから開始されます。

割り込みルーチンは、デバイスのステータスを調べて、デバイスが転送を正常に完了しているかどうかを判断します。完了していない場合は、エラー回復処理が行われます。転送が正常に行われた場合、割り込みルーチンは論理転送が完了しているかどうかを調べる必要があります。完全な転送には、buf(9S) 構造体で指定されたオブジェクト全体が含まれています。部分的な転送では、1 つの DMA ウィンドウだけが移動されます。部分的な転送では、割り込みルーチンは ddi_dma_getwin(9F) を使ってウィンドウを移動し、新しい cookie を取得して、別の DMA 転送を開始します。

論理要求が完了している場合、割り込みルーチンは保留中の要求がないかどうか確認します。必要があれば、割り込みルーチンは転送を開始します。必要がなければ、割り込みルーチンは別の DMA 転送を呼び出さずに復帰します。次の例は、通常のフロー制御を示しています。

例 9-8 DMA ウィンドウを使用した割り込みハンドラ

static uint_t
xxintr(caddr_t arg)
{
    struct xxstate *xsp = (struct xxstate *)arg;
    uint8_t    status;
    volatile   uint8_t   temp;
    mutex_enter(&xsp->mu);
    /* read status */
    status = ddi_get8(xsp->access_hdl, &xsp->regp->csr);
    if (!(status & INTERRUPTING)) {
        mutex_exit(&xsp->mu);
        return (DDI_INTR_UNCLAIMED);
    }
    ddi_put8(xsp->access_hdl,&xsp->regp->csr, CLEAR_INTERRUPT);
    /* for store buffers */
    temp = ddi_get8(xsp->access_hdl, &xsp->regp->csr);
    if ( /* an error occurred during transfer */ ) {
        bioerror(xsp->bp, EIO);
        xsp->partial = 0;
    } else {
        xsp->bp->b_resid -= /* amount transferred */ ;
    }

    if (xsp->partial && (++xsp->windex < xsp->nwin)) {
        /* device still marked busy to protect state */
        mutex_exit(&xsp->mu);
        (void) ddi_dma_getwin(xsp->handle, xsp->windex,
            &offset, &len, &cookie, &ccount);
        /* Program the DMA engine with the new cookie(s). */
        return (DDI_INTR_CLAIMED);
    }
    ddi_dma_unbind_handle(xsp->handle);
    biodone(xsp->bp);
    xsp->busy = 0;
    xsp->partial = 0;
    mutex_exit(&xsp->mu);
    if ( /* pending transfers */ ) {
        (void) xxstart((caddr_t)xsp);
    }
    return (DDI_INTR_CLAIMED);
}