ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
プログラム式入出力をサポートするデバイスには、デバイスのアドレス指定可能領域にマップされるバスアドレス空間の 1 つ以上の領域が割り当てられます。これらのマッピングは、デバイスに関連付けられた reg プロパティー内の値ペアとして記述されます。各値ペアはバスアドレスの 1 つのセグメントを記述します。
ドライバは、特定のバスアドレスマッピングを特定するために、レジスタ番号または regspec を指定します。この番号は、デバイスの reg プロパティー内でのインデックスです。reg プロパティーは、デバイスの busaddr と size を特定します。ドライバは、ddi_regs_map_setup(9F) などの DDI 関数を呼び出すときに、このレジスタ番号を渡します。ドライバ内で、デバイスに割り当てられたマップ可能領域の個数を判定するには、ddi_dev_nregs(9F) を呼び出します。
ホストのデータ形式は、デバイスのデータ形式とは異なるエンディアン特性を備えている可能性があります。そのような場合、ホストとデバイスとの間で転送されるデータをバイトスワップすることで、転送先のデータ形式の要件に合わせる必要があります。ホストと同じエンディアン特性を備えたデバイスでは、データのバイトスワップを行う必要はありません。
ドライバでデバイスのエンディアン特性を指定するには、ddi_device_acc_attr(9S) に渡される ddi_regs_map_setup(9F) 構造体の対応するフラグを設定します。そうした場合、ドライバが ddi_get8(9F) などの ddi_getX ルーチンや ddi_put16(9F) などの ddi_putX ルーチンを呼び出してデバイスメモリーに対する読み書きを行うときに、DDI フレームワークによって必要なバイトスワップがすべて実行されます。
各プラットフォームでは、データのロードや格納の順序を変更することでパフォーマンスを最適化できます。デバイスによっては順序変更が許されない場合もあるため、ドライバでデバイスへのマッピングを設定する際にデバイスの順序付け要件を指定する必要があります。
この構造体は、デバイスのエンディアン要件とデータ順序要件を記述します。ドライバは、この構造体を初期化し、ddi_regs_map_setup(9F) の引数として渡す必要があります。
typedef struct ddi_device_acc_attr { ushort_t devacc_attr_version; uchar_t devacc_attr_endian_flags; uchar_t devacc_attr_dataorder; } ddi_device_acc_attr_t;
DDI_DEVICE_ATTR_V0 を指定します。
デバイスのエンディアン特性を記述します。ビット値として指定され、使用可能な値は次のとおりです。
DDI_NEVERSWAP_ACC – データのスワップを一切行わない
DDI_STRUCTURE_BE_ACC – デバイスのデータ形式がビッグエンディアンである
DDI_STRUCTURE_LE_ACC – デバイスのデータ形式がリトルエンディアンである
CPU がデバイスから要求されたデータを参照する際に従うべき順序を記述します。列挙値として指定されます。ただし、データアクセス制限は、厳格度の高いものから順に並べられます。
DDI_STRICTORDER_ACC – ホストは、プログラマによって指定された順番で参照を発行する必要があります。このフラグがデフォルトの動作です。
DDI_UNORDERED_OK_ACC – ホストは、デバイスメモリーに対するロードや格納の順序を変更できます。
DDI_MERGING_OK_ACC – ホストは、個々の格納をマージして連続する場所にまとめることができます。この設定では暗黙的に順序変更も許可されます。
DDI_LOADCACHING_OK_ACC – 格納が発生するまで、ホストはデバイスからデータを読み取ることができます。
DDI_STORECACHING_OK_ACC – ホストは、デバイスに書き込むデータをキャッシュに格納しておくことができます。このときホストは、デバイスへのデータ書き込みを、将来必要になるまで遅らせることができます。
注 - システムは、ドライバで devacc_attr_dataorder に指定されているよりも厳格に、データへのアクセスを行うことができます。厳格なデータ順序付けからキャッシュ格納へと移る間、ドライバによるデータアクセスに関してホストの制限が小さくなります。
ドライバは通常、attach(9E) の実行中にデバイスのすべての領域をマップします。ドライバ内でデバイスメモリーの 1 つの領域をマップするには、そのマップする領域のレジスタ番号、領域のデバイスアクセス属性、オフセット、およびサイズを指定して ddi_regs_map_setup(9F) を呼び出します。DDI フレームワークは、そのデバイス領域のマッピングを設定し、不透明なハンドルをドライバに返します。このデータアクセスハンドルは、デバイスのその領域からデータを読み取ったりその領域にデータを書き込んだりする際に、ddi_get8(9F) または ddi_put8(9F) ルーチンファミリの引数として渡されます。
ドライバは、デバイスマッピングの形式がドライバで求められる形式と一致しているかどうかを確認するために、デバイスからエクスポートされたマッピングの数をチェックします。ドライバは、ddi_dev_nregs(9F) を呼び出したあと、各マッピングのサイズを確認するために ddi_dev_regsize(9F) を呼び出します。
次に、DDI データアクセスインタフェースの簡単な例を示します。このドライバは、一度に 1 つの文字を受け付け、次の文字の受け付け準備が整ったら割り込みを生成するような、架空のリトルエンディアンデバイスに対するものです。このデバイスには 2 つのレジスタセットが実装されています。1 つは 8 ビット CSR レジスタ、もう 1 つは 8 ビットデータレジスタです。
例 7-1 マッピングの設定
#define CSR_REG 0 #define DATA_REG 1 /* * Initialize the device access attributes for the register * mapping */ dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; /* * Map in the csr register (register 0) */ if (ddi_regs_map_setup(dip, CSR_REG, (caddr_t *)&(pio_p->csr), 0, sizeof (Pio_csr), &dev_acc_attr, &pio_p->csr_handle) != DDI_SUCCESS) { mutex_destroy(&pio_p->mutex); ddi_soft_state_free(pio_softstate, instance); return (DDI_FAILURE); } /* * Map in the data register (register 1) */ if (ddi_regs_map_setup(dip, DATA_REG, (caddr_t *)&(pio_p->data), 0, sizeof (uchar_t), &dev_acc_attr, &pio_p->data_handle) \ != DDI_SUCCESS) { mutex_destroy(&pio_p->mutex); ddi_regs_map_free(&pio_p->csr_handle); ddi_soft_state_free(pio_softstate, instance); return (DDI_FAILURE); }