xref: /openbsd-src/sys/dev/pci/pci_subr.c (revision ebc9184232ccbd6ce977bb6a81e16e0127623ab0)
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