[BACK]Return to pci_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/pci_subr.c, Revision 1.61.4.1

1.61.4.1! yamt        1: /*     $NetBSD: pci_subr.c,v 1.61 2005/06/28 00:28:42 thorpej Exp $    */
1.3       cgd         2:
1.1       mycroft     3: /*
1.22      thorpej     4:  * Copyright (c) 1997 Zubin D. Dittia.  All rights reserved.
1.40      cgd         5:  * Copyright (c) 1995, 1996, 1998, 2000
1.26      cgd         6:  *     Christopher G. Demetriou.  All rights reserved.
1.30      mycroft     7:  * Copyright (c) 1994 Charles M. Hannum.  All rights reserved.
1.1       mycroft     8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
1.30      mycroft    19:  *     This product includes software developed by Charles M. Hannum.
1.1       mycroft    20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
1.10      cgd        36:  * PCI autoconfiguration support functions.
1.45      thorpej    37:  *
                     38:  * Note: This file is also built into a userland library (libpci).
                     39:  * Pay attention to this when you make modifications.
1.1       mycroft    40:  */
1.47      lukem      41:
                     42: #include <sys/cdefs.h>
1.61.4.1! yamt       43: __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.61 2005/06/28 00:28:42 thorpej Exp $");
1.21      enami      44:
1.45      thorpej    45: #ifdef _KERNEL_OPT
1.35      cgd        46: #include "opt_pci.h"
1.45      thorpej    47: #endif
1.1       mycroft    48:
                     49: #include <sys/param.h>
                     50:
1.45      thorpej    51: #ifdef _KERNEL
1.61.4.1! yamt       52: #include <sys/systm.h>
1.24      thorpej    53: #include <machine/intr.h>
1.45      thorpej    54: #else
                     55: #include <pci.h>
1.46      enami      56: #include <stdio.h>
1.45      thorpej    57: #endif
1.24      thorpej    58:
1.10      cgd        59: #include <dev/pci/pcireg.h>
1.45      thorpej    60: #ifdef _KERNEL
1.7       cgd        61: #include <dev/pci/pcivar.h>
1.45      thorpej    62: #endif
1.10      cgd        63: #ifdef PCIVERBOSE
                     64: #include <dev/pci/pcidevs.h>
                     65: #endif
                     66:
                     67: /*
                     68:  * Descriptions of known PCI classes and subclasses.
                     69:  *
                     70:  * Subclasses are described in the same way as classes, but have a
                     71:  * NULL subclass pointer.
                     72:  */
                     73: struct pci_class {
1.44      thorpej    74:        const char      *name;
1.10      cgd        75:        int             val;            /* as wide as pci_{,sub}class_t */
1.42      jdolecek   76:        const struct pci_class *subclasses;
1.10      cgd        77: };
                     78:
1.61      thorpej    79: static const struct pci_class pci_subclass_prehistoric[] = {
1.10      cgd        80:        { "miscellaneous",      PCI_SUBCLASS_PREHISTORIC_MISC,          },
                     81:        { "VGA",                PCI_SUBCLASS_PREHISTORIC_VGA,           },
                     82:        { 0 }
                     83: };
                     84:
1.61      thorpej    85: static const struct pci_class pci_subclass_mass_storage[] = {
1.10      cgd        86:        { "SCSI",               PCI_SUBCLASS_MASS_STORAGE_SCSI,         },
                     87:        { "IDE",                PCI_SUBCLASS_MASS_STORAGE_IDE,          },
                     88:        { "floppy",             PCI_SUBCLASS_MASS_STORAGE_FLOPPY,       },
                     89:        { "IPI",                PCI_SUBCLASS_MASS_STORAGE_IPI,          },
1.20      cgd        90:        { "RAID",               PCI_SUBCLASS_MASS_STORAGE_RAID,         },
1.40      cgd        91:        { "ATA",                PCI_SUBCLASS_MASS_STORAGE_ATA,          },
1.51      drochner   92:        { "SATA",               PCI_SUBCLASS_MASS_STORAGE_SATA,         },
1.10      cgd        93:        { "miscellaneous",      PCI_SUBCLASS_MASS_STORAGE_MISC,         },
                     94:        { 0 },
                     95: };
                     96:
1.61      thorpej    97: static const struct pci_class pci_subclass_network[] = {
1.10      cgd        98:        { "ethernet",           PCI_SUBCLASS_NETWORK_ETHERNET,          },
                     99:        { "token ring",         PCI_SUBCLASS_NETWORK_TOKENRING,         },
                    100:        { "FDDI",               PCI_SUBCLASS_NETWORK_FDDI,              },
1.20      cgd       101:        { "ATM",                PCI_SUBCLASS_NETWORK_ATM,               },
1.32      cgd       102:        { "ISDN",               PCI_SUBCLASS_NETWORK_ISDN,              },
1.40      cgd       103:        { "WorldFip",           PCI_SUBCLASS_NETWORK_WORLDFIP,          },
                    104:        { "PCMIG Multi Computing", PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, },
1.10      cgd       105:        { "miscellaneous",      PCI_SUBCLASS_NETWORK_MISC,              },
                    106:        { 0 },
                    107: };
                    108:
1.61      thorpej   109: static const struct pci_class pci_subclass_display[] = {
1.10      cgd       110:        { "VGA",                PCI_SUBCLASS_DISPLAY_VGA,               },
                    111:        { "XGA",                PCI_SUBCLASS_DISPLAY_XGA,               },
1.32      cgd       112:        { "3D",                 PCI_SUBCLASS_DISPLAY_3D,                },
1.10      cgd       113:        { "miscellaneous",      PCI_SUBCLASS_DISPLAY_MISC,              },
                    114:        { 0 },
                    115: };
                    116:
1.61      thorpej   117: static const struct pci_class pci_subclass_multimedia[] = {
1.10      cgd       118:        { "video",              PCI_SUBCLASS_MULTIMEDIA_VIDEO,          },
                    119:        { "audio",              PCI_SUBCLASS_MULTIMEDIA_AUDIO,          },
1.32      cgd       120:        { "telephony",          PCI_SUBCLASS_MULTIMEDIA_TELEPHONY,      },
1.10      cgd       121:        { "miscellaneous",      PCI_SUBCLASS_MULTIMEDIA_MISC,           },
                    122:        { 0 },
                    123: };
                    124:
1.61      thorpej   125: static const struct pci_class pci_subclass_memory[] = {
1.10      cgd       126:        { "RAM",                PCI_SUBCLASS_MEMORY_RAM,                },
                    127:        { "flash",              PCI_SUBCLASS_MEMORY_FLASH,              },
                    128:        { "miscellaneous",      PCI_SUBCLASS_MEMORY_MISC,               },
                    129:        { 0 },
                    130: };
                    131:
1.61      thorpej   132: static const struct pci_class pci_subclass_bridge[] = {
1.10      cgd       133:        { "host",               PCI_SUBCLASS_BRIDGE_HOST,               },
                    134:        { "ISA",                PCI_SUBCLASS_BRIDGE_ISA,                },
                    135:        { "EISA",               PCI_SUBCLASS_BRIDGE_EISA,               },
                    136:        { "MicroChannel",       PCI_SUBCLASS_BRIDGE_MC,                 },
                    137:        { "PCI",                PCI_SUBCLASS_BRIDGE_PCI,                },
                    138:        { "PCMCIA",             PCI_SUBCLASS_BRIDGE_PCMCIA,             },
1.20      cgd       139:        { "NuBus",              PCI_SUBCLASS_BRIDGE_NUBUS,              },
                    140:        { "CardBus",            PCI_SUBCLASS_BRIDGE_CARDBUS,            },
1.32      cgd       141:        { "RACEway",            PCI_SUBCLASS_BRIDGE_RACEWAY,            },
1.40      cgd       142:        { "Semi-transparent PCI", PCI_SUBCLASS_BRIDGE_STPCI,            },
                    143:        { "InfiniBand",         PCI_SUBCLASS_BRIDGE_INFINIBAND,         },
1.10      cgd       144:        { "miscellaneous",      PCI_SUBCLASS_BRIDGE_MISC,               },
                    145:        { 0 },
                    146: };
                    147:
