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