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
print_pci2pci_bridge_info(const pci_info * info,bool verbose)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
print_pci2cardbus_bridge_info(const pci_info * info,bool verbose)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
print_generic_info(const pci_info * info,bool verbose)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
print_capabilities(const pci_info * info)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
print_extended_capabilities(const pci_info * info)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
print_info_basic(const pci_info * info,bool verbose)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
pci_print_info()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 *
get_capability_name(uint8 cap_id)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 *
get_extended_capability_name(uint16 cap_id)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