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

Windows XP 支援已結束

Microsoft 於 2014 年 4 月 8 日結束對 Windows XP 的支援。此變更已影響您的軟體更新和安全性選項。 瞭解這對您的意義為何且如何持續受保護。

Windows Server 2003 的支援已於 2015 年 7 月 14 日結束

Microsoft 已於 2015 年 7 月 14 日結束對 Windows Server 2003 的支援。此變更已影響您的軟體更新和安全性選項。 瞭解這對您的意義為何且如何持續受保護。

重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。

按一下這裡查看此文章的英文版本: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 要求。

下列程式碼範例會示範如何取得組態資訊:
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;}				
因為您僅可以傳送封 [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:
    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:50 - 修訂: 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

  • kbnosurvey kbarchive kbmt kbhowto kbwdm KB253232 KbMtzh
意見反應