如何取得 PCI 裝置的組態和位置的資訊

文章翻譯 文章翻譯
文章編號: 253232 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

結論

本文將告訴您如何可以取得組態和位置資訊 (例如 BusNumber、 DeviceNumber 及函數的數字) 是目標裝置的驅動程式的一部分的驅動程式中的周邊元件連接 (PCI) 裝置的堆疊做為函式的任一個,或篩選驅動程式。

其他相關資訊

在 Windows NT 4.0 驅動程式會掃描匯流排並呼叫 HalGetBusData 和 HalGetBusDataByOffset API 取得這項資訊。Windows 2000 和更新版本的 Windows 作業系統,硬體匯流排是由其各自的匯流排驅動程式,而不是 HAL 所控制。因此,所有哈 API,用來提供匯流排相關的資訊都是在 Windows 2000 和更新版本的 Windows 作業系統中已過時。

Windows 2000 和更新版本的 Windows 作業系統,驅動程式並不需要查詢裝置尋找資源。驅動程式從隨插即用 (PnP) 專案經理在其 IRP_MN_START_DEVICE 要求中取得資源。通常,記載的驅動程式就不需要任何這項資訊才能正常運作。如果基於某些原因驅動程式會需要此資訊,程式碼範例,請依照下列示範如何取得資源。驅動程式應該是裝置的裝置的驅動程式堆疊的一部份,因為它需要基礎的實體裝置物件 (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;

}
				
因為您僅可以傳送封 [PnP I/O 要求包 (IRP) 在 PASSIVE_LEVEL,您無法使用上述函式來取得組態資訊在 DISPATCH_LEVEL。

您可以執行下列步驟來存取設定分享空間在 DISPATCH_LEVEL:
  1. 傳送一個 IRP_MN_QUERY_INTERFACE PASSIVE_LEVEL PCI 匯流排驅動程式從取得直接呼叫介面結構 (BUS_INTERFACE_STANDARD)。儲存這 (通常是在 DevcieExtension) 的未分頁集區記憶體。
  2. 呼叫 SetBusData 和 GetBusData 存取組態空間在 DISPATCH_LEVEL。
  3. PCI 匯流排驅動程式需要參考計數介面上它傳回之前因此不再需要時,您必須取消參考介面。
  4. 使用下列函數來取得 [BUS_INTERFACE_STANDARD 位於 PASSIVE_LEVEL:
    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年9月8日 - 版次: 2.1
這篇文章中的資訊適用於:
  • Microsoft Win32 Device Driver Kit for Windows 2000
  • Microsoft Windows XP Driver Development Kit
  • Microsoft Windows Server 2003 Driver Development Kit (DDK)
  • Microsoft Windows 2000 Professional Edition
  • Microsoft Windows XP Home Edition (家用版)
  • Microsoft Windows XP Professional
  • Microsoft Windows Server 2003 Service Pack 1
關鍵字:?
kbmt kbhowto kbwdm KB253232 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:253232
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

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