source: rtems/cpukit/libpci/pci_print.c @ a31845f7

4.11
Last change on this file since a31845f7 was a31845f7, checked in by Daniel Hellstrom <daniel@…>, on Nov 28, 2011 at 9:11:10 AM

LIBPCI: added PCI layer to cpukit/libpci

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