获取设备的 bus/device/function number


主要是看设备这些数据存放在哪里

设备管理器,查看设备属性,下图是我自己电脑上任意选的一个

可以看到 bus = 21, device = 0, function = 0 ,驱动为 ohci1394.sys

先说结果,device 和 function number存放在 DeviceExtension 里, bus number 存放在 _devobj_extension -> _device_node

lkd> !drvobj ohci1394
Driver object (896ba1d8) is for:
 \Driver\ohci1394
Driver Extension List: (id , addr)

Device Object list:
8a0e6030  896a4028                                                                        // 两个device Object
                                                           
lkd> !devstack 8a0e6030                                                // 第一个 Device Object
  !DevObj   !DrvObj            !DevExt   ObjectName
  896669d0  \Driver\NIC1394    89666a88  {228944B5-D441-460B-80EE-BD0D4A3BB923}
> 8a0e6030  \Driver\ohci1394   8a0e60e8  0000008d
!DevNode 8a0e6648 :
  DeviceInst is "V1394\NIC1394\2a1df1e561b03"
  ServiceName is "NIC1394"

lkd> !devstack 896a4028                                                // 第二个 Device Object
  !DevObj   !DrvObj            !DevExt   ObjectName
> 896a4028  \Driver\ohci1394   896a40e0  1394BUS0
  8a139b18  \Driver\PCI        8a139bd0  NTPNP_PCI0023                 // 挂在PCI上, _device_object = 0x8a139b18
!DevNode 8a1394a8 :
  DeviceInst is "PCI\VEN_1180&DEV_0832&SUBSYS_20C717AA&REV_04\4&1549efe7&0&01F0"
  ServiceName is "ohci1394"
//
// 下面通过 _device_object -> DeviceExtension  寻找 device number 和 functio number
//
lkd> dt _device_object 8a139b18
nt!_DEVICE_OBJECT
   +0x000 Type             : 0n3
   ...
   +0x028 DeviceExtension  : 0x8a139bd0 Void                            // device number , function number 在这里面
                                                                        // 这是一个可变结构,不同的deviceobject他的 extension 结构不一样
                                                                        // 在这里是个 _PCI_PDO_EXTENSION 结构
   +0x02c DeviceType       : 0x22
   ...
   +0x0ae Spare1           : 1
   +0x0b0 DeviceObjectExtension : 0x8a139c98 _DEVOBJ_EXTENSION

   +0x0b4 Reserved         : (null) 
//************************************************
//      DeviceExtension   = 0x8a139bd0 
//      _DEVOBJ_EXTENSION = 0x8a139c98 
//************************************************

lkd> dt _pci_pdo_extension
nt!_PCI_PDO_EXTENSION
   +0x000 Next             : Ptr32 _PCI_PDO_EXTENSION
   ...
   +0x020 Slot             : _PCI_SLOT_NUMBER                           // 偏移 +0x20  为一个 _PCI_SLOT_NUMBER 结构
lkd> dd 0x8a139bd0  + 0x20                                              // 
8a139bf0  00000020 8a139b18 8a1390d8 e10230d8                           //   typedef struct _PCI_SLOT_NUMBER {
                                                                        //    ULONG   DeviceNumber:5;   
                                                                        //    ULONG   FunctionNumber:3;
                                                                        //    ULONG   Reserved:24;
                                                                        //   } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
                                                                        // 可以看到值为00000020,二进制的0000 0010 0000
                                                                        // 低5为为device number = 0,随后3位为function number = 1
// 
// 下面寻找bus nunmber, _devobj_extension -> _device_node 里面
//
lkd> dt _devobj_extension 0x8a139c98 
nt!_DEVOBJ_EXTENSION
   +0x000 Type             : 0n13
   ...
   +0x014 DeviceNode       : 0x8a1394a8 Void                             // device_node = 0x8a1394a8 
   ...
   +0x028 Vpb              : (null) 
