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 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])); 121 } 122 123 124 static void 125 print_capabilities(const pci_info *info) 126 { 127 uint16 status; 128 uint8 cap_ptr; 129 uint8 cap_id; 130 int i; 131 132 TRACE(("PCI: Capabilities: ")); 133 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; 138 } 139 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; 151 } 152 153 cap_ptr &= ~3; 154 if (!cap_ptr) { 155 TRACE(("(empty list)\n")); 156 return; 157 } 158 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((", ")); 166 } 167 name = get_capability_name(cap_id); 168 if (name) { 169 TRACE(("%s", name)); 170 } else { 171 TRACE(("0x%02x", cap_id)); 172 } 173 if (!cap_ptr) 174 break; 175 } 176 TRACE(("\n")); 177 } 178 179 180 static void 181 print_extended_capabilities(const pci_info *info) 182 { 183 if (pci_find_capability(info->bus, info->device, info->function, 184 PCI_cap_id_pcie, NULL) != B_OK) 185 return; 186 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; 194 } 195 196 for (int i = 0; i < 48; i++) { 197 if (i) { 198 TRACE((", ")); 199 } 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))); 206 } 207 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); 213 } 214 215 TRACE(("\n")); 216 } 217 218 219 static void 220 print_info_basic(const pci_info *info, bool verbose) 221 { 222 uint8 domain; 223 uint8 bus; 224 225 __pci_resolve_virtual_bus(info->bus, &domain, &bus); 226 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)); 232 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)); 244 } 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)); 255 } 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 260 } 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)); 263 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")); 276 } 277 278 print_capabilities(info); 279 print_extended_capabilities(info); 280 } 281 282 283 void 284 pci_print_info() 285 { 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); 289 } 290 } 291 292 293 const char * 294 get_capability_name(uint8 cap_id) 295 { 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; 339 } 340 } 341 342 343 const char * 344 get_extended_capability_name(uint16 cap_id) 345 { 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; 407 } 408 } 409 410