1 /* 2 ** Copyright 2003-2005, Marcus Overhagen. All rights reserved. 3 ** Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <KernelExport.h> 8 #include <PCI.h> 9 #include <string.h> 10 #include "pci_info.h" 11 #include "pci_priv.h" 12 #include "pci.h" 13 14 #define PCI_VERBOSE 1 15 #define USE_PCI_HEADER 1 16 17 #if USE_PCI_HEADER 18 # include "pcihdr.h" 19 #endif 20 21 22 void print_bridge_info(const pci_info *info, bool verbose); 23 void print_generic_info(const pci_info *info, bool verbose); 24 void print_capabilities(const pci_info *info); 25 void print_info_basic(const pci_info *info, bool verbose); 26 void get_vendor_info(uint16 vendorID, const char **venShort, const char **venFull); 27 void get_device_info(uint16 vendorID, uint16 deviceID, const char **devShort, const char **devFull); 28 const char *get_class_info(uint8 class_base, uint8 class_sub, uint8 class_api); 29 const char *get_capability_name(uint8 cap_id); 30 31 32 void 33 print_bridge_info(const pci_info *info, bool verbose) 34 { 35 TRACE(("PCI: primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, secondary_latency %02x\n", 36 info->u.h1.primary_bus, info->u.h1.secondary_bus, info->u.h1.subordinate_bus, info->u.h1.secondary_latency)); 37 TRACE(("PCI: io_base %04x%02x, io_limit %04x%02x\n", 38 info->u.h1.io_base_upper16, info->u.h1.io_base, info->u.h1.io_limit_upper16, info->u.h1.io_limit)); 39 TRACE(("PCI: memory_base %04x, memory_limit %04x\n", 40 info->u.h1.memory_base, info->u.h1.memory_limit)); 41 TRACE(("PCI: prefetchable memory base %08lx%04x, limit %08lx%04x\n", 42 info->u.h1.prefetchable_memory_base_upper32, info->u.h1.prefetchable_memory_base, 43 info->u.h1.prefetchable_memory_limit_upper32, info->u.h1.prefetchable_memory_limit)); 44 TRACE(("PCI: bridge_control %04x, secondary_status %04x\n", 45 info->u.h1.bridge_control, info->u.h1.secondary_status)); 46 TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x\n", 47 info->u.h1.interrupt_line, info->u.h1.interrupt_pin)); 48 TRACE(("PCI: ROM base host %08lx, pci %08lx, size ??\n", 49 info->u.h1.rom_base, info->u.h1.rom_base_pci)); 50 for (int i = 0; i < 2; i++) 51 TRACE(("PCI: base reg %d: host %08lx, pci %08lx, size %08lx, flags %02x\n", 52 i, info->u.h1.base_registers[i], info->u.h1.base_registers_pci[i], 53 info->u.h1.base_register_sizes[i], info->u.h1.base_register_flags[i])); 54 } 55 56 57 void 58 print_generic_info(const pci_info *info, bool verbose) 59 { 60 TRACE(("PCI: ROM base host %08lx, pci %08lx, size %08lx\n", 61 info->u.h0.rom_base, info->u.h0.rom_base_pci, info->u.h0.rom_size)); 62 TRACE(("PCI: cardbus_CIS %08lx, subsystem_id %04x, subsystem_vendor_id %04x\n", 63 info->u.h0.cardbus_cis, info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id)); 64 TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x, min_grant %02x, max_latency %02x\n", 65 info->u.h0.interrupt_line, info->u.h0.interrupt_pin, info->u.h0.min_grant, info->u.h0.max_latency)); 66 for (int i = 0; i < 6; i++) 67 TRACE(("PCI: base reg %d: host %08lx, pci %08lx, size %08lx, flags %02x\n", 68 i, info->u.h0.base_registers[i], info->u.h0.base_registers_pci[i], 69 info->u.h0.base_register_sizes[i], info->u.h0.base_register_flags[i])); 70 } 71 72 73 void 74 print_capabilities(const pci_info *info) 75 { 76 uint16 status; 77 uint8 cap_ptr; 78 uint8 cap_id; 79 int i; 80 81 TRACE(("PCI: Capabilities: ")); 82 83 status = pci_read_config(info->bus, info->device, info->function, PCI_status, 2); 84 if (!(status & PCI_status_capabilities)) { 85 TRACE(("(not supported)\n")); 86 return; 87 } 88 89 cap_ptr = pci_read_config(info->bus, info->device, info->function, PCI_capabilities_ptr, 1); 90 cap_ptr &= ~3; 91 if (!cap_ptr) { 92 TRACE(("(empty list)\n")); 93 return; 94 } 95 96 for (i = 0; i < 48; i++) { 97 const char *name; 98 cap_id = pci_read_config(info->bus, info->device, info->function, cap_ptr, 1); 99 cap_ptr = pci_read_config(info->bus, info->device, info->function, cap_ptr + 1, 1); 100 cap_ptr &= ~3; 101 if (i) { 102 TRACE((", ")); 103 } 104 name = get_capability_name(cap_id); 105 if (name) { 106 TRACE(("%s", name)); 107 } else { 108 TRACE(("0x%02x", cap_id)); 109 } 110 if (!cap_ptr) 111 break; 112 } 113 TRACE(("\n")); 114 } 115 116 117 void 118 print_info_basic(const pci_info *info, bool verbose) 119 { 120 TRACE(("PCI: bus %2d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n", 121 info->bus, info->device, info->function, info->vendor_id, info->device_id, info->revision)); 122 TRACE(("PCI: class_base %02x, class_function %02x, class_api %02x\n", 123 info->class_base, info->class_sub, info->class_api)); 124 125 if (verbose) { 126 #if USE_PCI_HEADER 127 const char *venShort; 128 const char *venFull; 129 get_vendor_info(info->vendor_id, &venShort, &venFull); 130 if (!venShort && !venFull) { 131 TRACE(("PCI: vendor %04x: Unknown\n", info->vendor_id)); 132 } else if (venShort && venFull) { 133 TRACE(("PCI: vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull)); 134 } else { 135 TRACE(("PCI: vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull)); 136 } 137 const char *devShort; 138 const char *devFull; 139 get_device_info(info->vendor_id, info->device_id, &devShort, &devFull); 140 if (!devShort && !devFull) { 141 TRACE(("PCI: device %04x: Unknown\n", info->device_id)); 142 } else if (devShort && devFull) { 143 TRACE(("PCI: device %04x: %s - %s\n", info->device_id, devShort, devFull)); 144 } else { 145 TRACE(("PCI: device %04x: %s\n", info->device_id, devShort ? devShort : devFull)); 146 } 147 #endif 148 TRACE(("PCI: info: %s\n", get_class_info(info->class_base, info->class_sub, info->class_api))); 149 } 150 TRACE(("PCI: line_size %02x, latency %02x, header_type %02x, BIST %02x\n", 151 info->line_size, info->latency, info->header_type, info->bist)); 152 153 switch (info->header_type & PCI_header_type_mask) { 154 case 0: 155 print_generic_info(info, verbose); 156 break; 157 case 1: 158 print_bridge_info(info, verbose); 159 break; 160 default: 161 TRACE(("PCI: unknown header type\n")); 162 } 163 164 print_capabilities(info); 165 } 166 167 168 void 169 pci_print_info() 170 { 171 pci_info info; 172 for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) { 173 print_info_basic(&info, PCI_VERBOSE); 174 } 175 } 176 177 178 const char * 179 get_class_info(uint8 class_base, uint8 class_sub, uint8 class_api) 180 { 181 switch (class_base) { 182 case PCI_early: 183 switch (class_sub) { 184 case PCI_early_not_vga: 185 return "Not VGA-compatible pre-2.0 PCI specification device"; 186 case PCI_early_vga: 187 return "VGA-compatible pre-2.0 PCI specification device"; 188 default: 189 return "Unknown pre-2.0 PCI specification device"; 190 } 191 192 case PCI_mass_storage: 193 switch (class_sub) { 194 case PCI_scsi: 195 return "SCSI mass storage controller"; 196 case PCI_ide: 197 return "IDE mass storage controller"; 198 case PCI_floppy: 199 return "Floppy disk controller"; 200 case PCI_ipi: 201 return "IPI mass storage controller"; 202 case PCI_raid: 203 return "RAID mass storage controller"; 204 case PCI_mass_storage_other: 205 return "Other mass storage controller"; 206 default: 207 return "Unknown mass storage controller"; 208 } 209 210 case PCI_network: 211 switch (class_sub) { 212 case PCI_ethernet: 213 return "Ethernet network controller"; 214 case PCI_token_ring: 215 return "Token ring network controller"; 216 case PCI_fddi: 217 return "FDDI network controller"; 218 case PCI_atm: 219 return "ATM network controller"; 220 case PCI_isdn: 221 return "ISDN network controller"; 222 case PCI_network_other: 223 return "Other network controller"; 224 default: 225 return "Unknown network controller"; 226 } 227 228 case PCI_display: 229 switch (class_sub) { 230 case PCI_vga: 231 switch (class_api) { 232 case 0x00: 233 return "VGA-compatible display controller"; 234 case 0x01: 235 return "8514-compatible display controller"; 236 default: 237 return "Unknown VGA display controller"; 238 } 239 case PCI_xga: 240 return "XGA display controller"; 241 case PCI_3d: 242 return "3D display controller"; 243 case PCI_display_other: 244 return "Other display controller"; 245 default: 246 return "Unknown display controller"; 247 } 248 249 case PCI_multimedia: 250 switch (class_sub) { 251 case PCI_video: 252 return "Video multimedia device"; 253 case PCI_audio: 254 return "Audio multimedia device"; 255 case PCI_telephony: 256 return "Computer telephony multimedia device"; 257 case PCI_multimedia_other: 258 return "Other multimedia device"; 259 default: 260 return "Unknown multimedia device"; 261 } 262 263 case PCI_memory: 264 switch (class_sub) { 265 case PCI_ram: 266 return "RAM memory controller"; 267 case PCI_flash: 268 return "Flash memory controller"; 269 case PCI_memory_other: 270 return "Other memory controller"; 271 default: 272 return "Unknown memory controller"; 273 } 274 275 case PCI_bridge: 276 switch (class_sub) { 277 case PCI_host: 278 return "Host/PCI bridge device"; 279 case PCI_isa: 280 return "PCI/ISA bridge device"; 281 case PCI_eisa: 282 return "PCI/EISA bridge device"; 283 case PCI_microchannel: 284 return "PCI/Micro Channel bridge device"; 285 case PCI_pci: 286 switch (class_api) { 287 case 0x00: 288 return "PCI/PCI bridge device"; 289 case 0x01: 290 return "Transparent PCI/PCI bridge device"; 291 default: 292 return "Unknown PCI/PCI bridge device"; 293 } 294 case PCI_pcmcia: 295 return "PCI/PCMCIA bridge device"; 296 case PCI_nubus: 297 return "PCI/NuBus bridge device"; 298 case PCI_cardbus: 299 return "PCI/CardBus bridge device"; 300 case PCI_raceway: 301 if (class_api & 1) 302 return "PCI/RACEway bridge device, end-point mode"; 303 else 304 return "PCI/RACEway bridge device, transparent mode"; 305 case PCI_bridge_other: 306 return "Other bridge device"; 307 default: 308 return "Unknown bridge device"; 309 } 310 311 case PCI_simple_communications: 312 switch (class_sub) { 313 case PCI_serial: 314 switch (class_api) { 315 case PCI_serial_xt: 316 return "Generic XT-compatible serial communications controller"; 317 case PCI_serial_16450: 318 return "16450-compatible serial communications controller"; 319 case PCI_serial_16550: 320 return "16550-compatible serial communications controller"; 321 case 0x03: 322 return "16650-compatible serial communications controller"; 323 case 0x04: 324 return "16750-compatible serial communications controller"; 325 case 0x05: 326 return "16850-compatible serial communications controller"; 327 case 0x06: 328 return "16950-compatible serial communications controller"; 329 default: 330 return "Unknown serial communications controller"; 331 } 332 case PCI_parallel: 333 switch (class_api) { 334 case PCI_parallel_simple: 335 return "Simple parallel port communications controller"; 336 case PCI_parallel_bidirectional: 337 return "Bi-directional parallel port communications controller"; 338 case PCI_parallel_ecp: 339 return "ECP 1.x compliant parallel port communications controller"; 340 case 0x03: 341 return "IEEE 1284 parallel communications controller"; 342 case 0xfe: 343 return "IEEE 1284 parallel communications target device"; 344 default: 345 return "Unknown parallel communications controller"; 346 } 347 case PCI_multiport_serial: 348 return "Multiport serial communications controller"; 349 case PCI_modem: 350 switch (class_api) { 351 case 0x00: 352 return "Generic modem"; 353 case 0x01: 354 return "Hayes-compatible modem, 16450-compatible interface"; 355 case 0x02: 356 return "Hayes-compatible modem, 16550-compatible interface"; 357 case 0x03: 358 return "Hayes-compatible modem, 16650-compatible interface"; 359 case 0x04: 360 return "Hayes-compatible modem, 16750-compatible interface"; 361 default: 362 return "Unknown modem communications controller"; 363 } 364 case PCI_simple_communications_other: 365 return "Other simple communications controller"; 366 default: 367 return "Unknown simple communications controller"; 368 } 369 370 case PCI_base_peripheral: 371 switch (class_sub) { 372 case PCI_pic: 373 switch (class_api) { 374 case PCI_pic_8259: 375 return "Generic 8259 programmable interrupt controller (PIC)"; 376 case PCI_pic_isa: 377 return "ISA programmable interrupt controller (PIC)"; 378 case PCI_pic_eisa: 379 return "EISA programmable interrupt controller (PIC)"; 380 case 0x10: 381 return "IO advanced programmable interrupt controller (APIC)"; 382 case 0x20: 383 return "IO(x) advanced programmable interrupt controller (APIC)"; 384 default: 385 return "Unknown programmable interrupt controller (PIC)"; 386 } 387 case PCI_dma: 388 switch (class_api) { 389 case PCI_dma_8237: 390 return "Generic 8237 DMA controller"; 391 case PCI_dma_isa: 392 return "ISA DMA controller"; 393 case PCI_dma_eisa: 394 return "EISA DMA controller"; 395 default: 396 return "Unknown DMA controller"; 397 } 398 case PCI_timer: 399 switch (class_api) { 400 case PCI_timer_8254: 401 return "Generic 8254 timer"; 402 case PCI_timer_isa: 403 return "ISA system timers"; 404 case PCI_timer_eisa: 405 return "EISA system timers"; 406 default: 407 return "Unknown timer"; 408 } 409 case PCI_rtc: 410 switch (class_api) { 411 case PCI_rtc_generic: 412 return "Generic real time clock (RTC) controller"; 413 case PCI_rtc_isa: 414 return "ISA real time clock (RTC) controller"; 415 default: 416 return "Unknown real time clock (RTC) controller"; 417 } 418 case PCI_generic_hot_plug: 419 return "Generic PCI Hot-Plug controller"; 420 case PCI_system_peripheral_other: 421 return "Other base system peripheral"; 422 default: 423 return "Unknown base system peripheral"; 424 } 425 426 case PCI_input: 427 switch (class_sub) { 428 case PCI_keyboard: 429 return "Keyboard controller"; 430 case PCI_pen: 431 return "Digitizer (pen) input device"; 432 case PCI_mouse: 433 return "Mouse controller"; 434 case PCI_scanner: 435 return "Scanner controller"; 436 case PCI_gameport: 437 switch (class_api) { 438 case 0x00: 439 return "Generic gameport controller"; 440 case 0x10: 441 return "Gameport controller"; 442 default: 443 return "Unknown gameport controller"; 444 } 445 case PCI_input_other: 446 return "Other input controller"; 447 default: 448 return "Unknown input controller"; 449 } 450 451 case PCI_docking_station: 452 switch (class_sub) { 453 case PCI_docking_generic: 454 return "Generic docking station"; 455 case 0x80: 456 return "Other type of docking station"; 457 default: 458 return "Unknown docking station"; 459 } 460 461 case PCI_processor: 462 switch (class_sub) { 463 case PCI_386: 464 return "386 processor"; 465 case PCI_486: 466 return "486 processor"; 467 case PCI_pentium: 468 return "Pentium processor"; 469 case PCI_alpha: 470 return "Alpha processor"; 471 case PCI_PowerPC: 472 return "PowerPC processor"; 473 case PCI_mips: 474 return "MIPS processor"; 475 case PCI_coprocessor: 476 return "Co-processor"; 477 default: 478 return "Unknown processor"; 479 } 480 481 case PCI_serial_bus: 482 switch (class_sub) { 483 case PCI_firewire: 484 switch (class_api) { 485 case 0x00: 486 return "Firewire (IEEE 1394) serial bus controller"; 487 case 0x10: 488 return "Firewire (IEEE 1394) OpenHCI serial bus controller"; 489 default: 490 return "Unknown Firewire (IEEE 1394) serial bus controller"; 491 } 492 case PCI_access: 493 return "ACCESS serial bus controller"; 494 case PCI_ssa: 495 return "Serial Storage Architecture (SSA) controller"; 496 case PCI_usb: 497 switch (class_api) { 498 case PCI_usb_uhci: 499 return "USB UHCI controller"; 500 case PCI_usb_ohci: 501 return "USB OHCI controller"; 502 case 0x80: 503 return "Other USB controller"; 504 case 0xfe: 505 return "USB device"; 506 default: 507 return "Unknown USB serial bus controller"; 508 } 509 case PCI_fibre_channel: 510 return "Fibre Channel serial bus controller"; 511 case 0x05: 512 return "System Management Bus (SMBus) controller"; 513 default: 514 return "Unknown serial bus controller"; 515 } 516 517 case PCI_wireless: 518 switch (class_sub) { 519 case 0x00: 520 return "iRDA compatible wireless controller"; 521 case 0x01: 522 return "Consumer IR wireless controller"; 523 case 0x10: 524 return "RF wireless controller"; 525 case 0x80: 526 return "Other wireless controller"; 527 default: 528 return "Unknown wireless controller"; 529 } 530 531 case PCI_intelligent_io: 532 switch (class_sub) { 533 case 0x00: 534 return "Intelligent IO controller"; 535 default: 536 return "Unknown intelligent IO controller"; 537 } 538 539 case PCI_satellite_communications: 540 switch (class_sub) { 541 case 0x01: 542 return "TV satellite communications controller"; 543 case 0x02: 544 return "Audio satellite communications controller"; 545 case 0x03: 546 return "Voice satellite communications controller"; 547 case 0x04: 548 return "Data satellite communications controller"; 549 default: 550 return "Unknown satellite communications controller"; 551 } 552 553 case PCI_encryption_decryption: 554 switch (class_sub) { 555 case 0x00: 556 return "Network and computing encryption/decryption controller"; 557 case 0x10: 558 return "Entertainment encryption/decryption controller"; 559 case 0x80: 560 return "Other encryption/decryption controller"; 561 default: 562 return "Unknown encryption/decryption controller"; 563 } 564 565 case PCI_data_acquisition: 566 switch (class_sub) { 567 case 0x00: 568 return "DPIO modules (data acquisition and signal processing controller)"; 569 case 0x80: 570 return " Other data acquisition and signal processing controller"; 571 default: 572 return "Unknown data acquisition and signal processing controller"; 573 } 574 575 case PCI_undefined: 576 return "Does not fit any defined class"; 577 578 default: 579 return "Unknown device class base"; 580 } 581 } 582 583 584 const char * 585 get_capability_name(uint8 cap_id) 586 { 587 switch (cap_id) { 588 case PCI_cap_id_reserved: 589 return "reserved"; 590 case PCI_cap_id_pm: 591 return "PM"; 592 case PCI_cap_id_agp: 593 return "AGP"; 594 case PCI_cap_id_vpd: 595 return "VPD"; 596 case PCI_cap_id_slotid: 597 return "SlotID"; 598 case PCI_cap_id_msi: 599 return "MSI"; 600 case PCI_cap_id_chswp: 601 return "chswp"; 602 case PCI_cap_id_pcix: 603 return "PCI-X"; 604 case PCI_cap_id_ldt: 605 return "ldt"; 606 case PCI_cap_id_vendspec: 607 return "vendspec"; 608 case PCI_cap_id_debugport: 609 return "DebugPort"; 610 case PCI_cap_id_cpci_rsrcctl: 611 return "cpci_rsrcctl"; 612 case PCI_cap_id_hotplug: 613 return "HotPlug"; 614 default: 615 return NULL; 616 } 617 } 618 619 620 #if USE_PCI_HEADER 621 void 622 get_vendor_info(uint16 vendorID, const char **venShort, const char **venFull) 623 { 624 for (int i = 0; i < (int)PCI_VENTABLE_LEN; i++) { 625 if (PciVenTable[i].VenId == vendorID) { 626 if (0 == strcmp(PciVenTable[i].VenShort, PciVenTable[i].VenFull)) { 627 *venShort = PciVenTable[i].VenShort[0] ? PciVenTable[i].VenShort : NULL; 628 *venFull = NULL; 629 } else { 630 *venShort = PciVenTable[i].VenShort[0] ? PciVenTable[i].VenShort : NULL; 631 *venFull = PciVenTable[i].VenFull[0] ? PciVenTable[i].VenFull : NULL; 632 } 633 return; 634 } 635 } 636 *venShort = NULL; 637 *venFull = NULL; 638 } 639 640 641 void 642 get_device_info(uint16 vendorID, uint16 deviceID, const char **devShort, const char **devFull) 643 { 644 for (int i = 0; i < (int)PCI_DEVTABLE_LEN; i++) { 645 if (PciDevTable[i].VenId == vendorID && PciDevTable[i].DevId == deviceID ) { 646 *devShort = PciDevTable[i].Chip[0] ? PciDevTable[i].Chip : NULL; 647 *devFull = PciDevTable[i].ChipDesc[0] ? PciDevTable[i].ChipDesc : NULL; 648 return; 649 } 650 } 651 *devShort = NULL; 652 *devFull = NULL; 653 } 654 #endif /* USE_PCI_HEADER */ 655