source: rtems/cpukit/libpci/pci_print.c @ 71e8a5c

4.11
Last change on this file since 71e8a5c was 71e8a5c, checked in by Daniel Hellstrom <daniel@…>, on Feb 27, 2015 at 3:45:59 PM

LIBPCI: moved copyright into a single line

  • Property mode set to 100644
File size: 4.9 KB
Line 
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.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
22void 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
154void pci_print_device(int bus, int slot, int function)
155{
156        pci_print_dev(PCI_DEV(bus, slot, function));
157}
158
159void 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}
Note: See TracBrowser for help on using the repository browser.