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[64]; 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