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