赞
踩
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 级别获取配置信息。1. | 在 PASSIVE_LEVEL 级别发送一个 IRP_MN_QUERY_INTERFACE,以便从 PCI 总线驱动程序获取直接调用接口结构 (BUS_INTERFACE_STANDARD)。将该结构存储在非分页池内存中(通常存储在 DevcieExtension 中)。 |
2. | 调用 SetBusData 和 GetBusData,以便在 DISPATCH_LEVEL 级别访问配置空间。 |
3. | 由于 PCI 总线驱动程序将在它返回之前获取接口上的引用计数,因此当不再需要该接口时,必须取消对它的引用。 |
4. | 请使用以下函数在 PASSIVE_LEVEL 级别获取 BUS_INTERFACE_STANDARD: |
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 端口。这可能会引发系统故障。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。