[PATCH RFC 10/15] pci: Add pci_print() and pci_type_desc()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Cc: Thomas Huth <thuth@xxxxxxxxxx>
Cc: Andrew Jones <drjones@xxxxxxxxxx>
Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxx>
---
 lib/asm-generic/pci.h |  6 +++++
 lib/pci.c             | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/pci.h             |  3 +++
 3 files changed, 76 insertions(+)

diff --git a/lib/asm-generic/pci.h b/lib/asm-generic/pci.h
index 15f23079f27e..3f2c6913f0d4 100644
--- a/lib/asm-generic/pci.h
+++ b/lib/asm-generic/pci.h
@@ -22,4 +22,10 @@ phys_addr_t pci_xlate_addr(pcidevaddr_t __unused dev, uint64_t addr)
 }
 #endif
 
+#ifndef pci_print_arch
+static inline void pci_print_arch(void)
+{
+}
+#endif
+
 #endif
diff --git a/lib/pci.c b/lib/pci.c
index 46aee60e0f90..a3c680670fe0 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -116,3 +116,70 @@ bool pci_bar_is64(pcidevaddr_t dev, int bar_num)
 	else
 		return false;
 }
+
+void pci_type_desc(int type, char *desc, int len)
+{
+	if ((type & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+		strcpy(desc, "PIO");	/* strncpy() would be better */
+	} else {
+		static char *str[] = { "32", "1M", "64" };
+		int idx = (type & PCI_BASE_ADDRESS_MEM_TYPE_MASK) >> 1;
+		int pfetch = type & PCI_BASE_ADDRESS_MEM_PREFETCH;
+		snprintf(desc, len, "MEM%s%s", str[idx], pfetch ? "/p" : "");
+	}
+}
+
+static void pci_dev_print(pcidevaddr_t dev)
+{
+	uint16_t vendor_id = pci_config_readw(dev, PCI_VENDOR_ID);
+	uint16_t device_id = pci_config_readw(dev, PCI_DEVICE_ID);
+	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 bar;
+
+	printf("dev %2d fn %d vendor_id %04x device_id %04x type %02x "
+	       "progif %02x class %02x subclass %02x\n",
+	       dev / 8, dev % 8, vendor_id, device_id, header,
+	       progif, class, subclass);
+
+	if (header != PCI_HEADER_TYPE_NORMAL)
+		return;
+
+	for (bar = 0; bar < 6; bar++) {
+		phys_addr_t start, end;
+		char desc[8];
+
+		if (!pci_bar_is_valid(dev, bar))
+			break;
+
+		start = pci_bar_addr(dev, bar);
+		end = start + pci_bar_size(dev, bar) - 1;
+
+		pci_type_desc(bar, desc, sizeof(desc));
+
+		if (pci_bar_is64(dev, bar)) {
+			printf("\tBAR#%d,%d [%-7s %" PRIx64 "-%" PRIx64 "]\n",
+			       bar, bar + 1, desc, start, end);
+			bar++;
+		} else {
+			printf("\tBAR#%d    [%-7s %02x-%02x]\n",
+			       bar, desc, (uint32_t)start, (uint32_t)end);
+		}
+	}
+}
+
+void pci_print(void)
+{
+	pcidevaddr_t dev;
+
+	pci_print_arch();
+
+	for (dev = 0; dev < 256; ++dev) {
+		if (pci_config_readw(dev, PCI_VENDOR_ID) != (uint16_t)~0 &&
+		    pci_config_readw(dev, PCI_DEVICE_ID) != (uint16_t)~0) {
+			pci_dev_print(dev);
+		}
+	}
+}
diff --git a/lib/pci.h b/lib/pci.h
index 69d2a62f1b32..36dd67e19838 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -22,6 +22,9 @@ bool pci_bar_is64(pcidevaddr_t dev, int bar_num);
 bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num);
 bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
 
+void pci_type_desc(int type, char *desc, int len);
+void pci_print(void);
+
 /*
  * pci-testdev is a driver for the pci-testdev qemu pci device. The
  * device enables testing mmio and portio exits, and measuring their
-- 
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



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux