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 } 402