1 | /* PCI Print Current Configuration To Terminal |
---|
2 | * |
---|
3 | * COPYRIGHT (c) 2010 Cobham Gaisler AB. |
---|
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.org/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, PCIR_REVID, &tmp); |
---|
35 | tmp >>= 16; |
---|
36 | if (tmp == PCID_PCI2PCI_BRIDGE) { |
---|
37 | maxbars = 2; |
---|
38 | romadrs = 0x38; |
---|
39 | str = "(BRIDGE)"; |
---|
40 | } |
---|
41 | |
---|
42 | PCI_CFG_R32(dev, PCIR_VENDOR, &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, PCIR_PRIBUS_1, &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, PCIR_INTLINE, &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, PCIR_BAR(0) + pos*4, &tmp); |
---|
62 | PCI_CFG_W32(dev, PCIR_BAR(0) + pos*4, 0xffffffff); |
---|
63 | PCI_CFG_R32(dev, PCIR_BAR(0) + pos*4, &tmp2); |
---|
64 | PCI_CFG_W32(dev, PCIR_BAR(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 &= PCIM_BIOS_ADDR_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_SLOTMAX; slot++) { |
---|
169 | for (func=0; func <= PCI_FUNCMAX; func++) { |
---|
170 | |
---|
171 | dev = PCI_DEV(bus, slot, func); |
---|
172 | fail = PCI_CFG_R32(dev, PCIR_VENDOR, &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, PCIR_HDRTYPE, &header); |
---|
180 | if ((header & PCIM_MFDEV) == 0) |
---|
181 | break; |
---|
182 | } |
---|
183 | } else if (func == 0) |
---|
184 | break; |
---|
185 | } |
---|
186 | } |
---|
187 | } |
---|
188 | printf("\n"); |
---|
189 | } |
---|