欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

How to use IO BAR in linux PCIe device driver

程序员文章站 2022-03-26 19:19:46
...

How to use IO BAR in linux PCIe device driver

-v0.1 2017.6.8 Sherlock init

  1. IO window parse analysis

    In an ACPI based system, we parse the IO window configured in DSDT table, as
    showed in this link: blog.csdn.net/scarecrow_byr/article/details/53966460.

    We can see in pci_acpi_root_prepare_resources:

        pci_acpi_root_prepare_resources
            --> acpi_pci_probe_root_resources
                --> acpi_pci_root_remap_iospace

in acpi_pci_root_remap_iospace, CPU address of one PCIe IO window will be
mapped to PCI_IOBASE based system IO space, like below picture:

     PCI_IOBASE            PCI_IOBASE + PCIE_IO_SIZE - 1
           |<------------->|
   --------+---------------+---------------------------   <- CPU VA in kernel
       |   |      |\      \
       |   |      | \      \                  
       v   |      |  \      \                  maps supported by MMU
           |      |   \      \       
           |      |    \      \
           |<---->|     |<---->|   <- CPU PA
       |    \      \     \      \
       |     \      \     \      \             maps supported by ATU
       v      \      \     \      \
               \      \     \      \
                \      \     \      \
                 |<---->|     |<---->|  <- PCI address

                IO window 1   IO window 2
               host bridge 1  host bridge 2

and offset between CPU VA and PCI_IOBASE will be stored in resource_entry,
which will be passed to PCI enumeration. The offset in resource_entry will be
offset(above) - PCI address. In the process of the enumeration, IO BAR will
be allocated in related IO window.

the base of IO BAR will be stored in (pci_dev -> resource[IO BAR].start), which
is the offset to PCI_IOBASE in CPU VA.

  1. How to use in PCIe device driver

    In one hardware arch, we use inb/outb, inw/outw … function to access IO
    space. In ARM64, these functions are defined in linux/include/asm-generic/io.h,
    like:

        #ifndef outb
        #define outb outb
        static inline void outb(u8 value, unsigned long addr)
        {
                writeb(value, PCI_IOBASE + addr);
        }
        #endif

So when we want to read/write IO BAR in PCIe device driver, we should:

  1. get the base of one IO BAR by: addr = pci_resource_start(dev, bar)
  2. use outb(value, addr) for an example to do port input by byte-width.