IO window parse analysis
   In an ACPI based system, we parse the IO window configured in DSDT table, as
   showed in this link.
We can see in pci_acpi_root_prepare_resources:
1  | pci_acpi_root_prepare_resources  | 
   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:
1  | PCI_IOBASE PCI_IOBASE + PCIE_IO_SIZE - 1  | 
   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.
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: 
1  | #ifndef outb  | 
So when we want to read/write IO BAR in PCIe device driver, we should:
- get the base of one IO BAR by: addr = pci_resource_start(dev, bar)
 - use outb(value, addr) for an example to do port input by byte-width.