Go to main content
Oracle® Solaris 11.3 デバイスドライバの記述

印刷ビューの終了

更新: 2016 年 11 月
 
 

ロード可能なドライバインタフェース

デバイスドライバは、動的にロード可能である必要があります。ドライバは、メモリーリソースの節約に役立つように、アンロード可能にもなっています。また、アンロード可能なドライバは、テスト、デバッグ、パッチ適用がより容易でもあります。

ドライバのロードとアンロードをサポートするには、各デバイスドライバが _init(9E)_fini(9E)、および _info(9E) エントリポイントを実装する必要があります。次の例は、ロード可能なドライバインタフェースの標準的な実装を示しています。

使用例 8  ロード可能なインタフェースのセクション
static void *statep;                /* for soft state routines */
static struct cb_ops xx_cb_ops;     /* forward reference */
static struct dev_ops xx_ops = {
    DEVO_REV,
    0,
    xxgetinfo,
    nulldev,
    xxprobe,
    xxattach,
    xxdetach,
    xxreset,
    nodev,
    &xx_cb_ops,
    NULL,
    xxpower,
    ddi_quiesce_not_needed,
};

static struct modldrv modldrv = {
    &mod_driverops,
    "xx driver v1.0",
    &xx_ops
};

static struct modlinkage modlinkage = {
    MODREV_1,
    &modldrv,
    NULL
};

int
_init(void)
{
    int error;
    ddi_soft_state_init(&statep, sizeof (struct xxstate),
        estimated_number_of_instances);
    /* further per-module initialization if necessary */
    error = mod_install(&modlinkage);
    if (error != 0) {
        /* undo any per-module initialization done earlier */
        ddi_soft_state_fini(&statep);
    }
    return (error);
}

int
_fini(void)
{
    int error;
    error = mod_remove(&modlinkage);
    if (error == 0) {
        /* release per-module resources if any were allocated */
        ddi_soft_state_fini(&statep);
    }
    return (error);
}

int
_info(struct modinfo *modinfop)
{
    return (mod_info(&modlinkage, modinfop));
}

_init() の例

次の例は、標準的な _init(9E) インタフェースを示しています。

使用例 9  _init() 関数
static void *xxstatep;
int
_init(void)
{
    int error;
    const int max_instance = 20;    /* estimated max device instances */

    ddi_soft_state_init(&xxstatep, sizeof (struct xxstate), max_instance);
    error = mod_install(&xxmodlinkage);
    if (error != 0) {
        /*
         * Cleanup after a failure
         */
        ddi_soft_state_fini(&xxstatep);
    }
    return (error);
}

ドライバは、1 回限りのリソース割り当てまたはデータ初期化を _init() でのドライバのロード中に実行します。たとえば、ドライバは、そのドライバに対してグローバルな mutex をすべてこのルーチン内で初期化します。ただし、ドライバは _init(9E) を使用して、デバイスの特定のインスタンスと関係があるものを割り当てたり、初期化したりしません。インスタンスごとの初期化は、attach(9E) で実行する必要があります。たとえば、プリンタのドライバが一度に複数のプリンタを処理できる場合、そのドライバは、各プリンタインスタンスに固有のリソースを attach() で割り当てます。


注 - _init(9E)mod_install(9F) を呼び出したあとは、システムがそのデータ構造体をコピーまたは変更する可能性があるため、ドライバは modlinkage(9S) 構造体に接続されたデータ構造体を変更しません。

_fini() の例

次の例は、_fini() ルーチンを示しています。

int
_fini(void)
{
    int error;
    error = mod_remove(&modlinkage);
    if (error != 0) {
        return (error);
    }
    /*
     * Cleanup resources allocated in _init()
     */
    ddi_soft_state_fini(&xxstatep);
    return (0);
}

同様に、ドライバは _fini() で、_init() で割り当てられたリソースをすべて解放します。ドライバは、システムモジュールリストから自身を削除する必要があります。


注 - ドライバがハードウェアインスタンスに接続されているときに _fini() が呼び出される可能性があります。この場合は、mod_remove(9F) が失敗を返します。そのため、mod_remove() が成功を返すまで、ドライバリソースを解放しません。

_info() の例

次の例は、_info(9E) ルーチンを示しています。

int
_info(struct modinfo *modinfop)
{
    return (mod_info(&xxmodlinkage, modinfop));
}

ドライバは、モジュール情報を返すために呼び出されます。このエントリポイントは、上に示すように実装します。