1 /* $OpenBSD: pci_subr.c,v 1.14 2002/04/07 19:21:40 tdeval 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 #endif 47 48 /* 49 * Descriptions of known PCI classes and subclasses. 50 * 51 * Subclasses are described in the same way as classes, but have a 52 * NULL subclass pointer. 53 */ 54 struct pci_class { 55 const char *name; 56 int val; /* as wide as pci_{,sub}class_t */ 57 const struct pci_class *subclasses; 58 }; 59 60 const struct pci_class pci_subclass_prehistoric[] = { 61 { "miscellaneous", PCI_SUBCLASS_PREHISTORIC_MISC, }, 62 { "VGA", PCI_SUBCLASS_PREHISTORIC_VGA, }, 63 { 0 } 64 }; 65 66 const struct pci_class pci_subclass_mass_storage[] = { 67 { "SCSI", PCI_SUBCLASS_MASS_STORAGE_SCSI, }, 68 { "IDE", PCI_SUBCLASS_MASS_STORAGE_IDE, }, 69 { "floppy", PCI_SUBCLASS_MASS_STORAGE_FLOPPY, }, 70 { "IPI", PCI_SUBCLASS_MASS_STORAGE_IPI, }, 71 { "RAID", PCI_SUBCLASS_MASS_STORAGE_RAID, }, 72 { "ATA", PCI_SUBCLASS_MASS_STORAGE_ATA, }, 73 { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, }, 74 { 0 }, 75 }; 76 77 const struct pci_class pci_subclass_network[] = { 78 { "ethernet", PCI_SUBCLASS_NETWORK_ETHERNET, }, 79 { "token ring", PCI_SUBCLASS_NETWORK_TOKENRING, }, 80 { "FDDI", PCI_SUBCLASS_NETWORK_FDDI, }, 81 { "ATM", PCI_SUBCLASS_NETWORK_ATM, }, 82 { "ISDN", PCI_SUBCLASS_NETWORK_ISDN, }, 83 { "WorldFip", PCI_SUBCLASS_NETWORK_WORLDFIP, }, 84 { "PCMIG Multi Computing", PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, }, 85 { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, }, 86 { 0 }, 87 }; 88 89 const struct pci_class pci_subclass_display[] = { 90 { "VGA", PCI_SUBCLASS_DISPLAY_VGA, }, 91 { "XGA", PCI_SUBCLASS_DISPLAY_XGA, }, 92 { "3D", PCI_SUBCLASS_DISPLAY_3D, }, 93 { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, }, 94 { 0 }, 95 }; 96 97 const struct pci_class pci_subclass_multimedia[] = { 98 { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, }, 99 { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, }, 100 { "telephony", PCI_SUBCLASS_MULTIMEDIA_TELEPHONY, }, 101 { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, }, 102 { 0 }, 103 }; 104 105 const struct pci_class pci_subclass_memory[] = { 106 { "RAM", PCI_SUBCLASS_MEMORY_RAM, }, 107 { "flash", PCI_SUBCLASS_MEMORY_FLASH, }, 108 { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, }, 109 { 0 }, 110 }; 111 112 const struct pci_class pci_subclass_bridge[] = { 113 { "host", PCI_SUBCLASS_BRIDGE_HOST, }, 114 { "ISA", PCI_SUBCLASS_BRIDGE_ISA, }, 115 { "EISA", PCI_SUBCLASS_BRIDGE_EISA, }, 116 { "MicroChannel", PCI_SUBCLASS_BRIDGE_MC, }, 117 { "PCI", PCI_SUBCLASS_BRIDGE_PCI, }, 118 { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, }, 119 { "NuBus", PCI_SUBCLASS_BRIDGE_NUBUS, }, 120 { "CardBus", PCI_SUBCLASS_BRIDGE_CARDBUS, }, 121 { "RACEway", PCI_SUBCLASS_BRIDGE_RACEWAY, }, 122 { "Semi-transparent PCI", PCI_SUBCLASS_BRIDGE_STPCI, }, 123 { "InfiniBand", PCI_SUBCLASS_BRIDGE_INFINIBAND, }, 124 { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, }, 125 { 0 }, 126 }; 127 128 const struct pci_class pci_subclass_communications[] = { 129 { "serial", PCI_SUBCLASS_COMMUNICATIONS_SERIAL, }, 130 { "parallel", PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, }, 131 { "multi-port serial", PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL, }, 132 { "modem", PCI_SUBCLASS_COMMUNICATIONS_MODEM, }, 133 { "miscellaneous", PCI_SUBCLASS_COMMUNICATIONS_MISC, }, 134 { 0 }, 135 }; 136 137 const struct pci_class pci_subclass_system[] = { 138 { "8259 PIC", PCI_SUBCLASS_SYSTEM_PIC, }, 139 { "8237 DMA", PCI_SUBCLASS_SYSTEM_DMA, }, 140 { "8254 timer", PCI_SUBCLASS_SYSTEM_TIMER, }, 141 { "RTC", PCI_SUBCLASS_SYSTEM_RTC, }, 142 { "PCI Hot-Plug", PCI_SUBCLASS_SYSTEM_PCIHOTPLUG, }, 143 { "miscellaneous", PCI_SUBCLASS_SYSTEM_MISC, }, 144 { 0 }, 145 }; 146 147 const struct pci_class pci_subclass_input[] = { 148 { "keyboard", PCI_SUBCLASS_INPUT_KEYBOARD, }, 149 { "digitizer", PCI_SUBCLASS_INPUT_DIGITIZER, }, 150 { "mouse", PCI_SUBCLASS_INPUT_MOUSE, }, 151 { "scanner", PCI_SUBCLASS_INPUT_SCANNER, }, 152 { "game port", PCI_SUBCLASS_INPUT_GAMEPORT, }, 153 { "miscellaneous", PCI_SUBCLASS_INPUT_MISC, }, 154 { 0 }, 155 }; 156 157 const struct pci_class pci_subclass_dock[] = { 158 { "generic", PCI_SUBCLASS_DOCK_GENERIC, }, 159 { "miscellaneous", PCI_SUBCLASS_DOCK_MISC, }, 160 { 0 }, 161 }; 162 163 const struct pci_class pci_subclass_processor[] = { 164 { "386", PCI_SUBCLASS_PROCESSOR_386, }, 165 { "486", PCI_SUBCLASS_PROCESSOR_486, }, 166 { "Pentium", PCI_SUBCLASS_PROCESSOR_PENTIUM, }, 167 { "Alpha", PCI_SUBCLASS_PROCESSOR_ALPHA, }, 168 { "PowerPC", PCI_SUBCLASS_PROCESSOR_POWERPC, }, 169 { "MIPS", PCI_SUBCLASS_PROCESSOR_MIPS, }, 170 { "Co-processor", PCI_SUBCLASS_PROCESSOR_COPROC, }, 171 { 0 }, 172 }; 173 174 const struct pci_class pci_subclass_serialbus[] = { 175 { "Firewire", PCI_SUBCLASS_SERIALBUS_FIREWIRE, }, 176 { "ACCESS.bus", PCI_SUBCLASS_SERIALBUS_ACCESS, }, 177 { "SSA", PCI_SUBCLASS_SERIALBUS_SSA, }, 178 { "USB", PCI_SUBCLASS_SERIALBUS_USB, }, 179 /* XXX Fiber Channel/_FIBRECHANNEL */ 180 { "Fiber Channel", PCI_SUBCLASS_SERIALBUS_FIBER, }, 181 { "SMBus", PCI_SUBCLASS_SERIALBUS_SMBUS, }, 182 { "InfiniBand", PCI_SUBCLASS_SERIALBUS_INFINIBAND, }, 183 { "IPMI", PCI_SUBCLASS_SERIALBUS_IPMI, }, 184 { "SERCOS", PCI_SUBCLASS_SERIALBUS_SERCOS, }, 185 { "CANbus", PCI_SUBCLASS_SERIALBUS_CANBUS, }, 186 { 0 }, 187 }; 188 189 const struct pci_class pci_subclass_wireless[] = { 190 { "IrDA", PCI_SUBCLASS_WIRELESS_IRDA, }, 191 { "Consumer IR", PCI_SUBCLASS_WIRELESS_CONSUMERIR, }, 192 { "RF", PCI_SUBCLASS_WIRELESS_RF, }, 193 { "miscellaneous", PCI_SUBCLASS_WIRELESS_MISC, }, 194 { 0 }, 195 }; 196 197 const struct pci_class pci_subclass_i2o[] = { 198 { "standard", PCI_SUBCLASS_I2O_STANDARD, }, 199 { 0 }, 200 }; 201 202 const struct pci_class pci_subclass_satcom[] = { 203 { "TV", PCI_SUBCLASS_SATCOM_TV, }, 204 { "audio", PCI_SUBCLASS_SATCOM_AUDIO, }, 205 { "voice", PCI_SUBCLASS_SATCOM_VOICE, }, 206 { "data", PCI_SUBCLASS_SATCOM_DATA, }, 207 { 0 }, 208 }; 209 210 const struct pci_class pci_subclass_crypto[] = { 211 { "network/computing", PCI_SUBCLASS_CRYPTO_NETCOMP, }, 212 { "entertainment", PCI_SUBCLASS_CRYPTO_ENTERTAINMENT, }, 213 { "miscellaneous", PCI_SUBCLASS_CRYPTO_MISC, }, 214 { 0 }, 215 }; 216 217 const struct pci_class pci_subclass_dasp[] = { 218 { "DPIO", PCI_SUBCLASS_DASP_DPIO, }, 219 { "Time and Frequency", PCI_SUBCLASS_DASP_TIMEFREQ, }, 220 { "miscellaneous", PCI_SUBCLASS_DASP_MISC, }, 221 { 0 }, 222 }; 223 224 const struct pci_class pci_class[] = { 225 { "prehistoric", PCI_CLASS_PREHISTORIC, 226 pci_subclass_prehistoric, }, 227 { "mass storage", PCI_CLASS_MASS_STORAGE, 228 pci_subclass_mass_storage, }, 229 { "network", PCI_CLASS_NETWORK, 230 pci_subclass_network, }, 231 { "display", PCI_CLASS_DISPLAY, 232 pci_subclass_display, }, 233 { "multimedia", PCI_CLASS_MULTIMEDIA, 234 pci_subclass_multimedia, }, 235 { "memory", PCI_CLASS_MEMORY, 236 pci_subclass_memory, }, 237 { "bridge", PCI_CLASS_BRIDGE, 238 pci_subclass_bridge, }, 239 { "communications", PCI_CLASS_COMMUNICATIONS, 240 pci_subclass_communications, }, 241 { "system", PCI_CLASS_SYSTEM, 242 pci_subclass_system, }, 243 { "input", PCI_CLASS_INPUT, 244 pci_subclass_input, }, 245 { "dock", PCI_CLASS_DOCK, 246 pci_subclass_dock, }, 247 { "processor", PCI_CLASS_PROCESSOR, 248 pci_subclass_processor, }, 249 { "serial bus", PCI_CLASS_SERIALBUS, 250 pci_subclass_serialbus, }, 251 { "wireless", PCI_CLASS_WIRELESS, 252 pci_subclass_wireless, }, 253 { "I2O", PCI_CLASS_I2O, 254 pci_subclass_i2o, }, 255 { "satellite comm", PCI_CLASS_SATCOM, 256 pci_subclass_satcom, }, 257 { "crypto", PCI_CLASS_CRYPTO, 258 pci_subclass_crypto, }, 259 { "DASP", PCI_CLASS_DASP, 260 pci_subclass_dasp, }, 261 { "undefined", PCI_CLASS_UNDEFINED, 262 0, }, 263 { 0 }, 264 }; 265 266 #ifdef PCIVERBOSE 267 /* 268 * Descriptions of known vendors and devices ("products"). 269 */ 270 struct pci_known_vendor { 271 pci_vendor_id_t vendor; 272 const char *vendorname; 273 }; 274 275 struct pci_known_product { 276 pci_vendor_id_t vendor; 277 pci_product_id_t product; 278 const char *productname; 279 }; 280 281 #include <dev/pci/pcidevs_data.h> 282 #endif /* PCIVERBOSE */ 283 284 const char * 285 pci_findvendor(pcireg_t id_reg) 286 { 287 #ifdef PCIVERBOSE 288 pci_vendor_id_t vendor = PCI_VENDOR(id_reg); 289 const struct pci_known_vendor *kdp; 290 291 kdp = pci_known_vendors; 292 while (kdp->vendorname != NULL) { /* all have vendor name */ 293 if (kdp->vendor == vendor) 294 break; 295 kdp++; 296 } 297 return (kdp->vendorname); 298 #else 299 return (NULL); 300 #endif 301 } 302 303 void 304 pci_devinfo(id_reg, class_reg, showclass, cp) 305 pcireg_t id_reg, class_reg; 306 int showclass; 307 char *cp; 308 { 309 pci_vendor_id_t vendor; 310 pci_product_id_t product; 311 pci_class_t class; 312 pci_subclass_t subclass; 313 pci_interface_t interface; 314 pci_revision_t revision; 315 const char *vendor_namep = NULL, *product_namep = NULL; 316 const struct pci_class *classp, *subclassp; 317 #ifdef PCIVERBOSE 318 const struct pci_known_vendor *pkv; 319 const struct pci_known_product *pkp; 320 const char *unmatched = "unknown "; 321 #else 322 const char *unmatched = ""; 323 #endif 324 325 vendor = PCI_VENDOR(id_reg); 326 product = PCI_PRODUCT(id_reg); 327 328 class = PCI_CLASS(class_reg); 329 subclass = PCI_SUBCLASS(class_reg); 330 interface = PCI_INTERFACE(class_reg); 331 revision = PCI_REVISION(class_reg); 332 333 #ifdef PCIVERBOSE 334 pkv = pci_known_vendors; 335 while (pkv->vendorname != NULL) { /* all have vendor name */ 336 if (pkv->vendor == vendor) { 337 vendor_namep = pkv->vendorname; 338 break; 339 } 340 pkv++; 341 } 342 if (vendor_namep) { 343 pkp = pci_known_products; 344 while (pkp->productname != NULL) { /* all have product name */ 345 if (pkp->vendor == vendor && pkp->product == product) { 346 product_namep = pkp->productname; 347 break; 348 } 349 pkp++; 350 } 351 } 352 #endif /* PCIVERBOSE */ 353 354 classp = pci_class; 355 while (classp->name != NULL) { 356 if (class == classp->val) 357 break; 358 classp++; 359 } 360 361 subclassp = (classp->name != NULL) ? classp->subclasses : NULL; 362 while (subclassp && subclassp->name != NULL) { 363 if (subclass == subclassp->val) 364 break; 365 subclassp++; 366 } 367 368 if (vendor_namep == NULL) 369 cp += sprintf(cp, "%svendor 0x%04x product 0x%04x", 370 unmatched, vendor, product); 371 else if (product_namep != NULL) 372 cp += sprintf(cp, "\"%s %s\"", vendor_namep, product_namep); 373 else 374 cp += sprintf(cp, "vendor \"%s\", unknown product 0x%x", 375 vendor_namep, product); 376 if (showclass && product_namep == NULL) { 377 cp += sprintf(cp, " ("); 378 if (classp->name == NULL) 379 cp += sprintf(cp, 380 "unknown class 0x%02x, subclass 0x%02x", 381 class, subclass); 382 else { 383 cp += sprintf(cp, "class %s, ", classp->name); 384 if (subclassp == NULL || subclassp->name == NULL) 385 cp += sprintf(cp, "unknown subclass 0x%02x", 386 subclass); 387 else 388 cp += sprintf(cp, "subclass %s", 389 subclassp->name); 390 } 391 #if 0 /* not very useful */ 392 cp += sprintf(cp, ", interface 0x%02x", interface); 393 #endif 394 cp += sprintf(cp, ", rev 0x%02x)", revision); 395 } else 396 cp += sprintf(cp, " rev 0x%02x", revision); 397 } 398