xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_info.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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(__i386__) || 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 const char *get_extended_capability_name(uint16 cap_id);
30 
31 
32 static void
33 print_pci2pci_bridge_info(const pci_info *info, bool verbose)
34 {
35 	TRACE(("PCI:   subsystem_id %04x, subsystem_vendor_id %04x\n",
36 		info->u.h1.subsystem_id, info->u.h1.subsystem_vendor_id));
37 	TRACE(("PCI:   primary_bus %02x, secondary_bus %02x, subordinate_bus %02x,"
38 		" secondary_latency %02x\n", info->u.h1.primary_bus,
39 		info->u.h1.secondary_bus, info->u.h1.subordinate_bus, info->u.h1.secondary_latency));
40 	uint32 io_base = ((uint32)info->u.h1.io_base & 0xf0) << 8;
41 	if (info->u.h1.io_base & 1)
42 		 io_base += ((uint32)info->u.h1.io_base_upper16 << 16);
43 	uint32 io_limit = (((uint32)info->u.h1.io_limit & 0xf0) << 8) + 0xfff;
44 	if (info->u.h1.io_limit & 1)
45 		 io_limit += info->u.h1.io_limit_upper16 << 16;
46 	TRACE(("PCI:   I/O window %04" B_PRIx32 "-%04" B_PRIx32 "\n", io_base,
47 		io_limit));
48 	uint32 memory_base = ((uint32)info->u.h1.memory_base & 0xfff0) << 16;
49 	uint32 memory_limit = (((uint32)info->u.h1.memory_limit & 0xfff0) << 16)
50 		+ 0xfffff;
51 	TRACE(("PCI:   memory window %08" B_PRIx32 "-%08" B_PRIx32 "\n",
52 		memory_base, memory_limit));
53 	uint64 prefetchable_memory_base =
54 		((uint32)info->u.h1.prefetchable_memory_base & 0xfff0) << 16;
55 	if (info->u.h1.prefetchable_memory_base & 1) {
56 		prefetchable_memory_base +=
57 			(uint64)info->u.h1.prefetchable_memory_base_upper32 << 32;
58 	}
59 	uint64 prefetchable_memory_limit =
60 		(((uint32)info->u.h1.prefetchable_memory_limit & 0xfff0) << 16)
61 		+ 0xfffff;
62 	if (info->u.h1.prefetchable_memory_limit & 1) {
63 		prefetchable_memory_limit +=
64 			(uint64)info->u.h1.prefetchable_memory_limit_upper32 << 32;
65 	}
66 	TRACE(("PCI:   prefetchable memory window %016" B_PRIx64 "-%016" B_PRIx64 "\n",
67 		prefetchable_memory_base, prefetchable_memory_limit));
68 	TRACE(("PCI:   bridge_control %04x, secondary_status %04x\n",
69 			info->u.h1.bridge_control, info->u.h1.secondary_status));
70 	TRACE(("PCI:   interrupt_line %02x, interrupt_pin %02x\n",
71 			info->u.h1.interrupt_line, info->u.h1.interrupt_pin));
72 	TRACE(("PCI:   ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size ??\n",
73 			info->u.h1.rom_base, info->u.h1.rom_base_pci));
74 	for (int i = 0; i < 2; i++)
75 		TRACE(("PCI:   base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", "
76 			"size %08" B_PRIx32 ", flags %02x\n", i, info->u.h1.base_registers[i],
77 			info->u.h1.base_registers_pci[i], info->u.h1.base_register_sizes[i],
78 			info->u.h1.base_register_flags[i]));
79 }
80 
81 
82 static void
83 print_pci2cardbus_bridge_info(const pci_info *info, bool verbose)
84 {
85 	TRACE(("PCI:   subsystem_id %04x, subsystem_vendor_id %04x\n",
86 		info->u.h2.subsystem_id, info->u.h2.subsystem_vendor_id));
87 	TRACE(("PCI:   primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, "
88 		"secondary_latency %02x\n", info->u.h2.primary_bus,
89 		info->u.h2.secondary_bus, info->u.h2.subordinate_bus,
90 		info->u.h2.secondary_latency));
91 	TRACE(("PCI:   bridge_control %04x, secondary_status %04x\n",
92 		info->u.h2.bridge_control, info->u.h2.secondary_status));
93 	TRACE(("PCI:   memory_base_upper32  %08" B_PRIx32 ", memory_base  %08"
94 		B_PRIx32 "\n", info->u.h2.memory_base_upper32, info->u.h2.memory_base));
95 	TRACE(("PCI:   memory_limit_upper32 %08" B_PRIx32 ", memory_limit %08"
96 		B_PRIx32 "\n", info->u.h2.memory_limit_upper32, info->u.h2.memory_limit));
97 	TRACE(("PCI:   io_base_upper32  %08" B_PRIx32 ", io_base  %08" B_PRIx32 "\n",
98 		info->u.h2.io_base_upper32, info->u.h2.io_base));
99 	TRACE(("PCI:   io_limit_upper32 %08" B_PRIx32 ", io_limit %08" B_PRIx32 "\n",
100 		info->u.h2.io_limit_upper32, info->u.h2.io_limit));
101 }
102 
103 
104 static void
105 print_generic_info(const pci_info *info, bool verbose)
106 {
107 	TRACE(("PCI:   ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size "
108 		"%08" B_PRIx32 "\n", info->u.h0.rom_base, info->u.h0.rom_base_pci,
109 		info->u.h0.rom_size));
110 	TRACE(("PCI:   cardbus_CIS %08" B_PRIx32 ", subsystem_id %04x, "
111 		"subsystem_vendor_id %04x\n", info->u.h0.cardbus_cis,
112 		info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id));
113 	TRACE(("PCI:   interrupt_line %02x, interrupt_pin %02x, min_grant %02x, "
114 		"max_latency %02x\n", info->u.h0.interrupt_line, info->u.h0.interrupt_pin,
115 		info->u.h0.min_grant, info->u.h0.max_latency));
116 	for (int i = 0; i < 6; i++) {
117 		if ((info->u.h0.base_register_flags[i] & PCI_address_type) == PCI_address_type_64) {
118 			TRACE(("PCI:   base reg %d: host %016" B_PRIx64 ", pci %016" B_PRIx64 ", "
119 				"size %08" B_PRIx64 ", flags %02x %02x\n", i,
120 				info->u.h0.base_registers[i] | ((uint64)info->u.h0.base_registers[i + 1] << 32),
121 				info->u.h0.base_registers_pci[i] | ((uint64)info->u.h0.base_registers_pci[i + 1] << 32),
122 				info->u.h0.base_register_sizes[i] | ((uint64)info->u.h0.base_register_sizes[i + 1] << 32),
123 				info->u.h0.base_register_flags[i], info->u.h0.base_register_flags[i + 1]));
124 			i++;
125 		} else {
126 			TRACE(("PCI:   base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", "
127 				"size %08" B_PRIx32 ", flags %02x\n", i, info->u.h0.base_registers[i],
128 				info->u.h0.base_registers_pci[i], info->u.h0.base_register_sizes[i],
129 				info->u.h0.base_register_flags[i]));
130 		}
131 	}
132 }
133 
134 
135 static void
136 print_capabilities(const pci_info *info)
137 {
138 	uint16	status;
139 	uint8	cap_ptr;
140 	uint8	cap_id;
141 	int		i;
142 
143 	TRACE(("PCI:   Capabilities: "));
144 
145 	status = pci_read_config(info->bus, info->device, info->function, PCI_status, 2);
146 	if (!(status & PCI_status_capabilities)) {
147 		TRACE(("(not supported)\n"));
148 		return;
149 	}
150 
151 	switch (info->header_type & PCI_header_type_mask) {
152 		case PCI_header_type_generic:
153 		case PCI_header_type_PCI_to_PCI_bridge:
154 			cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr, 1);
155 			break;
156 		case PCI_header_type_cardbus:
157 			cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr_2, 1);
158 			break;
159 		default:
160 			TRACE(("(unknown header type)\n"));
161 			return;
162 	}
163 
164 	cap_ptr &= ~3;
165 	if (!cap_ptr) {
166 		TRACE(("(empty list)\n"));
167 		return;
168 	}
169 
170 	for (i = 0; i < 48; i++) {
171 		const char *name;
172 		cap_id  = pci_read_config(info->bus, info->device, info->function, cap_ptr, 1);
173 		cap_ptr = pci_read_config(info->bus, info->device, info->function, cap_ptr + 1, 1);
174 		cap_ptr &= ~3;
175 		if (i) {
176 			TRACE((", "));
177 		}
178 		name = get_capability_name(cap_id);
179 		if (name) {
180 			TRACE(("%s", name));
181 		} else {
182 			TRACE(("0x%02x", cap_id));
183 		}
184 		if (!cap_ptr)
185 			break;
186 	}
187 	TRACE(("\n"));
188 }
189 
190 
191 static void
192 print_extended_capabilities(const pci_info *info)
193 {
194 	if (pci_find_capability(info->bus, info->device, info->function,
195 			PCI_cap_id_pcie, NULL) != B_OK)
196 		return;
197 
198 	uint16 capPointer = PCI_extended_capability;
199 	uint32 capability = pci_read_config(info->bus, info->device,
200 		info->function, capPointer, 4);
201 	TRACE(("PCI:   Extended capabilities: "));
202 	if (capability == 0 || capability == 0xffffffff) {
203 		TRACE(("(empty list)\n"));
204 		return;
205 	}
206 
207 	for (int i = 0; i < 48; i++) {
208 		if (i) {
209 			TRACE((", "));
210 		}
211 		const char *name = get_extended_capability_name(
212 			PCI_extcap_id(capability));
213 		if (name) {
214 			TRACE(("%s", name));
215 		} else {
216 			TRACE(("0x%04" B_PRIx32, PCI_extcap_id(capability)));
217 		}
218 
219 		capPointer = PCI_extcap_next_ptr(capability) & ~3;
220 		if (capPointer < PCI_extended_capability)
221 			break;
222 		capability = pci_read_config(info->bus, info->device, info->function,
223 			capPointer, 4);
224 	}
225 
226 	TRACE(("\n"));
227 }
228 
229 
230 static void
231 print_info_basic(const pci_info *info, bool verbose)
232 {
233 	uint8 domain;
234 	uint8 bus;
235 
236 	__pci_resolve_virtual_bus(info->bus, &domain, &bus);
237 
238 	TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
239 			domain, bus, info->bus /* virtual bus*/,
240 			info->device, info->function, info->vendor_id, info->device_id, info->revision));
241 	TRACE(("PCI:   class_base %02x, class_function %02x, class_api %02x\n",
242 			info->class_base, info->class_sub, info->class_api));
243 
244 	if (verbose) {
245 #if USE_PCI_HEADER
246 		const char *venShort;
247 		const char *venFull;
248 		get_vendor_info(info->vendor_id, &venShort, &venFull);
249 		if (!venShort && !venFull) {
250 			TRACE(("PCI:   vendor %04x: Unknown\n", info->vendor_id));
251 		} else if (venShort && venFull) {
252 			TRACE(("PCI:   vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull));
253 		} else {
254 			TRACE(("PCI:   vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull));
255 		}
256 		const char *devShort;
257 		const char *devFull;
258 		get_device_info(info->vendor_id, info->device_id, info->u.h0.subsystem_vendor_id, info->u.h0.subsystem_id,
259 			&devShort, &devFull);
260 		if (!devShort && !devFull) {
261 			TRACE(("PCI:   device %04x: Unknown\n", info->device_id));
262 		} else if (devShort && devFull) {
263 			TRACE(("PCI:   device %04x: %s (%s)\n", info->device_id, devShort, devFull));
264 		} else {
265 			TRACE(("PCI:   device %04x: %s\n", info->device_id, devShort ? devShort : devFull));
266 		}
267 		char classInfo[128];
268 		get_class_info(info->class_base, info->class_sub, info->class_api, classInfo, sizeof(classInfo));
269 		TRACE(("PCI:   info: %s\n", classInfo));
270 #endif
271 	}
272 	TRACE(("PCI:   line_size %02x, latency %02x, header_type %02x, BIST %02x\n",
273 			info->line_size, info->latency, info->header_type, info->bist));
274 
275 	switch (info->header_type & PCI_header_type_mask) {
276 		case PCI_header_type_generic:
277 			print_generic_info(info, verbose);
278 			break;
279 		case PCI_header_type_PCI_to_PCI_bridge:
280 			print_pci2pci_bridge_info(info, verbose);
281 			break;
282 		case PCI_header_type_cardbus:
283 			print_pci2cardbus_bridge_info(info, verbose);
284 			break;
285 		default:
286 			TRACE(("PCI:   unknown header type\n"));
287 	}
288 
289 	print_capabilities(info);
290 	print_extended_capabilities(info);
291 }
292 
293 
294 void
295 pci_print_info()
296 {
297 	pci_info info;
298 	for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) {
299 		print_info_basic(&info, PCI_VERBOSE);
300 	}
301 }
302 
303 
304 const char *
305 get_capability_name(uint8 cap_id)
306 {
307 	switch (cap_id) {
308 		case PCI_cap_id_reserved:
309 			return "reserved";
310 		case PCI_cap_id_pm:
311 			return "PM";
312 		case PCI_cap_id_agp:
313 			return "AGP";
314 		case PCI_cap_id_vpd:
315 			return "VPD";
316 		case PCI_cap_id_slotid:
317 			return "SlotID";
318 		case PCI_cap_id_msi:
319 			return "MSI";
320 		case PCI_cap_id_chswp:
321 			return "CompactPCIHotSwap";
322 		case PCI_cap_id_pcix:
323 			return "PCI-X";
324 		case PCI_cap_id_ht:
325 			return "HyperTransport";
326 		case PCI_cap_id_vendspec:
327 			return "vendspec";
328 		case PCI_cap_id_debugport:
329 			return "DebugPort";
330 		case PCI_cap_id_cpci_rsrcctl:
331 			return "cpci_rsrcctl";
332 		case PCI_cap_id_hotplug:
333 			return "HotPlug";
334 		case PCI_cap_id_subvendor:
335 			return "subvendor";
336 		case PCI_cap_id_agp8x:
337 			return "AGP8x";
338 		case PCI_cap_id_secure_dev:
339 			return "Secure Device";
340 		case PCI_cap_id_pcie:
341 			return "PCIe";
342 		case PCI_cap_id_msix:
343 			return "MSI-X";
344 		case PCI_cap_id_sata:
345 			return "SATA";
346 		case PCI_cap_id_pciaf:
347 			return "AdvancedFeatures";
348 		default:
349 			return NULL;
350 	}
351 }
352 
353 
354 const char *
355 get_extended_capability_name(uint16 cap_id)
356 {
357 	switch (cap_id) {
358 		case PCI_extcap_id_aer:
359 			return "Advanced Error Reporting";
360 		case PCI_extcap_id_vc:
361 			return "Virtual Channel";
362 		case PCI_extcap_id_serial:
363 			return "Serial Number";
364 		case PCI_extcap_id_power_budget:
365 			return "Power Budgeting";
366 		case PCI_extcap_id_rcl_decl:
367 			return "Root Complex Link Declaration";
368 		case PCI_extcap_id_rcil_ctl:
369 			return "Root Complex Internal Link Control";
370 		case PCI_extcap_id_rcec_assoc:
371 			return "Root Complex Event Collector Association";
372 		case PCI_extcap_id_mfvc:
373 			return "MultiFunction Virtual Channel";
374 		case PCI_extcap_id_vc2:
375 			return "Virtual Channel 2";
376 		case PCI_extcap_id_rcrb_header:
377 			return "RCRB Header";
378 		case PCI_extcap_id_vendor:
379 			return "Vendor Unique";
380 		case PCI_extcap_id_acs:
381 			return "Access Control Services";
382 		case PCI_extcap_id_ari:
383 			return "Alternative Routing Id Interpretation";
384 		case PCI_extcap_id_ats:
385 			return "Address Translation Services";
386 		case PCI_extcap_id_srio_virtual:
387 			return "Single Root I/O Virtualization";
388 		case PCI_extcap_id_mrio_virtual:
389 			return "Multiple Root I/O Virtual";
390 		case PCI_extcap_id_multicast:
391 			return "Multicast";
392 		case PCI_extcap_id_page_request:
393 			return "Page Request";
394 		case PCI_extcap_id_amd:
395 			return "AMD Reserved";
396 		case PCI_extcap_id_resizable_bar:
397 			return "Resizable Bar";
398 		case PCI_extcap_id_dyn_power_alloc:
399 			return "Dynamic Power Allocation";
400 		case PCI_extcap_id_tph_requester:
401 			return "TPH Requester";
402 		case PCI_extcap_id_latency_tolerance:
403 			return "Latency Tolerance Reporting";
404 		case PCI_extcap_id_2ndpcie:
405 			return "Secondary PCIe";
406 		case PCI_extcap_id_pmux:
407 			return "Protocol Multiplexing";
408 		case PCI_extcap_id_pasid:
409 			return "Process Address Space Id";
410 		case PCI_extcap_id_ln_requester:
411 			return "LN Requester";
412 		case PCI_extcap_id_dpc:
413 			return "Downstream Porto Containment";
414 		case PCI_extcap_id_l1pm:
415 			return "L1 Power Management Substates";
416 		case PCI_extcap_id_ptm:
417 			return "Precision Time Measurement";
418 		case PCI_extcap_id_m_pcie:
419 			return "PCIe over M-PHY";
420 		case PCI_extcap_id_frs:
421 			return "FRS Queuing";
422 		case PCI_extcap_id_rtr:
423 			return "Readiness Time Reporting";
424 		case PCI_extcap_id_dvsec:
425 			return "Designated Vendor-Specific";
426 		case PCI_extcap_id_vf_resizable_bar:
427 			return "VF Resizable BAR";
428 		case PCI_extcap_id_datalink:
429 			return "Data Link Feature";
430 		case PCI_extcap_id_16gt:
431 			return "Physical Layer 16.0 GT/s";
432 		case PCI_extcap_id_lmr:
433 			return "Lane Marging at the Receiver";
434 		case PCI_extcap_id_hierarchy_id:
435 			return "Hierarchy ID";
436 		case PCI_extcap_id_npem:
437 			return "Native PCIe Enclosure Management";
438 		case PCI_extcap_id_pl32:
439 			return "Physical Layer 32.0 GT/s";
440 		case PCI_extcap_id_ap:
441 			return "Alternate Protocol";
442 		case PCI_extcap_id_sfi:
443 			return "System Firmware Intermediary";
444 		case PCI_extcap_id_sf:
445 			return "Shadow Functions";
446 		case PCI_extcap_id_doe:
447 			return "Data Object Exchange";
448 
449 		default:
450 			return NULL;
451 	}
452 }
453 
454