この文書は、Windows NT の PCI デバイスドライバの作成方法について紹介しています。デバイスドライバは、デバイス オブジェクトの生成などの多くの関数を実行しなければなりません。さらに、PCI デバイスをサポートするために、ドライバ初期化中に実行する多くの関数があります。以下に説明する関数のいくつかは非 PCI ドライバでも使用することができることに注意してください。
先頭へ戻る
以下が、ドライバ作成を達成するための必要なステップです:
| 1. |
HalGetBusData で PCI デバイスを見つけます:
PCI デバイスの位置を見つけるために、すべてのバスとスロットをスキャンします。HalGetBusData で返されたバッファの中に、デバイスの PCI VendorId と DeviceId が一致するものを探します。
デバイスドライバが PCI コンフィグレーション空間から追加情報を必要とする場合、HalGetBusData または HalGetBusDataByOffset を使います。PCI コンフィグレーション空間のフィールドは、HalSetBusData または HalSetBusDataByOffset で設定することができます。
重要 : PCI コンフィグレーション空間のベースアドレスレジスタ( BAR )または割り込み情報を設定しないでください。また、そのデバイスで使われるそれらの BAR オリジナル設定値を期待しないでください。PCI は動的に構成可能ですから、オペレーティング システムはそれに適した BAR に変更する権利を保有しています。
3 つの FOR ループで PCI デバイスを見つけます: 1 つはバス用、もう 1 つはデバイス番号用、そしてもう 1 つはファンクション番号のためです。PCI_SLOT_NUMBER 構造体は、デバイス番号とファンクション番号の情報を含むことに注意してください。
|
| 2. |
HalAssignSlotResources でデバイスリソースを要求します:
PCI デバイスの位置を見つ桁ら、そのバスとスロット情報を HalAssignSlotResources に渡します。この API は、コンフィグレーション空間に指定されたリソースで競合がないことを保証します。HalAssignSlotResources が呼び出された時、HAL はデバイスのメモリまたはポート範囲を変更するかもしれないので、コンフィグレーション空間から直接その値を使わないでください。その代わり、リソースリストに返された値を使用して、下記のステップ 4 と 5 の中で示した方法を行ってください。HAL はデバイス用のリソースを自発的に変更しませんが、HalAssignSlotResources 呼び出し結果に応じてのみ、リソースを変更します。
HAL がまだ要求されていない別の PCI デバイス上の PCI デバイスリソースを変更する時に、たまに、HalAssignSlotResources の呼び出しで問題を引き起こすことがあります。Boot.ini ファイルに PCILOCK オプションを付加することでこれを防ぐことができます。PCILOCK オプションに関する情報として、Microsoft Knowledge Base の以下の文書を参照してください:
Article ID : 148501 (http://support.microsoft.com/kb/148501/EN-US/)
Title : Preventing PCI Resource Conflicts on Intel-Based Computers
PCILOCK オプションを付加してもうまく動作しない場合、PCI デバイスリソースは IoReportResourceUsage で要求しなければなりません。
先頭へ戻る
HalAssignSlotResources の代わりに IoReportResourceUsage を使います:
ベースアドレスレジスタが再プログラムされた時か、PCI デバイスが特定のリソース割り当てで動作するだけの時に、PCI デバイスはその機能を中止します。これらの PCI デバイス上で、HalAssignSlotResources はたびたび失敗します。このような場合は、HalAssignSlotResources の代わりに IoReportResourceUsage を使ってください。
IoReportResourceUsage を使うために、HalGetBusData/HalGetBusDataByOffset を通して、PCI デバイスのコンフィグレーション空間を読み込んで、現在のデバイス設定値を取得します。PCI コンフィグレーション空間の情報に基づいたリソースリストを組み立てて、IoReportResourceUsage を使ってリソースを要求します。リソースリストの InterfaceType が正しく PCIBus に設定されていることを確認することが重要です。また、PCI 割り込みはレベルセンシティブとみなされ、共有されるので、適当なフラグがリソースリストに設定されていることを確認してください。
コンフィグレーション空間から返された割り込み値は、ドライバがチェックビルド版で動作していた時の範囲外かもしれません。これは、チェック版 HAL が本当の割り込み値に、0x2B で排他論理和( XOR )を行うためです。この値の解読方法は HAL が知っていますから、HalGetBusData/HalGetBusDataByOffset によって返された値を変更しないで使用してください。また、HalGetInterruptVector 呼び出しのための、BusInterruptLevel と BusInterruptVector パラメタも同様に、IoReportResourceUsage のリソースリストに返された値を使用してください。
|
| 3. |
デバイスリソース用のリソースリストを解析します:
HalAssignSlotResources は、PCI デバイスリソースを要求して、CM_RESOURCE_LIST 構造体の中に要求されたリソースを返します。ドライバは、割り込み、メモリ範囲と I/O 範囲情報を取得するために、このリソースリストを解析しなければなりません。1 つの PCI デバイスが複数のメモリと I/O 範囲を持つことができることに注意してください。必要ならば、後の解析のためにこの情報をドライバのデバイス拡張領域に保存してください。I/O またはメモリ空間をアクセスするために、生のリソース情報を使わないでください。
この点で、ドライバが PCI コンフィグレーション空間を調べる場合、BAR は CM_RESOURCE_LIST 構造体に返されたものと同じものでなければなりません。しかし、リソースリストに返された情報を使ってください。
PCI リソースが IoReportResourceUsage で要求された場合、ドライバが組み立てて、該当するドライバ位置に情報を格納したリソースリストを解析してください。
|
| 4. |
各メモリ範囲を要求するために、HalTranslateBusAddress と MmMapIoSpace を呼び出します:
HalTranslateBusAddress は、バス特有アドレスを対応するシステム論理アドレスに翻訳します。この API の呼び出し後、4 番めのパラメタをチェックします。API の入り口で、ゼロはメモリ空間を示します。API の出口で、値がゼロのままならば通常の場合で、メモリ翻訳のために、ドライバは MmMapIoSpace を呼び出さなければなりません。
デバイス拡張領域のようにドライバがアクセス可能な領域内に、翻訳されたメモリ範囲情報を保存します。メモリ空間をアクセスするために翻訳された範囲を使用します。
|
| 5. |
各 I/O 範囲を要求するために、HalTranslateBusAddress を呼び出し、必要なら MmMapIoSpace を呼び出します:
マッピングは、メモリ空間の場合と似ています。しかし、HalTranslateBusAddress の入り口で、4 番めのパラメタは、I/O 空間を示す 1 になります。出口で、API がこのパラメタをゼロに変えてしまった場合、そのドライバは、MmMapIoSpace を呼ばなければなりません。
デバイス拡張領域のようにドライバがアクセス可能な領域内に、翻訳された I/O 範囲情報を保存します。I/O 空間をアクセスするために翻訳された範囲を使用します。
RISC ベースのシステムの中には、I/O 空間がないものがあります: I/O 空間はメモリ空間にマップされています。このような状況では、I/O 空間を示している 4 番めのパラメタは、メモリ空間にマップされたことを示す値に変更されます。x86 ベースのシステムでは、I/O 空間の翻訳は、HalTranslateBusAddress を使って MmMapIoSpace は使いません。RISC ベースのシステムでは、HalTranslateBusAddress と MmMapIoSpace の両方が呼ばれるかもしれません。この API の呼び出し後に、HalTranslateBusAddress の 4 番めのパラメタをチェックすることが重要です。
これは x86 ベースのマシンから RISC プラットホームへ移植する時に共通の問題です。ドライバ作成者は、I/O 範囲を翻訳する場合に、MmMapIoSpace の呼び出しが決して必要ではないと仮定することがあります。これは誤りです。
|
| 6. |
デバイスが割り込みをサポートする場合、HalGetInterruptVector と IoConnectInterrupt を呼び出します:
IoConnectInterrupt が呼ばれた時、PCI デバイスが割り込んでいる場合、ドライバの割込みサービスルーチン( ISR )が呼び出されるかもしれません。これは、すべてのデバイスレジスタを翻訳した後に、割り込みを接続するために最良の方法だからです。前回の翻訳が発生していないか、情報(たとえば、翻訳されたメモリと I/O 範囲がデバイス拡張領域に保存されていない)が ISR で利用可能でない場合、ISR は PCI デバイスレジスタをチェックして、割り込みをクリアすることができません。割り込みがクリアされない場合、システムはハングします。
|
先頭へ戻る
Windows NT デバイスドライバキット (DDK)、カーネル モードドライバ、Windows NT デバイスドライバの概要のためのデザインガイドを参照してください。上記の API の説明は Windows NT デバイスドライバキット、カーネル モードドライバ、リファレンスに詳細があります。
先頭へ戻る
この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID
152044 (http://support.microsoft.com/kb/152044/EN-US/)
(最終更新日 1998-03-31) をもとに作成したものです。
先頭へ戻る