1.61      thorpej   148: static const struct pci_class pci_subclass_communications[] = {
1.20      cgd       149:        { "serial",             PCI_SUBCLASS_COMMUNICATIONS_SERIAL,     },
                    150:        { "parallel",           PCI_SUBCLASS_COMMUNICATIONS_PARALLEL,   },
1.32      cgd       151:        { "multi-port serial",  PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL,   },
                    152:        { "modem",              PCI_SUBCLASS_COMMUNICATIONS_MODEM,      },
1.48      drochner  153:        { "GPIB",               PCI_SUBCLASS_COMMUNICATIONS_GPIB,       },
                    154:        { "smartcard",          PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD,  },
1.20      cgd       155:        { "miscellaneous",      PCI_SUBCLASS_COMMUNICATIONS_MISC,       },
                    156:        { 0 },
                    157: };
                    158:
1.61      thorpej   159: static const struct pci_class pci_subclass_system[] = {
1.50      sommerfe  160:        { "interrupt",          PCI_SUBCLASS_SYSTEM_PIC,                },
1.20      cgd       161:        { "8237 DMA",           PCI_SUBCLASS_SYSTEM_DMA,                },
                    162:        { "8254 timer",         PCI_SUBCLASS_SYSTEM_TIMER,              },
                    163:        { "RTC",                PCI_SUBCLASS_SYSTEM_RTC,                },
1.32      cgd       164:        { "PCI Hot-Plug",       PCI_SUBCLASS_SYSTEM_RTC,                },
1.20      cgd       165:        { "miscellaneous",      PCI_SUBCLASS_SYSTEM_MISC,               },
                    166:        { 0 },
                    167: };
                    168:
1.61      thorpej   169: static const struct pci_class pci_subclass_input[] = {
1.20      cgd       170:        { "keyboard",           PCI_SUBCLASS_INPUT_KEYBOARD,            },
                    171:        { "digitizer",          PCI_SUBCLASS_INPUT_DIGITIZER,           },
                    172:        { "mouse",              PCI_SUBCLASS_INPUT_MOUSE,               },
1.32      cgd       173:        { "scanner",            PCI_SUBCLASS_INPUT_SCANNER,             },
                    174:        { "game port",          PCI_SUBCLASS_INPUT_GAMEPORT,            },
1.20      cgd       175:        { "miscellaneous",      PCI_SUBCLASS_INPUT_MISC,                },
                    176:        { 0 },
                    177: };
                    178:
1.61      thorpej   179: static const struct pci_class pci_subclass_dock[] = {
1.20      cgd       180:        { "generic",            PCI_SUBCLASS_DOCK_GENERIC,              },
                    181:        { "miscellaneous",      PCI_SUBCLASS_DOCK_MISC,                 },
                    182:        { 0 },
                    183: };
                    184:
1.61      thorpej   185: static const struct pci_class pci_subclass_processor[] = {
1.20      cgd       186:        { "386",                PCI_SUBCLASS_PROCESSOR_386,             },
                    187:        { "486",                PCI_SUBCLASS_PROCESSOR_486,             },
                    188:        { "Pentium",            PCI_SUBCLASS_PROCESSOR_PENTIUM,         },
                    189:        { "Alpha",              PCI_SUBCLASS_PROCESSOR_ALPHA,           },
                    190:        { "PowerPC",            PCI_SUBCLASS_PROCESSOR_POWERPC,         },
1.32      cgd       191:        { "MIPS",               PCI_SUBCLASS_PROCESSOR_MIPS,            },
1.20      cgd       192:        { "Co-processor",       PCI_SUBCLASS_PROCESSOR_COPROC,          },
                    193:        { 0 },
                    194: };
                    195:
1.61      thorpej   196: static const struct pci_class pci_subclass_serialbus[] = {
1.20      cgd       197:        { "Firewire",           PCI_SUBCLASS_SERIALBUS_FIREWIRE,        },
                    198:        { "ACCESS.bus",         PCI_SUBCLASS_SERIALBUS_ACCESS,          },
                    199:        { "SSA",                PCI_SUBCLASS_SERIALBUS_SSA,             },
                    200:        { "USB",                PCI_SUBCLASS_SERIALBUS_USB,             },
1.32      cgd       201:        /* XXX Fiber Channel/_FIBRECHANNEL */
1.20      cgd       202:        { "Fiber Channel",      PCI_SUBCLASS_SERIALBUS_FIBER,           },
1.32      cgd       203:        { "SMBus",              PCI_SUBCLASS_SERIALBUS_SMBUS,           },
1.40      cgd       204:        { "InfiniBand",         PCI_SUBCLASS_SERIALBUS_INFINIBAND,      },
                    205:        { "IPMI",               PCI_SUBCLASS_SERIALBUS_IPMI,            },
                    206:        { "SERCOS",             PCI_SUBCLASS_SERIALBUS_SERCOS,          },
                    207:        { "CANbus",             PCI_SUBCLASS_SERIALBUS_CANBUS,          },
1.32      cgd       208:        { 0 },
                    209: };
                    210:
1.61      thorpej   211: static const struct pci_class pci_subclass_wireless[] = {
1.41      soren     212:        { "IrDA",               PCI_SUBCLASS_WIRELESS_IRDA,             },
1.32      cgd       213:        { "Consumer IR",        PCI_SUBCLASS_WIRELESS_CONSUMERIR,       },
                    214:        { "RF",                 PCI_SUBCLASS_WIRELESS_RF,               },
1.48      drochner  215:        { "bluetooth",          PCI_SUBCLASS_WIRELESS_BLUETOOTH,        },
                    216:        { "broadband",          PCI_SUBCLASS_WIRELESS_BROADBAND,        },
1.51      drochner  217:        { "802.11a (5 GHz)",    PCI_SUBCLASS_WIRELESS_802_11A,          },
                    218:        { "802.11b (2.4 GHz)",  PCI_SUBCLASS_WIRELESS_802_11B,          },
1.32      cgd       219:        { "miscellaneous",      PCI_SUBCLASS_WIRELESS_MISC,             },
                    220:        { 0 },
                    221: };
                    222:
1.61      thorpej   223: static const struct pci_class pci_subclass_i2o[] = {
1.40      cgd       224:        { "standard",           PCI_SUBCLASS_I2O_STANDARD,              },
1.32      cgd       225:        { 0 },
                    226: };
                    227:
1.61      thorpej   228: static const struct pci_class pci_subclass_satcom[] = {
1.32      cgd       229:        { "TV",                 PCI_SUBCLASS_SATCOM_TV,                 },
                    230:        { "audio",              PCI_SUBCLASS_SATCOM_AUDIO,              },
                    231:        { "voice",              PCI_SUBCLASS_SATCOM_VOICE,              },
                    232:        { "data",               PCI_SUBCLASS_SATCOM_DATA,               },
                    233:        { 0 },
                    234: };
                    235:
1.61      thorpej   236: static const struct pci_class pci_subclass_crypto[] = {
1.32      cgd       237:        { "network/computing",  PCI_SUBCLASS_CRYPTO_NETCOMP,            },
                    238:        { "entertainment",      PCI_SUBCLASS_CRYPTO_ENTERTAINMENT,      },
                    239:        { "miscellaneous",      PCI_SUBCLASS_CRYPTO_MISC,               },
                    240:        { 0 },
                    241: };
                    242:
1.61      thorpej   243: static const struct pci_class pci_subclass_dasp[] = {
1.32      cgd       244:        { "DPIO",               PCI_SUBCLASS_DASP_DPIO,                 },
1.40      cgd       245:        { "Time and Frequency", PCI_SUBCLASS_DASP_TIMEFREQ,             },
1.48      drochner  246:        { "synchronization",    PCI_SUBCLASS_DASP_SYNC,                 },
                    247:        { "management",         PCI_SUBCLASS_DASP_MGMT,                 },
1.32      cgd       248:        { "miscellaneous",      PCI_SUBCLASS_DASP_MISC,                 },
1.20      cgd       249:        { 0 },
                    250: };
                    251:
