現在オフラインです。再接続するためにインターネットの接続を待っています

PCI デバイスの構成情報と場所情報の取得方法

Windows XP のサポートは終了しました

マイクロソフトでは、2014 年 4 月 8 日に Windows XP のサポートを終了しました。この変更は、ソフトウェアの更新プログラムおよびセキュリティ オプションに影響しています。 この変更の意味および保護された状態を維持する方法について説明します。

Windows Server 2003 のサポートは 2015 年 7 月 14 日で終了しています

Windows Server 2003 のサポートは 2015 年 7 月 14 日で終了しています。この変更は、ソフトウェアの更新プログラムおよびセキュリティ オプションに影響しています。 この変更の意味および保護された状態を維持する方法について説明します。

この記事は、以前は次の ID で公開されていました: JP253232
この資料は、アーカイブされました。これは "現状のまま" で提供され、更新されることはありません。
概要
この資料では、対象のデバイスのドライバ スタックにある任意のドライバ (関数ドライバまたはフィルタ ドライバ) において、PCI (Peripheral Component Interconnect) デバイスの構成情報と場所情報 (バス番号、デバイス番号、機能番号など) を取得する方法について説明します。
詳細
Windows NT 4.0 では、ドライバは、バスのスキャンと HalGetBusData API および HalGetBusDataByOffset API を呼び出すことによって構成情報および場所情報を取得します。Windows 2000 以降のオペレーティング システムでは、ハードウェア バスは HAL ではなくオペレーティング システムの各バス ドライバによって制御されます。そのため、バスに関する情報を提供していたすべての HAL API が、Windows 2000 以降のオペレーティング システムでは使用されなくなりました。

Windows 2000 以降のオペレーティング システムでは、ドライバはデバイスに問い合わせてリソースを検出する必要がなくなりました。ドライバは、IRP_MN_START_DEVICE 要求によって、プラグ アンド プレイ (PnP) マネージャからリソースを取得します。通常、適切に設計されたドライバであれば、正常に機能するためにこのような情報が必要になることはありません。何らかの理由によりこのような情報が必要になる場合は、リソースの取得方法を示した以下のサンプル コードを使用します。ドライバは、基礎となっている、デバイスの物理デバイス オブジェクト (PDO) に対し、PnP 要求を送信するように要求するため、デバイスのドライバ スタックの一部である必要があります。

