Cc: Thomas Huth <thuth@xxxxxxxxxx> Cc: Andrew Jones <drjones@xxxxxxxxxx> Cc: Peter Xu <peterx@xxxxxxxxxx> Suggested-by: Andrew Jones <drjones@xxxxxxxxxx> Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx> Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxx> --- lib/pci.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pci.h | 3 +++ 2 files changed, 92 insertions(+) diff --git a/lib/pci.c b/lib/pci.c index 42f47d93abfd..e03c67c1a707 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -126,3 +126,92 @@ bool pci_bar_is64(pcidevaddr_t dev, int bar_num) return (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64; } + +static void pci_bar_print(pcidevaddr_t dev, int bar_num) +{ + phys_addr_t size, start, end; + uint32_t bar; + + size = pci_bar_size(dev, bar_num); + if (!size) + return; + + bar = pci_bar_get(dev, bar_num); + start = pci_bar_get_addr(dev, bar_num); + end = start + size - 1; + + if (pci_bar_is64(dev, bar_num)) { + printf("BAR#%d,%d [%" PRIx64 "-%" PRIx64 " ", + bar_num, bar_num + 1, start, end); + } else { + printf("BAR#%d [%02x-%02x ", + bar_num, (uint32_t)start, (uint32_t)end); + } + + if (bar & PCI_BASE_ADDRESS_SPACE_IO) { + printf("PIO"); + } else { + printf("MEM"); + switch (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + printf("32"); + break; + case PCI_BASE_ADDRESS_MEM_TYPE_1M: + printf("1M"); + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + printf("64"); + break; + default: + assert(0); + } + } + + if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) + printf("/p"); + + printf("]"); +} + +static void pci_dev_print_id(pcidevaddr_t dev) +{ + printf("00.%02x.%1x %04x:%04x", dev / 8, dev % 8, + pci_config_readw(dev, PCI_VENDOR_ID), + pci_config_readw(dev, PCI_DEVICE_ID)); +} + +static void pci_dev_print(pcidevaddr_t dev) +{ + uint8_t header = pci_config_readb(dev, PCI_HEADER_TYPE); + uint8_t progif = pci_config_readb(dev, PCI_CLASS_PROG); + uint8_t subclass = pci_config_readb(dev, PCI_CLASS_DEVICE); + uint8_t class = pci_config_readb(dev, PCI_CLASS_DEVICE + 1); + int i; + + pci_dev_print_id(dev); + printf(" type %02x progif %02x class %02x subclass %02x\n", + header, progif, class, subclass); + + if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL) + return; + + for (i = 0; i < 6; i++) { + if (pci_bar_size(dev, i)) { + printf("\t"); + pci_bar_print(dev, i); + printf("\n"); + } + if (pci_bar_is64(dev, i)) + i++; + } +} + +void pci_print(void) +{ + pcidevaddr_t dev; + + for (dev = 0; dev < 256; ++dev) { + if (pci_dev_exists(dev)) + pci_dev_print(dev); + } +} diff --git a/lib/pci.h b/lib/pci.h index 1462aa2f0e1a..fc0940adc299 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -15,6 +15,7 @@ enum { PCIDEVADDR_INVALID = 0xffff, }; +extern void pci_print(void); extern bool pci_dev_exists(pcidevaddr_t dev); extern pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id); @@ -57,4 +58,6 @@ struct pci_test_dev_hdr { uint8_t name[]; }; +#define PCI_HEADER_TYPE_MASK 0x7f + #endif /* PCI_H */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html