1.61      thorpej   252: static const struct pci_class pci_class[] = {
1.10      cgd       253:        { "prehistoric",        PCI_CLASS_PREHISTORIC,
                    254:            pci_subclass_prehistoric,                           },
                    255:        { "mass storage",       PCI_CLASS_MASS_STORAGE,
                    256:            pci_subclass_mass_storage,                          },
                    257:        { "network",            PCI_CLASS_NETWORK,
                    258:            pci_subclass_network,                               },
                    259:        { "display",            PCI_CLASS_DISPLAY,
1.11      cgd       260:            pci_subclass_display,                               },
1.10      cgd       261:        { "multimedia",         PCI_CLASS_MULTIMEDIA,
                    262:            pci_subclass_multimedia,                            },
                    263:        { "memory",             PCI_CLASS_MEMORY,
                    264:            pci_subclass_memory,                                },
                    265:        { "bridge",             PCI_CLASS_BRIDGE,
                    266:            pci_subclass_bridge,                                },
1.20      cgd       267:        { "communications",     PCI_CLASS_COMMUNICATIONS,
                    268:            pci_subclass_communications,                        },
                    269:        { "system",             PCI_CLASS_SYSTEM,
                    270:            pci_subclass_system,                                },
                    271:        { "input",              PCI_CLASS_INPUT,
                    272:            pci_subclass_input,                                 },
                    273:        { "dock",               PCI_CLASS_DOCK,
                    274:            pci_subclass_dock,                                  },
                    275:        { "processor",          PCI_CLASS_PROCESSOR,
                    276:            pci_subclass_processor,                             },
                    277:        { "serial bus",         PCI_CLASS_SERIALBUS,
                    278:            pci_subclass_serialbus,                             },
1.32      cgd       279:        { "wireless",           PCI_CLASS_WIRELESS,
                    280:            pci_subclass_wireless,                              },
                    281:        { "I2O",                PCI_CLASS_I2O,
                    282:            pci_subclass_i2o,                                   },
                    283:        { "satellite comm",     PCI_CLASS_SATCOM,
                    284:            pci_subclass_satcom,                                },
                    285:        { "crypto",             PCI_CLASS_CRYPTO,
                    286:            pci_subclass_crypto,                                },
                    287:        { "DASP",               PCI_CLASS_DASP,
                    288:            pci_subclass_dasp,                                  },
1.10      cgd       289:        { "undefined",          PCI_CLASS_UNDEFINED,
                    290:            0,                                                  },
                    291:        { 0 },
                    292: };
                    293:
                    294: #ifdef PCIVERBOSE
                    295: /*
                    296:  * Descriptions of of known vendors and devices ("products").
                    297:  */
1.59      mycroft   298: struct pci_vendor {
                    299:        pci_vendor_id_t         vendor;
                    300:        const char              *vendorname;
                    301: };
                    302: struct pci_product {
1.10      cgd       303:        pci_vendor_id_t         vendor;
                    304:        pci_product_id_t        product;
1.59      mycroft   305:        const char              *productname;
1.10      cgd       306: };
                    307:
                    308: #include <dev/pci/pcidevs_data.h>
                    309: #endif /* PCIVERBOSE */
1.29      augustss  310:
1.59      mycroft   311: const char *
1.44      thorpej   312: pci_findvendor(pcireg_t id_reg)
1.29      augustss  313: {
                    314: #ifdef PCIVERBOSE
                    315:        pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
1.59      mycroft   316:        int n;
1.29      augustss  317:
1.59      mycroft   318:        for (n = 0; n < pci_nvendors; n++)
                    319:                if (pci_vendors[n].vendor == vendor)
                    320:                        return (pci_vendors[n].vendorname);
                    321: #endif
1.29      augustss  322:        return (NULL);
1.59      mycroft   323: }
                    324:
                    325: const char *
                    326: pci_findproduct(pcireg_t id_reg)
                    327: {
                    328: #ifdef PCIVERBOSE
                    329:        pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
                    330:        pci_product_id_t product = PCI_PRODUCT(id_reg);
                    331:        int n;
                    332:
                    333:        for (n = 0; n < pci_nproducts; n++)
                    334:                if (pci_products[n].vendor == vendor &&
                    335:                    pci_products[n].product == product)
                    336:                        return (pci_products[n].productname);
1.29      augustss  337: #endif
1.59      mycroft   338:        return (NULL);
1.29      augustss  339: }
1.10      cgd       340:
                    341: void
1.58      itojun    342: pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp,
                    343:     size_t l)
1.10      cgd       344: {
                    345:        pci_vendor_id_t vendor;
                    346:        pci_product_id_t product;
                    347:        pci_class_t class;
                    348:        pci_subclass_t subclass;
                    349:        pci_interface_t interface;
                    350:        pci_revision_t revision;
1.59      mycroft   351:        const char *vendor_namep, *product_namep;
1.42      jdolecek  352:        const struct pci_class *classp, *subclassp;
1.10      cgd       353: #ifdef PCIVERBOSE
1.16      cgd       354:        const char *unmatched = "unknown ";
1.15      cgd       355: #else
1.16      cgd       356:        const char *unmatched = "";
1.10      cgd       357: #endif
1.58      itojun    358:        char *ep;
                    359:
                    360:        ep = cp + l;
1.10      cgd       361:
                    362:        vendor = PCI_VENDOR(id_reg);
                    363:        product = PCI_PRODUCT(id_reg);
                    364:
                    365:        class = PCI_CLASS(class_reg);
                    366:        subclass = PCI_SUBCLASS(class_reg);
                    367:        interface = PCI_INTERFACE(class_reg);
                    368:        revision = PCI_REVISION(class_reg);
                    369:
1.59      mycroft   370:        vendor_namep = pci_findvendor(id_reg);
                    371:        product_namep = pci_findproduct(id_reg);
1.10      cgd       372:
                    373:        classp = pci_class;
                    374:        while (classp->name != NULL) {
                    375:                if (class == classp->val)
                    376:                        break;
                    377:                classp++;
                    378:        }
                    379:
                    380:        subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
                    381:        while (subclassp && subclassp->name != NULL) {
                    382:                if (subclass == subclassp->val)
                    383:                        break;
                    384:                subclassp++;
                    385:        }
                    386:
                    387:        if (vendor_namep == NULL)
1.58      itojun    388:                cp += snprintf(cp, ep - cp, "%svendor 0x%04x product 0x%04x",
1.15      cgd       389:                    unmatched, vendor, product);
1.10      cgd       390:        else if (product_namep != NULL)
1.58      itojun    391:                cp += snprintf(cp, ep - cp, "%s %s", vendor_namep,
                    392:                    product_namep);
1.10      cgd       393:        else
1.58      itojun    394:                cp += snprintf(cp, ep - cp, "%s product 0x%04x",
1.10      cgd       395:                    vendor_namep, product);
1.13      cgd       396:        if (showclass) {
1.58      itojun    397:                cp += snprintf(cp, ep - cp, " (");
1.13      cgd       398:                if (classp->name == NULL)
1.58      itojun    399:                        cp += snprintf(cp, ep - cp,
                    400:                            "class 0x%02x, subclass 0x%02x", class, subclass);
1.13      cgd       401:                else {
                    402:                        if (subclassp == NULL || subclassp->name == NULL)
1.58      itojun    403:                                cp += snprintf(cp, ep - cp,
1.20      cgd       404:                                    "%s subclass 0x%02x",
                    405:                                    classp->name, subclass);
1.13      cgd       406:                        else
1.58      itojun    407:                                cp += snprintf(cp, ep - cp, "%s %s",
1.20      cgd       408:                                    subclassp->name, classp->name);
1.13      cgd       409:                }
1.20      cgd       410:                if (interface != 0)
1.58      itojun    411:                        cp += snprintf(cp, ep - cp, ", interface 0x%02x",
                    412:                            interface);
1.20      cgd       413:                if (revision != 0)
1.58      itojun    414:                        cp += snprintf(cp, ep - cp, ", revision 0x%02x",
                    415:                            revision);
                    416:                cp += snprintf(cp, ep - cp, ")");
1.13      cgd       417:        }
1.22      thorpej   418: }
                    419:
                    420: /*
                    421:  * Print out most of the PCI configuration registers.  Typically used
                    422:  * in a device attach routine like this:
                    423:  *
                    424:  *     #ifdef MYDEV_DEBUG
                    425:  *             printf("%s: ", sc->sc_dev.dv_xname);
1.43      enami     426:  *             pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
1.22      thorpej   427:  *     #endif
                    428:  */
1.26      cgd       429:
                    430: #define        i2o(i)  ((i) * 4)
                    431: #define        o2i(o)  ((o) / 4)
1.27      cgd       432: #define        onoff(str, bit)                                                 \
                    433:        printf("      %s: %s\n", (str), (rval & (bit)) ? "on" : "off");
1.26      cgd       434:
                    435: static void
1.45      thorpej   436: pci_conf_print_common(
                    437: #ifdef _KERNEL
                    438:     pci_chipset_tag_t pc, pcitag_t tag,
                    439: #endif
                    440:     const pcireg_t *regs)
