pci_subr.c revision 1.14 1 /* $NetBSD: pci_subr.c,v 1.14 1996/02/28 01:44:43 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 #endif
166
167 vendor = PCI_VENDOR(id_reg);
168 product = PCI_PRODUCT(id_reg);
169
170 class = PCI_CLASS(class_reg);
171 subclass = PCI_SUBCLASS(class_reg);
172 interface = PCI_INTERFACE(class_reg);
173 revision = PCI_REVISION(class_reg);
174
175 #ifdef PCIVERBOSE
176 kdp = pci_knowndevs;
177 while (kdp->vendorname != NULL) { /* all have vendor name */
178 if (kdp->vendor == vendor && (kdp->product == product ||
179 (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0))
180 break;
181 kdp++;
182 }
183 if (kdp->vendorname == NULL)
184 vendor_namep = product_namep = NULL;
185 else {
186 vendor_namep = kdp->vendorname;
187 product_namep = (kdp->flags & PCI_KNOWNDEV_NOPROD) == 0 ?
188 kdp->productname : NULL;
189 }
190 #else /* PCIVERBOSE */
191 vendor_namep = product_namep = NULL;
192 #endif /* PCIVERBOSE */
193
194 classp = pci_class;
195 while (classp->name != NULL) {
196 if (class == classp->val)
197 break;
198 classp++;
199 }
200
201 subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
202 while (subclassp && subclassp->name != NULL) {
203 if (subclass == subclassp->val)
204 break;
205 subclassp++;
206 }
207
208 if (vendor_namep == NULL)
209 cp += sprintf(cp, "unknown vendor/product: 0x%04x/0x%04x",
210 vendor, product);
211 else if (product_namep != NULL)
212 cp += sprintf(cp, "%s %s", vendor_namep, product_namep);
213 else
214 cp += sprintf(cp, "vendor: %s, unknown product: 0x%x",
215 vendor_namep, product);
216 if (showclass) {
217 cp += sprintf(cp, " (");
218 if (classp->name == NULL)
219 cp += sprintf(cp,
220 "unknown class/subclass: 0x%02x/0x%02x",
221 class, subclass);
222 else {
223 cp += sprintf(cp, "class: %s, ", classp->name);
224 if (subclassp == NULL || subclassp->name == NULL)
225 cp += sprintf(cp, "unknown subclass: 0x%02x",
226 subclass);
227 else
228 cp += sprintf(cp, "subclass: %s",
229 subclassp->name);
230 }
231 #if 0 /* not very useful */
232 cp += sprintf(cp, ", interface: 0x%02x", interface);
233 #endif
234 cp += sprintf(cp, ", revision: 0x%02x)", revision);
235 }
236 }
237