pci_subr.c revision 1.16 1 /* $NetBSD: pci_subr.c,v 1.16 1996/03/02 01:09:13 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/product: 0x%04x/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/subclass: 0x%02x/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