Win7 x64 - Reading PCI Configuration Space okay, extended space reads all 1

Hello All,

I’m working on a WDM device driver (based off the ioctl example in the Windows DDK) which can read and write configuration space of devices on the PCI bus. Why would I need to do this, you might ask? The company I work for produces a LiveInsertion bus extender, which allows users to power on and power off PCIe devices, allowing for quick testing without needing to power cycle the whole machine. In order to do this, we need a piece of software that can read and then write the configuration space of any device on the PCI bus. I’m aware that this is sort of risky, and won’t work on all systems etc etc, but the ability has been invaluable to some customers, and I need to support it.

Anyway, on to the question. The function I’m using to read and or write the configuration space is here (it is the first function, ReadWriteConfigSpace):
http://support.microsoft.com/default.aspx?ID=KB;EN-US;Q253232&

Using this function, I’m able to read and write the 256-byte configuration space of any device on the PCI bus. The problem comes as soon as I want to read or write anything past 256 bytes. If I try and read, for example, 257 bytes from a PCI device, the read predictably fails (i.e. the return of IoCallDriver is not successful). However, if I try and read 257 bytes of a PCIe device, the read “succeeds”- the return of IoCallDriver evaluates to TRUE with NT_SUCCESS(return). However, the data returned by the read is incorrect- the entire buffer is all 1s.

Anybody have any idea what I’m doing wrong? I’m new at writing Windows device drivers, and admittedly what I’m doing is sort of a hack, but I’m getting the feeling that I might be missing some key bit of information. Its not the end of the world if I’m unable to get extended space to work, but I’d like that functionality.

Thanks in advance for your help,
Nate

The PCIe extended region is gathered from a series of pointers expressed in the base config region, not simply from offset (255 + x) … you get the pointer, dereference and cast that area as a structure, repeat down the chain. I’d read the PCI spec on extended regions, do some googling, or check out the WinOF source base to see how it’s done …

As an aside, you’re going to be going down a deep, dark, sad path if you’re trying to fiddle with PCI regions of other cards due to a) needing to handle all of the bridges in the way, b) dealing with PCI and NUMA rebalancing happening any 'ole time the OS feels like it behind your back and c) the synchronization issues of other driver(s) and PCI.SYS fiddling with those same config regions you’re fiddling with – and some devices don’t take kindly to that. If your product is a true bridge solution (like the Magma products) then you’re OK, if you’re trying to do this entirely from software then inserting yourself as a filter driver just between the card and PCI.SYS is a good approach (look at the toaster dynamic bus driver for a start) …

Cheers!

IIRC, When an invalid address is read the bus master will abort the attempt and return -1 (i.e. all bits set to 1).

Larry C

From the MSDN:

"If a device does not have an extended configuration space or the platform does not define a path for an extended configuration space on a device, the read requests will return 0xFFFF and the write requests will have no effect. "

Larry C

Craig- Thanks for the tip about the extended space pointers. I’m looking at the spec now, but a little googling turned up nothing.

As for your aside, our product is a bit different the the Magma solution. The “extender” means that the UUT is extended away from the motherboard so it can be more easily accessed under power. It only supports one PCIe device. The board itself is pretty dumb, and it doesn’t work for every application.

Larry- Considering what Craig said, the system returning -1 in the memory buffer makes sense. I’m trying to read the extended space simply by using an offset, which would result in an invalid address.

While I’m at it, anyone know of any good resources for extracting the extended space pointers from the non-extended space?

Thanks again for the help.