blob: 607ec0c624a8b90750ec3aaeec95ede1585841b2 [file] [log] [blame]
Lee Leahye1ba3da2015-03-31 17:30:01 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
5 * Copyright (C) 2015 Intel Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <device/device.h>
22#include <device/pci.h>
23#include <device/pciexp.h>
24#include <device/pci_ids.h>
25#include <stdlib.h>
26
27typedef struct {
28 const unsigned char subclass_id;
29 const char *subclass_name;
30} PCI_SUBCLASS;
31
32typedef struct {
33 const unsigned char class_id;
34 const PCI_SUBCLASS *subclass_list;
35 const unsigned int subclass_entries;
36 const char *class_name;
37} PCI_CLASS;
38
39static const PCI_SUBCLASS unclassified[] = {
40 { 0x00, "Non-VGA device" },
41 { 0x01, "VGA compatible device" }
42};
43
44static const PCI_SUBCLASS mass_storage[] = {
45 { 0x00, "SCSI storage controller" },
46 { 0x01, "IDE interface" },
47 { 0x02, "Floppy disk controller" },
48 { 0x03, "IPI bus controller" },
49 { 0x04, "RAID bus controller" },
50 { 0x05, "ATA controller" },
51 { 0x06, "SATA controller" },
52 { 0x07, "Serial Attached SCSI controller" },
53 { 0x08, "Non-Volatile memory controller" },
54 { 0x80, "Mass storage controller" }
55};
56
57static const PCI_SUBCLASS network[] = {
58 { 0x00, "Ethernet controller" },
59 { 0x01, "Token ring network controller" },
60 { 0x02, "FDDI network controller" },
61 { 0x03, "ATM network controller" },
62 { 0x04, "ISDN controller" },
63 { 0x05, "WorldFip controller" },
64 { 0x06, "PICMG controller" },
65 { 0x80, "Network controller" }
66};
67
68static const PCI_SUBCLASS display[] = {
69 { 0x00, "VGA compatible controller" },
70 { 0x01, "XGA compatible controller" },
71 { 0x02, "3D controller" },
72 { 0x80, "Display controller" }
73};
74
75static const PCI_SUBCLASS multimedia[] = {
76 { 0x00, "Multimedia video controller" },
77 { 0x01, "Multimedia audio controller" },
78 { 0x02, "Computer telephony device" },
79 { 0x03, "Audio device" },
80 { 0x80, "Multimedia controller" }
81};
82
83static const PCI_SUBCLASS memory[] = {
84 { 0x00, "RAM memory" },
85 { 0x01, "FLASH memory" },
86 { 0x80, "Memory controller" }
87};
88
89static const PCI_SUBCLASS bridge[] = {
90 { 0x00, "Host bridge" },
91 { 0x01, "ISA bridge" },
92 { 0x02, "EISA bridge" },
93 { 0x03, "MicroChannel bridge" },
94 { 0x04, "PCI bridge" },
95 { 0x05, "PCMCIA bridge" },
96 { 0x06, "NuBus bridge" },
97 { 0x07, "CardBus bridge" },
98 { 0x08, "RACEway bridge" },
99 { 0x09, "Semi-transparent PCI-to-PCI bridge" },
100 { 0x0a, "InfiniBand to PCI host bridge" },
101 { 0x80, "Bridge" }
102};
103
104static const PCI_SUBCLASS communication[] = {
105 { 0x00, "Serial controller" },
106 { 0x01, "Parallel controller" },
107 { 0x02, "Multiport serial controller" },
108 { 0x03, "Modem" },
109 { 0x04, "GPIB controller" },
110 { 0x05, "Smard Card controller" },
111 { 0x80, "Communication controller" }
112};
113
114static const PCI_SUBCLASS generic[] = {
115 { 0x00, "PIC" },
116 { 0x01, "DMA controller" },
117 { 0x02, "Timer" },
118 { 0x03, "RTC" },
119 { 0x04, "PCI Hot-plug controller" },
120 { 0x05, "SD Host controller" },
121 { 0x06, "IOMMU" },
122 { 0x80, "System peripheral" }
123};
124
125static const PCI_SUBCLASS input_device[] = {
126 { 0x00, "Keyboard controller" },
127 { 0x01, "Digitizer Pen" },
128 { 0x02, "Mouse controller" },
129 { 0x03, "Scanner controller" },
130 { 0x04, "Gameport controller" },
131 { 0x80, "Input device controller" }
132};
133
134static const PCI_SUBCLASS docking_station[] = {
135 { 0x00, "Generic Docking Station" },
136 { 0x80, "Docking Station" }
137};
138
139static const PCI_SUBCLASS processor[] = {
140 { 0x00, "386" },
141 { 0x01, "486" },
142 { 0x02, "Pentium" },
143 { 0x10, "Alpha" },
144 { 0x20, "Power PC" },
145 { 0x30, "MIPS" },
146 { 0x40, "Co-processor" }
147};
148
149static const PCI_SUBCLASS serial_bus[] = {
150 { 0x00, "FireWire (IEEE 1394)" },
151 { 0x01, "ACCESS Bus" },
152 { 0x02, "SSA" },
153 { 0x03, "USB controller" },
154 { 0x04, "Fibre Channel" },
155 { 0x05, "SMBus" },
156 { 0x06, "InfiniBand" },
157 { 0x07, "IPMI SMIC interface" },
158 { 0x08, "SERCOS interface" },
159 { 0x09, "CANBUS" }
160};
161
162static const PCI_SUBCLASS wireless[] = {
163 { 0x00, "IRDA controller" },
164 { 0x01, "Consumer IR controller" },
165 { 0x10, "RF controller" },
166 { 0x11, "Bluetooth" },
167 { 0x12, "Broadband" },
168 { 0x20, "802.1a controller" },
169 { 0x21, "802.1b controller" },
170 { 0x80, "Wireless controller" }
171};
172
173static const PCI_SUBCLASS intellegient_controller[] = {
174 { 0x00, "I2O" }
175};
176
177static const PCI_SUBCLASS satellite_controller[] = {
178 { 0x01, "Satellite TV controller" },
179 { 0x02, "Satellite audio communication controller" },
180 { 0x03, "Satellite voice communication controller" },
181 { 0x04, "Satellite data communication controller" }
182};
183
184static const PCI_SUBCLASS encryption[] = {
185 { 0x00, "Network and computing encryption device" },
186 { 0x10, "Entertainment encryption device" },
187 { 0x80, "Encryption controller" }
188};
189
190static const PCI_SUBCLASS signal_processing[] = {
191 { 0x00, "DPIO module" },
192 { 0x01, "Performance counters" },
193 { 0x10, "Communication synchronizer" },
194 { 0x20, "Signal processing management" },
195 { 0x80, "Signal processing controller" }
196};
197
198static const PCI_CLASS class_list[] = {
199 { 0x00, &unclassified[0], ARRAY_SIZE(unclassified),
200 "Unclassified device" },
201 { 0x01, &mass_storage[0], ARRAY_SIZE(mass_storage), "Mass storage" },
202 { 0x02, &network[0], ARRAY_SIZE(network), "Network" },
203 { 0x03, &display[0], ARRAY_SIZE(display), "Display" },
204 { 0x04, &multimedia[0], ARRAY_SIZE(multimedia), "Multimedia" },
205 { 0x05, &memory[0], ARRAY_SIZE(memory), "Memory" },
206 { 0x06, &bridge[0], ARRAY_SIZE(bridge), "Bridge" },
207 { 0x07, &communication[0], ARRAY_SIZE(communication), "Communication" },
208 { 0x08, &generic[0], ARRAY_SIZE(generic), "Generic system peripheral" },
209 { 0x09, &input_device[0], ARRAY_SIZE(input_device), "Input device" },
210 { 0x0a, &docking_station[0], ARRAY_SIZE(docking_station),
211 "Docking station" },
212 { 0x0b, &processor[0], ARRAY_SIZE(processor), "Processor" },
213 { 0x0c, &serial_bus[0], ARRAY_SIZE(serial_bus), "Serial bus" },
214 { 0x0d, &wireless[0], ARRAY_SIZE(wireless), "Wireless" },
215 { 0x0e, &intellegient_controller[0],
216 ARRAY_SIZE(intellegient_controller),
217 "Intelligent controller" },
218 { 0x0f, &satellite_controller[0], ARRAY_SIZE(satellite_controller),
219 "Satellite communications" },
220 { 0x10, &encryption[0], ARRAY_SIZE(encryption), "Encryption" },
221 { 0x11, &signal_processing[0], ARRAY_SIZE(signal_processing),
222 "Signal processing" },
223 { 0xff, NULL, 0, "Unassigned class" }
224};
225static const unsigned int class_entries = ARRAY_SIZE(class_list);
226
227static const PCI_CLASS *get_pci_class_entry(device_t dev)
228{
229 unsigned char class;
230 const PCI_CLASS *class_entry;
231 const PCI_CLASS *class_list_end;
232
233 /* Get the PCI device class */
234 class = pci_read_config8(dev, PCI_CLASS_DEVICE+1);
235
236 /* Locate the class entry */
237 class_entry = &class_list[0];
238 class_list_end = &class_entry[class_entries];
239 while (class_list_end > class_entry) {
240 if (class_entry->class_id == class)
241 return class_entry;
242 class_entry += 1;
243 }
244 return NULL;
245}
246
247const char *get_pci_class_name(device_t dev)
248{
249 const PCI_CLASS *class_entry;
250
251 class_entry = get_pci_class_entry(dev);
252 return class_entry ? class_entry->class_name : "???";
253}
254
255const char *get_pci_subclass_name(device_t dev)
256{
257 const PCI_CLASS *class_entry;
258 unsigned char subclass;
259 const PCI_SUBCLASS *subclass_entry;
260 const PCI_SUBCLASS *subclass_list_end;
261 const char *subclass_name;
262
263 /* Get the PCI device subclass */
264 subclass = pci_read_config8(dev, PCI_CLASS_DEVICE);
265
266 /* Locate the subclass name */
267 subclass_name = "???";
268 class_entry = get_pci_class_entry(dev);
269 subclass_entry = class_entry ? class_entry->subclass_list : NULL;
270 if (NULL != subclass_entry) {
271 subclass_list_end =
272 &subclass_entry[class_entry->subclass_entries];
273 while (subclass_list_end > subclass_entry) {
274 if (subclass_entry->subclass_id == subclass) {
275 subclass_name = subclass_entry->subclass_name;
276 break;
277 }
278 subclass_entry += 1;
279 }
280 }
281 return subclass_name;
282}