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