lkd> dt _device_node 8a1394a8
nt!_DEVICE_NODE
   +0x000 Sibling          : (null) 
   ...
   +0x08c ResourceList     : 0xe1002700 _CM_RESOURCE_LIST              // 这里也是有价值的地方,resource 里面包含了设备的io port,memeory,dma等信息 
   +0x090 ResourceListTranslated : 0xe1011cd8 _CM_RESOURCE_LIST        // 关于resource ,https://blog.csdn.net/xiangbaohui/article/details/105134068
   +0x094 InstancePath     : _UNICODE_STRING "PCI\VEN_1180&DEV_0832&SUBSYS_20C717AA&REV_04\4&1549efe7&0&01F0"
   +0x09c ServiceName      : _UNICODE_STRING "ohci1394"
   +0x0a4 DuplicatePDO     : (null) 
   +0x0a8 ResourceRequirements : 0xe14ff1a0 _IO_RESOURCE_REQUIREMENTS_LIST
   +0x0ac InterfaceType    : 0xffffffff (No matching name)
   +0x0b0 BusNumber        : 0xfffffff0
   +0x0b4 ChildInterfaceType : 5 ( PCIBus )
   +0x0b8 ChildBusNumber   : 0x15                                        // bus number= 0x15, 转化为10进制 = 21  
   +0x0bc ChildBusTypeIndex : 0
   ...
   +0x10c LegacyBusListEntry : _LIST_ENTRY [ 0x8a1395b4 - 0x8a1395b4 ]

写程序去获得bus/device/funtion number, 都是通过调用IoGetDeviceProperty函数

  • 参数DevicePropertyBusNumber获得bus number
  • 参数DevicePropertyAddress 获得device number 和 function number
case DevicePropertyBusNumber
      if ((deviceNode->ChildBusNumber & 0x80000000) != 0x80000000) {
            *ResultLength = sizeof(ULONG);
            if(*ResultLength <= BufferLength) {
                *(PULONG)PropertyBuffer = deviceNode->ChildBusNumber;     // _devobj_extension -> _device_node -> ChildBusNumber
                
            ...
      }
还有一种是

 (PPCI_FDO_EXTENSION) ( (PPCI_PDO_EXTENSION)(_device_object->DeviceExtension) ->ParentFdoExtension ) -> BaseBus

case DevicePropertyAddress
      status = PipQueryDeviceCapabilities(deviceNode, &capabilities);      //  调用 PipQueryDeviceCapabilities
      if (NT_SUCCESS(status) && (capabilities.Address != 0xFFFFFFFF)) {
            *ResultLength = sizeof(ULONG);
            if(*ResultLength <= BufferLength) {
                *(PULONG)PropertyBuffer = capabilities.Address;            // Address 包含了device number 和 function number 

            ...
      }
-----------
PipQueryDeviceCapabilities(...)
{
      irpStack.MajorFunction = IRP_MJ_PNP;
      irpStack.MinorFunction = IRP_MN_QUERY_CAPABILITIES;
      irpStack.Parameters.DeviceCapabilities.Capabilities = Capabilities;

      status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &irpStack, NULL);      // 会把irp发到 PciDispatchIrp 进行处理                                                              
}
---
PciDispatchIrp(...)
{
      deviceExtension = ((PPCI_COMMON_EXTENSION)(DeviceObject->DeviceExtension));      
      dispatchTable = deviceExtension->IrpDispatchTable;                                   // PPCI_MJ_DISPATCH_TABLE 结构
      switch(irpSp->MajorFunction) {
        case IRP_MJ_PNP:

            minorTable    = dispatchTable->PnpIrpDispatchTable;
            minorTableMax = dispatchTable->PnpIrpMaximumMinorFunction;
            break;
      ...
      irpDispatchTableEntry = (irpSp->MinorFunction <= minorTableMax) ?                    // PPCI_MN_DISPATCH_TABLE 结构
            minorTable+irpSp->MinorFunction : minorTable+minorTableMax+1;                  // MinorFunction = IRP_MN_QUERY_CAPABILITIES

      irpDispatchStyle   = irpDispatchTableEntry->DispatchStyle;
      irpDispatchHandler = irpDispatchTableEntry->DispatchFunction;                        // PciPdoIrpQueryCapabilities
      
      status = (irpDispatchHandler)(Irp, irpSp, deviceExtension);                          // 调用 PciPdoIrpQueryCapabilities
}    
---
PciPdoIrpQueryCapabilities(...)
{
      return PciQueryCapabilities(...);
}
---
PciQueryCapabilities(...)
{
      ...
      Capabilities->Address =
        PdoExtension->Slot.u.bits.DeviceNumber << 16 |                                      // 可以看到 IoGetDeviceProperty (DevicePropertyAddress)
        PdoExtension->Slot.u.bits.FunctionNumber;                                           // 访问的就是device->deviceextension->Slot
      ...
}
以上都是基于Xp系统


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM