ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
自動構成をサポートするには、ドライバで次のデータ構造体を静的に初期化する必要があります。
ドライバは、図 5-1 のデータ構造体に依存しています。これらの構造体を正しく提供し、初期化する必要があります。これらのデータ構造体がない場合、ドライバが正しくロードされない可能性があります。その結果、必要なルーチンがロードされない可能性があります。ある操作がドライバによってサポートされていない場合は、nodev(9F) ルーチンのアドレスをプレースホルダとして使用できます。場合によっては、ドライバがエントリポイントをサポートするため、成功または失敗を返すだけで済むことがあります。その場合は、nulldev(9F) ルーチンのアドレスを使用できます。
注 - これらの構造体は、コンパイル時に初期化してください。ドライバは、それ以外のときにこれらの構造体へのアクセスや変更を行うべきではありません。
static struct modlinkage xxmodlinkage = { MODREV_1, /* ml_rev */ &xxmodldrv, /* ml_linkage[] */ NULL /* NULL termination */ };
最初のフィールドは、サブシステムをロードするモジュールのバージョン番号です。このフィールドは MODREV_1 にします。2 番目のフィールドは、次に定義されているドライバの modldrv 構造体を指しています。この構造体の最後の要素は、常に NULL にします。
static struct modldrv xxmodldrv = { &mod_driverops, /* drv_modops */ "generic driver v1.1", /* drv_linkinfo */ &xx_dev_ops /* drv_dev_ops */ };
この構造体では、モジュールについてさらに詳細に記述します。最初のフィールドでは、モジュールのインストールに関連した情報を提供します。このフィールドは、ドライバモジュールの &mod_driverops に設定します。2 番目のフィールドは、modinfo(1M) で表示される文字列です。2 番目のフィールドには、ドライバのバイナリを生成したソースコードのバージョンを識別するために十分な情報を含めます。最後のフィールドは、次のセクションで定義されるドライバの dev_ops 構造体を指しています。
static struct dev_ops xx_dev_ops = { DEVO_REV, /* devo_rev */ 0, /* devo_refcnt */ xxgetinfo, /* devo_getinfo: getinfo(9E) */ nulldev, /* devo_identify: identify(9E) */ xxprobe, /* devo_probe: probe(9E) */ xxattach, /* devo_attach: attach(9E) */ xxdetach, /* devo_detach: detach(9E) */ nodev, /* devo_reset: see devo_quiesce */ &xx_cb_ops, /* devo_cb_ops */ NULL, /* devo_bus_ops */ &xxpower, /* devo_power: power(9E) */ ddi_quiesce_not_needed, /* devo_quiesce: quiesce(9E) */ };
dev_ops(9S) 構造体は、カーネルがデバイスドライバの自動構成エントリポイントを見つけることができるようにします。devo_rev フィールドは、構造体のリビジョン番号を識別します。このフィールドは DEVO_REV に設定する必要があります。devo_refcnt フィールドは 0 に初期化する必要があります。次の場合を除き、関数のアドレスフィールドには該当するドライバエントリポイントのアドレスを入力します。
devo_identify フィールドを nulldev(9F) に設定します。identify() エントリポイントは廃止されています。
probe(9E) ルーチンが必要ない場合は、devo_probe フィールドを nulldev(9F) に設定します。
devo_reset フィールドを nodev(9F) に設定します。nodev() 関数は ENXIO を返します。devo_quiesce を参照してください。
power() ルーチンが必要ない場合は、devo_power フィールドを NULL に設定します。電源管理機能を提供するデバイスのドライバには、power(9E) エントリポイントが必要です。第 12 章電源管理を参照してください。
ドライバに休止を実装する必要がない場合には、devo_quiesce フィールドを ddi_quiesce_not_needed() に設定します。デバイスを管理するドライバは、quiesce(9E) エントリポイントを提供する必要があります。
devo_cb_ops メンバーには、cb_ops(9S) 構造体のアドレスを含めます。devo_bus_ops フィールドは NULL に設定する必要があります。
static struct cb_ops xx_cb_ops = { xxopen, /* open(9E) */ xxclose, /* close(9E) */ xxstrategy, /* strategy(9E) */ xxprint, /* print(9E) */ xxdump, /* dump(9E) */ xxread, /* read(9E) */ xxwrite, /* write(9E) */ xxioctl, /* ioctl(9E) */ xxdevmap, /* devmap(9E) */ nodev, /* mmap(9E) */ xxsegmap, /* segmap(9E) */ xxchpoll, /* chpoll(9E) */ xxprop_op, /* prop_op(9E) */ NULL, /* streamtab(9S) */ D_MP | D_64BIT, /* cb_flag */ CB_REV, /* cb_rev */ xxaread, /* aread(9E) */ xxawrite /* awrite(9E) */ };
cb_ops(9S) 構造体には、デバイスドライバの文字操作とブロック操作のためのエントリポイントが含まれています。ドライバでサポートされていないエントリポイントはすべて、nodev(9F) に初期化します。たとえば、文字デバイスドライバは、ブロックのみのフィールド (cb_stategy など) をすべて nodev(9F)に設定します。mmap(9E) エントリポイントは、以前のリリースとの互換性のために保持されていることに注意してください。ドライバは、devmap(9E) エントリポイントをデバイスメモリーのマッピングのために使用します。devmap(9E) がサポートされている場合は、mmap(9E) を nodev(9F) に設定します。
streamtab フィールドは、ドライバが STREAMS ベースかどうかを示します。STREAMS ベースであるのは、第 19 章ネットワークデバイスのドライバで説明されているネットワークデバイスドライバのみです。STREAMS ベースでないドライバではすべて、streamtab フィールドを NULL に設定する必要があります。
cb_flag メンバーには、次のフラグが含まれています。
D_MP フラグは、このドライバがマルチスレッド化に対して安全であることを示します。Oracle Solaris OS はスレッドセーフなドライバのみをサポートしているため、D_MP を設定する必要があります。
D_64BIT フラグを指定すると、ドライバは uio(9S) 構造体の uio_loffset フィールドを使用します。64 ビットオフセットを正しく処理するため、ドライバは cb_flag フィールドに D_64BIT フラグを設定します。
D_DEVMAP フラグは、devmap(9E) エントリポイントをサポートしています。devmap(9E) については、第 10 章デバイスメモリーおよびカーネルメモリーのマッピングを参照してください。
cb_rev は cb_ops 構造体のリビジョン番号です。このフィールドは CB_REV に設定する必要があります。