Annotation of sys/dev/pci/pci_subr.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pci_subr.c,v 1.21 2007/02/21 13:08:22 dlg Exp $ */
! 2: /* $NetBSD: pci_subr.c,v 1.19 1996/10/13 01:38:29 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved.
! 6: * Copyright (c) 1994 Charles Hannum. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed by Charles Hannum.
! 19: * 4. The name of the author may not be used to endorse or promote products
! 20: * derived from this software without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 32: */
! 33:
! 34: /*
! 35: * PCI autoconfiguration support functions.
! 36: */
! 37:
! 38: #include <sys/param.h>
! 39: #include <sys/systm.h>
! 40: #include <sys/device.h>
! 41:
! 42: #include <dev/pci/pcireg.h>
! 43: #include <dev/pci/pcivar.h>
! 44: #ifdef PCIVERBOSE
! 45: #include <dev/pci/pcidevs.h>
! 46: #include <dev/pci/pcidevs_data.h>
! 47: #endif
! 48:
! 49: /*
! 50: * Descriptions of known PCI classes and subclasses.
! 51: *
! 52: * Subclasses are described in the same way as classes, but have a
! 53: * NULL subclass pointer.
! 54: */
! 55: struct pci_class {
! 56: const char *name;
! 57: int val; /* as wide as pci_{,sub}class_t */
! 58: const struct pci_class *subclasses;
! 59: };
! 60:
! 61: const struct pci_class pci_subclass_prehistoric[] = {
! 62: { "miscellaneous", PCI_SUBCLASS_PREHISTORIC_MISC, },
! 63: { "VGA", PCI_SUBCLASS_PREHISTORIC_VGA, },
! 64: { 0 }
! 65: };
! 66:
! 67: const struct pci_class pci_subclass_mass_storage[] = {
! 68: { "SCSI", PCI_SUBCLASS_MASS_STORAGE_SCSI, },
! 69: { "IDE", PCI_SUBCLASS_MASS_STORAGE_IDE, },
! 70: { "floppy", PCI_SUBCLASS_MASS_STORAGE_FLOPPY, },
! 71: { "IPI", PCI_SUBCLASS_MASS_STORAGE_IPI, },
! 72: { "RAID", PCI_SUBCLASS_MASS_STORAGE_RAID, },
! 73: { "ATA", PCI_SUBCLASS_MASS_STORAGE_ATA, },
! 74: { "SATA", PCI_SUBCLASS_MASS_STORAGE_SATA, },
! 75: { "SAS", PCI_SUBCLASS_MASS_STORAGE_SAS, },
! 76: { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, },
! 77: { 0 },
! 78: };
! 79:
! 80: const struct pci_class pci_subclass_network[] = {
! 81: { "ethernet", PCI_SUBCLASS_NETWORK_ETHERNET, },
! 82: { "token ring", PCI_SUBCLASS_NETWORK_TOKENRING, },
! 83: { "FDDI", PCI_SUBCLASS_NETWORK_FDDI, },
! 84: { "ATM", PCI_SUBCLASS_NETWORK_ATM, },
! 85: { "ISDN", PCI_SUBCLASS_NETWORK_ISDN, },
! 86: { "WorldFip", PCI_SUBCLASS_NETWORK_WORLDFIP, },
! 87: { "PCMIG Multi Computing", PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, },
! 88: { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, },
! 89: { 0 },
! 90: };
! 91:
! 92: const struct pci_class pci_subclass_display[] = {
! 93: { "VGA", PCI_SUBCLASS_DISPLAY_VGA, },
! 94: { "XGA", PCI_SUBCLASS_DISPLAY_XGA, },
! 95: { "3D", PCI_SUBCLASS_DISPLAY_3D, },
! 96: { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, },
! 97: { 0 },
! 98: };
! 99:
! 100: const struct pci_class pci_subclass_multimedia[] = {
! 101: { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, },
! 102: { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, },
! 103: { "telephony", PCI_SUBCLASS_MULTIMEDIA_TELEPHONY, },
! 104: { "hdaudio", PCI_SUBCLASS_MULTIMEDIA_HDAUDIO, },
! 105: { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, },
! 106: { 0 },
! 107: };
! 108:
! 109: const struct pci_class pci_subclass_memory[] = {
! 110: { "RAM", PCI_SUBCLASS_MEMORY_RAM, },
! 111: { "flash", PCI_SUBCLASS_MEMORY_FLASH, },
! 112: { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, },
! 113: { 0 },
! 114: };
! 115:
! 116: const struct pci_class pci_subclass_bridge[] = {
! 117: { "host", PCI_SUBCLASS_BRIDGE_HOST, },
! 118: { "ISA", PCI_SUBCLASS_BRIDGE_ISA, },
! 119: { "EISA", PCI_SUBCLASS_BRIDGE_EISA, },
! 120: { "MicroChannel", PCI_SUBCLASS_BRIDGE_MC, },
! 121: { "PCI", PCI_SUBCLASS_BRIDGE_PCI, },
! 122: { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, },
! 123: { "NuBus", PCI_SUBCLASS_BRIDGE_NUBUS, },
! 124: { "CardBus", PCI_SUBCLASS_BRIDGE_CARDBUS, },
! 125: { "RACEway", PCI_SUBCLASS_BRIDGE_RACEWAY, },
! 126: { "Semi-transparent PCI", PCI_SUBCLASS_BRIDGE_STPCI, },
! 127: { "InfiniBand", PCI_SUBCLASS_BRIDGE_INFINIBAND, },
! 128: { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, },
! 129: { 0 },
! 130: };
! 131:
! 132: const struct pci_class pci_subclass_communications[] = {
! 133: { "serial", PCI_SUBCLASS_COMMUNICATIONS_SERIAL, },
! 134: { "parallel", PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, },
! 135: { "multi-port serial", PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL, },
! 136: { "modem", PCI_SUBCLASS_COMMUNICATIONS_MODEM, },
! 137: { "GPIB", PCI_SUBCLASS_COMMUNICATIONS_GPIB, },
! 138: { "smartcard", PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD, },
! 139: { "miscellaneous", PCI_SUBCLASS_COMMUNICATIONS_MISC, },
! 140: { 0 },
! 141: };
! 142:
! 143: const struct pci_class pci_subclass_system[] = {
! 144: { "interrupt", PCI_SUBCLASS_SYSTEM_PIC, },
! 145: { "8237 DMA", PCI_SUBCLASS_SYSTEM_DMA, },
! 146: { "8254 timer", PCI_SUBCLASS_SYSTEM_TIMER, },
! 147: { "RTC", PCI_SUBCLASS_SYSTEM_RTC, },
! 148: { "PCI Hot-Plug", PCI_SUBCLASS_SYSTEM_PCIHOTPLUG, },
! 149: { "SD Host Controller", PCI_SUBCLASS_SYSTEM_SDHC, },
! 150: { "miscellaneous", PCI_SUBCLASS_SYSTEM_MISC, },
! 151: { 0 },
! 152: };
! 153:
! 154: const struct pci_class pci_subclass_input[] = {
! 155: { "keyboard", PCI_SUBCLASS_INPUT_KEYBOARD, },
! 156: { "digitizer", PCI_SUBCLASS_INPUT_DIGITIZER, },
! 157: { "mouse", PCI_SUBCLASS_INPUT_MOUSE, },
! 158: { "scanner", PCI_SUBCLASS_INPUT_SCANNER, },
! 159: { "game port", PCI_SUBCLASS_INPUT_GAMEPORT, },
! 160: { "miscellaneous", PCI_SUBCLASS_INPUT_MISC, },
! 161: { 0 },
! 162: };
! 163:
! 164: const struct pci_class pci_subclass_dock[] = {
! 165: { "generic", PCI_SUBCLASS_DOCK_GENERIC, },
! 166: { "miscellaneous", PCI_SUBCLASS_DOCK_MISC, },
! 167: { 0 },
! 168: };
! 169:
! 170: const struct pci_class pci_subclass_processor[] = {
! 171: { "386", PCI_SUBCLASS_PROCESSOR_386, },
! 172: { "486", PCI_SUBCLASS_PROCESSOR_486, },
! 173: { "Pentium", PCI_SUBCLASS_PROCESSOR_PENTIUM, },
! 174: { "Alpha", PCI_SUBCLASS_PROCESSOR_ALPHA, },
! 175: { "PowerPC", PCI_SUBCLASS_PROCESSOR_POWERPC, },
! 176: { "MIPS", PCI_SUBCLASS_PROCESSOR_MIPS, },
! 177: { "Co-processor", PCI_SUBCLASS_PROCESSOR_COPROC, },
! 178: { 0 },
! 179: };
! 180:
! 181: const struct pci_class pci_subclass_serialbus[] = {
! 182: { "Firewire", PCI_SUBCLASS_SERIALBUS_FIREWIRE, },
! 183: { "ACCESS.bus", PCI_SUBCLASS_SERIALBUS_ACCESS, },
! 184: { "SSA", PCI_SUBCLASS_SERIALBUS_SSA, },
! 185: { "USB", PCI_SUBCLASS_SERIALBUS_USB, },
! 186: /* XXX Fiber Channel/_FIBRECHANNEL */
! 187: { "Fiber Channel", PCI_SUBCLASS_SERIALBUS_FIBER, },
! 188: { "SMBus", PCI_SUBCLASS_SERIALBUS_SMBUS, },
! 189: { "InfiniBand", PCI_SUBCLASS_SERIALBUS_INFINIBAND, },
! 190: { "IPMI", PCI_SUBCLASS_SERIALBUS_IPMI, },
! 191: { "SERCOS", PCI_SUBCLASS_SERIALBUS_SERCOS, },
! 192: { "CANbus", PCI_SUBCLASS_SERIALBUS_CANBUS, },
! 193: { 0 },
! 194: };
! 195:
! 196: const struct pci_class pci_subclass_wireless[] = {
! 197: { "IrDA", PCI_SUBCLASS_WIRELESS_IRDA, },
! 198: { "Consumer IR", PCI_SUBCLASS_WIRELESS_CONSUMERIR, },
! 199: { "RF", PCI_SUBCLASS_WIRELESS_RF, },
! 200: { "bluetooth", PCI_SUBCLASS_WIRELESS_BLUETOOTH, },
! 201: { "broadband", PCI_SUBCLASS_WIRELESS_BROADBAND, },
! 202: { "802.11a (5 GHz)", PCI_SUBCLASS_WIRELESS_802_11A, },
! 203: { "802.11b (2.4 GHz)", PCI_SUBCLASS_WIRELESS_802_11B, },
! 204: { "miscellaneous", PCI_SUBCLASS_WIRELESS_MISC, },
! 205: { 0 },
! 206: };
! 207:
! 208: const struct pci_class pci_subclass_i2o[] = {
! 209: { "standard", PCI_SUBCLASS_I2O_STANDARD, },
! 210: { 0 },
! 211: };
! 212:
! 213: const struct pci_class pci_subclass_satcom[] = {
! 214: { "TV", PCI_SUBCLASS_SATCOM_TV, },
! 215: { "audio", PCI_SUBCLASS_SATCOM_AUDIO, },
! 216: { "voice", PCI_SUBCLASS_SATCOM_VOICE, },
! 217: { "data", PCI_SUBCLASS_SATCOM_DATA, },
! 218: { 0 },
! 219: };
! 220:
! 221: const struct pci_class pci_subclass_crypto[] = {
! 222: { "network/computing", PCI_SUBCLASS_CRYPTO_NETCOMP, },
! 223: { "entertainment", PCI_SUBCLASS_CRYPTO_ENTERTAINMENT, },
! 224: { "miscellaneous", PCI_SUBCLASS_CRYPTO_MISC, },
! 225: { 0 },
! 226: };
! 227:
! 228: const struct pci_class pci_subclass_dasp[] = {
! 229: { "DPIO", PCI_SUBCLASS_DASP_DPIO, },
! 230: { "Time and Frequency", PCI_SUBCLASS_DASP_TIMEFREQ, },
! 231: { "synchronization", PCI_SUBCLASS_DASP_SYNC, },
! 232: { "management", PCI_SUBCLASS_DASP_MGMT, },
! 233: { "miscellaneous", PCI_SUBCLASS_DASP_MISC, },
! 234: { 0 },
! 235: };
! 236:
! 237: const struct pci_class pci_class[] = {
! 238: { "prehistoric", PCI_CLASS_PREHISTORIC,
! 239: pci_subclass_prehistoric, },
! 240: { "mass storage", PCI_CLASS_MASS_STORAGE,
! 241: pci_subclass_mass_storage, },
! 242: { "network", PCI_CLASS_NETWORK,
! 243: pci_subclass_network, },
! 244: { "display", PCI_CLASS_DISPLAY,
! 245: pci_subclass_display, },
! 246: { "multimedia", PCI_CLASS_MULTIMEDIA,
! 247: pci_subclass_multimedia, },
! 248: { "memory", PCI_CLASS_MEMORY,
! 249: pci_subclass_memory, },
! 250: { "bridge", PCI_CLASS_BRIDGE,
! 251: pci_subclass_bridge, },
! 252: { "communications", PCI_CLASS_COMMUNICATIONS,
! 253: pci_subclass_communications, },
! 254: { "system", PCI_CLASS_SYSTEM,
! 255: pci_subclass_system, },
! 256: { "input", PCI_CLASS_INPUT,
! 257: pci_subclass_input, },
! 258: { "dock", PCI_CLASS_DOCK,
! 259: pci_subclass_dock, },
! 260: { "processor", PCI_CLASS_PROCESSOR,
! 261: pci_subclass_processor, },
! 262: { "serial bus", PCI_CLASS_SERIALBUS,
! 263: pci_subclass_serialbus, },
! 264: { "wireless", PCI_CLASS_WIRELESS,
! 265: pci_subclass_wireless, },
! 266: { "I2O", PCI_CLASS_I2O,
! 267: pci_subclass_i2o, },
! 268: { "satellite comm", PCI_CLASS_SATCOM,
! 269: pci_subclass_satcom, },
! 270: { "crypto", PCI_CLASS_CRYPTO,
! 271: pci_subclass_crypto, },
! 272: { "DASP", PCI_CLASS_DASP,
! 273: pci_subclass_dasp, },
! 274: { "undefined", PCI_CLASS_UNDEFINED,
! 275: 0, },
! 276: { 0 },
! 277: };
! 278:
! 279: const char *
! 280: pci_findvendor(pcireg_t id_reg)
! 281: {
! 282: #ifdef PCIVERBOSE
! 283: pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
! 284: const struct pci_known_vendor *kdp;
! 285:
! 286: kdp = pci_known_vendors;
! 287: while (kdp->vendorname != NULL) { /* all have vendor name */
! 288: if (kdp->vendor == vendor)
! 289: break;
! 290: kdp++;
! 291: }
! 292: return (kdp->vendorname);
! 293: #else
! 294: return (NULL);
! 295: #endif
! 296: }
! 297:
! 298: const char *
! 299: pci_findproduct(pcireg_t id_reg)
! 300: {
! 301: #ifdef PCIVERBOSE
! 302: pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
! 303: pci_product_id_t product = PCI_PRODUCT(id_reg);
! 304: const struct pci_known_product *pkp;
! 305:
! 306: pkp = pci_known_products;
! 307: while (pkp->productname != NULL) { /* all have product name */
! 308: if (pkp->vendor == vendor && pkp->product == product)
! 309: break;
! 310: pkp++;
! 311: }
! 312: return (pkp->productname);
! 313: #else
! 314: return NULL;
! 315: #endif
! 316: }
! 317:
! 318: void
! 319: pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp,
! 320: size_t cp_max)
! 321: {
! 322: pci_vendor_id_t vendor;
! 323: pci_product_id_t product;
! 324: pci_class_t class;
! 325: pci_subclass_t subclass;
! 326: pci_interface_t interface;
! 327: pci_revision_t revision;
! 328: const char *vendor_namep = NULL, *product_namep = NULL;
! 329: const struct pci_class *classp, *subclassp;
! 330: size_t cp_len = 0;
! 331: #ifdef PCIVERBOSE
! 332: const char *unmatched = "unknown ";
! 333: #else
! 334: const char *unmatched = "";
! 335: #endif
! 336:
! 337: vendor = PCI_VENDOR(id_reg);
! 338: product = PCI_PRODUCT(id_reg);
! 339:
! 340: class = PCI_CLASS(class_reg);
! 341: subclass = PCI_SUBCLASS(class_reg);
! 342: interface = PCI_INTERFACE(class_reg);
! 343: revision = PCI_REVISION(class_reg);
! 344:
! 345: #ifdef PCIVERBOSE
! 346: vendor_namep = pci_findvendor(id_reg);
! 347: if (vendor_namep != NULL)
! 348: product_namep = pci_findproduct(id_reg);
! 349: #endif /* PCIVERBOSE */
! 350:
! 351: classp = pci_class;
! 352: while (classp->name != NULL) {
! 353: if (class == classp->val)
! 354: break;
! 355: classp++;
! 356: }
! 357:
! 358: subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
! 359: while (subclassp && subclassp->name != NULL) {
! 360: if (subclass == subclassp->val)
! 361: break;
! 362: subclassp++;
! 363: }
! 364:
! 365: if (vendor_namep == NULL)
! 366: snprintf(cp, cp_max, "%svendor 0x%04x product 0x%04x",
! 367: unmatched, vendor, product);
! 368: else if (product_namep != NULL)
! 369: snprintf(cp, cp_max, "\"%s %s\"", vendor_namep, product_namep);
! 370: else
! 371: snprintf(cp, cp_max, "vendor \"%s\", unknown product 0x%04x",
! 372: vendor_namep, product);
! 373: if (showclass && product_namep == NULL) {
! 374: strlcat(cp, " (", cp_max);
! 375: cp_len = strlen(cp);
! 376: if (classp->name == NULL)
! 377: snprintf(cp + cp_len, cp_max - cp_len,
! 378: "unknown class 0x%02x, subclass 0x%02x",
! 379: class, subclass);
! 380: else if (subclassp == NULL || subclassp->name == NULL)
! 381: snprintf(cp + cp_len, cp_max - cp_len,
! 382: "class %s unknown subclass 0x%02x", classp->name,
! 383: subclass);
! 384: else
! 385: snprintf(cp + cp_len, cp_max - cp_len,
! 386: "class %s subclass %s", classp->name,
! 387: subclassp->name);
! 388: #if 0 /* not very useful */
! 389: cp_len = strlen(cp);
! 390: snprintf(cp + cp_len, cp_max - cp_len,
! 391: ", interface 0x%02x", interface);
! 392: #endif
! 393: cp_len = strlen(cp);
! 394: snprintf(cp + cp_len, cp_max - cp_len,
! 395: ", rev 0x%02x)", revision);
! 396: } else {
! 397: cp_len = strlen(cp);
! 398: snprintf(cp + cp_len, cp_max - cp_len, " rev 0x%02x",
! 399: revision);
! 400: }
! 401: }
CVSweb