1.22      thorpej   441: {
1.59      mycroft   442:        const char *name;
1.42      jdolecek  443:        const struct pci_class *classp, *subclassp;
1.26      cgd       444:        pcireg_t rval;
1.22      thorpej   445:
1.26      cgd       446:        rval = regs[o2i(PCI_ID_REG)];
1.59      mycroft   447:        name = pci_findvendor(rval);
                    448:        if (name)
                    449:                printf("    Vendor Name: %s (0x%04x)\n", name,
1.26      cgd       450:                    PCI_VENDOR(rval));
1.22      thorpej   451:        else
1.26      cgd       452:                printf("    Vendor ID: 0x%04x\n", PCI_VENDOR(rval));
1.59      mycroft   453:        name = pci_findproduct(rval);
                    454:        if (name)
                    455:                printf("    Device Name: %s (0x%04x)\n", name,
1.26      cgd       456:                    PCI_PRODUCT(rval));
1.22      thorpej   457:        else
1.26      cgd       458:                printf("    Device ID: 0x%04x\n", PCI_PRODUCT(rval));
1.22      thorpej   459:
1.26      cgd       460:        rval = regs[o2i(PCI_COMMAND_STATUS_REG)];
1.23      drochner  461:
1.26      cgd       462:        printf("    Command register: 0x%04x\n", rval & 0xffff);
                    463:        onoff("I/O space accesses", PCI_COMMAND_IO_ENABLE);
                    464:        onoff("Memory space accesses", PCI_COMMAND_MEM_ENABLE);
                    465:        onoff("Bus mastering", PCI_COMMAND_MASTER_ENABLE);
                    466:        onoff("Special cycles", PCI_COMMAND_SPECIAL_ENABLE);
                    467:        onoff("MWI transactions", PCI_COMMAND_INVALIDATE_ENABLE);
                    468:        onoff("Palette snooping", PCI_COMMAND_PALETTE_ENABLE);
                    469:        onoff("Parity error checking", PCI_COMMAND_PARITY_ENABLE);
                    470:        onoff("Address/data stepping", PCI_COMMAND_STEPPING_ENABLE);
                    471:        onoff("System error (SERR)", PCI_COMMAND_SERR_ENABLE);
                    472:        onoff("Fast back-to-back transactions", PCI_COMMAND_BACKTOBACK_ENABLE);
                    473:
                    474:        printf("    Status register: 0x%04x\n", (rval >> 16) & 0xffff);
1.33      kleink    475:        onoff("Capability List support", PCI_STATUS_CAPLIST_SUPPORT);
1.26      cgd       476:        onoff("66 MHz capable", PCI_STATUS_66MHZ_SUPPORT);
                    477:        onoff("User Definable Features (UDF) support", PCI_STATUS_UDF_SUPPORT);
                    478:        onoff("Fast back-to-back capable", PCI_STATUS_BACKTOBACK_SUPPORT);
                    479:        onoff("Data parity error detected", PCI_STATUS_PARITY_ERROR);
1.22      thorpej   480:
1.26      cgd       481:        printf("      DEVSEL timing: ");
1.22      thorpej   482:        switch (rval & PCI_STATUS_DEVSEL_MASK) {
                    483:        case PCI_STATUS_DEVSEL_FAST:
                    484:                printf("fast");
                    485:                break;
                    486:        case PCI_STATUS_DEVSEL_MEDIUM:
                    487:                printf("medium");
                    488:                break;
                    489:        case PCI_STATUS_DEVSEL_SLOW:
                    490:                printf("slow");
                    491:                break;
1.26      cgd       492:        default:
                    493:                printf("unknown/reserved");     /* XXX */
                    494:                break;
1.22      thorpej   495:        }
1.26      cgd       496:        printf(" (0x%x)\n", (rval & PCI_STATUS_DEVSEL_MASK) >> 25);
1.22      thorpej   497:
1.26      cgd       498:        onoff("Slave signaled Target Abort", PCI_STATUS_TARGET_TARGET_ABORT);
                    499:        onoff("Master received Target Abort", PCI_STATUS_MASTER_TARGET_ABORT);
                    500:        onoff("Master received Master Abort", PCI_STATUS_MASTER_ABORT);
                    501:        onoff("Asserted System Error (SERR)", PCI_STATUS_SPECIAL_ERROR);
                    502:        onoff("Parity error detected", PCI_STATUS_PARITY_DETECT);
1.22      thorpej   503:
1.26      cgd       504:        rval = regs[o2i(PCI_CLASS_REG)];
1.22      thorpej   505:        for (classp = pci_class; classp->name != NULL; classp++) {
                    506:                if (PCI_CLASS(rval) == classp->val)
                    507:                        break;
                    508:        }
                    509:        subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
                    510:        while (subclassp && subclassp->name != NULL) {
                    511:                if (PCI_SUBCLASS(rval) == subclassp->val)
                    512:                        break;
                    513:                subclassp++;
                    514:        }
                    515:        if (classp->name != NULL) {
1.26      cgd       516:                printf("    Class Name: %s (0x%02x)\n", classp->name,
                    517:                    PCI_CLASS(rval));
1.22      thorpej   518:                if (subclassp != NULL && subclassp->name != NULL)
1.26      cgd       519:                        printf("    Subclass Name: %s (0x%02x)\n",
                    520:                            subclassp->name, PCI_SUBCLASS(rval));
1.22      thorpej   521:                else
1.26      cgd       522:                        printf("    Subclass ID: 0x%02x\n", PCI_SUBCLASS(rval));
1.22      thorpej   523:        } else {
1.26      cgd       524:                printf("    Class ID: 0x%02x\n", PCI_CLASS(rval));
                    525:                printf("    Subclass ID: 0x%02x\n", PCI_SUBCLASS(rval));
1.22      thorpej   526:        }
1.26      cgd       527:        printf("    Interface: 0x%02x\n", PCI_INTERFACE(rval));
                    528:        printf("    Revision ID: 0x%02x\n", PCI_REVISION(rval));
1.22      thorpej   529:
1.26      cgd       530:        rval = regs[o2i(PCI_BHLC_REG)];
                    531:        printf("    BIST: 0x%02x\n", PCI_BIST(rval));
                    532:        printf("    Header Type: 0x%02x%s (0x%02x)\n", PCI_HDRTYPE_TYPE(rval),
                    533:            PCI_HDRTYPE_MULTIFN(rval) ? "+multifunction" : "",
                    534:            PCI_HDRTYPE(rval));
                    535:        printf("    Latency Timer: 0x%02x\n", PCI_LATTIMER(rval));
                    536:        printf("    Cache Line Size: 0x%02x\n", PCI_CACHELINE(rval));
                    537: }
1.22      thorpej   538:
1.37      nathanw   539: static int
1.45      thorpej   540: pci_conf_print_bar(
                    541: #ifdef _KERNEL
                    542:     pci_chipset_tag_t pc, pcitag_t tag,
                    543: #endif
                    544:     const pcireg_t *regs, int reg, const char *name
                    545: #ifdef _KERNEL
                    546:     , int sizebar
                    547: #endif
                    548:     )
1.26      cgd       549: {
1.45      thorpej   550:        int width;
                    551:        pcireg_t rval, rval64h;
                    552: #ifdef _KERNEL
                    553:        int s;
                    554:        pcireg_t mask, mask64h;
                    555: #endif
                    556:
1.37      nathanw   557:        width = 4;
1.22      thorpej   558:
1.27      cgd       559:        /*
                    560:         * Section 6.2.5.1, `Address Maps', tells us that:
                    561:         *
                    562:         * 1) The builtin software should have already mapped the
                    563:         * device in a reasonable way.
                    564:         *
                    565:         * 2) A device which wants 2^n bytes of memory will hardwire
                    566:         * the bottom n bits of the address to 0.  As recommended,
                    567:         * we write all 1s and see what we get back.
                    568:         */
1.45      thorpej   569:
1.27      cgd       570:        rval = regs[o2i(reg)];
1.45      thorpej   571:        if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM &&
                    572:            PCI_MAPREG_MEM_TYPE(rval) == PCI_MAPREG_MEM_TYPE_64BIT) {
                    573:                rval64h = regs[o2i(reg + 4)];
                    574:                width = 8;
                    575:        } else
                    576:                rval64h = 0;
                    577:
                    578: #ifdef _KERNEL
