[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.66

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

CVSweb <webmaster@jp.NetBSD.org>