Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:20

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  PCI Print Current Configuration To Terminal
0004  *
0005  *  COPYRIGHT (c) 2010 Cobham Gaisler AB.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #include <inttypes.h>
0030 #include <stdio.h>
0031 #include <pci.h>
0032 #include <pci/access.h>
0033 
0034 /* PCI Access Library shortcuts */
0035 #define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
0036 #define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
0037 #define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
0038 #define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
0039 #define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
0040 #define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
0041 
0042 void pci_print_dev(pci_dev_t dev)
0043 {
0044     int maxbars, pos, romadrs;
0045     uint32_t tmp, tmp2, id;
0046     uint16_t irq;
0047     uint8_t irq_pin;
0048     char *str, *str2;
0049     uint32_t base, limit;
0050 
0051     maxbars = 6;
0052     romadrs = 0x30;
0053     str = "";
0054     PCI_CFG_R32(dev, PCIR_REVID, &tmp);
0055     tmp >>= 16;
0056     if (tmp == PCID_PCI2PCI_BRIDGE) {
0057         maxbars = 2;
0058         romadrs = 0x38;
0059         str = "(BRIDGE)";
0060     }
0061 
0062     PCI_CFG_R32(dev, PCIR_VENDOR, &id);
0063     printf("\nBus %x Slot %x function: %x [0x%x] %s\n",
0064         PCI_DEV_EXPAND(dev), dev, str);
0065     printf("\tVendor id: 0x%" PRIx32 ", device id: 0x%" PRIx32 "\n",
0066         id & 0xffff, id >> 16);
0067     if (maxbars == 2) {
0068         PCI_CFG_R32(dev, PCIR_PRIBUS_1, &tmp);
0069         printf("\tPrimary: %" PRIx32 "  Secondary: %" PRIx32
0070             "  Subordinate: %" PRIx32 "\n",
0071             tmp & 0xff, (tmp >> 8) & 0xff, (tmp >> 16) & 0xff);
0072     }
0073 
0074     PCI_CFG_R16(dev, PCIR_INTLINE, &irq);
0075     irq_pin = irq >> 8;
0076     if ((irq_pin > 0) && (irq_pin < 5))
0077         printf("\tIRQ INT%c#  LINE: %d\n",
0078             (irq_pin - 1) + 'A', (irq & 0xff));
0079 
0080     /* Print standard BARs */
0081     for (pos = 0; pos < maxbars; pos++) {
0082         PCI_CFG_R32(dev, PCIR_BAR(0) + pos*4, &tmp);
0083         PCI_CFG_W32(dev, PCIR_BAR(0) + pos*4, 0xffffffff);
0084         PCI_CFG_R32(dev, PCIR_BAR(0) + pos*4, &tmp2);
0085         PCI_CFG_W32(dev, PCIR_BAR(0) + pos*4, tmp);
0086 
0087         if (tmp2 != 0 && tmp2 != 0xffffffff && ((tmp2 & 0x1) ||
0088             ((tmp2 & 0x6) == 0))) {
0089             uint32_t mask = ~0xf;
0090             if ((tmp2 & 0x1) == 1) {
0091                 /* I/O Bar */
0092                 mask = ~3;
0093                 tmp2 = tmp2 | 0xffffff00;
0094             }
0095             tmp2 &= mask;
0096             tmp2 = ~tmp2+1; /* Size of BAR */
0097             if (tmp2 < 0x1000) {
0098                 str = "B";
0099             } else if (tmp2 < 0x100000) {
0100                 str = "kB";
0101                 tmp2 = tmp2 / 1024;
0102             } else {
0103                 str = "MB";
0104                 tmp2 = tmp2 / (1024*1024);
0105             }
0106             printf("\tBAR %d: %" PRIx32 " [%" PRIu32 "%s]\n",
0107                 pos, tmp, tmp2, str);
0108         }
0109     }
0110 
0111     /* Print ROM BARs */
0112     PCI_CFG_R32(dev, romadrs, &tmp);
0113     PCI_CFG_W32(dev, romadrs, 0xffffffff);
0114     PCI_CFG_R32(dev, romadrs, &tmp2);
0115     PCI_CFG_W32(dev, romadrs, tmp);
0116     if (tmp2 & 1) {
0117         /* ROM BAR available */
0118         tmp2 &= PCIM_BIOS_ADDR_MASK;
0119         tmp2 = (~tmp2 + 1); /* Size of BAR */
0120         if (tmp2 < 0x1000) {
0121             str = "B";
0122         } else if (tmp2 < 0x100000) {
0123             str = "kB";
0124             tmp2 = tmp2 / 1024;
0125         } else {
0126             str = "MB";
0127             tmp2 = tmp2 / (1024*1024);
0128         }
0129         str2 = tmp & 1 ? "ENABLED" : "DISABLED";
0130         printf("\tROM:   %08" PRIx32 " [%" PRIu32 "%s] (%s)\n",
0131             tmp, tmp2, str, str2);
0132     }
0133 
0134     /* Print Bridge addresses */
0135     if (maxbars == 2) {
0136         tmp = 0;
0137         PCI_CFG_R32(dev, 0x1C, &tmp);
0138         if (tmp != 0) {
0139             base = (tmp & 0x00f0) << 8;
0140             limit = (tmp & 0xf000) | 0xfff;
0141             PCI_CFG_R32(dev, 0x30, &tmp);
0142             base |= (tmp & 0xffff) << 16;
0143             limit |= (tmp & 0xffff0000);
0144             str = "ENABLED";
0145             if (limit < base)
0146                 str = "DISABLED";
0147             printf("\tI/O:   BASE: 0x%08" PRIx32 ", LIMIT: 0x%08"
0148                 PRIx32 " (%s)\n", base, limit, str);
0149         }
0150 
0151         PCI_CFG_R32(dev, 0x20, &tmp);
0152         if (tmp != 0) {
0153             base = (tmp & 0xfff0) << 16;
0154             limit = (tmp & 0xfff00000) | 0xfffff;
0155             str = "ENABLED";
0156             if (limit < base)
0157                 str = "DISABLED";
0158             printf("\tMEMIO: BASE: 0x%08" PRIx32 ", LIMIT: 0x%08"
0159                 PRIx32 " (%s)\n", base, limit, str);
0160         }
0161 
0162         PCI_CFG_R32(dev, 0x24, &tmp);
0163         if (tmp != 0) {
0164             base = (tmp & 0xfff0) << 16;
0165             limit = (tmp & 0xfff00000) | 0xfffff;
0166             str = "ENABLED";
0167             if (limit < base)
0168                 str = "DISABLED";
0169             printf("\tMEM:   BASE: 0x%08" PRIx32 ", LIMIT: 0x%08"
0170                 PRIx32 " (%s)\n", base, limit, str);
0171         }
0172     }
0173     printf("\n");
0174 }
0175 
0176 void pci_print_device(int bus, int slot, int function)
0177 {
0178     pci_print_dev(PCI_DEV(bus, slot, function));
0179 }
0180 
0181 void pci_print(void)
0182 {
0183     int fail, bus, slot, func;
0184     pci_dev_t dev;
0185     uint8_t header;
0186     uint32_t id;
0187 
0188     printf("\nPCI devices found and configured:\n");
0189     for (bus = 0; bus < pci_bus_count(); bus++) {
0190         for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
0191             for (func=0; func <= PCI_FUNCMAX; func++) {
0192 
0193                 dev = PCI_DEV(bus, slot, func);
0194                 fail = PCI_CFG_R32(dev, PCIR_VENDOR, &id);
0195 
0196                 if (!fail && id != PCI_INVALID_VENDORDEVICEID && id != 0) {
0197                     pci_print_dev(dev);
0198 
0199                     /* Stop if not a multi-function device */
0200                     if (func == 0) {
0201                         PCI_CFG_R8(dev, PCIR_HDRTYPE, &header);
0202                         if ((header & PCIM_MFDEV) == 0)
0203                             break;
0204                     }
0205         } else if (func == 0)
0206             break;
0207             }
0208         }
0209     }
0210     printf("\n");
0211 }