1.38      cgd       579:        /* XXX don't size unknown memory type? */
                    580:        if (rval != 0 && sizebar) {
1.24      thorpej   581:                /*
1.27      cgd       582:                 * The following sequence seems to make some devices
                    583:                 * (e.g. host bus bridges, which don't normally
                    584:                 * have their space mapped) very unhappy, to
                    585:                 * the point of crashing the system.
1.24      thorpej   586:                 *
1.27      cgd       587:                 * Therefore, if the mapping register is zero to
                    588:                 * start out with, don't bother trying.
1.24      thorpej   589:                 */
1.27      cgd       590:                s = splhigh();
                    591:                pci_conf_write(pc, tag, reg, 0xffffffff);
                    592:                mask = pci_conf_read(pc, tag, reg);
                    593:                pci_conf_write(pc, tag, reg, rval);
1.37      nathanw   594:                if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM &&
                    595:                    PCI_MAPREG_MEM_TYPE(rval) == PCI_MAPREG_MEM_TYPE_64BIT) {
                    596:                        pci_conf_write(pc, tag, reg + 4, 0xffffffff);
                    597:                        mask64h = pci_conf_read(pc, tag, reg + 4);
                    598:                        pci_conf_write(pc, tag, reg + 4, rval64h);
1.54      scw       599:                } else
                    600:                        mask64h = 0;
1.27      cgd       601:                splx(s);
                    602:        } else
1.54      scw       603:                mask = mask64h = 0;
1.45      thorpej   604: #endif /* _KERNEL */
1.27      cgd       605:
1.28      cgd       606:        printf("    Base address register at 0x%02x", reg);
                    607:        if (name)
                    608:                printf(" (%s)", name);
                    609:        printf("\n      ");
1.27      cgd       610:        if (rval == 0) {
                    611:                printf("not implemented(?)\n");
1.37      nathanw   612:                return width;
1.60      perry     613:        }
1.28      cgd       614:        printf("type: ");
                    615:        if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM) {
1.34      drochner  616:                const char *type, *prefetch;
1.27      cgd       617:
                    618:                switch (PCI_MAPREG_MEM_TYPE(rval)) {
                    619:                case PCI_MAPREG_MEM_TYPE_32BIT:
                    620:                        type = "32-bit";
                    621:                        break;
                    622:                case PCI_MAPREG_MEM_TYPE_32BIT_1M:
                    623:                        type = "32-bit-1M";
                    624:                        break;
                    625:                case PCI_MAPREG_MEM_TYPE_64BIT:
                    626:                        type = "64-bit";
                    627:                        break;
                    628:                default:
                    629:                        type = "unknown (XXX)";
                    630:                        break;
1.22      thorpej   631:                }
1.34      drochner  632:                if (PCI_MAPREG_MEM_PREFETCHABLE(rval))
                    633:                        prefetch = "";
1.27      cgd       634:                else
1.34      drochner  635:                        prefetch = "non";
                    636:                printf("%s %sprefetchable memory\n", type, prefetch);
1.37      nathanw   637:                switch (PCI_MAPREG_MEM_TYPE(rval)) {
                    638:                case PCI_MAPREG_MEM_TYPE_64BIT:
1.38      cgd       639:                        printf("      base: 0x%016llx, ",
1.37      nathanw   640:                            PCI_MAPREG_MEM64_ADDR(
1.38      cgd       641:                                ((((long long) rval64h) << 32) | rval)));
1.45      thorpej   642: #ifdef _KERNEL
1.38      cgd       643:                        if (sizebar)
                    644:                                printf("size: 0x%016llx",
                    645:                                    PCI_MAPREG_MEM64_SIZE(
                    646:                                      ((((long long) mask64h) << 32) | mask)));
                    647:                        else
1.45      thorpej   648: #endif /* _KERNEL */
1.38      cgd       649:                                printf("not sized");
                    650:                        printf("\n");
1.37      nathanw   651:                        break;
                    652:                case PCI_MAPREG_MEM_TYPE_32BIT:
                    653:                case PCI_MAPREG_MEM_TYPE_32BIT_1M:
                    654:                default:
1.38      cgd       655:                        printf("      base: 0x%08x, ",
                    656:                            PCI_MAPREG_MEM_ADDR(rval));
1.45      thorpej   657: #ifdef _KERNEL
1.38      cgd       658:                        if (sizebar)
                    659:                                printf("size: 0x%08x",
                    660:                                    PCI_MAPREG_MEM_SIZE(mask));
                    661:                        else
1.45      thorpej   662: #endif /* _KERNEL */
1.38      cgd       663:                                printf("not sized");
                    664:                        printf("\n");
1.37      nathanw   665:                        break;
                    666:                }
1.27      cgd       667:        } else {
1.45      thorpej   668: #ifdef _KERNEL
1.38      cgd       669:                if (sizebar)
                    670:                        printf("%d-bit ", mask & ~0x0000ffff ? 32 : 16);
1.45      thorpej   671: #endif /* _KERNEL */
1.27      cgd       672:                printf("i/o\n");
1.38      cgd       673:                printf("      base: 0x%08x, ", PCI_MAPREG_IO_ADDR(rval));
1.45      thorpej   674: #ifdef _KERNEL
1.38      cgd       675:                if (sizebar)
                    676:                        printf("size: 0x%08x", PCI_MAPREG_IO_SIZE(mask));
                    677:                else
1.45      thorpej   678: #endif /* _KERNEL */
1.38      cgd       679:                        printf("not sized");
                    680:                printf("\n");
1.22      thorpej   681:        }
1.37      nathanw   682:
                    683:        return width;
1.27      cgd       684: }
1.28      cgd       685:
                    686: static void
1.44      thorpej   687: pci_conf_print_regs(const pcireg_t *regs, int first, int pastlast)
1.28      cgd       688: {
                    689:        int off, needaddr, neednl;
                    690:
                    691:        needaddr = 1;
                    692:        neednl = 0;
                    693:        for (off = first; off < pastlast; off += 4) {
                    694:                if ((off % 16) == 0 || needaddr) {
                    695:                        printf("    0x%02x:", off);
                    696:                        needaddr = 0;
                    697:                }
                    698:                printf(" 0x%08x", regs[o2i(off)]);
                    699:                neednl = 1;
                    700:                if ((off % 16) == 12) {
                    701:                        printf("\n");
                    702:                        neednl = 0;
                    703:                }
                    704:        }
                    705:        if (neednl)
                    706:                printf("\n");
                    707: }
                    708:
1.27      cgd       709: static void
1.45      thorpej   710: pci_conf_print_type0(
                    711: #ifdef _KERNEL
                    712:     pci_chipset_tag_t pc, pcitag_t tag,
                    713: #endif
                    714:     const pcireg_t *regs
                    715: #ifdef _KERNEL
                    716:     , int sizebars
                    717: #endif
                    718:     )
