1 /* $OpenBSD: pci_subr.c,v 1.3 1996/10/31 03:29:11 millert Exp $ */ 2 /* $NetBSD: pci_subr.c,v 1.17 1996/03/02 02:28:48 cgd 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 char *name; 56 int val; /* as wide as pci_{,sub}class_t */ 57 struct pci_class *subclasses; 58 }; 59 60 struct pci_class pci_subclass_prehistoric[] = { 61 { "miscellaneous", PCI_SUBCLASS_PREHISTORIC_MISC, }, 62 { "VGA", PCI_SUBCLASS_PREHISTORIC_VGA, }, 63 { 0 } 64 }; 65 66 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 { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, }, 72 { 0 }, 73 }; 74 75 struct pci_class pci_subclass_network[] = { 76 { "ethernet", PCI_SUBCLASS_NETWORK_ETHERNET, }, 77 { "token ring", PCI_SUBCLASS_NETWORK_TOKENRING, }, 78 { "FDDI", PCI_SUBCLASS_NETWORK_FDDI, }, 79 { "ATM", PCI_SUBCLASS_NETWORK_ATM, }, 80 { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, }, 81 { 0 }, 82 }; 83 84 struct pci_class pci_subclass_display[] = { 85 { "VGA", PCI_SUBCLASS_DISPLAY_VGA, }, 86 { "XGA", PCI_SUBCLASS_DISPLAY_XGA, }, 87 { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, }, 88 { 0 }, 89 }; 90 91 struct pci_class pci_subclass_multimedia[] = { 92 { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, }, 93 { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, }, 94 { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, }, 95 { 0 }, 96 }; 97 98 struct pci_class pci_subclass_memory[] = { 99 { "RAM", PCI_SUBCLASS_MEMORY_RAM, }, 100 { "flash", PCI_SUBCLASS_MEMORY_FLASH, }, 101 { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, }, 102 { 0 }, 103 }; 104 105 struct pci_class pci_subclass_bridge[] = { 106 { "host", PCI_SUBCLASS_BRIDGE_HOST, }, 107 { "ISA", PCI_SUBCLASS_BRIDGE_ISA, }, 108 { "EISA", PCI_SUBCLASS_BRIDGE_EISA, }, 109 { "MicroChannel", PCI_SUBCLASS_BRIDGE_MC, }, 110 { "PCI", PCI_SUBCLASS_BRIDGE_PCI, }, 111 { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, }, 112 { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, }, 113 { 0 }, 114 }; 115 116 struct pci_class pci_class[] = { 117 { "prehistoric", PCI_CLASS_PREHISTORIC, 118 pci_subclass_prehistoric, }, 119 { "mass storage", PCI_CLASS_MASS_STORAGE, 120 pci_subclass_mass_storage, }, 121 { "network", PCI_CLASS_NETWORK, 122 pci_subclass_network, }, 123 { "display", PCI_CLASS_DISPLAY, 124 pci_subclass_display, }, 125 { "multimedia", PCI_CLASS_MULTIMEDIA, 126 pci_subclass_multimedia, }, 127 { "memory", PCI_CLASS_MEMORY, 128 pci_subclass_memory, }, 129 { "bridge", PCI_CLASS_BRIDGE, 130 pci_subclass_bridge, }, 131 { "undefined", PCI_CLASS_UNDEFINED, 132 0, }, 133 { 0 }, 134 }; 135 136 #ifdef PCIVERBOSE 137 /* 138 * Descriptions of of known vendors and devices ("products"). 139 */ 140 struct pci_knowndev { 141 pci_vendor_id_t vendor; 142 pci_product_id_t product; 143 int flags; 144 char *vendorname, *productname; 145 }; 146 #define PCI_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ 147 148 #include <dev/pci/pcidevs_data.h> 149 #endif /* PCIVERBOSE */ 150 151 void 152 pci_devinfo(id_reg, class_reg, showclass, cp) 153 pcireg_t id_reg, class_reg; 154 int showclass; 155 char *cp; 156 { 157 pci_vendor_id_t vendor; 158 pci_product_id_t product; 159 pci_class_t class; 160 pci_subclass_t subclass; 161 pci_interface_t interface; 162 pci_revision_t revision; 163 char *vendor_namep, *product_namep; 164 struct pci_class *classp, *subclassp; 165 #ifdef PCIVERBOSE 166 struct pci_knowndev *kdp; 167 const char *unmatched = "unknown "; 168 #else 169 const char *unmatched = ""; 170 #endif 171 172 vendor = PCI_VENDOR(id_reg); 173 product = PCI_PRODUCT(id_reg); 174 175 class = PCI_CLASS(class_reg); 176 subclass = PCI_SUBCLASS(class_reg); 177 interface = PCI_INTERFACE(class_reg); 178 revision = PCI_REVISION(class_reg); 179 180 #ifdef PCIVERBOSE 181 kdp = pci_knowndevs; 182 while (kdp->vendorname != NULL) { /* all have vendor name */ 183 if (kdp->vendor == vendor && (kdp->product == product || 184 (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0)) 185 break; 186 kdp++; 187 } 188 if (kdp->vendorname == NULL) 189 vendor_namep = product_namep = NULL; 190 else { 191 vendor_namep = kdp->vendorname; 192 product_namep = (kdp->flags & PCI_KNOWNDEV_NOPROD) == 0 ? 193 kdp->productname : NULL; 194 } 195 #else /* PCIVERBOSE */ 196 vendor_namep = product_namep = NULL; 197 #endif /* PCIVERBOSE */ 198 199 classp = pci_class; 200 while (classp->name != NULL) { 201 if (class == classp->val) 202 break; 203 classp++; 204 } 205 206 subclassp = (classp->name != NULL) ? classp->subclasses : NULL; 207 while (subclassp && subclassp->name != NULL) { 208 if (subclass == subclassp->val) 209 break; 210 subclassp++; 211 } 212 213 if (vendor_namep == NULL) 214 cp += sprintf(cp, "%svendor 0x%04x product 0x%04x", 215 unmatched, vendor, product); 216 else if (product_namep != NULL) 217 cp += sprintf(cp, "%s %s", vendor_namep, product_namep); 218 else 219 cp += sprintf(cp, "vendor %s, unknown product 0x%x", 220 vendor_namep, product); 221 if (showclass) { 222 cp += sprintf(cp, " ("); 223 if (classp->name == NULL) 224 cp += sprintf(cp, 225 "unknown class 0x%2x, subclass 0x%02x", 226 class, subclass); 227 else { 228 cp += sprintf(cp, "class %s, ", classp->name); 229 if (subclassp == NULL || subclassp->name == NULL) 230 cp += sprintf(cp, "unknown subclass 0x%02x", 231 subclass); 232 else 233 cp += sprintf(cp, "subclass %s", 234 subclassp->name); 235 } 236 #if 0 /* not very useful */ 237 cp += sprintf(cp, ", interface 0x%02x", interface); 238 #endif 239 cp += sprintf(cp, ", revision 0x%02x)", revision); 240 } 241 } 242