diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2011-11-28 10:11:10 +0100 |
---|---|---|
committer | Daniel Hellstrom <daniel@gaisler.com> | 2015-04-17 01:10:15 +0200 |
commit | a31845f7f9b4770cf9ddd8b6820641d2f4f4c1da (patch) | |
tree | 0d7f215ec45d7c4cf6f1293af72ece2fbde1ddc3 /cpukit/libpci/pci_print.c | |
parent | leon3,ngmp: simplify cpucounter initialization (diff) | |
download | rtems-a31845f7f9b4770cf9ddd8b6820641d2f4f4c1da.tar.bz2 |
LIBPCI: added PCI layer to cpukit/libpci
Diffstat (limited to 'cpukit/libpci/pci_print.c')
-rw-r--r-- | cpukit/libpci/pci_print.c | 190 |
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"); +} |