1.27      cgd       719: {
1.37      nathanw   720:        int off, width;
1.27      cgd       721:        pcireg_t rval;
                    722:
1.45      thorpej   723:        for (off = PCI_MAPREG_START; off < PCI_MAPREG_END; off += width) {
                    724: #ifdef _KERNEL
1.38      cgd       725:                width = pci_conf_print_bar(pc, tag, regs, off, NULL, sizebars);
1.45      thorpej   726: #else
                    727:                width = pci_conf_print_bar(regs, off, NULL);
                    728: #endif
                    729:        }
1.22      thorpej   730:
1.26      cgd       731:        printf("    Cardbus CIS Pointer: 0x%08x\n", regs[o2i(0x28)]);
1.22      thorpej   732:
1.31      drochner  733:        rval = regs[o2i(PCI_SUBSYS_ID_REG)];
1.26      cgd       734:        printf("    Subsystem vendor ID: 0x%04x\n", PCI_VENDOR(rval));
                    735:        printf("    Subsystem ID: 0x%04x\n", PCI_PRODUCT(rval));
                    736:
                    737:        /* XXX */
                    738:        printf("    Expansion ROM Base Address: 0x%08x\n", regs[o2i(0x30)]);
1.33      kleink    739:
                    740:        if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
                    741:                printf("    Capability list pointer: 0x%02x\n",
                    742:                    PCI_CAPLIST_PTR(regs[o2i(PCI_CAPLISTPTR_REG)]));
                    743:        else
                    744:                printf("    Reserved @ 0x34: 0x%08x\n", regs[o2i(0x34)]);
                    745:
1.26      cgd       746:        printf("    Reserved @ 0x38: 0x%08x\n", regs[o2i(0x38)]);
                    747:
                    748:        rval = regs[o2i(PCI_INTERRUPT_REG)];
                    749:        printf("    Maximum Latency: 0x%02x\n", (rval >> 24) & 0xff);
                    750:        printf("    Minimum Grant: 0x%02x\n", (rval >> 16) & 0xff);
1.27      cgd       751:        printf("    Interrupt pin: 0x%02x ", PCI_INTERRUPT_PIN(rval));
1.22      thorpej   752:        switch (PCI_INTERRUPT_PIN(rval)) {
                    753:        case PCI_INTERRUPT_PIN_NONE:
1.27      cgd       754:                printf("(none)");
1.22      thorpej   755:                break;
                    756:        case PCI_INTERRUPT_PIN_A:
1.27      cgd       757:                printf("(pin A)");
1.22      thorpej   758:                break;
                    759:        case PCI_INTERRUPT_PIN_B:
1.27      cgd       760:                printf("(pin B)");
1.22      thorpej   761:                break;
                    762:        case PCI_INTERRUPT_PIN_C:
1.27      cgd       763:                printf("(pin C)");
1.22      thorpej   764:                break;
                    765:        case PCI_INTERRUPT_PIN_D:
1.27      cgd       766:                printf("(pin D)");
                    767:                break;
                    768:        default:
1.36      mrg       769:                printf("(? ? ?)");
1.22      thorpej   770:                break;
                    771:        }
                    772:        printf("\n");
1.26      cgd       773:        printf("    Interrupt line: 0x%02x\n", PCI_INTERRUPT_LINE(rval));
1.51      drochner  774: }
                    775:
                    776: static void
                    777: pci_conf_print_caplist(
                    778: #ifdef _KERNEL
                    779:     pci_chipset_tag_t pc, pcitag_t tag,
                    780: #endif
1.52      drochner  781:     const pcireg_t *regs, int capoff)
1.51      drochner  782: {
                    783:        int off;
                    784:        pcireg_t rval;
1.33      kleink    785:
1.52      drochner  786:        for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]);
1.51      drochner  787:             off != 0;
                    788:             off = PCI_CAPLIST_NEXT(regs[o2i(off)])) {
                    789:                rval = regs[o2i(off)];
                    790:                printf("  Capability register at 0x%02x\n", off);
                    791:
                    792:                printf("    type: 0x%02x (", PCI_CAPLIST_CAP(rval));
                    793:                switch (PCI_CAPLIST_CAP(rval)) {
                    794:                case PCI_CAP_RESERVED0:
                    795:                        printf("reserved");
                    796:                        break;
                    797:                case PCI_CAP_PWRMGMT:
                    798:                        printf("Power Management, rev. %d.0",
                    799:                               (rval >> 0) & 0x07); /* XXX not clear */
                    800:                        break;
                    801:                case PCI_CAP_AGP:
                    802:                        printf("AGP, rev. %d.%d",
1.57      soren     803:                                PCI_CAP_AGP_MAJOR(rval),
                    804:                                PCI_CAP_AGP_MINOR(rval));
1.51      drochner  805:                        break;
                    806:                case PCI_CAP_VPD:
                    807:                        printf("VPD");
                    808:                        break;
                    809:                case PCI_CAP_SLOTID:
                    810:                        printf("SlotID");
                    811:                        break;
                    812:                case PCI_CAP_MSI:
                    813:                        printf("MSI");
                    814:                        break;
                    815:                case PCI_CAP_CPCI_HOTSWAP:
                    816:                        printf("CompactPCI Hot-swapping");
                    817:                        break;
                    818:                case PCI_CAP_PCIX:
                    819:                        printf("PCI-X");
                    820:                        break;
                    821:                case PCI_CAP_LDT:
                    822:                        printf("LDT");
                    823:                        break;
                    824:                case PCI_CAP_VENDSPEC:
                    825:                        printf("Vendor-specific");
                    826:                        break;
                    827:                case PCI_CAP_DEBUGPORT:
                    828:                        printf("Debug Port");
                    829:                        break;
                    830:                case PCI_CAP_CPCI_RSRCCTL:
                    831:                        printf("CompactPCI Resource Control");
                    832:                        break;
                    833:                case PCI_CAP_HOTPLUG:
                    834:                        printf("Hot-Plug");
                    835:                        break;
                    836:                case PCI_CAP_AGP8:
                    837:                        printf("AGP 8x");
                    838:                        break;
                    839:                case PCI_CAP_SECURE:
                    840:                        printf("Secure Device");
                    841:                        break;
                    842:                case PCI_CAP_PCIEXPRESS:
                    843:                        printf("PCI Express");
                    844:                        break;
                    845:                case PCI_CAP_MSIX:
                    846:                        printf("MSI-X");
                    847:                        break;
                    848:                default:
                    849:                        printf("unknown");
1.33      kleink    850:                }
1.51      drochner  851:                printf(")\n");
1.33      kleink    852:        }
1.26      cgd       853: }
                    854:
1.27      cgd       855: static void
1.45      thorpej   856: pci_conf_print_type1(
                    857: #ifdef _KERNEL
                    858:     pci_chipset_tag_t pc, pcitag_t tag,
                    859: #endif
                    860:     const pcireg_t *regs
                    861: #ifdef _KERNEL
                    862:     , int sizebars
                    863: #endif
                    864:     )
1.27      cgd       865: {
1.37      nathanw   866:        int off, width;
1.27      cgd       867:        pcireg_t rval;
                    868:
                    869:        /*
                    870:         * XXX these need to be printed in more detail, need to be
                    871:         * XXX checked against specs/docs, etc.
                    872:         *
                    873:         * This layout was cribbed from the TI PCI2030 PCI-to-PCI
                    874:         * Bridge chip documentation, and may not be correct with
                    875:         * respect to various standards. (XXX)
                    876:         */
                    877:
1.45      thorpej   878:        for (off = 0x10; off < 0x18; off += width) {
                    879: #ifdef _KERNEL
1.38      cgd       880:                width = pci_conf_print_bar(pc, tag, regs, off, NULL, sizebars);
1.45      thorpej   881: #else
                    882:                width = pci_conf_print_bar(regs, off, NULL);
                    883: #endif
                    884:        }
1.27      cgd       885:
                    886:        printf("    Primary bus number: 0x%02x\n",
                    887:            (regs[o2i(0x18)] >> 0) & 0xff);
                    888:        printf("    Secondary bus number: 0x%02x\n",
                    889:            (regs[o2i(0x18)] >> 8) & 0xff);
                    890:        printf("    Subordinate bus number: 0x%02x\n",
                    891:            (regs[o2i(0x18)] >> 16) & 0xff);
                    892:        printf("    Secondary bus latency timer: 0x%02x\n",
                    893:            (regs[o2i(0x18)] >> 24) & 0xff);
                    894:
                    895:        rval = (regs[o2i(0x1c)] >> 16) & 0xffff;
                    896:        printf("    Secondary status register: 0x%04x\n", rval); /* XXX bits */
                    897:        onoff("66 MHz capable", 0x0020);
                    898:        onoff("User Definable Features (UDF) support", 0x0040);
                    899:        onoff("Fast back-to-back capable", 0x0080);
                    900:        onoff("Data parity error detected", 0x0100);
                    901:
                    902:        printf("      DEVSEL timing: ");
                    903:        switch (rval & 0x0600) {
                    904:        case 0x0000:
                    905:                printf("fast");
                    906:                break;
                    907:        case 0x0200:
                    908:                printf("medium");
                    909:                break;
                    910:        case 0x0400:
                    911:                printf("slow");
                    912:                break;
                    913:        default:
                    914:                printf("unknown/reserved");     /* XXX */
                    915:                break;
                    916:        }
                    917:        printf(" (0x%x)\n", (rval & 0x0600) >> 9);
                    918:
                    919:        onoff("Signaled Target Abort", 0x0800);
                    920:        onoff("Received Target Abort", 0x1000);
                    921:        onoff("Received Master Abort", 0x2000);
                    922:        onoff("System Error", 0x4000);
                    923:        onoff("Parity Error", 0x8000);
                    924:
                    925:        /* XXX Print more prettily */
                    926:        printf("    I/O region:\n");
                    927:        printf("      base register:  0x%02x\n", (regs[o2i(0x1c)] >> 0) & 0xff);
                    928:        printf("      limit register: 0x%02x\n", (regs[o2i(0x1c)] >> 8) & 0xff);
                    929:        printf("      base upper 16 bits register:  0x%04x\n",
                    930:            (regs[o2i(0x30)] >> 0) & 0xffff);
                    931:        printf("      limit upper 16 bits register: 0x%04x\n",
                    932:            (regs[o2i(0x30)] >> 16) & 0xffff);
                    933:
                    934:        /* XXX Print more prettily */
                    935:        printf("    Memory region:\n");
                    936:        printf("      base register:  0x%04x\n",
                    937:            (regs[o2i(0x20)] >> 0) & 0xffff);
                    938:        printf("      limit register: 0x%04x\n",
                    939:            (regs[o2i(0x20)] >> 16) & 0xffff);
                    940:
                    941:        /* XXX Print more prettily */
                    942:        printf("    Prefetchable memory region:\n");
                    943:        printf("      base register:  0x%04x\n",
                    944:            (regs[o2i(0x24)] >> 0) & 0xffff);
                    945:        printf("      limit register: 0x%04x\n",
                    946:            (regs[o2i(0x24)] >> 16) & 0xffff);
                    947:        printf("      base upper 32 bits register:  0x%08x\n", regs[o2i(0x28)]);
                    948:        printf("      limit upper 32 bits register: 0x%08x\n", regs[o2i(0x2c)]);
                    949:
1.53      drochner  950:        if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
                    951:                printf("    Capability list pointer: 0x%02x\n",
                    952:                    PCI_CAPLIST_PTR(regs[o2i(PCI_CAPLISTPTR_REG)]));
                    953:        else
                    954:                printf("    Reserved @ 0x34: 0x%08x\n", regs[o2i(0x34)]);
                    955:
1.27      cgd       956:        /* XXX */
                    957:        printf("    Expansion ROM Base Address: 0x%08x\n", regs[o2i(0x38)]);
                    958:
                    959:        printf("    Interrupt line: 0x%02x\n",
                    960:            (regs[o2i(0x3c)] >> 0) & 0xff);
                    961:        printf("    Interrupt pin: 0x%02x ",
                    962:            (regs[o2i(0x3c)] >> 8) & 0xff);
                    963:        switch ((regs[o2i(0x3c)] >> 8) & 0xff) {
                    964:        case PCI_INTERRUPT_PIN_NONE:
                    965:                printf("(none)");
                    966:                break;
                    967:        case PCI_INTERRUPT_PIN_A:
                    968:                printf("(pin A)");
                    969:                break;
                    970:        case PCI_INTERRUPT_PIN_B:
                    971:                printf("(pin B)");
                    972:                break;
                    973:        case PCI_INTERRUPT_PIN_C:
                    974:                printf("(pin C)");
                    975:                break;
                    976:        case PCI_INTERRUPT_PIN_D:
                    977:                printf("(pin D)");
                    978:                break;
                    979:        default:
1.36      mrg       980:                printf("(? ? ?)");
1.27      cgd       981:                break;
                    982:        }
                    983:        printf("\n");
                    984:        rval = (regs[o2i(0x3c)] >> 16) & 0xffff;
                    985:        printf("    Bridge control register: 0x%04x\n", rval); /* XXX bits */
                    986:        onoff("Parity error response", 0x0001);
                    987:        onoff("Secondary SERR forwarding", 0x0002);
                    988:        onoff("ISA enable", 0x0004);
                    989:        onoff("VGA enable", 0x0008);
                    990:        onoff("Master abort reporting", 0x0020);
                    991:        onoff("Secondary bus reset", 0x0040);
                    992:        onoff("Fast back-to-back capable", 0x0080);
                    993: }
                    994:
                    995: static void
