xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_info.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  * Copyright 2003-2006, Marcus Overhagen. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <KernelExport.h>
8 #define __HAIKU_PCI_BUS_MANAGER_TESTING 1
9 #include <PCI.h>
10 #include <string.h>
11 #include "pci_info.h"
12 #include "pci_private.h"
13 #include "pci.h"
14 
15 #define PCI_VERBOSE	1
16 #if defined(__INTEL__) || defined(__x86_64__)
17 // enabling it makes the pci bus_manager binary about 1MB
18 // some other platforms have issues with floppy image size...
19 // TODO: Move this define to BuildSetup?
20 #define USE_PCI_HEADER 1
21 #endif
22 
23 #if USE_PCI_HEADER
24 #	include "pcihdr.h"
25 #	include "pci-utils.h"
26 #endif
27 
28 const char *get_capability_name(uint8 cap_id);
29 
30 
31 static void
32 print_pci2pci_bridge_info(const pci_info *info, bool verbose)
33 {
34 	TRACE(("PCI:   subsystem_id %04x, subsystem_vendor_id %04x\n",
35 		info->u.h1.subsystem_id, info->u.h1.subsystem_vendor_id));
36 	TRACE(("PCI:   primary_bus %02x, secondary_bus %02x, subordinate_bus %02x,"
37 		" secondary_latency %02x\n", info->u.h1.primary_bus,
38 		info->u.h1.secondary_bus, info->u.h1.subordinate_bus, info->u.h1.secondary_latency));
39 	uint32 io_base = ((uint32)info->u.h1.io_base & 0xf0) << 8;
40 	if (info->u.h1.io_base & 1)
41 		 io_base += ((uint32)info->u.h1.io_base_upper16 << 16);
42 	uint32 io_limit = (((uint32)info->u.h1.io_limit & 0xf0) << 8) + 0xfff;
43 	if (info->u.h1.io_limit & 1)
44 		 io_limit += info->u.h1.io_limit_upper16 << 16;
45 	TRACE(("PCI:   I/O window %04" B_PRIx32 "-%04" B_PRIx32 "\n", io_base,
46 		io_limit));
47 	uint32 memory_base = ((uint32)info->u.h1.memory_base & 0xfff0) << 16;
48 	uint32 memory_limit = (((uint32)info->u.h1.memory_limit & 0xfff0) << 16)
49 		+ 0xfffff;
50 	TRACE(("PCI:   memory window %04" B_PRIx32 "-%04" B_PRIx32 "\n",
51 		memory_base, memory_limit));
52 	uint64 prefetchable_memory_base =
53 		((uint32)info->u.h1.prefetchable_memory_base & 0xfff0) << 16;
54 	if (info->u.h1.prefetchable_memory_base & 1) {
55 		prefetchable_memory_base +=
56 			(uint64)info->u.h1.prefetchable_memory_base_upper32 << 32;
57 	}
58 	uint64 prefetchable_memory_limit =
59 		(((uint32)info->u.h1.prefetchable_memory_limit & 0xfff0) << 16)
60 		+ 0xfffff;
61 	if (info->u.h1.prefetchable_memory_limit & 1) {
62 		prefetchable_memory_limit +=
63 			(uint64)info->u.h1.prefetchable_memory_limit_upper32 << 32;
64 	}
65 	TRACE(("PCI:   prefetchable memory window %016" B_PRIx64 "-%016" B_PRIx64 "\n",
66 		prefetchable_memory_base, prefetchable_memory_limit));
67 	TRACE(("PCI:   bridge_control %04x, secondary_status %04x\n",
68 			info->u.h1.bridge_control, info->u.h1.secondary_status));
69 	TRACE(("PCI:   interrupt_line %02x, interrupt_pin %02x\n",
70 			info->u.h1.interrupt_line, info->u.h1.interrupt_pin));
71 	TRACE(("PCI:   ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size ??\n",
72 			info->u.h1.rom_base, info->u.h1.rom_base_pci));
73 	for (int i = 0; i < 2; i++)
74 		TRACE(("PCI:   base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", "
75 			"size %08" B_PRIx32 ", flags %02x\n", i, info->u.h1.base_registers[i],
76 			info->u.h1.base_registers_pci[i], info->u.h1.base_register_sizes[i],
77 			info->u.h1.base_register_flags[i]));
78 }
79 
80 
81 static void
82 print_pci2cardbus_bridge_info(const pci_info *info, bool verbose)
83 {
84 	TRACE(("PCI:   subsystem_id %04x, subsystem_vendor_id %04x\n",
85 		info->u.h2.subsystem_id, info->u.h2.subsystem_vendor_id));
86 	TRACE(("PCI:   primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, "
87 		"secondary_latency %02x\n", info->u.h2.primary_bus,
88 		info->u.h2.secondary_bus, info->u.h2.subordinate_bus,
89 		info->u.h2.secondary_latency));
90 	TRACE(("PCI:   bridge_control %04x, secondary_status %04x\n",
91 		info->u.h2.bridge_control, info->u.h2.secondary_status));
92 	TRACE(("PCI:   memory_base_upper32  %08" B_PRIx32 ", memory_base  %08"
93 		B_PRIx32 "\n", info->u.h2.memory_base_upper32, info->u.h2.memory_base));
94 	TRACE(("PCI:   memory_limit_upper32 %08" B_PRIx32 ", memory_limit %08"
95 		B_PRIx32 "\n", info->u.h2.memory_limit_upper32, info->u.h2.memory_limit));
96 	TRACE(("PCI:   io_base_upper32  %08" B_PRIx32 ", io_base  %08" B_PRIx32 "\n",
97 		info->u.h2.io_base_upper32, info->u.h2.io_base));
98 	TRACE(("PCI:   io_limit_upper32 %08" B_PRIx32 ", io_limit %08" B_PRIx32 "\n",
99 		info->u.h2.io_limit_upper32, info->u.h2.io_limit));
100 }
101 
102 
103 static void
104 print_generic_info(const pci_info *info, bool verbose)
105 {
106 	TRACE(("PCI:   ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size "
107 		"%08" B_PRIx32 "\n", info->u.h0.rom_base, info->u.h0.rom_base_pci,
108 		info->u.h0.rom_size));
109 	TRACE(("PCI:   cardbus_CIS %08" B_PRIx32 ", subsystem_id %04x, "
110 		"subsystem_vendor_id %04x\n", info->u.h0.cardbus_cis,
111 		info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id));
112 	TRACE(("PCI:   interrupt_line %02x, interrupt_pin %02x, min_grant %02x, "
113 		"max_latency %02x\n", info->u.h0.interrupt_line, info->u.h0.interrupt_pin,
114 		info->u.h0.min_grant, info->u.h0.max_latency));
115 	for (int i = 0; i < 6; i++)
116 		TRACE(("PCI:   base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", "
117 			"size %08" B_PRIx32 ", flags %02x\n", i, info->u.h0.base_registers[i],
118 			info->u.h0.base_registers_pci[i], info->u.h0.base_register_sizes[i],
119 			info->u.h0.base_register_flags[i]));
120 }
121 
122 
123 static void
124 print_capabilities(const pci_info *info)
125 {
126 	uint16	status;
127 	uint8	cap_ptr;
128 	uint8	cap_id;
129 	int		i;
130 
131 	TRACE(("PCI:   Capabilities: "));
132 
133 	status = pci_read_config(info->bus, info->device, info->function, PCI_status, 2);
134 	if (!(status & PCI_status_capabilities)) {
135 		TRACE(("(not supported)\n"));
136 		return;
137 	}
138 
139 	switch (info->header_type & PCI_header_type_mask) {
140 		case PCI_header_type_generic:
141 		case PCI_header_type_PCI_to_PCI_bridge:
142 			cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr, 1);
143 			break;
144 		case PCI_header_type_cardbus:
145 			cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr_2, 1);
146 			break;
147 		default:
148 			TRACE(("(unknown header type)\n"));
149 			return;
150 	}
151 
152 	cap_ptr &= ~3;
153 	if (!cap_ptr) {
154 		TRACE(("(empty list)\n"));
155 		return;
156 	}
157 
158 	for (i = 0; i < 48; i++) {
159 		const char *name;
160 		cap_id  = pci_read_config(info->bus, info->device, info->function, cap_ptr, 1);
161 		cap_ptr = pci_read_config(info->bus, info->device, info->function, cap_ptr + 1, 1);
162 		cap_ptr &= ~3;
163 		if (i) {
164 			TRACE((", "));
165 		}
166 		name = get_capability_name(cap_id);
167 		if (name) {
168 			TRACE(("%s", name));
169 		} else {
170 			TRACE(("0x%02x", cap_id));
171 		}
172 		if (!cap_ptr)
173 			break;
174 	}
175 	TRACE(("\n"));
176 }
177 
178 
179 static void
180 print_info_basic(const pci_info *info, bool verbose)
181 {
182 	int domain;
183 	uint8 bus;
184 
185 	__pci_resolve_virtual_bus(info->bus, &domain, &bus);
186 
187 	TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
188 			domain, bus, info->bus /* virtual bus*/,
189 			info->device, info->function, info->vendor_id, info->device_id, info->revision));
190 	TRACE(("PCI:   class_base %02x, class_function %02x, class_api %02x\n",
191 			info->class_base, info->class_sub, info->class_api));
192 
193 	if (verbose) {
194 #if USE_PCI_HEADER
195 		const char *venShort;
196 		const char *venFull;
197 		get_vendor_info(info->vendor_id, &venShort, &venFull);
198 		if (!venShort && !venFull) {
199 			TRACE(("PCI:   vendor %04x: Unknown\n", info->vendor_id));
200 		} else if (venShort && venFull) {
201 			TRACE(("PCI:   vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull));
202 		} else {
203 			TRACE(("PCI:   vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull));
204 		}
205 		const char *devShort;
206 		const char *devFull;
207 		get_device_info(info->vendor_id, info->device_id, info->u.h0.subsystem_vendor_id, info->u.h0.subsystem_id,
208 			&devShort, &devFull);
209 		if (!devShort && !devFull) {
210 			TRACE(("PCI:   device %04x: Unknown\n", info->device_id));
211 		} else if (devShort && devFull) {
212 			TRACE(("PCI:   device %04x: %s (%s)\n", info->device_id, devShort, devFull));
213 		} else {
214 			TRACE(("PCI:   device %04x: %s\n", info->device_id, devShort ? devShort : devFull));
215 		}
216 		char classInfo[64];
217 		get_class_info(info->class_base, info->class_sub, info->class_api, classInfo, sizeof(classInfo));
218 		TRACE(("PCI:   info: %s\n", classInfo));
219 #endif
220 	}
221 	TRACE(("PCI:   line_size %02x, latency %02x, header_type %02x, BIST %02x\n",
222 			info->line_size, info->latency, info->header_type, info->bist));
223 
224 	switch (info->header_type & PCI_header_type_mask) {
225 		case PCI_header_type_generic:
226 			print_generic_info(info, verbose);
227 			break;
228 		case PCI_header_type_PCI_to_PCI_bridge:
229 			print_pci2pci_bridge_info(info, verbose);
230 			break;
231 		case PCI_header_type_cardbus:
232 			print_pci2cardbus_bridge_info(info, verbose);
233 			break;
234 		default:
235 			TRACE(("PCI:   unknown header type\n"));
236 	}
237 
238 	print_capabilities(info);
239 }
240 
241 
242 void
243 pci_print_info()
244 {
245 	pci_info info;
246 	for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) {
247 		print_info_basic(&info, PCI_VERBOSE);
248 	}
249 }
250 
251 
252 const char *
253 get_capability_name(uint8 cap_id)
254 {
255 	switch (cap_id) {
256 		case PCI_cap_id_reserved:
257 			return "reserved";
258 		case PCI_cap_id_pm:
259 			return "PM";
260 		case PCI_cap_id_agp:
261 			return "AGP";
262 		case PCI_cap_id_vpd:
263 			return "VPD";
264 		case PCI_cap_id_slotid:
265 			return "SlotID";
266 		case PCI_cap_id_msi:
267 			return "MSI";
268 		case PCI_cap_id_chswp:
269 			return "CompactPCIHotSwap";
270 		case PCI_cap_id_pcix:
271 			return "PCI-X";
272 		case PCI_cap_id_ldt:
273 			return "ldt";
274 		case PCI_cap_id_vendspec:
275 			return "vendspec";
276 		case PCI_cap_id_debugport:
277 			return "DebugPort";
278 		case PCI_cap_id_cpci_rsrcctl:
279 			return "cpci_rsrcctl";
280 		case PCI_cap_id_hotplug:
281 			return "HotPlug";
282 		case PCI_cap_id_subvendor:
283 			return "subvendor";
284 		case PCI_cap_id_agp8x:
285 			return "AGP8x";
286 		case PCI_cap_id_secure_dev:
287 			return "Secure Device";
288 		case PCI_cap_id_pcie:
289 			return "PCIe";
290 		case PCI_cap_id_msix:
291 			return "MSI-X";
292 		case PCI_cap_id_sata:
293 			return "SATA";
294 		case PCI_cap_id_pciaf:
295 			return "AdvancedFeatures";
296 		default:
297 			return NULL;
298 	}
299 }
300 
301