Help and Support

文書番号: 152044 - 最終更新日: 2004年3月30日 - リビジョン: 4.0

[NT DDK] PCI デバイスドライバの作成方法

この記事は、以前は次の ID で公開されていました: JP152044
すべて展開する | すべて折りたたむ

概要

この文書は、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) をもとに作成したものです。


この資料は以下の製品について記述したものです。
  • Microsoft Win32 Device Driver Kit for Windows NT 4.0
  • Microsoft Win32 Device Driver Kit for Windows NT 3.5
  • Microsoft Win32 Device Driver Kit for Windows NT 3.51
キーワード:?
kbinfo ntddkkmode KB152044
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"
Retired KB Articleサポート期間が終了した「サポート技術情報」資料に関する免責事項
この資料は、マイクロソフトでサポートされていない製品について記述したものです。そのため、この資料は現状ベースで提供されており、今後更新されることはありません。

サポート技術情報の翻訳