主要是看设备这些数据存放在哪里
设备管理器,查看设备属性,下图是我自己电脑上任意选的一个
可以看到 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
...
}