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

文書翻訳 文書翻訳
文書番号: 253232 - 対象製品
この記事は、以前は次の 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 要求を送信するように要求するため、デバイスのドライバ スタックの一部である必要があります。

以下のサンプル コードでは、構成情報の取得方法を示します。
NTSTATUS
ReadWriteConfigSpace(
    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 を取得します。
    NTSTATUS
    GetPCIBusInterfaceStandard(
        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 - 最終更新日: 2005年12月1日 - リビジョン: 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
キーワード:?
kbhowto kbwdm KB253232
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com