[a31845f7] | 1 | /* PCI Print Current Configuration To Terminal |
---|
| 2 | * |
---|
[71e8a5c] | 3 | * COPYRIGHT (c) 2010 Cobham Gaisler AB. |
---|
[a31845f7] | 4 | * |
---|
| 5 | * The license and distribution terms for this file may be |
---|
| 6 | * found in the file LICENSE in this distribution or at |
---|
| 7 | * http://www.rtems.com/license/LICENSE. |
---|
| 8 | */ |
---|
| 9 | |
---|
| 10 | #include <stdio.h> |
---|
| 11 | #include <pci.h> |
---|
| 12 | #include <pci/access.h> |
---|
| 13 | |
---|
| 14 | /* PCI Access Library shortcuts */ |
---|
| 15 | #define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args) |
---|
| 16 | #define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args) |
---|
| 17 | #define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args) |
---|
| 18 | #define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args) |
---|
| 19 | #define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args) |
---|
| 20 | #define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args) |
---|
| 21 | |
---|
| 22 | void pci_print_dev(pci_dev_t dev) |
---|
| 23 | { |
---|
| 24 | int maxbars, pos, romadrs; |
---|
| 25 | uint32_t tmp, tmp2, id; |
---|
| 26 | uint16_t irq; |
---|
| 27 | uint8_t irq_pin; |
---|
| 28 | char *str, *str2; |
---|
| 29 | uint32_t base, limit; |
---|
| 30 | |
---|
| 31 | maxbars = 6; |
---|
| 32 | romadrs = 0x30; |
---|
| 33 | str = ""; |
---|
| 34 | PCI_CFG_R32(dev, PCI_CLASS_REVISION, &tmp); |
---|
| 35 | tmp >>= 16; |
---|
| 36 | if (tmp == PCI_CLASS_BRIDGE_PCI) { |
---|
| 37 | maxbars = 2; |
---|
| 38 | romadrs = 0x38; |
---|
| 39 | str = "(BRIDGE)"; |
---|
| 40 | } |
---|
| 41 | |
---|
| 42 | PCI_CFG_R32(dev, PCI_VENDOR_ID, &id); |
---|
| 43 | printf("\nBus %x Slot %x function: %x [0x%x] %s\n", |
---|
| 44 | PCI_DEV_EXPAND(dev), dev, str); |
---|
| 45 | printf("\tVendor id: 0x%lx, device id: 0x%lx\n", |
---|
| 46 | id & 0xffff, id >> 16); |
---|
| 47 | if (maxbars == 2) { |
---|
| 48 | PCI_CFG_R32(dev, PCI_PRIMARY_BUS, &tmp); |
---|
| 49 | printf("\tPrimary: %lx Secondary: %lx Subordinate: %lx\n", |
---|
| 50 | tmp & 0xff, (tmp >> 8) & 0xff, (tmp >> 16) & 0xff); |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | PCI_CFG_R16(dev, PCI_INTERRUPT_LINE, &irq); |
---|
| 54 | irq_pin = irq >> 8; |
---|
| 55 | if ((irq_pin > 0) && (irq_pin < 5)) |
---|
| 56 | printf("\tIRQ INT%c# LINE: %d\n", |
---|
| 57 | (irq_pin - 1) + 'A', (irq & 0xff)); |
---|
| 58 | |
---|
| 59 | /* Print standard BARs */ |
---|
| 60 | for (pos = 0; pos < maxbars; pos++) { |
---|
| 61 | PCI_CFG_R32(dev, PCI_BASE_ADDRESS_0 + pos*4, &tmp); |
---|
| 62 | PCI_CFG_W32(dev, PCI_BASE_ADDRESS_0 + pos*4, 0xffffffff); |
---|
| 63 | PCI_CFG_R32(dev, PCI_BASE_ADDRESS_0 + pos*4, &tmp2); |
---|
| 64 | PCI_CFG_W32(dev, PCI_BASE_ADDRESS_0 + pos*4, tmp); |
---|
| 65 | |
---|
| 66 | if (tmp2 != 0 && tmp2 != 0xffffffff && ((tmp2 & 0x1) || |
---|
| 67 | ((tmp2 & 0x6) == 0))) { |
---|
| 68 | uint32_t mask = ~0xf; |
---|
| 69 | if ((tmp2 & 0x1) == 1) { |
---|
| 70 | /* I/O Bar */ |
---|
| 71 | mask = ~3; |
---|
| 72 | tmp2 = tmp2 | 0xffffff00; |
---|
| 73 | } |
---|
| 74 | tmp2 &= mask; |
---|
| 75 | tmp2 = ~tmp2+1; /* Size of BAR */ |
---|
| 76 | if (tmp2 < 0x1000) { |
---|
| 77 | str = "B"; |
---|
| 78 | } else if (tmp2 < 0x100000) { |
---|
| 79 | str = "kB"; |
---|
| 80 | tmp2 = tmp2 / 1024; |
---|
| 81 | } else { |
---|
| 82 | str = "MB"; |
---|
| 83 | tmp2 = tmp2 / (1024*1024); |
---|
| 84 | } |
---|
| 85 | printf("\tBAR %d: %lx [%lu%s]\n", pos, tmp, tmp2, str); |
---|
| 86 | } |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | /* Print ROM BARs */ |
---|
| 90 | PCI_CFG_R32(dev, romadrs, &tmp); |
---|
| 91 | PCI_CFG_W32(dev, romadrs, 0xffffffff); |
---|
| 92 | PCI_CFG_R32(dev, romadrs, &tmp2); |
---|
| 93 | PCI_CFG_W32(dev, romadrs, tmp); |
---|
| 94 | if (tmp2 & 1) { |
---|
| 95 | /* ROM BAR available */ |
---|
| 96 | tmp2 &= PCI_ROM_ADDRESS_MASK; |
---|
| 97 | tmp2 = (~tmp2 + 1); /* Size of BAR */ |
---|
| 98 | if (tmp2 < 0x1000) { |
---|
| 99 | str = "B"; |
---|
| 100 | } else if (tmp2 < 0x100000) { |
---|
| 101 | str = "kB"; |
---|
| 102 | tmp2 = tmp2 / 1024; |
---|
| 103 | } else { |
---|
| 104 | str = "MB"; |
---|
| 105 | tmp2 = tmp2 / (1024*1024); |
---|
| 106 | } |
---|
| 107 | str2 = tmp & 1 ? "ENABLED" : "DISABLED"; |
---|
| 108 | printf("\tROM: %08lx [%lu%s] (%s)\n", |
---|
| 109 | tmp, tmp2, str, str2); |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | /* Print Bridge addresses */ |
---|
| 113 | if (maxbars == 2) { |
---|
| 114 | tmp = 0; |
---|
| 115 | PCI_CFG_R32(dev, 0x1C, &tmp); |
---|
| 116 | if (tmp != 0) { |
---|
| 117 | base = (tmp & 0x00f0) << 8; |
---|
| 118 | limit = (tmp & 0xf000) | 0xfff; |
---|
| 119 | PCI_CFG_R32(dev, 0x30, &tmp); |
---|
| 120 | base |= (tmp & 0xffff) << 16; |
---|
| 121 | limit |= (tmp & 0xffff0000); |
---|
| 122 | str = "ENABLED"; |
---|
| 123 | if (limit < base) |
---|
| 124 | str = "DISABLED"; |
---|
| 125 | printf("\tI/O: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n", |
---|
| 126 | base, limit, str); |
---|
| 127 | } |
---|
| 128 | |
---|
| 129 | PCI_CFG_R32(dev, 0x20, &tmp); |
---|
| 130 | if (tmp != 0) { |
---|
| 131 | base = (tmp & 0xfff0) << 16; |
---|
| 132 | limit = (tmp & 0xfff00000) | 0xfffff; |
---|
| 133 | str = "ENABLED"; |
---|
| 134 | if (limit < base) |
---|
| 135 | str = "DISABLED"; |
---|
| 136 | printf("\tMEMIO: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n", |
---|
| 137 | base, limit, str); |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | PCI_CFG_R32(dev, 0x24, &tmp); |
---|
| 141 | if (tmp != 0) { |
---|
| 142 | base = (tmp & 0xfff0) << 16; |
---|
| 143 | limit = (tmp & 0xfff00000) | 0xfffff; |
---|
| 144 | str = "ENABLED"; |
---|
| 145 | if (limit < base) |
---|
| 146 | str = "DISABLED"; |
---|
| 147 | printf("\tMEM: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n", |
---|
| 148 | base, limit, str); |
---|
| 149 | } |
---|
| 150 | } |
---|
| 151 | printf("\n"); |
---|
| 152 | } |
---|
| 153 | |
---|
| 154 | void pci_print_device(int bus, int slot, int function) |
---|
| 155 | { |
---|
| 156 | pci_print_dev(PCI_DEV(bus, slot, function)); |
---|
| 157 | } |
---|
| 158 | |
---|
| 159 | void pci_print(void) |
---|
| 160 | { |
---|
| 161 | int fail, bus, slot, func; |
---|
| 162 | pci_dev_t dev; |
---|
| 163 | uint8_t header; |
---|
| 164 | uint32_t id; |
---|
| 165 | |
---|
| 166 | printf("\nPCI devices found and configured:\n"); |
---|
| 167 | for (bus = 0; bus < pci_bus_count(); bus++) { |
---|
| 168 | for (slot = 0; slot < PCI_MAX_DEVICES; slot++) { |
---|
| 169 | for (func=0; func < PCI_MAX_FUNCTIONS; func++) { |
---|
| 170 | |
---|
| 171 | dev = PCI_DEV(bus, slot, func); |
---|
| 172 | fail = PCI_CFG_R32(dev, PCI_VENDOR_ID, &id); |
---|
| 173 | |
---|
| 174 | if (!fail && id != PCI_INVALID_VENDORDEVICEID && id != 0) { |
---|
| 175 | pci_print_dev(dev); |
---|
| 176 | |
---|
| 177 | /* Stop if not a multi-function device */ |
---|
| 178 | if (func == 0) { |
---|
| 179 | PCI_CFG_R8(dev, PCI_HEADER_TYPE, &header); |
---|
| 180 | if ((header & PCI_MULTI_FUNCTION) == 0) |
---|
| 181 | break; |
---|
| 182 | } |
---|
| 183 | } else if (func == 0) |
---|
| 184 | break; |
---|
| 185 | } |
---|
| 186 | } |
---|
| 187 | } |
---|
| 188 | printf("\n"); |
---|
| 189 | } |
---|