Reputation: 11
We have a prototype PCIe endpoint that we control via out-of-band, external connections (ie a USB cable to the board itself, letting us load the FPGA, perform register access, load and debug firmware, etc). We are looking into transitioning to performing at least some of these actions in-band, over the PCIe connection itself.
However, my knowledge in this area (PCIe) is rather limited. So before diving headlong down one path or another, I want to make sure we're not taking a deliberately difficult route or missing something obvious.
In the most basic sense, it should be sufficient to be able to pass 32-bit values back and forth at will with the endpoint's firmware. In other words, if we wanted to execute a "read", we could send an "address" value down to the device, and retrieve a "data" value. No DMA, no fancy stuff - just peek and poke transactions to the firmware. That's it.
I haven't found any generic method to accomplish this for PCIe - by contrast, if I wanted to (say) do something similar to a SCSI device, I could do things in the form of a CDB. The only vaguely similar method I can find would be to access the PCIe endpoint's configuration space; write a "value" to a certain known location, and poll for completion/data. But that capability seems to be restricted to drivers. This significantly complicating things, especially with the more restrictive hoops required in 64-bit versions (to say nothing of the inherent complexity that writing your very first driver entails).
So, two real questions.
This is intended for a Windows-based environment. It's probably safe to restrict to Vista/7 and higher (most of the test machines are W7 anyway), though if possible it should be doable on both 32-bit and 64-bit. Linux compatibility is a non-issue.
Thank you in advance.
Upvotes: 1
Views: 3523
Reputation: 2636
You can use uio_pci_generic driver in the kernel to expose the device to user-space and then you can use the device directly from user-space. It requires minimal configuration in the kernel to make the device attach to the uio_pci_generic driver and then not too hard interface to map the PCIe BAR to the user-space memory and from there on it will be a simple memory read/write.
I am using NVMe and network devices through SPDK and DPDK and you can find in these examples for how to utilize uio_pci_generic. There may also be other examples for simpler devices that you can find.
Upvotes: 1