1 /* $NetBSD: pci_subr.c,v 1.21 1997/09/13 08:49:51 enami Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved. 5 * Copyright (c) 1994 Charles Hannum. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Charles Hannum. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * PCI autoconfiguration support functions. 35 */ 36 37 #include "opt_pciverbose.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 43 #include <dev/pci/pcireg.h> 44 #include <dev/pci/pcivar.h> 45 #ifdef PCIVERBOSE 46 #include <dev/pci/pcidevs.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 char *name; 57 int val; /* as wide as pci_{,sub}class_t */ 58 struct pci_class *subclasses; 59 }; 60 61 struct pci_class pci_subclass_prehistoric[] = { 62 { "miscellaneous", PCI_SUBCLASS_PREHISTORIC_MISC, }, 63 { "VGA", PCI_SUBCLASS_PREHISTORIC_VGA, }, 64 { 0 } 65 }; 66 67 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 { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, }, 74 { 0 }, 75 }; 76 77 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 { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, }, 83 { 0 }, 84 }; 85 86 struct pci_class pci_subclass_display[] = { 87 { "VGA", PCI_SUBCLASS_DISPLAY_VGA, }, 88 { "XGA", PCI_SUBCLASS_DISPLAY_XGA, }, 89 { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, }, 90 { 0 }, 91 }; 92 93 struct pci_class pci_subclass_multimedia[] = { 94 { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, }, 95 { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, }, 96 { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, }, 97 { 0 }, 98 }; 99 100 struct pci_class pci_subclass_memory[] = { 101 { "RAM", PCI_SUBCLASS_MEMORY_RAM, }, 102 { "flash", PCI_SUBCLASS_MEMORY_FLASH, }, 103 { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, }, 104 { 0 }, 105 }; 106 107 struct pci_class pci_subclass_bridge[] = { 108 { "host", PCI_SUBCLASS_BRIDGE_HOST, }, 109 { "ISA", PCI_SUBCLASS_BRIDGE_ISA, }, 110 { "EISA", PCI_SUBCLASS_BRIDGE_EISA, }, 111 { "MicroChannel", PCI_SUBCLASS_BRIDGE_MC, }, 112 { "PCI", PCI_SUBCLASS_BRIDGE_PCI, }, 113 { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, }, 114 { "NuBus", PCI_SUBCLASS_BRIDGE_NUBUS, }, 115 { "CardBus", PCI_SUBCLASS_BRIDGE_CARDBUS, }, 116 { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, }, 117 { 0 }, 118 }; 119 120 struct pci_class pci_subclass_communications[] = { 121 { "serial", PCI_SUBCLASS_COMMUNICATIONS_SERIAL, }, 122 { "parallel", PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, }, 123 { "miscellaneous", PCI_SUBCLASS_COMMUNICATIONS_MISC, }, 124 { 0 }, 125 }; 126 127 struct pci_class pci_subclass_system[] = { 128 { "8259 PIC", PCI_SUBCLASS_SYSTEM_PIC, }, 129 { "8237 DMA", PCI_SUBCLASS_SYSTEM_DMA, }, 130 { "8254 timer", PCI_SUBCLASS_SYSTEM_TIMER, }, 131 { "RTC", PCI_SUBCLASS_SYSTEM_RTC, }, 132 { "miscellaneous", PCI_SUBCLASS_SYSTEM_MISC, }, 133 { 0 }, 134 }; 135 136 struct pci_class pci_subclass_input[] = { 137 { "keyboard", PCI_SUBCLASS_INPUT_KEYBOARD, }, 138 { "digitizer", PCI_SUBCLASS_INPUT_DIGITIZER, }, 139 { "mouse", PCI_SUBCLASS_INPUT_MOUSE, }, 140 { "miscellaneous", PCI_SUBCLASS_INPUT_MISC, }, 141 { 0 }, 142 }; 143 144 struct pci_class pci_subclass_dock[] = { 145 { "generic", PCI_SUBCLASS_DOCK_GENERIC, }, 146 { "miscellaneous", PCI_SUBCLASS_DOCK_MISC, }, 147 { 0 }, 148 }; 149 150 struct pci_class pci_subclass_processor[] = { 151 { "386", PCI_SUBCLASS_PROCESSOR_386, }, 152 { "486", PCI_SUBCLASS_PROCESSOR_486, }, 153 { "Pentium", PCI_SUBCLASS_PROCESSOR_PENTIUM, }, 154 { "Alpha", PCI_SUBCLASS_PROCESSOR_ALPHA, }, 155 { "PowerPC", PCI_SUBCLASS_PROCESSOR_POWERPC, }, 156 { "Co-processor", PCI_SUBCLASS_PROCESSOR_COPROC, }, 157 { 0 }, 158 }; 159 160 struct pci_class pci_subclass_serialbus[] = { 161 { "Firewire", PCI_SUBCLASS_SERIALBUS_FIREWIRE, }, 162 { "ACCESS.bus", PCI_SUBCLASS_SERIALBUS_ACCESS, }, 163 { "SSA", PCI_SUBCLASS_SERIALBUS_SSA, }, 164 { "USB", PCI_SUBCLASS_SERIALBUS_USB, }, 165 { "Fiber Channel", PCI_SUBCLASS_SERIALBUS_FIBER, }, 166 { 0 }, 167 }; 168 169 struct pci_class pci_class[] = { 170 { "prehistoric", PCI_CLASS_PREHISTORIC, 171 pci_subclass_prehistoric, }, 172 { "mass storage", PCI_CLASS_MASS_STORAGE, 173 pci_subclass_mass_storage, }, 174 { "network", PCI_CLASS_NETWORK, 175 pci_subclass_network, }, 176 { "display", PCI_CLASS_DISPLAY, 177 pci_subclass_display, }, 178 { "multimedia", PCI_CLASS_MULTIMEDIA, 179 pci_subclass_multimedia, }, 180 { "memory", PCI_CLASS_MEMORY, 181 pci_subclass_memory, }, 182 { "bridge", PCI_CLASS_BRIDGE, 183 pci_subclass_bridge, }, 184 { "communications", PCI_CLASS_COMMUNICATIONS, 185 pci_subclass_communications, }, 186 { "system", PCI_CLASS_SYSTEM, 187 pci_subclass_system, }, 188 { "input", PCI_CLASS_INPUT, 189 pci_subclass_input, }, 190 { "dock", PCI_CLASS_DOCK, 191 pci_subclass_dock, }, 192 { "processor", PCI_CLASS_PROCESSOR, 193 pci_subclass_processor, }, 194 { "serial bus", PCI_CLASS_SERIALBUS, 195 pci_subclass_serialbus, }, 196 { "undefined", PCI_CLASS_UNDEFINED, 197 0, }, 198 { 0 }, 199 }; 200 201 #ifdef PCIVERBOSE 202 /* 203 * Descriptions of of known vendors and devices ("products"). 204 */ 205 struct pci_knowndev { 206 pci_vendor_id_t vendor; 207 pci_product_id_t product; 208 int flags; 209 char *vendorname, *productname; 210 }; 211 #define PCI_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ 212 213 #include <dev/pci/pcidevs_data.h> 214 #endif /* PCIVERBOSE */ 215 216 void 217 pci_devinfo(id_reg, class_reg, showclass, cp) 218 pcireg_t id_reg, class_reg; 219 int showclass; 220 char *cp; 221 { 222 pci_vendor_id_t vendor; 223 pci_product_id_t product; 224 pci_class_t class; 225 pci_subclass_t subclass; 226 pci_interface_t interface; 227 pci_revision_t revision; 228 char *vendor_namep, *product_namep; 229 struct pci_class *classp, *subclassp; 230 #ifdef PCIVERBOSE 231 struct pci_knowndev *kdp; 232 const char *unmatched = "unknown "; 233 #else 234 const char *unmatched = ""; 235 #endif 236 237 vendor = PCI_VENDOR(id_reg); 238 product = PCI_PRODUCT(id_reg); 239 240 class = PCI_CLASS(class_reg); 241 subclass = PCI_SUBCLASS(class_reg); 242 interface = PCI_INTERFACE(class_reg); 243 revision = PCI_REVISION(class_reg); 244 245 #ifdef PCIVERBOSE 246 kdp = pci_knowndevs; 247 while (kdp->vendorname != NULL) { /* all have vendor name */ 248 if (kdp->vendor == vendor && (kdp->product == product || 249 (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0)) 250 break; 251 kdp++; 252 } 253 if (kdp->vendorname == NULL) 254 vendor_namep = product_namep = NULL; 255 else { 256 vendor_namep = kdp->vendorname; 257 product_namep = (kdp->flags & PCI_KNOWNDEV_NOPROD) == 0 ? 258 kdp->productname : NULL; 259 } 260 #else /* PCIVERBOSE */ 261 vendor_namep = product_namep = NULL; 262 #endif /* PCIVERBOSE */ 263 264 classp = pci_class; 265 while (classp->name != NULL) { 266 if (class == classp->val) 267 break; 268 classp++; 269 } 270 271 subclassp = (classp->name != NULL) ? classp->subclasses : NULL; 272 while (subclassp && subclassp->name != NULL) { 273 if (subclass == subclassp->val) 274 break; 275 subclassp++; 276 } 277 278 if (vendor_namep == NULL) 279 cp += sprintf(cp, "%svendor 0x%04x product 0x%04x", 280 unmatched, vendor, product); 281 else if (product_namep != NULL) 282 cp += sprintf(cp, "%s %s", vendor_namep, product_namep); 283 else 284 cp += sprintf(cp, "%s product 0x%04x", 285 vendor_namep, product); 286 if (showclass) { 287 cp += sprintf(cp, " ("); 288 if (classp->name == NULL) 289 cp += sprintf(cp, "class 0x%02x, subclass 0x%02x", 290 class, subclass); 291 else { 292 if (subclassp == NULL || subclassp->name == NULL) 293 cp += sprintf(cp, 294 "%s subclass 0x%02x", 295 classp->name, subclass); 296 else 297 cp += sprintf(cp, "%s %s", 298 subclassp->name, classp->name); 299 } 300 if (interface != 0) 301 cp += sprintf(cp, ", interface 0x%02x", interface); 302 if (revision != 0) 303 cp += sprintf(cp, ", revision 0x%02x", revision); 304 cp += sprintf(cp, ")"); 305 } 306 } 307