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