1.45      thorpej   996: pci_conf_print_type2(
                    997: #ifdef _KERNEL
                    998:     pci_chipset_tag_t pc, pcitag_t tag,
                    999: #endif
                   1000:     const pcireg_t *regs
                   1001: #ifdef _KERNEL
                   1002:     , int sizebars
                   1003: #endif
                   1004:     )
1.27      cgd      1005: {
                   1006:        pcireg_t rval;
                   1007:
                   1008:        /*
                   1009:         * XXX these need to be printed in more detail, need to be
                   1010:         * XXX checked against specs/docs, etc.
                   1011:         *
                   1012:         * This layout was cribbed from the TI PCI1130 PCI-to-CardBus
                   1013:         * controller chip documentation, and may not be correct with
                   1014:         * respect to various standards. (XXX)
                   1015:         */
                   1016:
1.45      thorpej  1017: #ifdef _KERNEL
1.28      cgd      1018:        pci_conf_print_bar(pc, tag, regs, 0x10,
1.38      cgd      1019:            "CardBus socket/ExCA registers", sizebars);
1.45      thorpej  1020: #else
                   1021:        pci_conf_print_bar(regs, 0x10, "CardBus socket/ExCA registers");
                   1022: #endif
1.27      cgd      1023:
1.53      drochner 1024:        if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
                   1025:                printf("    Capability list pointer: 0x%02x\n",
                   1026:                    PCI_CAPLIST_PTR(regs[o2i(PCI_CARDBUS_CAPLISTPTR_REG)]));
                   1027:        else
                   1028:                printf("    Reserved @ 0x14: 0x%04x\n",
                   1029:                       (regs[o2i(0x14)] >> 0) & 0xffff);
1.27      cgd      1030:        rval = (regs[o2i(0x14)] >> 16) & 0xffff;
                   1031:        printf("    Secondary status register: 0x%04x\n", rval);
                   1032:        onoff("66 MHz capable", 0x0020);
                   1033:        onoff("User Definable Features (UDF) support", 0x0040);
                   1034:        onoff("Fast back-to-back capable", 0x0080);
                   1035:        onoff("Data parity error detection", 0x0100);
                   1036:
                   1037:        printf("      DEVSEL timing: ");
                   1038:        switch (rval & 0x0600) {
                   1039:        case 0x0000:
                   1040:                printf("fast");
                   1041:                break;
                   1042:        case 0x0200:
                   1043:                printf("medium");
                   1044:                break;
                   1045:        case 0x0400:
                   1046:                printf("slow");
                   1047:                break;
                   1048:        default:
                   1049:                printf("unknown/reserved");     /* XXX */
                   1050:                break;
                   1051:        }
                   1052:        printf(" (0x%x)\n", (rval & 0x0600) >> 9);
                   1053:        onoff("PCI target aborts terminate CardBus bus master transactions",
                   1054:            0x0800);
                   1055:        onoff("CardBus target aborts terminate PCI bus master transactions",
                   1056:            0x1000);
                   1057:        onoff("Bus initiator aborts terminate initiator transactions",
                   1058:            0x2000);
                   1059:        onoff("System error", 0x4000);
                   1060:        onoff("Parity error", 0x8000);
                   1061:
                   1062:        printf("    PCI bus number: 0x%02x\n",
                   1063:            (regs[o2i(0x18)] >> 0) & 0xff);
                   1064:        printf("    CardBus bus number: 0x%02x\n",
                   1065:            (regs[o2i(0x18)] >> 8) & 0xff);
                   1066:        printf("    Subordinate bus number: 0x%02x\n",
                   1067:            (regs[o2i(0x18)] >> 16) & 0xff);
                   1068:        printf("    CardBus latency timer: 0x%02x\n",
                   1069:            (regs[o2i(0x18)] >> 24) & 0xff);
                   1070:
                   1071:        /* XXX Print more prettily */
                   1072:        printf("    CardBus memory region 0:\n");
                   1073:        printf("      base register:  0x%08x\n", regs[o2i(0x1c)]);
                   1074:        printf("      limit register: 0x%08x\n", regs[o2i(0x20)]);
                   1075:        printf("    CardBus memory region 1:\n");
                   1076:        printf("      base register:  0x%08x\n", regs[o2i(0x24)]);
                   1077:        printf("      limit register: 0x%08x\n", regs[o2i(0x28)]);
                   1078:        printf("    CardBus I/O region 0:\n");
                   1079:        printf("      base register:  0x%08x\n", regs[o2i(0x2c)]);
                   1080:        printf("      limit register: 0x%08x\n", regs[o2i(0x30)]);
                   1081:        printf("    CardBus I/O region 1:\n");
                   1082:        printf("      base register:  0x%08x\n", regs[o2i(0x34)]);
                   1083:        printf("      limit register: 0x%08x\n", regs[o2i(0x38)]);
                   1084:
                   1085:        printf("    Interrupt line: 0x%02x\n",
                   1086:            (regs[o2i(0x3c)] >> 0) & 0xff);
                   1087:        printf("    Interrupt pin: 0x%02x ",
                   1088:            (regs[o2i(0x3c)] >> 8) & 0xff);
                   1089:        switch ((regs[o2i(0x3c)] >> 8) & 0xff) {
                   1090:        case PCI_INTERRUPT_PIN_NONE:
                   1091:                printf("(none)");
                   1092:                break;
                   1093:        case PCI_INTERRUPT_PIN_A:
                   1094:                printf("(pin A)");
                   1095:                break;
                   1096:        case PCI_INTERRUPT_PIN_B:
                   1097:                printf("(pin B)");
                   1098:                break;
                   1099:        case PCI_INTERRUPT_PIN_C:
                   1100:                printf("(pin C)");
                   1101:                break;
                   1102:        case PCI_INTERRUPT_PIN_D:
                   1103:                printf("(pin D)");
                   1104:                break;
                   1105:        default:
1.36      mrg      1106:                printf("(? ? ?)");
1.27      cgd      1107:                break;
                   1108:        }
                   1109:        printf("\n");
                   1110:        rval = (regs[o2i(0x3c)] >> 16) & 0xffff;
                   1111:        printf("    Bridge control register: 0x%04x\n", rval);
                   1112:        onoff("Parity error response", 0x0001);
                   1113:        onoff("CardBus SERR forwarding", 0x0002);
                   1114:        onoff("ISA enable", 0x0004);
                   1115:        onoff("VGA enable", 0x0008);
                   1116:        onoff("CardBus master abort reporting", 0x0020);
                   1117:        onoff("CardBus reset", 0x0040);
                   1118:        onoff("Functional interrupts routed by ExCA registers", 0x0080);
                   1119:        onoff("Memory window 0 prefetchable", 0x0100);
                   1120:        onoff("Memory window 1 prefetchable", 0x0200);
                   1121:        onoff("Write posting enable", 0x0400);
1.28      cgd      1122:
                   1123:        rval = regs[o2i(0x40)];
                   1124:        printf("    Subsystem vendor ID: 0x%04x\n", PCI_VENDOR(rval));
                   1125:        printf("    Subsystem ID: 0x%04x\n", PCI_PRODUCT(rval));
                   1126:
1.45      thorpej  1127: #ifdef _KERNEL
1.38      cgd      1128:        pci_conf_print_bar(pc, tag, regs, 0x44, "legacy-mode registers",
                   1129:            sizebars);
1.45      thorpej  1130: #else
                   1131:        pci_conf_print_bar(regs, 0x44, "legacy-mode registers");
                   1132: #endif
1.27      cgd      1133: }
                   1134:
