It seems I looked everywhere, but it still unclear to me:
How to read PCI Configuration Address Space of exact device, which I know only by location: bus, slot and function?
I’ve got old driver code, that has special IOCTL code to read Configuration Address Space. There are implemented 2 methods to do so:
- Using HalGetBusDataByOffset
PCI_SLOT_NUMBER slot = { 0 };
slot.u.bits.DeviceNumber = dwSlot;
slot.u.bits.FunctionNumber = dwFunction;
data_len_ret = HalGetBusDataByOffset( PCIConfiguration,
dwBus, slot.u.AsULONG,
ulData, dwOffset, sizeof(ulData) );
It turned out that this way is not working anymore https://msdn.microsoft.com/en-us/library/windows/hardware/ff546644(v=vs.85).aspx . Or may be it never worked at all.
- Using direct access to ports 0xCF8 and 0xCFC
ULONG config_address = (1ul << 31) |
(bus << 16) | (slot << 11) | (function << 8) | offset ;
WRITE_PORT_ULONG( (PULONG )0xCF8, config_address );
ulData = READ_PORT_ULONG( (PULONG )0xCFC );
This way works, but it is not recommended. Because there is no synchronization. And having WDF its probably bad idea to touch the meat.
The proper ways to access Configuration Address Space in WDF are 2 following:
(According to https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/accessing-pci-device-configuration-space )
A. Send IRP_MN_READ_CONFIG package to exact device https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mn-read-config
B. Get BUS_INTERFACE_STANDARD struct and call method GetBusData from there.
I would like to use B method for many reasons. But here I completely lost concept.
Method BUS_INTERFACE_STANDARD::GetBusData has following signature:
ULONG GET_SET_DEVICE_DATA (
Inout_opt PVOID Context,
In ULONG DataType,
Inout_updates_bytes(Length) PVOID Buffer,
In ULONG Offset,
In_range(!=,0) ULONG Length
);
There is no way to specify Bus.Slot.Function.
So I assume, that information about bus location is stored in Context.
In this case, I had to request individual BUS_INTERFACE_STANDARD interface from the device instance located there.
But how I can do it? How can I get WDFDEVICE knowing only triplet Bus.Slot.Function ? I searched everywhere, but there is no API to do so.
Or maybe I should get this interface from the PCI Bus device itself. Its additional challenge, because the device has no strict name, and can be multiple. But moreover even if I get this interface somehow (maybe by developing/using yet another pci filter), how I can apply location triplet at GetBusData?
Also I hoped, that interface PCI_BUS_INTERFACE_STANDARD and method ReadConfig can save me. But it’s look like nobody provide it.
Like specified at http://www.hollistech.com/Resources/Misc%20articles/getbusdata.htm
“You might be tempted to use GUID_PCI_BUS_INTERFACE_STANDARD, but this will not work, even if you know for a fact that the pci bus driver is beneath you on the stack.”
Please, explain me how I can read Configuration Space by only Bus.Slot.Function using modern WDF.