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.  割り込みハンドラ

割り込みハンドラの概要

デバイス割り込み

高レベルの割り込み

レガシー割り込み

標準メッセージシグナル割り込みと拡張メッセージシグナル割り込み

MSI 割り込み

MSI-X 割り込み

ソフトウェア割り込み

DDI 割り込み関数

割り込み許可フラグ関数

割り込み初期化関数と割り込み破棄関数

優先順位管理関数

ソフト割り込み関数

割り込み関数の例

割り込みの登録

レガシー割り込みの登録

MSI 割り込みの登録

割り込みリソース管理

割り込みリソース管理機能

コールバックのインタフェース

コールバックハンドラ関数の登録

コールバックハンドラ関数の登録解除

コールバックハンドラ関数

割り込み要求のインタフェース

割り込みの割り当て

要求する割り込みベクターの数の変更

割り込みの使用率と柔軟性

割り込みリソース管理の実装例

割り込みハンドラの機能

高レベルの割り込みの処理

高レベルの mutex

高レベルの割り込み処理の例

9.  ダイレクトメモリーアクセス (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
貴重なご意見を有り難うございました!

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

高レベルの割り込みの処理

高レベルの割り込みとは、スケジューラおよびそれより上のレベルで行われる割り込みのことです。このレベルでは、スケジューラは実行できません。したがって、スケジューラであらかじめ高レベルの割り込みハンドラを無効にすることはできません。スケジューラが原因となって、高レベルの割り込みをブロックできません。高レベルの割り込みで可能なのは、相互排他ロックを使ってロックすることのみです。

ドライバは、デバイスが高レベルの割り込みを使用しているかどうかを判定する必要があります。このテストは、割り込みの登録時にドライバの attach(9E) エントリポイントで行います。「高レベルの割り込み処理の例」を参照してください。

高レベルの mutex

高レベルの割り込みを表す割り込み優先順位で初期化された mutex は、高レベルの mutex と呼ばれます。ドライバは、高レベルの mutex を保持している間、高レベルの割り込みハンドラと同じ制限に従います。

高レベルの割り込み処理の例

次の例では、高レベルの mutex (xsp->high_mu) は、高レベルの割り込みハンドラとソフト割り込みハンドラの間で共有されるデータを保護するためにのみ使用されます。保護されるデータには、高レベルの割り込みハンドラと低レベルのハンドラの両方で使用されるキューと、低レベルのハンドラが実行されていることを示すフラグが含まれています。別個の低レベルの mutex (xsp->low_mu) は、ドライバの残りの部分をソフト割り込みハンドラから保護します。

例 8-10 attach() を使用した高レベルの割り込みの処理

static int
mydevattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
    struct mydevstate *xsp;
    /* ... */

    ret = ddi_intr_get_supported_types(dip, &type);
    if ((ret != DDI_SUCCESS) || (!(type & DDI_INTR_TYPE_FIXED))) {
        cmn_err(CE_WARN, "ddi_intr_get_supported_types() failed");
        return (DDI_FAILURE);
    }

    ret = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count);

    /*
     * Fixed interrupts can only have one interrupt. Check to make
     * sure that number of supported interrupts and number of
     * available interrupts are both equal to 1.
     */
    if ((ret != DDI_SUCCESS) || (count != 1)) {
    cmn_err(CE_WARN, "No fixed interrupts found");
            return (DDI_FAILURE);
    }

    xsp->xs_htable = kmem_zalloc(count * sizeof (ddi_intr_handle_t),
        KM_SLEEP);

    ret = ddi_intr_alloc(dip, xsp->xs_htable, DDI_INTR_TYPE_FIXED, 0,
        count, &actual, 0);

    if ((ret != DDI_SUCCESS) || (actual != 1)) {
    cmn_err(CE_WARN, "ddi_intr_alloc failed 0x%x", ret");
        kmem_free(xsp->xs_htable, sizeof (ddi_intr_handle_t));
        return (DDI_FAILURE);
    }

    ret = ddi_intr_get_pri(xsp->xs_htable[0], &intr_pri);
    if (ret != DDI_SUCCESS) {
        cmn_err(CE_WARN, "ddi_intr_get_pri failed 0x%x", ret");
        (void) ddi_intr_free(xsp->xs_htable[0]);
        kmem_free(xsp->xs_htable, sizeof (ddi_intr_handle_t));
        return (DDI_FAILURE);
    }

    if (intr_pri >= ddi_intr_get_hilevel_pri()) {

        mutex_init(&xsp->high_mu, NULL, MUTEX_DRIVER,
            DDI_INTR_PRI(intr_pri));

        ret = ddi_intr_add_handler(xsp->xs_htable[0],
            mydevhigh_intr, (caddr_t)xsp, NULL);

        if (ret != DDI_SUCCESS) {
            cmn_err(CE_WARN, "ddi_intr_add_handler failed 0x%x", ret");
            mutex_destroy(&xsp>xs_int_mutex);
                (void) ddi_intr_free(xsp->xs_htable[0]);
                kmem_free(xsp->xs_htable, sizeof (ddi_intr_handle_t));
            return (DDI_FAILURE);
        }

        /* add soft interrupt */
        if (ddi_intr_add_softint(xsp->xs_dip, &xsp->xs_softint_hdl,
            DDI_INTR_SOFTPRI_MAX, xs_soft_intr, (caddr_t)xsp) !=
            DDI_SUCCESS) {
            cmn_err(CE_WARN, "add soft interrupt failed");
            mutex_destroy(&xsp->high_mu);
            (void) ddi_intr_remove_handler(xsp->xs_htable[0]);
            (void) ddi_intr_free(xsp->xs_htable[0]);
            kmem_free(xsp->xs_htable, sizeof (ddi_intr_handle_t));
            return (DDI_FAILURE);
        }

        xsp->low_soft_pri = DDI_INTR_SOFTPRI_MAX;

        mutex_init(&xsp->low_mu, NULL, MUTEX_DRIVER,
            DDI_INTR_PRI(xsp->low_soft_pri));

    } else {
    /*
     * regular interrupt registration continues from here
     * do not use a soft interrupt
     */
    }

    return (DDI_SUCCESS);
}

高レベルの割り込みルーチンは、デバイスを保守し、データをキューに入れます。低レベルのルーチンが実行されていない場合、高レベルのルーチンはソフトウェア割り込みをトリガーします。次に例を示します。

例 8-11 高レベルの割り込みルーチン

static uint_t
mydevhigh_intr(caddr_t arg1, caddr_t arg2)
{
    struct mydevstate    *xsp = (struct mydevstate *)arg1;
    uint8_t    status;
    volatile  uint8_t  temp;
    int    need_softint;

    mutex_enter(&xsp->high_mu);
    /* read status */
    status = ddi_get8(xsp->data_access_handle, &xsp->regp->csr);
    if (!(status & INTERRUPTING)) {
        mutex_exit(&xsp->high_mu);
        return (DDI_INTR_UNCLAIMED); /* dev not interrupting */
    }

    ddi_put8(xsp->data_access_handle,&xsp->regp->csr,
        CLEAR_INTERRUPT | ENABLE_INTERRUPTS);
    /* flush store buffers */
    temp = ddi_get8(xsp->data_access_handle, &xsp->regp->csr);

    /* read data from device, queue data for low-level interrupt handler */
    if (xsp->softint_running)
        need_softint = 0;
    else {
        xsp->softint_count++;
        need_softint = 1;
    }
    mutex_exit(&xsp->high_mu);

    /* read-only access to xsp->id, no mutex needed */
    if (need_softint) {
        ret = ddi_intr_trigger_softint(xsp->xs_softint_hdl, NULL);
        if (ret == DDI_EPENDING) {
            cmn_err(CE_WARN, "ddi_intr_trigger_softint() soft interrupt "
                "already pending for this handler");
        } else if (ret != DDI_SUCCESS) {
            cmn_err(CE_WARN, "ddi_intr_trigger_softint() failed");
        }           
    }

    return (DDI_INTR_CLAIMED);
}

低レベルの割り込みルーチンは、ソフトウェア割り込みをトリガーする高レベルの割り込みルーチンによって開始されます。低レベルの割り込みルーチンは、処理するものがなくなるまで実行されます。次に例を示します。

例 8-12 低レベルのソフト割り込みルーチン

static uint_t
mydev_soft_intr(caddr_t arg1, caddr_t arg2)
{
    struct mydevstate *mydevp = (struct mydevstate *)arg1;
    /* ... */
    mutex_enter(&mydevp->low_mu);
    mutex_enter(&mydevp->high_mu);
    if (mydevp->softint_count > 1) {
        mydevp->softint_count--;
        mutex_exit(&mydevp->high_mu);
        mutex_exit(&mydevp->low_mu);
        return (DDI_INTR_CLAIMED);
    }

    if ( /* queue empty */ ) {
        mutex_exit(&mydevp->high_mu);
        mutex_exit(&mydevp->low_mu);
        return (DDI_INTR_UNCLAIMED);
    }

    mydevp->softint_running = 1;
    while (EMBEDDED COMMENT:data on queue) {
        ASSERT(mutex_owned(&mydevp->high_mu);
        /* Dequeue data from high-level queue. */
        mutex_exit(&mydevp->high_mu);
        /* normal interrupt processing */
        mutex_enter(&mydevp->high_mu);
    }

    mydevp->softint_running = 0;
    mydevp->softint_count = 0;
    mutex_exit(&mydevp->high_mu);
    mutex_exit(&mydevp->low_mu);
    return (DDI_INTR_CLAIMED);
}