I have a Xilinx FPGA PCIe end-point on the PCI Bus. Linux picks up the device just fine and everything in lspci looks perfect.

My question is about PCI access options from user-space and what would be good/bad.

Option 1: Direct access via /sys/.../resource0

(only one I have managed to make work so far)

I can open and mmap say /sys/bus/pci/devices/XXXX:XX:XX.X/resource0 then mmap that and read/write. Just need to fix permissions first. My question is, is this a good or bad approach? It feels like this might not be the preferred approach of accessing PCI address space?

Option 2: using uio_pci_generic

I've managed to configure my FPGA so that this driver actually connects, the fact that it requires interrupts is really annoying. And it seems this gives access to nothing accept interrupts and configuration memory space? This doesn't seem very useful to me? Am I missing something?

Option 3: Write my own uio driver

This might be a reasonable option perhaps? I'm not really sure how difficult this is. One possible advantage of this is that I might get access to DMA and therefore speed things up quite a bit.

Option 4: Write a completely custom linux PCI driver

I would like to avoid this option if possible

My question is about what is the best approach and what are the down sides specifically of option 1. Or are there any other approaches I should consider?

(I'm running debian with kernel 3.14.15 rt patched)

  • how did you resolve it ? Did you use dma ?
    – ransh
    Commented Feb 6, 2018 at 17:03
  • 1
    Posted this a long time ago. In the end the only way to make PCI "fast" is with DMA and the only way to DMA is with custom kernel drivers under linux in order to get access to DMA capable memory. Also the device needs to support it, therefore I had to implement a DMA engine inside my FPGA to support this. Commented Feb 7, 2018 at 17:54

1 Answer 1


Option 1 (direct access via /sys/.../resource0)

Good for testing and nothing wrong with it functionally, although can not do anything advanced and no driver layer abstraction. I find this method icky by the way the user program interacts with the sysfs but that might be my personal opinion.

Option 2 (using uio_pci_generic)

I don't know what uio_pci_generic does, but it seems to add little functionality beyond allowing your user program to access pci legacy interrupts. Which is bad cause MSI is preferred anyhow.

Option 3 (custom uio driver)

I didn't try this but I suspect it is a bit of a waste of time compared to option 4

Option 4 (custom kernel driver)

This is really the best solution and only way to properly do things. You need a driver to be able to handle things like DMA and MSI properly and be able to provide any amount of abstraction via a character device. There are however ample documentation on how to write drivers for PCI cards online and the kernel provides a lot of support for managing things.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .