summaryrefslogtreecommitdiffstats
path: root/cpukit/libpci/pci_print.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libpci/pci_print.c')
-rw-r--r--cpukit/libpci/pci_print.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/cpukit/libpci/pci_print.c b/cpukit/libpci/pci_print.c
new file mode 100644
index 0000000000..9c40f1e437
--- /dev/null
+++ b/cpukit/libpci/pci_print.c
@@ -0,0 +1,190 @@
+/* PCI Print Current Configuration To Terminal
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdio.h>
+#include <pci.h>
+#include <pci/access.h>
+
+/* PCI Access Library shortcuts */
+#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
+#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
+#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
+#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
+#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
+#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
+
+void pci_print_dev(pci_dev_t dev)
+{
+ int maxbars, pos, romadrs;
+ uint32_t tmp, tmp2, id;
+ uint16_t irq;
+ uint8_t irq_pin;
+ char *str, *str2;
+ uint32_t base, limit;
+
+ maxbars = 6;
+ romadrs = 0x30;
+ str = "";
+ PCI_CFG_R32(dev, PCI_CLASS_REVISION, &tmp);
+ tmp >>= 16;
+ if (tmp == PCI_CLASS_BRIDGE_PCI) {
+ maxbars = 2;
+ romadrs = 0x38;
+ str = "(BRIDGE)";
+ }
+
+ PCI_CFG_R32(dev, PCI_VENDOR_ID, &id);
+ printf("\nBus %x Slot %x function: %x [0x%x] %s\n",
+ PCI_DEV_EXPAND(dev), dev, str);
+ printf("\tVendor id: 0x%lx, device id: 0x%lx\n",
+ id & 0xffff, id >> 16);
+ if (maxbars == 2) {
+ PCI_CFG_R32(dev, PCI_PRIMARY_BUS, &tmp);
+ printf("\tPrimary: %lx Secondary: %lx Subordinate: %lx\n",
+ tmp & 0xff, (tmp >> 8) & 0xff, (tmp >> 16) & 0xff);
+ }
+
+ PCI_CFG_R16(dev, PCI_INTERRUPT_LINE, &irq);
+ irq_pin = irq >> 8;
+ if ((irq_pin > 0) && (irq_pin < 5))
+ printf("\tIRQ INT%c# LINE: %d\n",
+ (irq_pin - 1) + 'A', (irq & 0xff));
+
+ /* Print standard BARs */
+ for (pos = 0; pos < maxbars; pos++) {
+ PCI_CFG_R32(dev, PCI_BASE_ADDRESS_0 + pos*4, &tmp);
+ PCI_CFG_W32(dev, PCI_BASE_ADDRESS_0 + pos*4, 0xffffffff);
+ PCI_CFG_R32(dev, PCI_BASE_ADDRESS_0 + pos*4, &tmp2);
+ PCI_CFG_W32(dev, PCI_BASE_ADDRESS_0 + pos*4, tmp);
+
+ if (tmp2 != 0 && tmp2 != 0xffffffff && ((tmp2 & 0x1) ||
+ ((tmp2 & 0x6) == 0))) {
+ uint32_t mask = ~0xf;
+ if ((tmp2 & 0x1) == 1) {
+ /* I/O Bar */
+ mask = ~3;
+ tmp2 = tmp2 | 0xffffff00;
+ }
+ tmp2 &= mask;
+ tmp2 = ~tmp2+1; /* Size of BAR */
+ if (tmp2 < 0x1000) {
+ str = "B";
+ } else if (tmp2 < 0x100000) {
+ str = "kB";
+ tmp2 = tmp2 / 1024;
+ } else {
+ str = "MB";
+ tmp2 = tmp2 / (1024*1024);
+ }
+ printf("\tBAR %d: %lx [%lu%s]\n", pos, tmp, tmp2, str);
+ }
+ }
+
+ /* Print ROM BARs */
+ PCI_CFG_R32(dev, romadrs, &tmp);
+ PCI_CFG_W32(dev, romadrs, 0xffffffff);
+ PCI_CFG_R32(dev, romadrs, &tmp2);
+ PCI_CFG_W32(dev, romadrs, tmp);
+ if (tmp2 & 1) {
+ /* ROM BAR available */
+ tmp2 &= PCI_ROM_ADDRESS_MASK;
+ tmp2 = (~tmp2 + 1); /* Size of BAR */
+ if (tmp2 < 0x1000) {
+ str = "B";
+ } else if (tmp2 < 0x100000) {
+ str = "kB";
+ tmp2 = tmp2 / 1024;
+ } else {
+ str = "MB";
+ tmp2 = tmp2 / (1024*1024);
+ }
+ str2 = tmp & 1 ? "ENABLED" : "DISABLED";
+ printf("\tROM: %08lx [%lu%s] (%s)\n",
+ tmp, tmp2, str, str2);
+ }
+
+ /* Print Bridge addresses */
+ if (maxbars == 2) {
+ tmp = 0;
+ PCI_CFG_R32(dev, 0x1C, &tmp);
+ if (tmp != 0) {
+ base = (tmp & 0x00f0) << 8;
+ limit = (tmp & 0xf000) | 0xfff;
+ PCI_CFG_R32(dev, 0x30, &tmp);
+ base |= (tmp & 0xffff) << 16;
+ limit |= (tmp & 0xffff0000);
+ str = "ENABLED";
+ if (limit < base)
+ str = "DISABLED";
+ printf("\tI/O: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n",
+ base, limit, str);
+ }
+
+ PCI_CFG_R32(dev, 0x20, &tmp);
+ if (tmp != 0) {
+ base = (tmp & 0xfff0) << 16;
+ limit = (tmp & 0xfff00000) | 0xfffff;
+ str = "ENABLED";
+ if (limit < base)
+ str = "DISABLED";
+ printf("\tMEMIO: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n",
+ base, limit, str);
+ }
+
+ PCI_CFG_R32(dev, 0x24, &tmp);
+ if (tmp != 0) {
+ base = (tmp & 0xfff0) << 16;
+ limit = (tmp & 0xfff00000) | 0xfffff;
+ str = "ENABLED";
+ if (limit < base)
+ str = "DISABLED";
+ printf("\tMEM: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n",
+ base, limit, str);
+ }
+ }
+ printf("\n");
+}
+
+void pci_print_device(int bus, int slot, int function)
+{
+ pci_print_dev(PCI_DEV(bus, slot, function));
+}
+
+void pci_print(void)
+{
+ int fail, bus, slot, func;
+ pci_dev_t dev;
+ uint8_t header;
+ uint32_t id;
+
+ printf("\nPCI devices found and configured:\n");
+ for (bus = 0; bus < pci_bus_count(); bus++) {
+ for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
+ for (func=0; func < PCI_MAX_FUNCTIONS; func++) {
+
+ dev = PCI_DEV(bus, slot, func);
+ fail = PCI_CFG_R32(dev, PCI_VENDOR_ID, &id);
+
+ if (!fail && id != PCI_INVALID_VENDORDEVICEID && id != 0) {
+ pci_print_dev(dev);
+
+ /* Stop if not a multi-function device */
+ if (func == 0) {
+ PCI_CFG_R8(dev, PCI_HEADER_TYPE, &header);
+ if ((header & PCI_MULTI_FUNCTION) == 0)
+ break;
+ }
+ } else if (func == 0)
+ break;
+ }
+ }
+ }
+ printf("\n");
+}