1 /* $OpenBSD: pcidump.c,v 1.68 2021/10/25 19:54:29 kn Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2007 David Gwynne <loki@animata.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/ioctl.h> 21 #include <sys/pciio.h> 22 23 #include <stdio.h> /* need NULL for dev/pci/ headers */ 24 25 #include <dev/pci/pcireg.h> 26 #include <dev/pci/pcidevs.h> 27 #include <dev/pci/pcidevs_data.h> 28 29 #include <err.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <paths.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <unistd.h> 36 #include <limits.h> 37 #include <vis.h> 38 39 #define PCIDEV "/dev/pci" 40 41 #ifndef nitems 42 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 43 #endif 44 45 __dead void usage(void); 46 void scanpcidomain(void); 47 int probe(int, int, int); 48 void dump(int, int, int); 49 void hexdump(int, int, int, int); 50 const char *str2busdevfunc(const char *, int *, int *, int *); 51 int pci_nfuncs(int, int); 52 int pci_read(int, int, int, u_int32_t, u_int32_t *); 53 int pci_readmask(int, int, int, u_int32_t, u_int32_t *); 54 void dump_bars(int, int, int, int); 55 void dump_caplist(int, int, int, u_int8_t); 56 void dump_vpd(int, int, int); 57 void dump_pci_powerstate(int, int, int, uint8_t); 58 void dump_pcie_linkspeed(int, int, int, uint8_t); 59 void dump_pcie_devserial(int, int, int, uint16_t); 60 void dump_msi(int, int, int, uint8_t); 61 void dump_msix(int, int, int, uint8_t); 62 void print_pcie_ls(uint8_t); 63 int dump_rom(int, int, int); 64 int dump_vga_bios(void); 65 66 static const char * 67 pci_class_name(pci_class_t); 68 static const char * 69 pci_subclass_name(pci_class_t, pci_subclass_t); 70 71 void dump_type0(int bus, int dev, int func); 72 void dump_type1(int bus, int dev, int func); 73 void dump_type2(int bus, int dev, int func); 74 75 __dead void 76 usage(void) 77 { 78 extern char *__progname; 79 80 fprintf(stderr, 81 "usage: %s [-v] [-x | -xx | -xxx] [-d pcidev] [bus:dev:func]\n" 82 " %s -r file [-d pcidev] bus:dev:func\n", 83 __progname, __progname); 84 exit(1); 85 } 86 87 int pcifd; 88 int romfd; 89 int verbose = 0; 90 int hex = 0; 91 int size = 64; 92 93 const char *pci_capnames[] = { 94 "Reserved", 95 "Power Management", 96 "AGP", 97 "Vital Product Data (VPD)", 98 "Slot Identification", 99 "Message Signalled Interrupts (MSI)", 100 "CompactPCI Hot Swap", 101 "PCI-X", 102 "AMD LDT/HT", 103 "Vendor Specific", 104 "Debug Port", 105 "CompactPCI Central Resource Control", 106 "PCI Hot-Plug", 107 "PCI-PCI", 108 "AGP8", 109 "Secure", 110 "PCI Express", 111 "Extended Message Signalled Interrupts (MSI-X)", 112 "SATA", 113 "PCI Advanced Features", 114 "Enhanced Allocation", 115 "Flattening Portal Bridge", 116 }; 117 118 const char *pci_enhanced_capnames[] = { 119 "Unknown", 120 "Advanced Error Reporting", 121 "Virtual Channel Capability", 122 "Device Serial Number", 123 "Power Budgeting", 124 "Root Complex Link Declaration", 125 "Root Complex Internal Link Control", 126 "Root Complex Event Collector", 127 "Multi-Function VC Capability", 128 "Virtual Channel Capability", 129 "Root Complex/Root Bridge", 130 "Vendor-Specific", 131 "Config Access", 132 "Access Control Services", 133 "Alternate Routing ID", 134 "Address Translation Services", 135 "Single Root I/O Virtualization", 136 "Multi Root I/O Virtualization", 137 "Multicast", 138 "Page Request Interface", 139 "Reserved for AMD", 140 "Resizable BAR", 141 "Dynamic Power Allocation", 142 "TPH Requester", 143 "Latency Tolerance Reporting", 144 "Secondary PCIe Capability", 145 "Protocol Multiplexing", 146 "Process Address Space ID", 147 "LN Requester", 148 "Downstream Port Containment", 149 "L1 PM", 150 "Precision Time Measurement", 151 "PCI Express over M-PHY", 152 "FRS Queueing", 153 "Readiness Time Reporting", 154 "Designated Vendor-Specific", 155 "VF Resizable BAR", 156 "Data Link Feature ", 157 "Physical Layer 16.0 GT/s", 158 "Lane Margining at the Receiver", 159 "Hierarchy ID", 160 "Native PCIe Enclosure Management", 161 "Physical Layer 32.0 GT/s", 162 "Alternate Protocol", 163 "System Firmware Intermediary", 164 "Shadow Functions", 165 "Data Object Exchange", 166 "Device 3", 167 "Integrity and Data Encryption", 168 }; 169 170 int 171 main(int argc, char *argv[]) 172 { 173 int nfuncs; 174 int bus, dev, func; 175 char pcidev[PATH_MAX] = PCIDEV; 176 char *romfile = NULL; 177 const char *errstr; 178 int c, error = 0, dumpall = 1, domid = 0; 179 180 while ((c = getopt(argc, argv, "d:r:vx")) != -1) { 181 switch (c) { 182 case 'd': 183 strlcpy(pcidev, optarg, sizeof(pcidev)); 184 dumpall = 0; 185 break; 186 case 'r': 187 romfile = optarg; 188 dumpall = 0; 189 break; 190 case 'v': 191 verbose = 1; 192 break; 193 case 'x': 194 hex++; 195 break; 196 default: 197 usage(); 198 } 199 } 200 argc -= optind; 201 argv += optind; 202 203 if (argc > 1 || (romfile && argc != 1)) 204 usage(); 205 206 if (romfile) { 207 romfd = open(romfile, O_WRONLY|O_CREAT|O_TRUNC, 0777); 208 if (romfd == -1) 209 err(1, "%s", romfile); 210 } 211 212 if (unveil("/dev", "r") == -1) 213 err(1, "unveil /dev"); 214 if (unveil(NULL, NULL) == -1) 215 err(1, "unveil"); 216 217 if (hex > 1) 218 size = 256; 219 if (hex > 2) 220 size = 4096; 221 222 if (argc == 1) 223 dumpall = 0; 224 225 if (dumpall == 0) { 226 pcifd = open(pcidev, O_RDONLY); 227 if (pcifd == -1) 228 err(1, "%s", pcidev); 229 } else { 230 for (;;) { 231 snprintf(pcidev, 16, "/dev/pci%d", domid++); 232 pcifd = open(pcidev, O_RDONLY); 233 if (pcifd == -1) { 234 if (errno == ENXIO || errno == ENOENT) { 235 return 0; 236 } else { 237 err(1, "%s", pcidev); 238 } 239 } 240 printf("Domain %s:\n", pcidev); 241 scanpcidomain(); 242 close(pcifd); 243 } 244 } 245 246 if (argc == 1) { 247 errstr = str2busdevfunc(argv[0], &bus, &dev, &func); 248 if (errstr != NULL) 249 errx(1, "\"%s\": %s", argv[0], errstr); 250 251 nfuncs = pci_nfuncs(bus, dev); 252 if (nfuncs == -1 || func > nfuncs) 253 error = ENXIO; 254 else if (romfile) 255 error = dump_rom(bus, dev, func); 256 else 257 error = probe(bus, dev, func); 258 259 if (error != 0) 260 errc(1, error, "\"%s\"", argv[0]); 261 } else { 262 printf("Domain %s:\n", pcidev); 263 scanpcidomain(); 264 } 265 266 return (0); 267 } 268 269 void 270 scanpcidomain(void) 271 { 272 int nfuncs; 273 int bus, dev, func; 274 275 for (bus = 0; bus < 256; bus++) { 276 for (dev = 0; dev < 32; dev++) { 277 nfuncs = pci_nfuncs(bus, dev); 278 for (func = 0; func < nfuncs; func++) { 279 probe(bus, dev, func); 280 } 281 } 282 } 283 } 284 285 const char * 286 str2busdevfunc(const char *string, int *bus, int *dev, int *func) 287 { 288 const char *errstr; 289 char b[80], *d, *f; 290 291 strlcpy(b, string, sizeof(b)); 292 293 d = strchr(b, ':'); 294 if (d == NULL) 295 return("device not specified"); 296 *d++ = '\0'; 297 298 f = strchr(d, ':'); 299 if (f == NULL) 300 return("function not specified"); 301 *f++ = '\0'; 302 303 *bus = strtonum(b, 0, 255, &errstr); 304 if (errstr != NULL) 305 return (errstr); 306 *dev = strtonum(d, 0, 31, &errstr); 307 if (errstr != NULL) 308 return (errstr); 309 *func = strtonum(f, 0, 7, &errstr); 310 if (errstr != NULL) 311 return (errstr); 312 313 return (NULL); 314 } 315 316 int 317 probe(int bus, int dev, int func) 318 { 319 u_int32_t id_reg; 320 const struct pci_known_vendor *pkv; 321 const struct pci_known_product *pkp; 322 const char *vendor = NULL, *product = NULL; 323 324 if (pci_read(bus, dev, func, PCI_ID_REG, &id_reg) != 0) 325 return (errno); 326 327 if (PCI_VENDOR(id_reg) == PCI_VENDOR_INVALID || 328 PCI_VENDOR(id_reg) == 0) 329 return (ENXIO); 330 331 for (pkv = pci_known_vendors; pkv->vendorname != NULL; pkv++) { 332 if (pkv->vendor == PCI_VENDOR(id_reg)) { 333 vendor = pkv->vendorname; 334 break; 335 } 336 } 337 338 if (vendor != NULL) { 339 for (pkp = pci_known_products; pkp->productname != NULL; pkp++) 340 if (pkp->vendor == PCI_VENDOR(id_reg) && 341 pkp->product == PCI_PRODUCT(id_reg)) { 342 product = pkp->productname; 343 break; 344 } 345 } 346 347 printf(" %d:%d:%d: %s %s\n", bus, dev, func, 348 (vendor == NULL) ? "unknown" : vendor, 349 (product == NULL) ? "unknown" : product); 350 351 if (verbose) 352 dump(bus, dev, func); 353 if (hex > 0) 354 hexdump(bus, dev, func, size); 355 356 return (0); 357 } 358 359 int 360 print_bytes(const uint8_t *buf, size_t len) 361 { 362 char dst[8]; 363 size_t i; 364 365 for (i = 0; i < len; i++) { 366 vis(dst, buf[i], VIS_TAB|VIS_NL, 0); 367 printf("%s", dst); 368 } 369 printf("\n"); 370 371 return (0); 372 } 373 374 int 375 print_vpd(const uint8_t *buf, size_t len) 376 { 377 const struct pci_vpd *vpd; 378 char key0[8]; 379 char key1[8]; 380 size_t vlen; 381 382 while (len > 0) { 383 if (len < sizeof(*vpd)) 384 return (1); 385 386 vpd = (const struct pci_vpd *)buf; 387 vis(key0, vpd->vpd_key0, VIS_TAB|VIS_NL, 0); 388 vis(key1, vpd->vpd_key1, VIS_TAB|VIS_NL, 0); 389 vlen = vpd->vpd_len; 390 391 printf("\t\t %s%s: ", key0, key1); 392 393 buf += sizeof(*vpd); 394 len -= sizeof(*vpd); 395 396 if (len < vlen) 397 return (1); 398 print_bytes(buf, vlen); 399 400 buf += vlen; 401 len -= vlen; 402 } 403 404 return (0); 405 } 406 407 void 408 dump_vpd(int bus, int dev, int func) 409 { 410 struct pci_vpd_req io; 411 uint32_t data[64]; /* XXX this can be up to 32k of data */ 412 uint8_t *buf = (uint8_t *)data; 413 size_t len = sizeof(data); 414 415 bzero(&io, sizeof(io)); 416 io.pv_sel.pc_bus = bus; 417 io.pv_sel.pc_dev = dev; 418 io.pv_sel.pc_func = func; 419 io.pv_offset = 0; 420 io.pv_count = nitems(data); 421 io.pv_data = data; 422 423 if (ioctl(pcifd, PCIOCGETVPD, &io) == -1) { 424 warn("PCIOCGETVPD"); 425 return; 426 } 427 428 do { 429 uint8_t vpd = *buf; 430 uint8_t type; 431 size_t hlen, vlen; 432 int (*print)(const uint8_t *, size_t) = print_bytes; 433 434 if (PCI_VPDRES_ISLARGE(vpd)) { 435 struct pci_vpd_largeres *res; 436 type = PCI_VPDRES_LARGE_NAME(vpd); 437 438 switch (type) { 439 case PCI_VPDRES_TYPE_IDENTIFIER_STRING: 440 printf("\t\tProduct Name: "); 441 break; 442 case PCI_VPDRES_TYPE_VPD: 443 print = print_vpd; 444 break; 445 default: 446 printf("%02x: ", type); 447 break; 448 } 449 450 if (len < sizeof(*res)) 451 goto trunc; 452 res = (struct pci_vpd_largeres *)buf; 453 454 hlen = sizeof(*res); 455 vlen = ((size_t)res->vpdres_len_msb << 8) | 456 (size_t)res->vpdres_len_lsb; 457 } else { /* small */ 458 type = PCI_VPDRES_SMALL_NAME(vpd); 459 if (type == PCI_VPDRES_TYPE_END_TAG) 460 break; 461 462 printf("\t\t"); 463 switch (type) { 464 case PCI_VPDRES_TYPE_COMPATIBLE_DEVICE_ID: 465 case PCI_VPDRES_TYPE_VENDOR_DEFINED: 466 default: 467 printf("%02x", type); 468 break; 469 } 470 471 hlen = sizeof(vpd); 472 vlen = PCI_VPDRES_SMALL_LENGTH(vpd); 473 } 474 buf += hlen; 475 len -= hlen; 476 477 if (len < vlen) 478 goto trunc; 479 (*print)(buf, vlen); 480 481 buf += vlen; 482 len -= vlen; 483 } while (len > 0); 484 485 return; 486 trunc: 487 /* i have spent too much time in tcpdump - dlg */ 488 printf("[|vpd]\n"); 489 } 490 491 void 492 dump_pci_powerstate(int bus, int dev, int func, uint8_t ptr) 493 { 494 u_int32_t pmcsr; 495 496 if (pci_read(bus, dev, func, ptr + PCI_PMCSR, &pmcsr) != 0) 497 return; 498 499 printf("\t\tState: D%d", pmcsr & PCI_PMCSR_STATE_MASK); 500 if (pmcsr & PCI_PMCSR_PME_EN) 501 printf(" PME# enabled"); 502 if (pmcsr & PCI_PMCSR_PME_STATUS) 503 printf(" PME# asserted"); 504 printf("\n"); 505 } 506 507 static unsigned int 508 pcie_dcap_mps(uint32_t dcap) 509 { 510 uint32_t shift = dcap & 0x7; 511 return (128 << shift); 512 } 513 514 static unsigned int 515 pcie_dcsr_mps(uint32_t dcsr) 516 { 517 uint32_t shift = (dcsr >> 5) & 0x7; 518 return (128 << shift); 519 } 520 521 static unsigned int 522 pcie_dcsr_mrrs(uint32_t dcsr) 523 { 524 uint32_t shift = (dcsr >> 12) & 0x7; 525 return (128 << shift); 526 } 527 528 void 529 print_pcie_ls(uint8_t speed) 530 { 531 if (speed & 4) 532 printf("8.0"); 533 else if (speed & 2) 534 printf("5.0"); 535 else if (speed & 1) 536 printf("2.5"); 537 else 538 printf("unknown (%d)", speed); 539 } 540 541 void 542 dump_pcie_linkspeed(int bus, int dev, int func, uint8_t ptr) 543 { 544 u_int32_t dcap, dcsr; 545 u_int32_t lcap, sreg, lcap2 = 0, xcap; 546 u_int8_t cwidth, cspeed, swidth, sspeed; 547 548 if (pci_read(bus, dev, func, ptr + PCI_PCIE_DCAP, &dcap) != 0) 549 return; 550 551 if (pci_read(bus, dev, func, ptr + PCI_PCIE_DCSR, &dcsr) != 0) 552 return; 553 554 printf("\t\tMax Payload Size: %u / %u bytes\n", 555 pcie_dcsr_mps(dcsr), pcie_dcap_mps(dcap)); 556 printf("\t\tMax Read Request Size: %u bytes\n", 557 pcie_dcsr_mrrs(dcsr)); 558 559 if (pci_read(bus, dev, func, ptr + PCI_PCIE_XCAP, &xcap) != 0) 560 return; 561 562 if (PCI_PCIE_XCAP_VER(xcap) >= 2) { 563 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP2, &lcap2) != 0) 564 lcap2 = 0; 565 else 566 cspeed = (lcap2 & 0x0e) >> 1; 567 } 568 569 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP, &lcap) != 0) 570 return; 571 if (lcap2 == 0) 572 cspeed = lcap & 0x0f; 573 574 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCSR, &sreg) != 0) 575 return; 576 sreg = sreg >> 16; 577 578 cwidth = (lcap >> 4) & 0x3f; 579 if (cwidth == 0) 580 return; 581 582 swidth = (sreg >> 4) & 0x3f; 583 sspeed = sreg & 0x0f; 584 585 printf("\t\tLink Speed: "); 586 print_pcie_ls(sspeed); 587 printf(" / "); 588 print_pcie_ls(cspeed); 589 printf(" GT/s\n"); 590 591 printf("\t\tLink Width: x%d / x%d\n", swidth, cwidth); 592 } 593 594 void 595 dump_pcie_devserial(int bus, int dev, int func, u_int16_t ptr) 596 { 597 uint32_t lower, upper; 598 uint64_t serial; 599 600 if ((pci_read(bus, dev, func, ptr + 8, &upper) != 0) || 601 (pci_read(bus, dev, func, ptr + 4, &lower) != 0)) 602 return; 603 604 serial = ((uint64_t)upper << 32) | (uint64_t)lower; 605 606 printf("\t\tSerial Number: %016llx\n", serial); 607 } 608 609 void 610 dump_msi(int bus, int dev, int func, u_int8_t ptr) 611 { 612 u_int32_t reg; 613 614 if (pci_read(bus, dev, func, ptr, ®) != 0) 615 return; 616 617 printf("\t\tEnabled: %s\n", reg & PCI_MSI_MC_MSIE ? "yes" : "no"); 618 } 619 620 void 621 dump_msix(int bus, int dev, int func, u_int8_t ptr) 622 { 623 u_int32_t reg; 624 u_int32_t table; 625 626 if ((pci_read(bus, dev, func, ptr, ®) != 0) || 627 (pci_read(bus, dev, func, ptr + PCI_MSIX_TABLE, &table) != 0)) 628 return; 629 630 printf("\t\tEnabled: %s; table size %d (BAR %d:%d)\n", 631 reg & PCI_MSIX_MC_MSIXE ? "yes" : "no", 632 PCI_MSIX_MC_TBLSZ(reg) + 1, 633 (table & PCI_MSIX_TABLE_BIR), 634 (table & PCI_MSIX_TABLE_OFF)); 635 } 636 637 void 638 dump_pcie_enhanced_caplist(int bus, int dev, int func) 639 { 640 u_int32_t reg; 641 u_int32_t capidx; 642 u_int16_t ptr; 643 u_int16_t ecap; 644 645 ptr = PCI_PCIE_ECAP; 646 647 do { 648 if (pci_read(bus, dev, func, ptr, ®) != 0) 649 return; 650 651 if (PCI_PCIE_ECAP_ID(reg) == 0xffff && 652 PCI_PCIE_ECAP_NEXT(reg) == PCI_PCIE_ECAP_LAST) 653 return; 654 655 ecap = PCI_PCIE_ECAP_ID(reg); 656 if (ecap >= nitems(pci_enhanced_capnames)) 657 capidx = 0; 658 else 659 capidx = ecap; 660 661 printf("\t0x%04x: Enhanced Capability 0x%02x: ", ptr, ecap); 662 printf("%s\n", pci_enhanced_capnames[capidx]); 663 664 switch (ecap) { 665 case 0x03: 666 dump_pcie_devserial(bus, dev, func, ptr); 667 break; 668 } 669 670 ptr = PCI_PCIE_ECAP_NEXT(reg); 671 672 } while (ptr != PCI_PCIE_ECAP_LAST); 673 } 674 675 void 676 dump_caplist(int bus, int dev, int func, u_int8_t ptr) 677 { 678 u_int32_t reg; 679 u_int8_t cap; 680 681 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, ®) != 0) 682 return; 683 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT)) 684 return; 685 686 if (pci_read(bus, dev, func, ptr, ®) != 0) 687 return; 688 ptr = PCI_CAPLIST_PTR(reg); 689 while (ptr != 0) { 690 if (pci_read(bus, dev, func, ptr, ®) != 0) 691 return; 692 cap = PCI_CAPLIST_CAP(reg); 693 printf("\t0x%04x: Capability 0x%02x: ", ptr, cap); 694 if (cap >= nitems(pci_capnames)) 695 cap = 0; 696 printf("%s\n", pci_capnames[cap]); 697 switch (cap) { 698 case PCI_CAP_PWRMGMT: 699 dump_pci_powerstate(bus, dev, func, ptr); 700 break; 701 case PCI_CAP_VPD: 702 dump_vpd(bus, dev, func); 703 break; 704 case PCI_CAP_PCIEXPRESS: 705 dump_pcie_linkspeed(bus, dev, func, ptr); 706 dump_pcie_enhanced_caplist(bus, dev, func); 707 break; 708 case PCI_CAP_MSI: 709 dump_msi(bus, dev,func, ptr); 710 break; 711 case PCI_CAP_MSIX: 712 dump_msix(bus, dev, func, ptr); 713 break; 714 } 715 ptr = PCI_CAPLIST_NEXT(reg); 716 } 717 } 718 719 void 720 dump_bars(int bus, int dev, int func, int end) 721 { 722 const char *memtype; 723 u_int64_t mem; 724 u_int64_t mask; 725 u_int32_t reg, reg1; 726 int bar; 727 728 for (bar = PCI_MAPREG_START; bar < end; bar += 0x4) { 729 if (pci_read(bus, dev, func, bar, ®) != 0 || 730 pci_readmask(bus, dev, func, bar, ®1) != 0) 731 warn("unable to read PCI_MAPREG 0x%02x", bar); 732 733 printf("\t0x%04x: BAR ", bar); 734 735 if (reg == 0 && reg1 == 0) { 736 printf("empty (%08x)\n", reg); 737 continue; 738 } 739 740 switch (PCI_MAPREG_TYPE(reg)) { 741 case PCI_MAPREG_TYPE_MEM: 742 printf("mem "); 743 if (PCI_MAPREG_MEM_PREFETCHABLE(reg)) 744 printf("prefetchable "); 745 746 memtype = "32bit 1m"; 747 switch (PCI_MAPREG_MEM_TYPE(reg)) { 748 case PCI_MAPREG_MEM_TYPE_32BIT: 749 memtype = "32bit"; 750 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 751 printf("%s ", memtype); 752 753 printf("addr: 0x%08x/0x%08x\n", 754 PCI_MAPREG_MEM_ADDR(reg), 755 PCI_MAPREG_MEM_SIZE(reg1)); 756 757 break; 758 case PCI_MAPREG_MEM_TYPE_64BIT: 759 mem = reg; 760 mask = reg1; 761 bar += 0x04; 762 if (pci_read(bus, dev, func, bar, ®) != 0 || 763 pci_readmask(bus, dev, func, bar, ®1) != 0) 764 warn("unable to read 0x%02x", bar); 765 766 mem |= (u_int64_t)reg << 32; 767 mask |= (u_int64_t)reg1 << 32; 768 769 printf("64bit addr: 0x%016llx/0x%08llx\n", 770 PCI_MAPREG_MEM64_ADDR(mem), 771 PCI_MAPREG_MEM64_SIZE(mask)); 772 773 break; 774 } 775 break; 776 777 case PCI_MAPREG_TYPE_IO: 778 printf("io addr: 0x%08x/0x%04x\n", 779 PCI_MAPREG_IO_ADDR(reg), 780 PCI_MAPREG_IO_SIZE(reg1)); 781 break; 782 } 783 } 784 } 785 786 void 787 dump_type0(int bus, int dev, int func) 788 { 789 u_int32_t reg; 790 791 dump_bars(bus, dev, func, PCI_MAPREG_END); 792 793 if (pci_read(bus, dev, func, PCI_CARDBUS_CIS_REG, ®) != 0) 794 warn("unable to read PCI_CARDBUS_CIS_REG"); 795 printf("\t0x%04x: Cardbus CIS: %08x\n", PCI_CARDBUS_CIS_REG, reg); 796 797 if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG, ®) != 0) 798 warn("unable to read PCI_SUBSYS_ID_REG"); 799 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n", 800 PCI_SUBSYS_ID_REG, PCI_VENDOR(reg), PCI_PRODUCT(reg)); 801 802 if (pci_read(bus, dev, func, PCI_ROM_REG, ®) != 0) 803 warn("unable to read PCI_ROM_REG"); 804 printf("\t0x%04x: Expansion ROM Base Address: %08x\n", 805 PCI_ROM_REG, reg); 806 807 if (pci_read(bus, dev, func, 0x38, ®) != 0) 808 warn("unable to read 0x38 (reserved)"); 809 printf("\t0x%04x: %08x\n", 0x38, reg); 810 811 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, ®) != 0) 812 warn("unable to read PCI_INTERRUPT_REG"); 813 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x Min Gnt: %02x" 814 " Max Lat: %02x\n", PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg), 815 PCI_INTERRUPT_LINE(reg), PCI_MIN_GNT(reg), PCI_MAX_LAT(reg)); 816 } 817 818 void 819 dump_type1(int bus, int dev, int func) 820 { 821 u_int32_t reg; 822 823 dump_bars(bus, dev, func, PCI_MAPREG_PPB_END); 824 825 if (pci_read(bus, dev, func, PCI_PRIBUS_1, ®) != 0) 826 warn("unable to read PCI_PRIBUS_1"); 827 printf("\t0x%04x: Primary Bus: %d, Secondary Bus: %d, " 828 "Subordinate Bus: %d,\n\t\tSecondary Latency Timer: %02x\n", 829 PCI_PRIBUS_1, (reg >> 0) & 0xff, (reg >> 8) & 0xff, 830 (reg >> 16) & 0xff, (reg >> 24) & 0xff); 831 832 if (pci_read(bus, dev, func, PCI_IOBASEL_1, ®) != 0) 833 warn("unable to read PCI_IOBASEL_1"); 834 printf("\t0x%04x: I/O Base: %02x, I/O Limit: %02x, " 835 "Secondary Status: %04x\n", PCI_IOBASEL_1, (reg >> 0 ) & 0xff, 836 (reg >> 8) & 0xff, (reg >> 16) & 0xffff); 837 838 if (pci_read(bus, dev, func, PCI_MEMBASE_1, ®) != 0) 839 warn("unable to read PCI_MEMBASE_1"); 840 printf("\t0x%04x: Memory Base: %04x, Memory Limit: %04x\n", 841 PCI_MEMBASE_1, (reg >> 0) & 0xffff, (reg >> 16) & 0xffff); 842 843 if (pci_read(bus, dev, func, PCI_PMBASEL_1, ®) != 0) 844 warn("unable to read PCI_PMBASEL_1"); 845 printf("\t0x%04x: Prefetch Memory Base: %04x, " 846 "Prefetch Memory Limit: %04x\n", PCI_PMBASEL_1, 847 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff); 848 849 #undef PCI_PMBASEH_1 850 #define PCI_PMBASEH_1 0x28 851 if (pci_read(bus, dev, func, PCI_PMBASEH_1, ®) != 0) 852 warn("unable to read PCI_PMBASEH_1"); 853 printf("\t0x%04x: Prefetch Memory Base Upper 32 Bits: %08x\n", 854 PCI_PMBASEH_1, reg); 855 856 #undef PCI_PMLIMITH_1 857 #define PCI_PMLIMITH_1 0x2c 858 if (pci_read(bus, dev, func, PCI_PMLIMITH_1, ®) != 0) 859 warn("unable to read PCI_PMLIMITH_1"); 860 printf("\t0x%04x: Prefetch Memory Limit Upper 32 Bits: %08x\n", 861 PCI_PMLIMITH_1, reg); 862 863 #undef PCI_IOBASEH_1 864 #define PCI_IOBASEH_1 0x30 865 if (pci_read(bus, dev, func, PCI_IOBASEH_1, ®) != 0) 866 warn("unable to read PCI_IOBASEH_1"); 867 printf("\t0x%04x: I/O Base Upper 16 Bits: %04x, " 868 "I/O Limit Upper 16 Bits: %04x\n", PCI_IOBASEH_1, 869 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff); 870 871 #define PCI_PPB_ROM_REG 0x38 872 if (pci_read(bus, dev, func, PCI_PPB_ROM_REG, ®) != 0) 873 warn("unable to read PCI_PPB_ROM_REG"); 874 printf("\t0x%04x: Expansion ROM Base Address: %08x\n", 875 PCI_PPB_ROM_REG, reg); 876 877 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, ®) != 0) 878 warn("unable to read PCI_INTERRUPT_REG"); 879 printf("\t0x%04x: Interrupt Pin: %02x, Line: %02x, " 880 "Bridge Control: %04x\n", 881 PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg), 882 PCI_INTERRUPT_LINE(reg), reg >> 16); 883 } 884 885 void 886 dump_type2(int bus, int dev, int func) 887 { 888 u_int32_t reg; 889 890 if (pci_read(bus, dev, func, PCI_MAPREG_START, ®) != 0) 891 warn("unable to read PCI_MAPREG\n"); 892 printf("\t0x%04x: Cardbus Control Registers Base Address: %08x\n", 893 PCI_MAPREG_START, reg); 894 895 if (pci_read(bus, dev, func, PCI_PRIBUS_2, ®) != 0) 896 warn("unable to read PCI_PRIBUS_2"); 897 printf("\t0x%04x: Primary Bus: %d Cardbus Bus: %d " 898 "Subordinate Bus: %d \n\t Cardbus Latency Timer: %02x\n", 899 PCI_PRIBUS_2, (reg >> 0) & 0xff, (reg >> 8) & 0xff, 900 (reg >> 16) & 0xff, (reg >> 24) & 0xff); 901 902 if (pci_read(bus, dev, func, PCI_MEMBASE0_2, ®) != 0) 903 warn("unable to read PCI_MEMBASE0_2\n"); 904 printf("\t0x%04x: Memory Base 0: %08x\n", PCI_MEMBASE0_2, reg); 905 906 if (pci_read(bus, dev, func, PCI_MEMLIMIT0_2, ®) != 0) 907 warn("unable to read PCI_MEMLIMIT0_2\n"); 908 printf("\t0x%04x: Memory Limit 0: %08x\n", PCI_MEMLIMIT0_2, reg); 909 910 if (pci_read(bus, dev, func, PCI_MEMBASE1_2, ®) != 0) 911 warn("unable to read PCI_MEMBASE1_2\n"); 912 printf("\t0x%04x: Memory Base 1: %08x\n", PCI_MEMBASE1_2, reg); 913 914 if (pci_read(bus, dev, func, PCI_MEMLIMIT1_2, ®) != 0) 915 warn("unable to read PCI_MEMLIMIT1_2\n"); 916 printf("\t0x%04x: Memory Limit 1: %08x\n", PCI_MEMLIMIT1_2, reg); 917 918 if (pci_read(bus, dev, func, PCI_IOBASE0_2, ®) != 0) 919 warn("unable to read PCI_IOBASE0_2\n"); 920 printf("\t0x%04x: I/O Base 0: %08x\n", PCI_IOBASE0_2, reg); 921 922 if (pci_read(bus, dev, func, PCI_IOLIMIT0_2, ®) != 0) 923 warn("unable to read PCI_IOLIMIT0_2\n"); 924 printf("\t0x%04x: I/O Limit 0: %08x\n", PCI_IOLIMIT0_2, reg); 925 926 if (pci_read(bus, dev, func, PCI_IOBASE1_2, ®) != 0) 927 warn("unable to read PCI_IOBASE1_2\n"); 928 printf("\t0x%04x: I/O Base 1: %08x\n", PCI_IOBASE1_2, reg); 929 930 if (pci_read(bus, dev, func, PCI_IOLIMIT1_2, ®) != 0) 931 warn("unable to read PCI_IOLIMIT1_2\n"); 932 printf("\t0x%04x: I/O Limit 1: %08x\n", PCI_IOLIMIT1_2, reg); 933 934 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, ®) != 0) 935 warn("unable to read PCI_INTERRUPT_REG"); 936 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x " 937 "Bridge Control: %04x\n", 938 PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg), 939 PCI_INTERRUPT_LINE(reg), reg >> 16); 940 941 if (pci_read(bus, dev, func, PCI_SUBVEND_2, ®) != 0) 942 warn("unable to read PCI_SUBVEND_2"); 943 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n", 944 PCI_SUBVEND_2, PCI_VENDOR(reg), PCI_PRODUCT(reg)); 945 946 if (pci_read(bus, dev, func, PCI_PCCARDIF_2, ®) != 0) 947 warn("unable to read PCI_PCCARDIF_2\n"); 948 printf("\t0x%04x: 16-bit Legacy Mode Base Address: %08x\n", 949 PCI_PCCARDIF_2, reg); 950 } 951 952 void 953 dump(int bus, int dev, int func) 954 { 955 u_int32_t reg; 956 u_int8_t capptr = PCI_CAPLISTPTR_REG; 957 pci_class_t class; 958 pci_subclass_t subclass; 959 960 if (pci_read(bus, dev, func, PCI_ID_REG, ®) != 0) 961 warn("unable to read PCI_ID_REG"); 962 printf("\t0x%04x: Vendor ID: %04x, Product ID: %04x\n", PCI_ID_REG, 963 PCI_VENDOR(reg), PCI_PRODUCT(reg)); 964 965 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, ®) != 0) 966 warn("unable to read PCI_COMMAND_STATUS_REG"); 967 printf("\t0x%04x: Command: %04x, Status: %04x\n", 968 PCI_COMMAND_STATUS_REG, reg & 0xffff, (reg >> 16) & 0xffff); 969 970 if (pci_read(bus, dev, func, PCI_CLASS_REG, ®) != 0) 971 warn("unable to read PCI_CLASS_REG"); 972 class = PCI_CLASS(reg); 973 subclass = PCI_SUBCLASS(reg); 974 printf("\t0x%04x:\tClass: %02x %s,", PCI_CLASS_REG, class, 975 pci_class_name(class)); 976 printf(" Subclass: %02x %s,", subclass, 977 pci_subclass_name(class, subclass)); 978 printf("\n\t\tInterface: %02x, Revision: %02x\n", 979 PCI_INTERFACE(reg), PCI_REVISION(reg)); 980 981 if (pci_read(bus, dev, func, PCI_BHLC_REG, ®) != 0) 982 warn("unable to read PCI_BHLC_REG"); 983 printf("\t0x%04x: BIST: %02x, Header Type: %02x, " 984 "Latency Timer: %02x,\n\t\tCache Line Size: %02x\n", PCI_BHLC_REG, 985 PCI_BIST(reg), PCI_HDRTYPE(reg), 986 PCI_LATTIMER(reg), PCI_CACHELINE(reg)); 987 988 switch (PCI_HDRTYPE_TYPE(reg)) { 989 case 2: 990 dump_type2(bus, dev, func); 991 capptr = PCI_CARDBUS_CAPLISTPTR_REG; 992 break; 993 case 1: 994 dump_type1(bus, dev, func); 995 break; 996 case 0: 997 dump_type0(bus, dev, func); 998 break; 999 default: 1000 break; 1001 } 1002 dump_caplist(bus, dev, func, capptr); 1003 } 1004 1005 void 1006 hexdump(int bus, int dev, int func, int size) 1007 { 1008 u_int32_t reg; 1009 int i; 1010 1011 for (i = 0; i < size; i += 4) { 1012 if (pci_read(bus, dev, func, i, ®) != 0) { 1013 if (errno == EINVAL) 1014 return; 1015 warn("unable to read 0x%02x", i); 1016 } 1017 1018 if ((i % 16) == 0) 1019 printf("\t0x%04x:", i); 1020 printf(" %08x", reg); 1021 1022 if ((i % 16) == 12) 1023 printf("\n"); 1024 } 1025 } 1026 1027 int 1028 pci_nfuncs(int bus, int dev) 1029 { 1030 u_int32_t hdr; 1031 1032 if (pci_read(bus, dev, 0, PCI_BHLC_REG, &hdr) != 0) 1033 return (-1); 1034 1035 return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1); 1036 } 1037 1038 int 1039 pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val) 1040 { 1041 struct pci_io io; 1042 int rv; 1043 1044 bzero(&io, sizeof(io)); 1045 io.pi_sel.pc_bus = bus; 1046 io.pi_sel.pc_dev = dev; 1047 io.pi_sel.pc_func = func; 1048 io.pi_reg = reg; 1049 io.pi_width = 4; 1050 1051 rv = ioctl(pcifd, PCIOCREAD, &io); 1052 if (rv != 0) 1053 return (rv); 1054 1055 *val = io.pi_data; 1056 1057 return (0); 1058 } 1059 1060 int 1061 pci_readmask(int bus, int dev, int func, u_int32_t reg, u_int32_t *val) 1062 { 1063 struct pci_io io; 1064 int rv; 1065 1066 bzero(&io, sizeof(io)); 1067 io.pi_sel.pc_bus = bus; 1068 io.pi_sel.pc_dev = dev; 1069 io.pi_sel.pc_func = func; 1070 io.pi_reg = reg; 1071 io.pi_width = 4; 1072 1073 rv = ioctl(pcifd, PCIOCREADMASK, &io); 1074 if (rv != 0) 1075 return (rv); 1076 1077 *val = io.pi_data; 1078 1079 return (0); 1080 } 1081 1082 int 1083 dump_rom(int bus, int dev, int func) 1084 { 1085 struct pci_rom rom; 1086 u_int32_t cr, addr; 1087 1088 if (pci_read(bus, dev, func, PCI_ROM_REG, &addr) != 0 || 1089 pci_read(bus, dev, func, PCI_CLASS_REG, &cr) != 0) 1090 return (errno); 1091 1092 if (addr == 0 && PCI_CLASS(cr) == PCI_CLASS_DISPLAY && 1093 PCI_SUBCLASS(cr) == PCI_SUBCLASS_DISPLAY_VGA) 1094 return dump_vga_bios(); 1095 1096 bzero(&rom, sizeof(rom)); 1097 rom.pr_sel.pc_bus = bus; 1098 rom.pr_sel.pc_dev = dev; 1099 rom.pr_sel.pc_func = func; 1100 if (ioctl(pcifd, PCIOCGETROMLEN, &rom) == -1) 1101 return (errno); 1102 1103 rom.pr_rom = malloc(rom.pr_romlen); 1104 if (rom.pr_rom == NULL) 1105 return (ENOMEM); 1106 1107 if (ioctl(pcifd, PCIOCGETROM, &rom) == -1) 1108 return (errno); 1109 1110 if (write(romfd, rom.pr_rom, rom.pr_romlen) == -1) 1111 return (errno); 1112 1113 return (0); 1114 } 1115 1116 #define VGA_BIOS_ADDR 0xc0000 1117 #define VGA_BIOS_LEN 0x10000 1118 1119 int 1120 dump_vga_bios(void) 1121 { 1122 #if defined(__amd64__) || defined(__i386__) 1123 void *bios; 1124 int fd; 1125 1126 fd = open(_PATH_MEM, O_RDONLY); 1127 if (fd == -1) 1128 err(1, "%s", _PATH_MEM); 1129 1130 bios = malloc(VGA_BIOS_LEN); 1131 if (bios == NULL) 1132 return (ENOMEM); 1133 1134 if (pread(fd, bios, VGA_BIOS_LEN, VGA_BIOS_ADDR) == -1) 1135 err(1, "%s", _PATH_MEM); 1136 1137 if (write(romfd, bios, VGA_BIOS_LEN) == -1) { 1138 free(bios); 1139 return (errno); 1140 } 1141 1142 free(bios); 1143 1144 return (0); 1145 #else 1146 return (ENODEV); 1147 #endif 1148 } 1149 1150 struct pci_subclass { 1151 pci_subclass_t subclass; 1152 const char *name; 1153 }; 1154 1155 struct pci_class { 1156 pci_class_t class; 1157 const char *name; 1158 const struct pci_subclass 1159 *subclass; 1160 size_t nsubclass; 1161 }; 1162 1163 static const struct pci_subclass pci_subclass_prehistoric[] = { 1164 { PCI_SUBCLASS_PREHISTORIC_MISC, "Miscellaneous" }, 1165 { PCI_SUBCLASS_PREHISTORIC_VGA, "VGA" }, 1166 }; 1167 1168 static const struct pci_subclass pci_subclass_mass_storage[] = { 1169 { PCI_SUBCLASS_MASS_STORAGE_SCSI, "SCSI" }, 1170 { PCI_SUBCLASS_MASS_STORAGE_IDE, "IDE" }, 1171 { PCI_SUBCLASS_MASS_STORAGE_FLOPPY, "Floppy" }, 1172 { PCI_SUBCLASS_MASS_STORAGE_IPI, "IPI" }, 1173 { PCI_SUBCLASS_MASS_STORAGE_RAID, "RAID" }, 1174 { PCI_SUBCLASS_MASS_STORAGE_ATA, "ATA" }, 1175 { PCI_SUBCLASS_MASS_STORAGE_SATA, "SATA" }, 1176 { PCI_SUBCLASS_MASS_STORAGE_SAS, "SAS" }, 1177 { PCI_SUBCLASS_MASS_STORAGE_UFS, "UFS" }, 1178 { PCI_SUBCLASS_MASS_STORAGE_NVM, "NVM" }, 1179 { PCI_SUBCLASS_MASS_STORAGE_MISC, "Miscellaneous" }, 1180 }; 1181 1182 static const struct pci_subclass pci_subclass_network[] = { 1183 { PCI_SUBCLASS_NETWORK_ETHERNET, "Ethernet" }, 1184 { PCI_SUBCLASS_NETWORK_TOKENRING, "Token Ring" }, 1185 { PCI_SUBCLASS_NETWORK_FDDI, "FDDI" }, 1186 { PCI_SUBCLASS_NETWORK_ATM, "ATM" }, 1187 { PCI_SUBCLASS_NETWORK_ISDN, "ISDN" }, 1188 { PCI_SUBCLASS_NETWORK_WORLDFIP, "WorldFip" }, 1189 { PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, "PCMIG Multi Computing" }, 1190 { PCI_SUBCLASS_NETWORK_INFINIBAND, "InfiniBand" }, 1191 { PCI_SUBCLASS_NETWORK_MISC, "Miscellaneous" }, 1192 }; 1193 1194 static const struct pci_subclass pci_subclass_display[] = { 1195 { PCI_SUBCLASS_DISPLAY_VGA, "VGA" }, 1196 { PCI_SUBCLASS_DISPLAY_XGA, "XGA" }, 1197 { PCI_SUBCLASS_DISPLAY_3D, "3D" }, 1198 { PCI_SUBCLASS_DISPLAY_MISC, "Miscellaneous" }, 1199 }; 1200 1201 static const struct pci_subclass pci_subclass_multimedia[] = { 1202 { PCI_SUBCLASS_MULTIMEDIA_VIDEO, "Video" }, 1203 { PCI_SUBCLASS_MULTIMEDIA_AUDIO, "Audio" }, 1204 { PCI_SUBCLASS_MULTIMEDIA_TELEPHONY, "Telephony" }, 1205 { PCI_SUBCLASS_MULTIMEDIA_HDAUDIO, "HD Audio" }, 1206 { PCI_SUBCLASS_MULTIMEDIA_MISC, "Miscellaneous" }, 1207 }; 1208 1209 static const struct pci_subclass pci_subclass_memory[] = { 1210 { PCI_SUBCLASS_MEMORY_RAM, "RAM" }, 1211 { PCI_SUBCLASS_MEMORY_FLASH, "Flash" }, 1212 { PCI_SUBCLASS_MEMORY_MISC, "Miscellaneous" }, 1213 }; 1214 1215 static const struct pci_subclass pci_subclass_bridge[] = { 1216 { PCI_SUBCLASS_BRIDGE_HOST, "Host" }, 1217 { PCI_SUBCLASS_BRIDGE_ISA, "ISA" }, 1218 { PCI_SUBCLASS_BRIDGE_EISA, "EISA" }, 1219 { PCI_SUBCLASS_BRIDGE_MC, "MicroChannel" }, 1220 { PCI_SUBCLASS_BRIDGE_PCI, "PCI" }, 1221 { PCI_SUBCLASS_BRIDGE_PCMCIA, "PCMCIA" }, 1222 { PCI_SUBCLASS_BRIDGE_NUBUS, "NuBus" }, 1223 { PCI_SUBCLASS_BRIDGE_RACEWAY, "RACEway" }, 1224 { PCI_SUBCLASS_BRIDGE_STPCI, "Semi-transparent PCI" }, 1225 { PCI_SUBCLASS_BRIDGE_INFINIBAND, "InfiniBand" }, 1226 { PCI_SUBCLASS_BRIDGE_MISC, "Miscellaneous" }, 1227 { PCI_SUBCLASS_BRIDGE_AS, "advanced switching" }, 1228 }; 1229 1230 static const struct pci_subclass pci_subclass_communications[] = { 1231 { PCI_SUBCLASS_COMMUNICATIONS_SERIAL, "Serial" }, 1232 { PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, "Parallel" }, 1233 { PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL, "Multi-port Serial" }, 1234 { PCI_SUBCLASS_COMMUNICATIONS_MODEM, "Modem" }, 1235 { PCI_SUBCLASS_COMMUNICATIONS_GPIB, "GPIB" }, 1236 { PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD, 1237 "Smartcard" }, 1238 { PCI_SUBCLASS_COMMUNICATIONS_MISC, "Miscellaneous" }, 1239 }; 1240 1241 static const struct pci_subclass pci_subclass_system[] = { 1242 { PCI_SUBCLASS_SYSTEM_PIC, "Interrupt" }, 1243 { PCI_SUBCLASS_SYSTEM_DMA, "8237 DMA" }, 1244 { PCI_SUBCLASS_SYSTEM_TIMER, "8254 Timer" }, 1245 { PCI_SUBCLASS_SYSTEM_RTC, "RTC" }, 1246 { PCI_SUBCLASS_SYSTEM_SDHC, "SDHC" }, 1247 { PCI_SUBCLASS_SYSTEM_IOMMU, "IOMMU" }, 1248 { PCI_SUBCLASS_SYSTEM_ROOTCOMPEVENT, "Root Complex Event" }, 1249 { PCI_SUBCLASS_SYSTEM_MISC, "Miscellaneous" }, 1250 }; 1251 1252 static const struct pci_subclass pci_subclass_input[] = { 1253 { PCI_SUBCLASS_INPUT_KEYBOARD, "Keyboard" }, 1254 { PCI_SUBCLASS_INPUT_DIGITIZER, "Digitizer" }, 1255 { PCI_SUBCLASS_INPUT_MOUSE, "Mouse" }, 1256 { PCI_SUBCLASS_INPUT_SCANNER, "Scanner" }, 1257 { PCI_SUBCLASS_INPUT_GAMEPORT, "Game Port" }, 1258 { PCI_SUBCLASS_INPUT_MISC, "Miscellaneous" }, 1259 }; 1260 1261 static const struct pci_subclass pci_subclass_dock[] = { 1262 { PCI_SUBCLASS_DOCK_GENERIC, "Generic" }, 1263 { PCI_SUBCLASS_DOCK_MISC, "Miscellaneous" }, 1264 }; 1265 1266 static const struct pci_subclass pci_subclass_processor[] = { 1267 { PCI_SUBCLASS_PROCESSOR_386, "386" }, 1268 { PCI_SUBCLASS_PROCESSOR_486, "486" }, 1269 { PCI_SUBCLASS_PROCESSOR_PENTIUM, "Pentium" }, 1270 { PCI_SUBCLASS_PROCESSOR_ALPHA, "Alpha" }, 1271 { PCI_SUBCLASS_PROCESSOR_POWERPC, "PowerPC" }, 1272 { PCI_SUBCLASS_PROCESSOR_MIPS, "MIPS" }, 1273 { PCI_SUBCLASS_PROCESSOR_COPROC, "Co-Processor" }, 1274 }; 1275 1276 static const struct pci_subclass pci_subclass_serialbus[] = { 1277 { PCI_SUBCLASS_SERIALBUS_FIREWIRE, "FireWire" }, 1278 { PCI_SUBCLASS_SERIALBUS_ACCESS, "ACCESS.bus" }, 1279 { PCI_SUBCLASS_SERIALBUS_SSA, "SSA" }, 1280 { PCI_SUBCLASS_SERIALBUS_USB, "USB" }, 1281 { PCI_SUBCLASS_SERIALBUS_FIBER, "Fiber Channel" }, 1282 { PCI_SUBCLASS_SERIALBUS_SMBUS, "SMBus" }, 1283 { PCI_SUBCLASS_SERIALBUS_INFINIBAND, "InfiniBand" }, 1284 { PCI_SUBCLASS_SERIALBUS_IPMI, "IPMI" }, 1285 { PCI_SUBCLASS_SERIALBUS_SERCOS, "SERCOS" }, 1286 { PCI_SUBCLASS_SERIALBUS_CANBUS, "CANbus" }, 1287 }; 1288 1289 static const struct pci_subclass pci_subclass_wireless[] = { 1290 { PCI_SUBCLASS_WIRELESS_IRDA, "IrDA" }, 1291 { PCI_SUBCLASS_WIRELESS_CONSUMERIR, "Consumer IR" }, 1292 { PCI_SUBCLASS_WIRELESS_RF, "RF" }, 1293 { PCI_SUBCLASS_WIRELESS_BLUETOOTH, "Bluetooth" }, 1294 { PCI_SUBCLASS_WIRELESS_BROADBAND, "Broadband" }, 1295 { PCI_SUBCLASS_WIRELESS_802_11A, "802.11a" }, 1296 { PCI_SUBCLASS_WIRELESS_802_11B, "802.11b" }, 1297 { PCI_SUBCLASS_WIRELESS_MISC, "Miscellaneous" }, 1298 }; 1299 1300 static const struct pci_subclass pci_subclass_i2o[] = { 1301 { PCI_SUBCLASS_I2O_STANDARD, "Standard" }, 1302 }; 1303 1304 static const struct pci_subclass pci_subclass_satcom[] = { 1305 { PCI_SUBCLASS_SATCOM_TV, "TV" }, 1306 { PCI_SUBCLASS_SATCOM_AUDIO, "Audio" }, 1307 { PCI_SUBCLASS_SATCOM_VOICE, "Voice" }, 1308 { PCI_SUBCLASS_SATCOM_DATA, "Data" }, 1309 }; 1310 1311 static const struct pci_subclass pci_subclass_crypto[] = { 1312 { PCI_SUBCLASS_CRYPTO_NETCOMP, "Network/Computing" }, 1313 { PCI_SUBCLASS_CRYPTO_ENTERTAINMENT, "Entertainment" }, 1314 { PCI_SUBCLASS_CRYPTO_MISC, "Miscellaneous" }, 1315 }; 1316 1317 static const struct pci_subclass pci_subclass_dasp[] = { 1318 { PCI_SUBCLASS_DASP_DPIO, "DPIO" }, 1319 { PCI_SUBCLASS_DASP_TIMEFREQ, "Time and Frequency" }, 1320 { PCI_SUBCLASS_DASP_SYNC, "Synchronization" }, 1321 { PCI_SUBCLASS_DASP_MGMT, "Management" }, 1322 { PCI_SUBCLASS_DASP_MISC, "Miscellaneous" }, 1323 }; 1324 1325 static const struct pci_subclass pci_subclass_accelerator[] = {}; 1326 static const struct pci_subclass pci_subclass_instrumentation[] = {}; 1327 1328 #define CLASS(_c, _n, _s) { \ 1329 .class = _c, \ 1330 .name = _n, \ 1331 .subclass = _s, \ 1332 .nsubclass = nitems(_s), \ 1333 } 1334 1335 static const struct pci_class pci_classes[] = { 1336 CLASS(PCI_CLASS_PREHISTORIC, "Prehistoric", 1337 pci_subclass_prehistoric), 1338 CLASS(PCI_CLASS_MASS_STORAGE, "Mass Storage", 1339 pci_subclass_mass_storage), 1340 CLASS(PCI_CLASS_NETWORK, "Network", 1341 pci_subclass_network), 1342 CLASS(PCI_CLASS_DISPLAY, "Display", 1343 pci_subclass_display), 1344 CLASS(PCI_CLASS_MULTIMEDIA, "Multimedia", 1345 pci_subclass_multimedia), 1346 CLASS(PCI_CLASS_MEMORY, "Memory", 1347 pci_subclass_memory), 1348 CLASS(PCI_CLASS_BRIDGE, "Bridge", 1349 pci_subclass_bridge), 1350 CLASS(PCI_CLASS_COMMUNICATIONS, "Communications", 1351 pci_subclass_communications), 1352 CLASS(PCI_CLASS_SYSTEM, "System", 1353 pci_subclass_system), 1354 CLASS(PCI_CLASS_INPUT, "Input", 1355 pci_subclass_input), 1356 CLASS(PCI_CLASS_DOCK, "Dock", 1357 pci_subclass_dock), 1358 CLASS(PCI_CLASS_PROCESSOR, "Processor", 1359 pci_subclass_processor), 1360 CLASS(PCI_CLASS_SERIALBUS, "Serial Bus", 1361 pci_subclass_serialbus), 1362 CLASS(PCI_CLASS_WIRELESS, "Wireless", 1363 pci_subclass_wireless), 1364 CLASS(PCI_CLASS_I2O, "I2O", 1365 pci_subclass_i2o), 1366 CLASS(PCI_CLASS_SATCOM, "Satellite Comm", 1367 pci_subclass_satcom), 1368 CLASS(PCI_CLASS_CRYPTO, "Crypto", 1369 pci_subclass_crypto), 1370 CLASS(PCI_CLASS_DASP, "DASP", 1371 pci_subclass_dasp), 1372 CLASS(PCI_CLASS_ACCELERATOR, "Accelerator", 1373 pci_subclass_accelerator), 1374 CLASS(PCI_CLASS_INSTRUMENTATION, "Instrumentation", 1375 pci_subclass_instrumentation), 1376 }; 1377 1378 static const struct pci_class * 1379 pci_class(pci_class_t class) 1380 { 1381 const struct pci_class *pc; 1382 size_t i; 1383 1384 for (i = 0; i < nitems(pci_classes); i++) { 1385 pc = &pci_classes[i]; 1386 if (pc->class == class) 1387 return (pc); 1388 } 1389 1390 return (NULL); 1391 } 1392 1393 static const struct pci_subclass * 1394 pci_subclass(const struct pci_class *pc, pci_subclass_t subclass) 1395 { 1396 const struct pci_subclass *ps; 1397 size_t i; 1398 1399 for (i = 0; i < pc->nsubclass; i++) { 1400 ps = &pc->subclass[i]; 1401 if (ps->subclass == subclass) 1402 return (ps); 1403 } 1404 1405 return (NULL); 1406 } 1407 1408 static const char * 1409 pci_class_name(pci_class_t class) 1410 { 1411 const struct pci_class *pc; 1412 1413 pc = pci_class(class); 1414 if (pc == NULL) 1415 return ("(unknown)"); 1416 1417 return (pc->name); 1418 } 1419 1420 static const char * 1421 pci_subclass_name(pci_class_t class, pci_subclass_t subclass) 1422 { 1423 const struct pci_class *pc; 1424 const struct pci_subclass *ps; 1425 1426 pc = pci_class(class); 1427 if (pc == NULL) 1428 return ("(unknown)"); 1429 1430 ps = pci_subclass(pc, subclass); 1431 if (ps == NULL || ps->name == NULL) 1432 return ("(unknown)"); 1433 1434 return (ps->name); 1435 } 1436