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