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(__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 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 30 31 static void 32 print_pci2pci_bridge_info(const pci_info *info, bool verbose) 33 { 34 TRACE(("PCI: subsystem_id %04x, subsystem_vendor_id %04x\n", 35 info->u.h1.subsystem_id, info->u.h1.subsystem_vendor_id)); 36 TRACE(("PCI: primary_bus %02x, secondary_bus %02x, subordinate_bus %02x," 37 " secondary_latency %02x\n", info->u.h1.primary_bus, 38 info->u.h1.secondary_bus, info->u.h1.subordinate_bus, info->u.h1.secondary_latency)); 39 uint32 io_base = ((uint32)info->u.h1.io_base & 0xf0) << 8; 40 if (info->u.h1.io_base & 1) 41 io_base += ((uint32)info->u.h1.io_base_upper16 << 16); 42 uint32 io_limit = (((uint32)info->u.h1.io_limit & 0xf0) << 8) + 0xfff; 43 if (info->u.h1.io_limit & 1) 44 io_limit += info->u.h1.io_limit_upper16 << 16; 45 TRACE(("PCI: I/O window %04" B_PRIx32 "-%04" B_PRIx32 "\n", io_base, 46 io_limit)); 47 uint32 memory_base = ((uint32)info->u.h1.memory_base & 0xfff0) << 16; 48 uint32 memory_limit = (((uint32)info->u.h1.memory_limit & 0xfff0) << 16) 49 + 0xfffff; 50 TRACE(("PCI: memory window %04" B_PRIx32 "-%04" B_PRIx32 "\n", 51 memory_base, memory_limit)); 52 uint64 prefetchable_memory_base = 53 ((uint32)info->u.h1.prefetchable_memory_base & 0xfff0) << 16; 54 if (info->u.h1.prefetchable_memory_base & 1) { 55 prefetchable_memory_base += 56 (uint64)info->u.h1.prefetchable_memory_base_upper32 << 32; 57 } 58 uint64 prefetchable_memory_limit = 59 (((uint32)info->u.h1.prefetchable_memory_limit & 0xfff0) << 16) 60 + 0xfffff; 61 if (info->u.h1.prefetchable_memory_limit & 1) { 62 prefetchable_memory_limit += 63 (uint64)info->u.h1.prefetchable_memory_limit_upper32 << 32; 64 } 65 TRACE(("PCI: prefetchable memory window %016" B_PRIx64 "-%016" B_PRIx64 "\n", 66 prefetchable_memory_base, prefetchable_memory_limit)); 67 TRACE(("PCI: bridge_control %04x, secondary_status %04x\n", 68 info->u.h1.bridge_control, info->u.h1.secondary_status)); 69 TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x\n", 70 info->u.h1.interrupt_line, info->u.h1.interrupt_pin)); 71 TRACE(("PCI: ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size ??\n", 72 info->u.h1.rom_base, info->u.h1.rom_base_pci)); 73 for (int i = 0; i < 2; i++) 74 TRACE(("PCI: base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", " 75 "size %08" B_PRIx32 ", flags %02x\n", i, info->u.h1.base_registers[i], 76 info->u.h1.base_registers_pci[i], info->u.h1.base_register_sizes[i], 77 info->u.h1.base_register_flags[i])); 78 } 79 80 81 static void 82 print_pci2cardbus_bridge_info(const pci_info *info, bool verbose) 83 { 84 TRACE(("PCI: subsystem_id %04x, subsystem_vendor_id %04x\n", 85 info->u.h2.subsystem_id, info->u.h2.subsystem_vendor_id)); 86 TRACE(("PCI: primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, " 87 "secondary_latency %02x\n", info->u.h2.primary_bus, 88 info->u.h2.secondary_bus, info->u.h2.subordinate_bus, 89 info->u.h2.secondary_latency)); 90 TRACE(("PCI: bridge_control %04x, secondary_status %04x\n", 91 info->u.h2.bridge_control, info->u.h2.secondary_status)); 92 TRACE(("PCI: memory_base_upper32 %08" B_PRIx32 ", memory_base %08" 93 B_PRIx32 "\n", info->u.h2.memory_base_upper32, info->u.h2.memory_base)); 94 TRACE(("PCI: memory_limit_upper32 %08" B_PRIx32 ", memory_limit %08" 95 B_PRIx32 "\n", info->u.h2.memory_limit_upper32, info->u.h2.memory_limit)); 96 TRACE(("PCI: io_base_upper32 %08" B_PRIx32 ", io_base %08" B_PRIx32 "\n", 97 info->u.h2.io_base_upper32, info->u.h2.io_base)); 98 TRACE(("PCI: io_limit_upper32 %08" B_PRIx32 ", io_limit %08" B_PRIx32 "\n", 99 info->u.h2.io_limit_upper32, info->u.h2.io_limit)); 100 } 101 102 103 static void 104 print_generic_info(const pci_info *info, bool verbose) 105 { 106 TRACE(("PCI: ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size " 107 "%08" B_PRIx32 "\n", info->u.h0.rom_base, info->u.h0.rom_base_pci, 108 info->u.h0.rom_size)); 109 TRACE(("PCI: cardbus_CIS %08" B_PRIx32 ", subsystem_id %04x, " 110 "subsystem_vendor_id %04x\n", info->u.h0.cardbus_cis, 111 info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id)); 112 TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x, min_grant %02x, " 113 "max_latency %02x\n", info->u.h0.interrupt_line, info->u.h0.interrupt_pin, 114 info->u.h0.min_grant, info->u.h0.max_latency)); 115 for (int i = 0; i < 6; i++) 116 TRACE(("PCI: base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", " 117 "size %08" B_PRIx32 ", flags %02x\n", i, info->u.h0.base_registers[i], 118 info->u.h0.base_registers_pci[i], info->u.h0.base_register_sizes[i], 119 info->u.h0.base_register_flags[i])); 120 } 121 122 123 static void 124 print_capabilities(const pci_info *info) 125 { 126 uint16 status; 127 uint8 cap_ptr; 128 uint8 cap_id; 129 int i; 130 131 TRACE(("PCI: Capabilities: ")); 132 133 status = pci_read_config(info->bus, info->device, info->function, PCI_status, 2); 134 if (!(status & PCI_status_capabilities)) { 135 TRACE(("(not supported)\n")); 136 return; 137 } 138 139 switch (info->header_type & PCI_header_type_mask) { 140 case PCI_header_type_generic: 141 case PCI_header_type_PCI_to_PCI_bridge: 142 cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr, 1); 143 break; 144 case PCI_header_type_cardbus: 145 cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr_2, 1); 146 break; 147 default: 148 TRACE(("(unknown header type)\n")); 149 return; 150 } 151 152 cap_ptr &= ~3; 153 if (!cap_ptr) { 154 TRACE(("(empty list)\n")); 155 return; 156 } 157 158 for (i = 0; i < 48; i++) { 159 const char *name; 160 cap_id = pci_read_config(info->bus, info->device, info->function, cap_ptr, 1); 161 cap_ptr = pci_read_config(info->bus, info->device, info->function, cap_ptr + 1, 1); 162 cap_ptr &= ~3; 163 if (i) { 164 TRACE((", ")); 165 } 166 name = get_capability_name(cap_id); 167 if (name) { 168 TRACE(("%s", name)); 169 } else { 170 TRACE(("0x%02x", cap_id)); 171 } 172 if (!cap_ptr) 173 break; 174 } 175 TRACE(("\n")); 176 } 177 178 179 static void 180 print_info_basic(const pci_info *info, bool verbose) 181 { 182 int domain; 183 uint8 bus; 184 185 __pci_resolve_virtual_bus(info->bus, &domain, &bus); 186 187 TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n", 188 domain, bus, info->bus /* virtual bus*/, 189 info->device, info->function, info->vendor_id, info->device_id, info->revision)); 190 TRACE(("PCI: class_base %02x, class_function %02x, class_api %02x\n", 191 info->class_base, info->class_sub, info->class_api)); 192 193 if (verbose) { 194 #if USE_PCI_HEADER 195 const char *venShort; 196 const char *venFull; 197 get_vendor_info(info->vendor_id, &venShort, &venFull); 198 if (!venShort && !venFull) { 199 TRACE(("PCI: vendor %04x: Unknown\n", info->vendor_id)); 200 } else if (venShort && venFull) { 201 TRACE(("PCI: vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull)); 202 } else { 203 TRACE(("PCI: vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull)); 204 } 205 const char *devShort; 206 const char *devFull; 207 get_device_info(info->vendor_id, info->device_id, info->u.h0.subsystem_vendor_id, info->u.h0.subsystem_id, 208 &devShort, &devFull); 209 if (!devShort && !devFull) { 210 TRACE(("PCI: device %04x: Unknown\n", info->device_id)); 211 } else if (devShort && devFull) { 212 TRACE(("PCI: device %04x: %s (%s)\n", info->device_id, devShort, devFull)); 213 } else { 214 TRACE(("PCI: device %04x: %s\n", info->device_id, devShort ? devShort : devFull)); 215 } 216 char classInfo[64]; 217 get_class_info(info->class_base, info->class_sub, info->class_api, classInfo, sizeof(classInfo)); 218 TRACE(("PCI: info: %s\n", classInfo)); 219 #endif 220 } 221 TRACE(("PCI: line_size %02x, latency %02x, header_type %02x, BIST %02x\n", 222 info->line_size, info->latency, info->header_type, info->bist)); 223 224 switch (info->header_type & PCI_header_type_mask) { 225 case PCI_header_type_generic: 226 print_generic_info(info, verbose); 227 break; 228 case PCI_header_type_PCI_to_PCI_bridge: 229 print_pci2pci_bridge_info(info, verbose); 230 break; 231 case PCI_header_type_cardbus: 232 print_pci2cardbus_bridge_info(info, verbose); 233 break; 234 default: 235 TRACE(("PCI: unknown header type\n")); 236 } 237 238 print_capabilities(info); 239 } 240 241 242 void 243 pci_print_info() 244 { 245 pci_info info; 246 for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) { 247 print_info_basic(&info, PCI_VERBOSE); 248 } 249 } 250 251 252 const char * 253 get_capability_name(uint8 cap_id) 254 { 255 switch (cap_id) { 256 case PCI_cap_id_reserved: 257 return "reserved"; 258 case PCI_cap_id_pm: 259 return "PM"; 260 case PCI_cap_id_agp: 261 return "AGP"; 262 case PCI_cap_id_vpd: 263 return "VPD"; 264 case PCI_cap_id_slotid: 265 return "SlotID"; 266 case PCI_cap_id_msi: 267 return "MSI"; 268 case PCI_cap_id_chswp: 269 return "CompactPCIHotSwap"; 270 case PCI_cap_id_pcix: 271 return "PCI-X"; 272 case PCI_cap_id_ldt: 273 return "ldt"; 274 case PCI_cap_id_vendspec: 275 return "vendspec"; 276 case PCI_cap_id_debugport: 277 return "DebugPort"; 278 case PCI_cap_id_cpci_rsrcctl: 279 return "cpci_rsrcctl"; 280 case PCI_cap_id_hotplug: 281 return "HotPlug"; 282 case PCI_cap_id_subvendor: 283 return "subvendor"; 284 case PCI_cap_id_agp8x: 285 return "AGP8x"; 286 case PCI_cap_id_secure_dev: 287 return "Secure Device"; 288 case PCI_cap_id_pcie: 289 return "PCIe"; 290 case PCI_cap_id_msix: 291 return "MSI-X"; 292 case PCI_cap_id_sata: 293 return "SATA"; 294 case PCI_cap_id_pciaf: 295 return "AdvancedFeatures"; 296 default: 297 return NULL; 298 } 299 } 300 301