1.26      cgd      1135: void
1.45      thorpej  1136: pci_conf_print(
                   1137: #ifdef _KERNEL
                   1138:     pci_chipset_tag_t pc, pcitag_t tag,
                   1139:     void (*printfn)(pci_chipset_tag_t, pcitag_t, const pcireg_t *)
                   1140: #else
                   1141:     int pcifd, u_int bus, u_int dev, u_int func
                   1142: #endif
                   1143:     )
1.26      cgd      1144: {
                   1145:        pcireg_t regs[o2i(256)];
1.52      drochner 1146:        int off, capoff, endoff, hdrtype;
1.27      cgd      1147:        const char *typename;
1.45      thorpej  1148: #ifdef _KERNEL
1.38      cgd      1149:        void (*typeprintfn)(pci_chipset_tag_t, pcitag_t, const pcireg_t *, int);
                   1150:        int sizebars;
1.45      thorpej  1151: #else
                   1152:        void (*typeprintfn)(const pcireg_t *);
                   1153: #endif
1.26      cgd      1154:
                   1155:        printf("PCI configuration registers:\n");
                   1156:
1.45      thorpej  1157:        for (off = 0; off < 256; off += 4) {
                   1158: #ifdef _KERNEL
1.26      cgd      1159:                regs[o2i(off)] = pci_conf_read(pc, tag, off);
1.45      thorpej  1160: #else
                   1161:                if (pcibus_conf_read(pcifd, bus, dev, func, off,
                   1162:                    &regs[o2i(off)]) == -1)
                   1163:                        regs[o2i(off)] = 0;
                   1164: #endif
                   1165:        }
1.26      cgd      1166:
1.45      thorpej  1167: #ifdef _KERNEL
1.38      cgd      1168:        sizebars = 1;
                   1169:        if (PCI_CLASS(regs[o2i(PCI_CLASS_REG)]) == PCI_CLASS_BRIDGE &&
                   1170:            PCI_SUBCLASS(regs[o2i(PCI_CLASS_REG)]) == PCI_SUBCLASS_BRIDGE_HOST)
                   1171:                sizebars = 0;
1.45      thorpej  1172: #endif
1.38      cgd      1173:
1.26      cgd      1174:        /* common header */
                   1175:        printf("  Common header:\n");
1.28      cgd      1176:        pci_conf_print_regs(regs, 0, 16);
                   1177:
1.26      cgd      1178:        printf("\n");
1.45      thorpej  1179: #ifdef _KERNEL
1.26      cgd      1180:        pci_conf_print_common(pc, tag, regs);
1.45      thorpej  1181: #else
                   1182:        pci_conf_print_common(regs);
                   1183: #endif
1.26      cgd      1184:        printf("\n");
                   1185:
                   1186:        /* type-dependent header */
                   1187:        hdrtype = PCI_HDRTYPE_TYPE(regs[o2i(PCI_BHLC_REG)]);
                   1188:        switch (hdrtype) {              /* XXX make a table, eventually */
                   1189:        case 0:
1.27      cgd      1190:                /* Standard device header */
                   1191:                typename = "\"normal\" device";
                   1192:                typeprintfn = &pci_conf_print_type0;
1.52      drochner 1193:                capoff = PCI_CAPLISTPTR_REG;
1.28      cgd      1194:                endoff = 64;
1.27      cgd      1195:                break;
                   1196:        case 1:
                   1197:                /* PCI-PCI bridge header */
                   1198:                typename = "PCI-PCI bridge";
1.26      cgd      1199:                typeprintfn = &pci_conf_print_type1;
1.52      drochner 1200:                capoff = PCI_CAPLISTPTR_REG;
1.28      cgd      1201:                endoff = 64;
1.26      cgd      1202:                break;
1.27      cgd      1203:        case 2:
                   1204:                /* PCI-CardBus bridge header */
                   1205:                typename = "PCI-CardBus bridge";
                   1206:                typeprintfn = &pci_conf_print_type2;
1.52      drochner 1207:                capoff = PCI_CARDBUS_CAPLISTPTR_REG;
1.28      cgd      1208:                endoff = 72;
1.27      cgd      1209:                break;
1.26      cgd      1210:        default:
1.27      cgd      1211:                typename = NULL;
1.26      cgd      1212:                typeprintfn = 0;
1.52      drochner 1213:                capoff = -1;
1.28      cgd      1214:                endoff = 64;
                   1215:                break;
1.26      cgd      1216:        }
1.27      cgd      1217:        printf("  Type %d ", hdrtype);
                   1218:        if (typename != NULL)
                   1219:                printf("(%s) ", typename);
                   1220:        printf("header:\n");
1.28      cgd      1221:        pci_conf_print_regs(regs, 16, endoff);
1.27      cgd      1222:        printf("\n");
1.45      thorpej  1223:        if (typeprintfn) {
                   1224: #ifdef _KERNEL
1.38      cgd      1225:                (*typeprintfn)(pc, tag, regs, sizebars);
1.45      thorpej  1226: #else
                   1227:                (*typeprintfn)(regs);
                   1228: #endif
                   1229:        } else
1.26      cgd      1230:                printf("    Don't know how to pretty-print type %d header.\n",
                   1231:                    hdrtype);
                   1232:        printf("\n");
1.51      drochner 1233:
1.55      jdolecek 1234:        /* capability list, if present */
1.52      drochner 1235:        if ((regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
                   1236:                && (capoff > 0)) {
1.51      drochner 1237: #ifdef _KERNEL
1.52      drochner 1238:                pci_conf_print_caplist(pc, tag, regs, capoff);
1.51      drochner 1239: #else
1.52      drochner 1240:                pci_conf_print_caplist(regs, capoff);
1.51      drochner 1241: #endif
                   1242:                printf("\n");
                   1243:        }
1.26      cgd      1244:
                   1245:        /* device-dependent header */
                   1246:        printf("  Device-dependent header:\n");
1.28      cgd      1247:        pci_conf_print_regs(regs, endoff, 256);
1.26      cgd      1248:        printf("\n");
1.49      nathanw  1249: #ifdef _KERNEL
1.26      cgd      1250:        if (printfn)
                   1251:                (*printfn)(pc, tag, regs);
                   1252:        else
                   1253:                printf("    Don't know how to pretty-print device-dependent header.\n");
                   1254:        printf("\n");
1.45      thorpej  1255: #endif /* _KERNEL */
1.1       mycroft  1256: }

CVSweb <webmaster@jp.NetBSD.org>