以下のサンプル コードでは、構成情報の取得方法を示します。
NTSTATUSReadWriteConfigSpace(    IN PDEVICE_OBJECT DeviceObject,    IN ULONG	      ReadOrWrite, // 0 for read 1 for write    IN PVOID	      Buffer,    IN ULONG	      Offset,    IN ULONG	      Length    ){    KEVENT event;    NTSTATUS status;    PIRP irp;    IO_STATUS_BLOCK ioStatusBlock;    PIO_STACK_LOCATION irpStack;    PDEVICE_OBJECT targetObject;    PAGED_CODE();    KeInitializeEvent( &event, NotificationEvent, FALSE );    targetObject = IoGetAttachedDeviceReference( DeviceObject );    irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,                                        targetObject,                                        NULL,                                        0,                                        NULL,                                        &event,                                        &ioStatusBlock );    if (irp == NULL) {        status = STATUS_INSUFFICIENT_RESOURCES;        goto End;    }    irpStack = IoGetNextIrpStackLocation( irp );    if (ReadOrWrite == 0) {        irpStack->MinorFunction = IRP_MN_READ_CONFIG;    }else {        irpStack->MinorFunction = IRP_MN_WRITE_CONFIG;    }    irpStack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;    irpStack->Parameters.ReadWriteConfig.Buffer = Buffer;    irpStack->Parameters.ReadWriteConfig.Offset = Offset;    irpStack->Parameters.ReadWriteConfig.Length = Length;    //     // Initialize the status to error in case the bus driver does not     // set it correctly.    //     irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;    status = IoCallDriver( targetObject, irp );    if (status == STATUS_PENDING) {        KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );        status = ioStatusBlock.Status;    }End:    //     // Done with reference    //     ObDereferenceObject( targetObject );    return status;}				
行えるのは PASSIVE_LEVEL での PnP I/O 要求パケット (IRP) の送信のみであるため、上記の関数を使用して DISPATCH_LEVEL で構成情報を取得することはできません。

以下の手順を実行すると、DISPATCH_LEVEL で構成領域にアクセスできます。
  1. PASSIVE_LEVEL で IRP_MN_QUERY_INTERFACE を送信し、PCI バス ドライバから直接呼出し用インターフェイス構造体 (BUS_INTERFACE_STANDARD) を取得します。これを非ページ プール メモリ (通常は DeviceExtension) に格納します。
  2. SetBusData と GetBusData を呼び出して、DISPATCH_LEVEL で構成領域にアクセスします。
  3. PCI バス ドライバは、インターフェイスの参照数を取得してから返されるので、不要になったインターフェイスについては、参照を解除する必要があります。
  4. 次の関数を使用して、PASSIVE_LEVEL で BUS_INTERFACE_STANDARD を取得します。
    NTSTATUSGetPCIBusInterfaceStandard(    IN  PDEVICE_OBJECT DeviceObject,    OUT PBUS_INTERFACE_STANDARD	BusInterfaceStandard    )/*++Routine Description:    This routine gets the bus interface standard information from the PDO.Arguments:    DeviceObject - Device object to query for this information.    BusInterface - Supplies a pointer to the retrieved information.Return Value:    NT status.--*/ {    KEVENT event;    NTSTATUS status;    PIRP irp;    IO_STATUS_BLOCK ioStatusBlock;    PIO_STACK_LOCATION irpStack;    PDEVICE_OBJECT targetObject;    Bus_KdPrint(("GetPciBusInterfaceStandard entered.\n"));    KeInitializeEvent( &event, NotificationEvent, FALSE );    targetObject = IoGetAttachedDeviceReference( DeviceObject );    irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,                                        targetObject,                                        NULL,                                        0,                                        NULL,                                        &event,                                        &ioStatusBlock );    if (irp == NULL) {        status = STATUS_INSUFFICIENT_RESOURCES;        goto End;    }    irpStack = IoGetNextIrpStackLocation( irp );    irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;    irpStack->Parameters.QueryInterface.InterfaceType =                         (LPGUID) &GUID_BUS_INTERFACE_STANDARD ;    irpStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);    irpStack->Parameters.QueryInterface.Version = 1;    irpStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterfaceStandard;    irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;    //     // Initialize the status to error in case the bus driver does not     // set it correctly.    //     irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;    status = IoCallDriver( targetObject, irp );    if (status == STATUS_PENDING) {        KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );        status = ioStatusBlock.Status;    }End:    //     // Done with reference    //     ObDereferenceObject( targetObject );    return status;}					
以下のコードでは、インターフェイスの直接呼出し関数を使用してバス データを取得する方法を示します。
    bytes = busInterfaceStandard.GetBusData(<BR/>                    busInterfaceStandard.Context,                    PCI_WHICHSPACE_CONFIG,                    Buffer                    Offset,                    Length);				
インターフェイスが不要になった場合、以下のコードを使用して、不要になったインターフェイスの参照を解除します。参照を解除した後は、インターフェイス ルーチンは呼び出さないでください。
    (busInterfaceStandard.InterfaceDereference)(                (PVOID)busInterfaceStandard.Context);				
以下のように、対象のデバイスの PDO に対して IoGetDeviceProperty 関数を使用し、バス番号、機能番号、およびデバイス番号を取得します。
    ULONG   propertyAddress, length;    USHORT  FunctionNumber; DeviceNumber;        //     // Get the BusNumber. Please read the warning to follow.    //     IoGetDeviceProperty(PhysicalDeviceObject,                        DevicePropertyBusNumber,                        sizeof(ULONG),                        (PVOID)&BusNumber,                        &length);    //     // Get the DevicePropertyAddress    //     IoGetDeviceProperty(PhysicalDeviceObject,                     DevicePropertyAddress,                     sizeof(ULONG),                     (PVOID)&propertyAddress,                     &length);    //     // For PCI, the DevicePropertyAddress has device number     // in the high word and the function number in the low word.     //     FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);    DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);				
重要 : PCI バス番号は動的で、いつでも変更できます。そのため、PCI ポートに直接アクセスするために、バス番号に依存すること、およびバス番号の情報を使用することはお勧めしません。システムが不安定になる場合があります。
関連情報
なお、この資料は英語版の翻訳であり、日本語環境での確認は行っておりません。
プロパティ

文書番号:253232 - 最終更新日: 12/05/2015 18:30:45 - リビジョン: 2.2

Microsoft Win32 Device Driver Kit for Windows 2000, Microsoft Windows XP Driver Development Kit (DDK), Microsoft Windows Server 2003 Driver Development Kit (DDK), Microsoft Windows 2000 Professional, Microsoft Windows XP Home Edition, Microsoft Windows XP Professional, Microsoft Windows Server 2003 Service Pack 1

  • kbnosurvey kbarchive kbhowto kbwdm KB253232
フィードバック