xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_info.cpp (revision 6dcd0ccf238263a3e5eb2e2a44e2ed0da1617a42)
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_priv.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 %02x, 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 %02x, 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 	TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
152 	// XXX this works only as long as PCI manager virtual bus mapping isn't changed:
153 			(info->bus >> 5) /* domain */, (info->bus & 0x1f) /* bus */,
154 			info->bus, info->device, info->function, info->vendor_id, info->device_id, info->revision));
155 	TRACE(("PCI:   class_base %02x, class_function %02x, class_api %02x\n",
156 			info->class_base, info->class_sub, info->class_api));
157 
158 	if (verbose) {
159 #if USE_PCI_HEADER
160 		const char *venShort;
161 		const char *venFull;
162 		get_vendor_info(info->vendor_id, &venShort, &venFull);
163 		if (!venShort && !venFull) {
164 			TRACE(("PCI:   vendor %04x: Unknown\n", info->vendor_id));
165 		} else if (venShort && venFull) {
166 			TRACE(("PCI:   vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull));
167 		} else {
168 			TRACE(("PCI:   vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull));
169 		}
170 		const char *devShort;
171 		const char *devFull;
172 		get_device_info(info->vendor_id, info->device_id, info->u.h0.subsystem_vendor_id, info->u.h0.subsystem_id,
173 			&devShort, &devFull);
174 		if (!devShort && !devFull) {
175 			TRACE(("PCI:   device %04x: Unknown\n", info->device_id));
176 		} else if (devShort && devFull) {
177 			TRACE(("PCI:   device %04x: %s - %s\n", info->device_id, devShort, devFull));
178 		} else {
179 			TRACE(("PCI:   device %04x: %s\n", info->device_id, devShort ? devShort : devFull));
180 		}
181 #endif
182 		char classInfo[64];
183 		get_class_info(info->class_base, info->class_sub, info->class_api, classInfo, 64);
184 		TRACE(("PCI:   info: %s\n", classInfo));
185 	}
186 	TRACE(("PCI:   line_size %02x, latency %02x, header_type %02x, BIST %02x\n",
187 			info->line_size, info->latency, info->header_type, info->bist));
188 
189 	switch (info->header_type & PCI_header_type_mask) {
190 		case PCI_header_type_generic:
191 			print_generic_info(info, verbose);
192 			break;
193 		case PCI_header_type_PCI_to_PCI_bridge:
194 			print_pci2pci_bridge_info(info, verbose);
195 			break;
196 		case PCI_header_type_cardbus:
197 			print_pci2cardbus_bridge_info(info, verbose);
198 			break;
199 		default:
200 			TRACE(("PCI:   unknown header type\n"));
201 	}
202 
203 	print_capabilities(info);
204 }
205 
206 
207 void
208 pci_print_info()
209 {
210 	pci_info info;
211 	for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) {
212 		print_info_basic(&info, PCI_VERBOSE);
213 	}
214 }
215 
216 
217 const char *
218 get_capability_name(uint8 cap_id)
219 {
220 	switch (cap_id) {
221 		case PCI_cap_id_reserved:
222 			return "reserved";
223 		case PCI_cap_id_pm:
224 			return "PM";
225 		case PCI_cap_id_agp:
226 			return "AGP";
227 		case PCI_cap_id_vpd:
228 			return "VPD";
229 		case PCI_cap_id_slotid:
230 			return "SlotID";
231 		case PCI_cap_id_msi:
232 			return "MSI";
233 		case PCI_cap_id_chswp:
234 			return "chswp";
235 		case PCI_cap_id_pcix:
236 			return "PCI-X";
237 		case PCI_cap_id_ldt:
238 			return "ldt";
239 		case PCI_cap_id_vendspec:
240 			return "vendspec";
241 		case PCI_cap_id_debugport:
242 			return "DebugPort";
243 		case PCI_cap_id_cpci_rsrcctl:
244 			return "cpci_rsrcctl";
245 		case PCI_cap_id_hotplug:
246 			return "HotPlug";
247 		case PCI_cap_id_pcie:
248 			return "PCIe";
249 		case PCI_cap_id_msix:
250 			return "MSI-X";
251 		case PCI_cap_id_sata:
252 			return "SATA";
253 		default:
254 			return NULL;
255 	}
256 }
257 
258