BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / bus_managers / pci / pci_info.cpp
blobf478b7f037d352bce57d29a903d877c0323bec75
1 /*
2 * Copyright 2003-2006, Marcus Overhagen. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
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"
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
23 #if USE_PCI_HEADER
24 # include "pcihdr.h"
25 # include "pci-utils.h"
26 #endif
28 const char *get_capability_name(uint8 cap_id);
29 const char *get_extended_capability_name(uint16 cap_id);
32 static void
33 print_pci2pci_bridge_info(const pci_info *info, bool verbose)
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;
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;
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]));
82 static void
83 print_pci2cardbus_bridge_info(const pci_info *info, bool verbose)
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));
104 static void
105 print_generic_info(const pci_info *info, bool verbose)
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 TRACE(("PCI: base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", "
118 "size %08" B_PRIx32 ", flags %02x\n", i, info->u.h0.base_registers[i],
119 info->u.h0.base_registers_pci[i], info->u.h0.base_register_sizes[i],
120 info->u.h0.base_register_flags[i]));
124 static void
125 print_capabilities(const pci_info *info)
127 uint16 status;
128 uint8 cap_ptr;
129 uint8 cap_id;
130 int i;
132 TRACE(("PCI: Capabilities: "));
134 status = pci_read_config(info->bus, info->device, info->function, PCI_status, 2);
135 if (!(status & PCI_status_capabilities)) {
136 TRACE(("(not supported)\n"));
137 return;
140 switch (info->header_type & PCI_header_type_mask) {
141 case PCI_header_type_generic:
142 case PCI_header_type_PCI_to_PCI_bridge:
143 cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr, 1);
144 break;
145 case PCI_header_type_cardbus:
146 cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr_2, 1);
147 break;
148 default:
149 TRACE(("(unknown header type)\n"));
150 return;
153 cap_ptr &= ~3;
154 if (!cap_ptr) {
155 TRACE(("(empty list)\n"));
156 return;
159 for (i = 0; i < 48; i++) {
160 const char *name;
161 cap_id = pci_read_config(info->bus, info->device, info->function, cap_ptr, 1);
162 cap_ptr = pci_read_config(info->bus, info->device, info->function, cap_ptr + 1, 1);
163 cap_ptr &= ~3;
164 if (i) {
165 TRACE((", "));
167 name = get_capability_name(cap_id);
168 if (name) {
169 TRACE(("%s", name));
170 } else {
171 TRACE(("0x%02x", cap_id));
173 if (!cap_ptr)
174 break;
176 TRACE(("\n"));
180 static void
181 print_extended_capabilities(const pci_info *info)
183 if (pci_find_capability(info->bus, info->device, info->function,
184 PCI_cap_id_pcie, NULL) != B_OK)
185 return;
187 uint16 capPointer = PCI_extended_capability;
188 uint32 capability = pci_read_config(info->bus, info->device,
189 info->function, capPointer, 4);
190 TRACE(("PCI: Extended capabilities: "));
191 if (capability == 0 || capability == 0xffffffff) {
192 TRACE(("(empty list)\n"));
193 return;
196 for (int i = 0; i < 48; i++) {
197 if (i) {
198 TRACE((", "));
200 const char *name = get_extended_capability_name(
201 PCI_extcap_id(capability));
202 if (name) {
203 TRACE(("%s", name));
204 } else {
205 TRACE(("0x%04" B_PRIx32, PCI_extcap_id(capability)));
208 capPointer = PCI_extcap_next_ptr(capability) & ~3;
209 if (capPointer < PCI_extended_capability)
210 break;
211 capability = pci_read_config(info->bus, info->device, info->function,
212 capPointer, 4);
215 TRACE(("\n"));
219 static void
220 print_info_basic(const pci_info *info, bool verbose)
222 uint8 domain;
223 uint8 bus;
225 __pci_resolve_virtual_bus(info->bus, &domain, &bus);
227 TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
228 domain, bus, info->bus /* virtual bus*/,
229 info->device, info->function, info->vendor_id, info->device_id, info->revision));
230 TRACE(("PCI: class_base %02x, class_function %02x, class_api %02x\n",
231 info->class_base, info->class_sub, info->class_api));
233 if (verbose) {
234 #if USE_PCI_HEADER
235 const char *venShort;
236 const char *venFull;
237 get_vendor_info(info->vendor_id, &venShort, &venFull);
238 if (!venShort && !venFull) {
239 TRACE(("PCI: vendor %04x: Unknown\n", info->vendor_id));
240 } else if (venShort && venFull) {
241 TRACE(("PCI: vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull));
242 } else {
243 TRACE(("PCI: vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull));
245 const char *devShort;
246 const char *devFull;
247 get_device_info(info->vendor_id, info->device_id, info->u.h0.subsystem_vendor_id, info->u.h0.subsystem_id,
248 &devShort, &devFull);
249 if (!devShort && !devFull) {
250 TRACE(("PCI: device %04x: Unknown\n", info->device_id));
251 } else if (devShort && devFull) {
252 TRACE(("PCI: device %04x: %s (%s)\n", info->device_id, devShort, devFull));
253 } else {
254 TRACE(("PCI: device %04x: %s\n", info->device_id, devShort ? devShort : devFull));
256 char classInfo[64];
257 get_class_info(info->class_base, info->class_sub, info->class_api, classInfo, sizeof(classInfo));
258 TRACE(("PCI: info: %s\n", classInfo));
259 #endif
261 TRACE(("PCI: line_size %02x, latency %02x, header_type %02x, BIST %02x\n",
262 info->line_size, info->latency, info->header_type, info->bist));
264 switch (info->header_type & PCI_header_type_mask) {
265 case PCI_header_type_generic:
266 print_generic_info(info, verbose);
267 break;
268 case PCI_header_type_PCI_to_PCI_bridge:
269 print_pci2pci_bridge_info(info, verbose);
270 break;
271 case PCI_header_type_cardbus:
272 print_pci2cardbus_bridge_info(info, verbose);
273 break;
274 default:
275 TRACE(("PCI: unknown header type\n"));
278 print_capabilities(info);
279 print_extended_capabilities(info);
283 void
284 pci_print_info()
286 pci_info info;
287 for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) {
288 print_info_basic(&info, PCI_VERBOSE);
293 const char *
294 get_capability_name(uint8 cap_id)
296 switch (cap_id) {
297 case PCI_cap_id_reserved:
298 return "reserved";
299 case PCI_cap_id_pm:
300 return "PM";
301 case PCI_cap_id_agp:
302 return "AGP";
303 case PCI_cap_id_vpd:
304 return "VPD";
305 case PCI_cap_id_slotid:
306 return "SlotID";
307 case PCI_cap_id_msi:
308 return "MSI";
309 case PCI_cap_id_chswp:
310 return "CompactPCIHotSwap";
311 case PCI_cap_id_pcix:
312 return "PCI-X";
313 case PCI_cap_id_ht:
314 return "HyperTransport";
315 case PCI_cap_id_vendspec:
316 return "vendspec";
317 case PCI_cap_id_debugport:
318 return "DebugPort";
319 case PCI_cap_id_cpci_rsrcctl:
320 return "cpci_rsrcctl";
321 case PCI_cap_id_hotplug:
322 return "HotPlug";
323 case PCI_cap_id_subvendor:
324 return "subvendor";
325 case PCI_cap_id_agp8x:
326 return "AGP8x";
327 case PCI_cap_id_secure_dev:
328 return "Secure Device";
329 case PCI_cap_id_pcie:
330 return "PCIe";
331 case PCI_cap_id_msix:
332 return "MSI-X";
333 case PCI_cap_id_sata:
334 return "SATA";
335 case PCI_cap_id_pciaf:
336 return "AdvancedFeatures";
337 default:
338 return NULL;
343 const char *
344 get_extended_capability_name(uint16 cap_id)
346 switch (cap_id) {
347 case PCI_extcap_id_aer:
348 return "Advanced Error Reporting";
349 case PCI_extcap_id_vc:
350 return "Virtual Channel";
351 case PCI_extcap_id_serial:
352 return "Serial Number";
353 case PCI_extcap_id_power_budget:
354 return "Power Budgeting";
355 case PCI_extcap_id_rcl_decl:
356 return "Root Complex Link Declaration";
357 case PCI_extcap_id_rcil_ctl:
358 return "Root Complex Internal Link Control";
359 case PCI_extcap_id_rcec_assoc:
360 return "Root Complex Event Collector Association";
361 case PCI_extcap_id_mfvc:
362 return "MultiFunction Virtual Channel";
363 case PCI_extcap_id_vc2:
364 return "Virtual Channel 2";
365 case PCI_extcap_id_rcrb_header:
366 return "RCRB Header";
367 case PCI_extcap_id_vendor:
368 return "Vendor Unique";
369 case PCI_extcap_id_acs:
370 return "Access Control Services";
371 case PCI_extcap_id_ari:
372 return "Alternative Routing Id Interpretation";
373 case PCI_extcap_id_ats:
374 return "Address Translation Services";
375 case PCI_extcap_id_srio_virtual:
376 return "Single Root I/O Virtualization";
377 case PCI_extcap_id_mrio_virtual:
378 return "Multiple Root I/O Virtual";
379 case PCI_extcap_id_multicast:
380 return "Multicast";
381 case PCI_extcap_id_page_request:
382 return "Page Request";
383 case PCI_extcap_id_amd:
384 return "AMD Reserved";
385 case PCI_extcap_id_resizable_bar:
386 return "Resizable Bar";
387 case PCI_extcap_id_dyn_power_alloc:
388 return "Dynamic Power Allocation";
389 case PCI_extcap_id_tph_requester:
390 return "TPH Requester";
391 case PCI_extcap_id_latency_tolerance:
392 return "Latency Tolerance Reporting";
393 case PCI_extcap_id_2ndpcie:
394 return "Secondary PCIe";
395 case PCI_extcap_id_pmux:
396 return "Protocol Multiplexing";
397 case PCI_extcap_id_pasid:
398 return "Process Address Space Id";
399 case PCI_extcap_id_ln_requester:
400 return "LN Requester";
401 case PCI_extcap_id_dpc:
402 return "Downstream Porto Containment";
403 case PCI_extcap_id_l1pm:
404 return "L1 Power Management Substates";
405 default:
406 return NULL;