Line data Source code
1 : /* $OpenBSD: pci_subr.c,v 1.22 2017/03/22 07:21:39 jsg 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 : { "UFS", PCI_SUBCLASS_MASS_STORAGE_UFS, },
77 : { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, },
78 : { 0 },
79 : };
80 :
81 : const struct pci_class pci_subclass_network[] = {
82 : { "ethernet", PCI_SUBCLASS_NETWORK_ETHERNET, },
83 : { "token ring", PCI_SUBCLASS_NETWORK_TOKENRING, },
84 : { "FDDI", PCI_SUBCLASS_NETWORK_FDDI, },
85 : { "ATM", PCI_SUBCLASS_NETWORK_ATM, },
86 : { "ISDN", PCI_SUBCLASS_NETWORK_ISDN, },
87 : { "WorldFip", PCI_SUBCLASS_NETWORK_WORLDFIP, },
88 : { "PCMIG Multi Computing", PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, },
89 : { "InfiniBand", PCI_SUBCLASS_NETWORK_INFINIBAND, },
90 : { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, },
91 : { 0 },
92 : };
93 :
94 : const struct pci_class pci_subclass_display[] = {
95 : { "VGA", PCI_SUBCLASS_DISPLAY_VGA, },
96 : { "XGA", PCI_SUBCLASS_DISPLAY_XGA, },
97 : { "3D", PCI_SUBCLASS_DISPLAY_3D, },
98 : { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, },
99 : { 0 },
100 : };
101 :
102 : const struct pci_class pci_subclass_multimedia[] = {
103 : { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, },
104 : { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, },
105 : { "telephony", PCI_SUBCLASS_MULTIMEDIA_TELEPHONY, },
106 : { "hdaudio", PCI_SUBCLASS_MULTIMEDIA_HDAUDIO, },
107 : { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, },
108 : { 0 },
109 : };
110 :
111 : const struct pci_class pci_subclass_memory[] = {
112 : { "RAM", PCI_SUBCLASS_MEMORY_RAM, },
113 : { "flash", PCI_SUBCLASS_MEMORY_FLASH, },
114 : { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, },
115 : { 0 },
116 : };
117 :
118 : const struct pci_class pci_subclass_bridge[] = {
119 : { "host", PCI_SUBCLASS_BRIDGE_HOST, },
120 : { "ISA", PCI_SUBCLASS_BRIDGE_ISA, },
121 : { "EISA", PCI_SUBCLASS_BRIDGE_EISA, },
122 : { "MicroChannel", PCI_SUBCLASS_BRIDGE_MC, },
123 : { "PCI", PCI_SUBCLASS_BRIDGE_PCI, },
124 : { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, },
125 : { "NuBus", PCI_SUBCLASS_BRIDGE_NUBUS, },
126 : { "CardBus", PCI_SUBCLASS_BRIDGE_CARDBUS, },
127 : { "RACEway", PCI_SUBCLASS_BRIDGE_RACEWAY, },
128 : { "Semi-transparent PCI", PCI_SUBCLASS_BRIDGE_STPCI, },
129 : { "InfiniBand", PCI_SUBCLASS_BRIDGE_INFINIBAND, },
130 : { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, },
131 : { "advanced switching", PCI_SUBCLASS_BRIDGE_AS, },
132 : { 0 },
133 : };
134 :
135 : const struct pci_class pci_subclass_communications[] = {
136 : { "serial", PCI_SUBCLASS_COMMUNICATIONS_SERIAL, },
137 : { "parallel", PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, },
138 : { "multi-port serial", PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL, },
139 : { "modem", PCI_SUBCLASS_COMMUNICATIONS_MODEM, },
140 : { "GPIB", PCI_SUBCLASS_COMMUNICATIONS_GPIB, },
141 : { "smartcard", PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD, },
142 : { "miscellaneous", PCI_SUBCLASS_COMMUNICATIONS_MISC, },
143 : { 0 },
144 : };
145 :
146 : const struct pci_class pci_subclass_system[] = {
147 : { "interrupt", PCI_SUBCLASS_SYSTEM_PIC, },
148 : { "8237 DMA", PCI_SUBCLASS_SYSTEM_DMA, },
149 : { "8254 timer", PCI_SUBCLASS_SYSTEM_TIMER, },
150 : { "RTC", PCI_SUBCLASS_SYSTEM_RTC, },
151 : { "PCI Hot-Plug", PCI_SUBCLASS_SYSTEM_PCIHOTPLUG, },
152 : { "SD Host Controller", PCI_SUBCLASS_SYSTEM_SDHC, },
153 : { "IOMMU", PCI_SUBCLASS_SYSTEM_IOMMU, },
154 : { "root complex event", PCI_SUBCLASS_SYSTEM_ROOTCOMPEVENT, },
155 : { "miscellaneous", PCI_SUBCLASS_SYSTEM_MISC, },
156 : { 0 },
157 : };
158 :
159 : const struct pci_class pci_subclass_input[] = {
160 : { "keyboard", PCI_SUBCLASS_INPUT_KEYBOARD, },
161 : { "digitizer", PCI_SUBCLASS_INPUT_DIGITIZER, },
162 : { "mouse", PCI_SUBCLASS_INPUT_MOUSE, },
163 : { "scanner", PCI_SUBCLASS_INPUT_SCANNER, },
164 : { "game port", PCI_SUBCLASS_INPUT_GAMEPORT, },
165 : { "miscellaneous", PCI_SUBCLASS_INPUT_MISC, },
166 : { 0 },
167 : };
168 :
169 : const struct pci_class pci_subclass_dock[] = {
170 : { "generic", PCI_SUBCLASS_DOCK_GENERIC, },
171 : { "miscellaneous", PCI_SUBCLASS_DOCK_MISC, },
172 : { 0 },
173 : };
174 :
175 : const struct pci_class pci_subclass_processor[] = {
176 : { "386", PCI_SUBCLASS_PROCESSOR_386, },
177 : { "486", PCI_SUBCLASS_PROCESSOR_486, },
178 : { "Pentium", PCI_SUBCLASS_PROCESSOR_PENTIUM, },
179 : { "Alpha", PCI_SUBCLASS_PROCESSOR_ALPHA, },
180 : { "PowerPC", PCI_SUBCLASS_PROCESSOR_POWERPC, },
181 : { "MIPS", PCI_SUBCLASS_PROCESSOR_MIPS, },
182 : { "Co-processor", PCI_SUBCLASS_PROCESSOR_COPROC, },
183 : { 0 },
184 : };
185 :
186 : const struct pci_class pci_subclass_serialbus[] = {
187 : { "Firewire", PCI_SUBCLASS_SERIALBUS_FIREWIRE, },
188 : { "ACCESS.bus", PCI_SUBCLASS_SERIALBUS_ACCESS, },
189 : { "SSA", PCI_SUBCLASS_SERIALBUS_SSA, },
190 : { "USB", PCI_SUBCLASS_SERIALBUS_USB, },
191 : /* XXX Fiber Channel/_FIBRECHANNEL */
192 : { "Fiber Channel", PCI_SUBCLASS_SERIALBUS_FIBER, },
193 : { "SMBus", PCI_SUBCLASS_SERIALBUS_SMBUS, },
194 : { "InfiniBand", PCI_SUBCLASS_SERIALBUS_INFINIBAND, },
195 : { "IPMI", PCI_SUBCLASS_SERIALBUS_IPMI, },
196 : { "SERCOS", PCI_SUBCLASS_SERIALBUS_SERCOS, },
197 : { "CANbus", PCI_SUBCLASS_SERIALBUS_CANBUS, },
198 : { 0 },
199 : };
200 :
201 : const struct pci_class pci_subclass_wireless[] = {
202 : { "IrDA", PCI_SUBCLASS_WIRELESS_IRDA, },
203 : { "Consumer IR", PCI_SUBCLASS_WIRELESS_CONSUMERIR, },
204 : { "RF", PCI_SUBCLASS_WIRELESS_RF, },
205 : { "bluetooth", PCI_SUBCLASS_WIRELESS_BLUETOOTH, },
206 : { "broadband", PCI_SUBCLASS_WIRELESS_BROADBAND, },
207 : { "802.11a (5 GHz)", PCI_SUBCLASS_WIRELESS_802_11A, },
208 : { "802.11b (2.4 GHz)", PCI_SUBCLASS_WIRELESS_802_11B, },
209 : { "miscellaneous", PCI_SUBCLASS_WIRELESS_MISC, },
210 : { 0 },
211 : };
212 :
213 : const struct pci_class pci_subclass_i2o[] = {
214 : { "standard", PCI_SUBCLASS_I2O_STANDARD, },
215 : { 0 },
216 : };
217 :
218 : const struct pci_class pci_subclass_satcom[] = {
219 : { "TV", PCI_SUBCLASS_SATCOM_TV, },
220 : { "audio", PCI_SUBCLASS_SATCOM_AUDIO, },
221 : { "voice", PCI_SUBCLASS_SATCOM_VOICE, },
222 : { "data", PCI_SUBCLASS_SATCOM_DATA, },
223 : { 0 },
224 : };
225 :
226 : const struct pci_class pci_subclass_crypto[] = {
227 : { "network/computing", PCI_SUBCLASS_CRYPTO_NETCOMP, },
228 : { "entertainment", PCI_SUBCLASS_CRYPTO_ENTERTAINMENT, },
229 : { "miscellaneous", PCI_SUBCLASS_CRYPTO_MISC, },
230 : { 0 },
231 : };
232 :
233 : const struct pci_class pci_subclass_dasp[] = {
234 : { "DPIO", PCI_SUBCLASS_DASP_DPIO, },
235 : { "Time and Frequency", PCI_SUBCLASS_DASP_TIMEFREQ, },
236 : { "synchronization", PCI_SUBCLASS_DASP_SYNC, },
237 : { "management", PCI_SUBCLASS_DASP_MGMT, },
238 : { "miscellaneous", PCI_SUBCLASS_DASP_MISC, },
239 : { 0 },
240 : };
241 :
242 : const struct pci_class pci_class[] = {
243 : { "prehistoric", PCI_CLASS_PREHISTORIC,
244 : pci_subclass_prehistoric, },
245 : { "mass storage", PCI_CLASS_MASS_STORAGE,
246 : pci_subclass_mass_storage, },
247 : { "network", PCI_CLASS_NETWORK,
248 : pci_subclass_network, },
249 : { "display", PCI_CLASS_DISPLAY,
250 : pci_subclass_display, },
251 : { "multimedia", PCI_CLASS_MULTIMEDIA,
252 : pci_subclass_multimedia, },
253 : { "memory", PCI_CLASS_MEMORY,
254 : pci_subclass_memory, },
255 : { "bridge", PCI_CLASS_BRIDGE,
256 : pci_subclass_bridge, },
257 : { "communications", PCI_CLASS_COMMUNICATIONS,
258 : pci_subclass_communications, },
259 : { "system", PCI_CLASS_SYSTEM,
260 : pci_subclass_system, },
261 : { "input", PCI_CLASS_INPUT,
262 : pci_subclass_input, },
263 : { "dock", PCI_CLASS_DOCK,
264 : pci_subclass_dock, },
265 : { "processor", PCI_CLASS_PROCESSOR,
266 : pci_subclass_processor, },
267 : { "serial bus", PCI_CLASS_SERIALBUS,
268 : pci_subclass_serialbus, },
269 : { "wireless", PCI_CLASS_WIRELESS,
270 : pci_subclass_wireless, },
271 : { "I2O", PCI_CLASS_I2O,
272 : pci_subclass_i2o, },
273 : { "satellite comm", PCI_CLASS_SATCOM,
274 : pci_subclass_satcom, },
275 : { "crypto", PCI_CLASS_CRYPTO,
276 : pci_subclass_crypto, },
277 : { "DASP", PCI_CLASS_DASP,
278 : pci_subclass_dasp, },
279 : { "accelerator", PCI_CLASS_ACCELERATOR,
280 : NULL, },
281 : { "instrumentation", PCI_CLASS_INSTRUMENTATION,
282 : NULL, },
283 : { "undefined", PCI_CLASS_UNDEFINED,
284 : 0, },
285 : { 0 },
286 : };
287 :
288 : const char *
289 0 : pci_findvendor(pcireg_t id_reg)
290 : {
291 : #ifdef PCIVERBOSE
292 0 : pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
293 : const struct pci_known_vendor *kdp;
294 :
295 : kdp = pci_known_vendors;
296 0 : while (kdp->vendorname != NULL) { /* all have vendor name */
297 0 : if (kdp->vendor == vendor)
298 : break;
299 0 : kdp++;
300 : }
301 0 : return (kdp->vendorname);
302 : #else
303 : return (NULL);
304 : #endif
305 : }
306 :
307 : const char *
308 0 : pci_findproduct(pcireg_t id_reg)
309 : {
310 : #ifdef PCIVERBOSE
311 0 : pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
312 0 : pci_product_id_t product = PCI_PRODUCT(id_reg);
313 : const struct pci_known_product *pkp;
314 :
315 : pkp = pci_known_products;
316 0 : while (pkp->productname != NULL) { /* all have product name */
317 0 : if (pkp->vendor == vendor && pkp->product == product)
318 : break;
319 0 : pkp++;
320 : }
321 0 : return (pkp->productname);
322 : #else
323 : return NULL;
324 : #endif
325 : }
326 :
327 : void
328 0 : pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp,
329 : size_t cp_max)
330 : {
331 : pci_vendor_id_t vendor;
332 : pci_product_id_t product;
333 : pci_class_t class;
334 : pci_subclass_t subclass;
335 : pci_interface_t interface;
336 : pci_revision_t revision;
337 : const char *vendor_namep = NULL, *product_namep = NULL;
338 : const struct pci_class *classp, *subclassp;
339 : size_t cp_len = 0;
340 : #ifdef PCIVERBOSE
341 : const char *unmatched = "unknown ";
342 : #else
343 : const char *unmatched = "";
344 : #endif
345 :
346 0 : vendor = PCI_VENDOR(id_reg);
347 0 : product = PCI_PRODUCT(id_reg);
348 :
349 0 : class = PCI_CLASS(class_reg);
350 0 : subclass = PCI_SUBCLASS(class_reg);
351 0 : interface = PCI_INTERFACE(class_reg);
352 0 : revision = PCI_REVISION(class_reg);
353 :
354 : #ifdef PCIVERBOSE
355 0 : vendor_namep = pci_findvendor(id_reg);
356 0 : if (vendor_namep != NULL)
357 0 : product_namep = pci_findproduct(id_reg);
358 : #endif /* PCIVERBOSE */
359 :
360 : classp = pci_class;
361 0 : while (classp->name != NULL) {
362 0 : if (class == classp->val)
363 : break;
364 0 : classp++;
365 : }
366 :
367 0 : subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
368 0 : while (subclassp && subclassp->name != NULL) {
369 0 : if (subclass == subclassp->val)
370 : break;
371 0 : subclassp++;
372 : }
373 :
374 0 : if (vendor_namep == NULL)
375 0 : snprintf(cp, cp_max, "%svendor 0x%04x product 0x%04x",
376 0 : unmatched, vendor, product);
377 0 : else if (product_namep != NULL)
378 0 : snprintf(cp, cp_max, "\"%s %s\"", vendor_namep, product_namep);
379 : else
380 0 : snprintf(cp, cp_max, "vendor \"%s\", unknown product 0x%04x",
381 0 : vendor_namep, product);
382 0 : if (showclass && product_namep == NULL) {
383 0 : strlcat(cp, " (", cp_max);
384 0 : cp_len = strlen(cp);
385 0 : if (classp->name == NULL)
386 0 : snprintf(cp + cp_len, cp_max - cp_len,
387 : "unknown class 0x%02x, subclass 0x%02x",
388 0 : class, subclass);
389 0 : else if (subclassp == NULL || subclassp->name == NULL)
390 0 : snprintf(cp + cp_len, cp_max - cp_len,
391 0 : "class %s unknown subclass 0x%02x", classp->name,
392 0 : subclass);
393 : else
394 0 : snprintf(cp + cp_len, cp_max - cp_len,
395 : "class %s subclass %s", classp->name,
396 : subclassp->name);
397 : #if 0 /* not very useful */
398 : cp_len = strlen(cp);
399 : snprintf(cp + cp_len, cp_max - cp_len,
400 : ", interface 0x%02x", interface);
401 : #endif
402 0 : cp_len = strlen(cp);
403 0 : snprintf(cp + cp_len, cp_max - cp_len,
404 0 : ", rev 0x%02x)", revision);
405 0 : } else {
406 0 : cp_len = strlen(cp);
407 0 : snprintf(cp + cp_len, cp_max - cp_len, " rev 0x%02x",
408 0 : revision);
409 : }
410 0 : }
|