blob: 460d85391b5a498e61b9b36d73f73bfb1a02edbd [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahye1ba3da2015-03-31 17:30:01 -07002
3#include <device/device.h>
4#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Lee Leahye1ba3da2015-03-31 17:30:01 -07006
7typedef struct {
8 const unsigned char subclass_id;
9 const char *subclass_name;
10} PCI_SUBCLASS;
11
12typedef struct {
13 const unsigned char class_id;
14 const PCI_SUBCLASS *subclass_list;
15 const unsigned int subclass_entries;
16 const char *class_name;
17} PCI_CLASS;
18
19static const PCI_SUBCLASS unclassified[] = {
20 { 0x00, "Non-VGA device" },
21 { 0x01, "VGA compatible device" }
22};
23
24static const PCI_SUBCLASS mass_storage[] = {
25 { 0x00, "SCSI storage controller" },
26 { 0x01, "IDE interface" },
27 { 0x02, "Floppy disk controller" },
28 { 0x03, "IPI bus controller" },
29 { 0x04, "RAID bus controller" },
30 { 0x05, "ATA controller" },
31 { 0x06, "SATA controller" },
32 { 0x07, "Serial Attached SCSI controller" },
33 { 0x08, "Non-Volatile memory controller" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +010034 { 0x09, "Universal Flash Storage controller" },
Lee Leahye1ba3da2015-03-31 17:30:01 -070035 { 0x80, "Mass storage controller" }
36};
37
38static const PCI_SUBCLASS network[] = {
39 { 0x00, "Ethernet controller" },
40 { 0x01, "Token ring network controller" },
41 { 0x02, "FDDI network controller" },
42 { 0x03, "ATM network controller" },
43 { 0x04, "ISDN controller" },
44 { 0x05, "WorldFip controller" },
45 { 0x06, "PICMG controller" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +010046 { 0x07, "InfiniBand Controller" },
47 { 0x08, "Host fabric controller" },
Lee Leahye1ba3da2015-03-31 17:30:01 -070048 { 0x80, "Network controller" }
49};
50
51static const PCI_SUBCLASS display[] = {
52 { 0x00, "VGA compatible controller" },
53 { 0x01, "XGA compatible controller" },
54 { 0x02, "3D controller" },
55 { 0x80, "Display controller" }
56};
57
58static const PCI_SUBCLASS multimedia[] = {
59 { 0x00, "Multimedia video controller" },
60 { 0x01, "Multimedia audio controller" },
61 { 0x02, "Computer telephony device" },
62 { 0x03, "Audio device" },
63 { 0x80, "Multimedia controller" }
64};
65
66static const PCI_SUBCLASS memory[] = {
67 { 0x00, "RAM memory" },
68 { 0x01, "FLASH memory" },
69 { 0x80, "Memory controller" }
70};
71
72static const PCI_SUBCLASS bridge[] = {
73 { 0x00, "Host bridge" },
74 { 0x01, "ISA bridge" },
75 { 0x02, "EISA bridge" },
76 { 0x03, "MicroChannel bridge" },
77 { 0x04, "PCI bridge" },
78 { 0x05, "PCMCIA bridge" },
79 { 0x06, "NuBus bridge" },
80 { 0x07, "CardBus bridge" },
81 { 0x08, "RACEway bridge" },
82 { 0x09, "Semi-transparent PCI-to-PCI bridge" },
83 { 0x0a, "InfiniBand to PCI host bridge" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +010084 { 0x0b, "Advanced Switching to PCI host bridge" },
Lee Leahye1ba3da2015-03-31 17:30:01 -070085 { 0x80, "Bridge" }
86};
87
88static const PCI_SUBCLASS communication[] = {
89 { 0x00, "Serial controller" },
90 { 0x01, "Parallel controller" },
91 { 0x02, "Multiport serial controller" },
92 { 0x03, "Modem" },
93 { 0x04, "GPIB controller" },
94 { 0x05, "Smard Card controller" },
95 { 0x80, "Communication controller" }
96};
97
98static const PCI_SUBCLASS generic[] = {
99 { 0x00, "PIC" },
100 { 0x01, "DMA controller" },
101 { 0x02, "Timer" },
102 { 0x03, "RTC" },
103 { 0x04, "PCI Hot-plug controller" },
104 { 0x05, "SD Host controller" },
105 { 0x06, "IOMMU" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +0100106 { 0x07, "Root Complex Event Collector" },
Lee Leahye1ba3da2015-03-31 17:30:01 -0700107 { 0x80, "System peripheral" }
108};
109
110static const PCI_SUBCLASS input_device[] = {
111 { 0x00, "Keyboard controller" },
112 { 0x01, "Digitizer Pen" },
113 { 0x02, "Mouse controller" },
114 { 0x03, "Scanner controller" },
115 { 0x04, "Gameport controller" },
116 { 0x80, "Input device controller" }
117};
118
119static const PCI_SUBCLASS docking_station[] = {
120 { 0x00, "Generic Docking Station" },
121 { 0x80, "Docking Station" }
122};
123
124static const PCI_SUBCLASS processor[] = {
125 { 0x00, "386" },
126 { 0x01, "486" },
127 { 0x02, "Pentium" },
128 { 0x10, "Alpha" },
129 { 0x20, "Power PC" },
130 { 0x30, "MIPS" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +0100131 { 0x40, "Co-processor" },
132 { 0x80, "Processor" }
Lee Leahye1ba3da2015-03-31 17:30:01 -0700133};
134
135static const PCI_SUBCLASS serial_bus[] = {
136 { 0x00, "FireWire (IEEE 1394)" },
137 { 0x01, "ACCESS Bus" },
138 { 0x02, "SSA" },
139 { 0x03, "USB controller" },
140 { 0x04, "Fibre Channel" },
141 { 0x05, "SMBus" },
142 { 0x06, "InfiniBand" },
143 { 0x07, "IPMI SMIC interface" },
144 { 0x08, "SERCOS interface" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +0100145 { 0x09, "CANBUS" },
146 { 0x0a, "MIPI I3C SM Host Controller Interface" },
147 { 0x80, "Serial Bus Controller" }
Lee Leahye1ba3da2015-03-31 17:30:01 -0700148};
149
150static const PCI_SUBCLASS wireless[] = {
151 { 0x00, "IRDA controller" },
152 { 0x01, "Consumer IR controller" },
153 { 0x10, "RF controller" },
154 { 0x11, "Bluetooth" },
155 { 0x12, "Broadband" },
156 { 0x20, "802.1a controller" },
157 { 0x21, "802.1b controller" },
Elyes HAOUAS26d1be12019-12-11 12:31:52 +0100158 { 0x40, "Cellular controller/modem" },
159 { 0x41, "Cellular controller/modem plus Ethernet (802.11)" },
Lee Leahye1ba3da2015-03-31 17:30:01 -0700160 { 0x80, "Wireless controller" }
161};
162
163static const PCI_SUBCLASS intellegient_controller[] = {
164 { 0x00, "I2O" }
165};
166
167static const PCI_SUBCLASS satellite_controller[] = {
168 { 0x01, "Satellite TV controller" },
169 { 0x02, "Satellite audio communication controller" },
170 { 0x03, "Satellite voice communication controller" },
171 { 0x04, "Satellite data communication controller" }
172};
173
174static const PCI_SUBCLASS encryption[] = {
175 { 0x00, "Network and computing encryption device" },
176 { 0x10, "Entertainment encryption device" },
177 { 0x80, "Encryption controller" }
178};
179
180static const PCI_SUBCLASS signal_processing[] = {
181 { 0x00, "DPIO module" },
182 { 0x01, "Performance counters" },
183 { 0x10, "Communication synchronizer" },
184 { 0x20, "Signal processing management" },
185 { 0x80, "Signal processing controller" }
186};
187
188static const PCI_CLASS class_list[] = {
189 { 0x00, &unclassified[0], ARRAY_SIZE(unclassified),
190 "Unclassified device" },
191 { 0x01, &mass_storage[0], ARRAY_SIZE(mass_storage), "Mass storage" },
192 { 0x02, &network[0], ARRAY_SIZE(network), "Network" },
193 { 0x03, &display[0], ARRAY_SIZE(display), "Display" },
194 { 0x04, &multimedia[0], ARRAY_SIZE(multimedia), "Multimedia" },
195 { 0x05, &memory[0], ARRAY_SIZE(memory), "Memory" },
196 { 0x06, &bridge[0], ARRAY_SIZE(bridge), "Bridge" },
197 { 0x07, &communication[0], ARRAY_SIZE(communication), "Communication" },
198 { 0x08, &generic[0], ARRAY_SIZE(generic), "Generic system peripheral" },
199 { 0x09, &input_device[0], ARRAY_SIZE(input_device), "Input device" },
200 { 0x0a, &docking_station[0], ARRAY_SIZE(docking_station),
201 "Docking station" },
202 { 0x0b, &processor[0], ARRAY_SIZE(processor), "Processor" },
203 { 0x0c, &serial_bus[0], ARRAY_SIZE(serial_bus), "Serial bus" },
204 { 0x0d, &wireless[0], ARRAY_SIZE(wireless), "Wireless" },
205 { 0x0e, &intellegient_controller[0],
206 ARRAY_SIZE(intellegient_controller),
207 "Intelligent controller" },
208 { 0x0f, &satellite_controller[0], ARRAY_SIZE(satellite_controller),
209 "Satellite communications" },
210 { 0x10, &encryption[0], ARRAY_SIZE(encryption), "Encryption" },
211 { 0x11, &signal_processing[0], ARRAY_SIZE(signal_processing),
212 "Signal processing" },
213 { 0xff, NULL, 0, "Unassigned class" }
214};
215static const unsigned int class_entries = ARRAY_SIZE(class_list);
216
Elyes HAOUAS69de0552018-05-02 21:32:54 +0200217static const PCI_CLASS *get_pci_class_entry(struct device *dev)
Lee Leahye1ba3da2015-03-31 17:30:01 -0700218{
219 unsigned char class;
220 const PCI_CLASS *class_entry;
221 const PCI_CLASS *class_list_end;
222
223 /* Get the PCI device class */
224 class = pci_read_config8(dev, PCI_CLASS_DEVICE+1);
225
226 /* Locate the class entry */
227 class_entry = &class_list[0];
228 class_list_end = &class_entry[class_entries];
229 while (class_list_end > class_entry) {
230 if (class_entry->class_id == class)
231 return class_entry;
232 class_entry += 1;
233 }
234 return NULL;
235}
236
Elyes HAOUAS69de0552018-05-02 21:32:54 +0200237const char *get_pci_class_name(struct device *dev)
Lee Leahye1ba3da2015-03-31 17:30:01 -0700238{
239 const PCI_CLASS *class_entry;
240
241 class_entry = get_pci_class_entry(dev);
242 return class_entry ? class_entry->class_name : "???";
243}
244
Elyes HAOUAS69de0552018-05-02 21:32:54 +0200245const char *get_pci_subclass_name(struct device *dev)
Lee Leahye1ba3da2015-03-31 17:30:01 -0700246{
247 const PCI_CLASS *class_entry;
248 unsigned char subclass;
249 const PCI_SUBCLASS *subclass_entry;
250 const PCI_SUBCLASS *subclass_list_end;
251 const char *subclass_name;
252
253 /* Get the PCI device subclass */
254 subclass = pci_read_config8(dev, PCI_CLASS_DEVICE);
255
256 /* Locate the subclass name */
257 subclass_name = "???";
258 class_entry = get_pci_class_entry(dev);
259 subclass_entry = class_entry ? class_entry->subclass_list : NULL;
Elyes HAOUAS0f8b8d92019-01-03 10:23:28 +0100260 if (subclass_entry != NULL) {
Lee Leahye1ba3da2015-03-31 17:30:01 -0700261 subclass_list_end =
262 &subclass_entry[class_entry->subclass_entries];
263 while (subclass_list_end > subclass_entry) {
264 if (subclass_entry->subclass_id == subclass) {
265 subclass_name = subclass_entry->subclass_name;
266 break;
267 }
268 subclass_entry += 1;
269 }
270 }
271 return subclass_name;
272}