1 /* $OpenBSD: pcidump.c,v 1.40 2016/08/27 04:38:48 guenther 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/*.h> */ 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 38 #define PCIDEV "/dev/pci" 39 40 #ifndef nitems 41 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 42 #endif 43 44 __dead void usage(void); 45 void scanpcidomain(void); 46 int probe(int, int, int); 47 void dump(int, int, int); 48 void hexdump(int, int, int, int); 49 const char *str2busdevfunc(const char *, int *, int *, int *); 50 int pci_nfuncs(int, int); 51 int pci_read(int, int, int, u_int32_t, u_int32_t *); 52 int pci_readmask(int, int, int, u_int32_t, u_int32_t *); 53 void dump_caplist(int, int, int, u_int8_t); 54 void dump_pci_powerstate(int, int, int, uint8_t); 55 void dump_pcie_linkspeed(int, int, int, uint8_t); 56 void print_pcie_ls(uint8_t); 57 int dump_rom(int, int, int); 58 int dump_vga_bios(void); 59 60 void dump_type0(int bus, int dev, int func); 61 void dump_type1(int bus, int dev, int func); 62 void dump_type2(int bus, int dev, int func); 63 64 __dead void 65 usage(void) 66 { 67 extern char *__progname; 68 69 fprintf(stderr, 70 "usage: %s [-v] [-x | -xx | -xxx] [-d pcidev] [bus:dev:func]\n" 71 " %s -r file [-d pcidev] bus:dev:func\n", 72 __progname, __progname); 73 exit(1); 74 } 75 76 int pcifd; 77 int romfd; 78 int verbose = 0; 79 int hex = 0; 80 int size = 64; 81 82 const char *pci_capnames[] = { 83 "Reserved", 84 "Power Management", 85 "AGP", 86 "Vital Product Data (VPD)", 87 "Slot Identification", 88 "Message Signaled Interrupts (MSI)", 89 "CompactPCI Hot Swap", 90 "PCI-X", 91 "AMD LDT/HT", 92 "Vendor Specific", 93 "Debug Port", 94 "CompactPCI Central Resource Control", 95 "PCI Hot-Plug", 96 "PCI-PCI", 97 "AGP8", 98 "Secure", 99 "PCI Express", 100 "Extended Message Signaled Interrupts (MSI-X)", 101 "SATA", 102 "PCI Advanced Features" 103 }; 104 105 int 106 main(int argc, char *argv[]) 107 { 108 int nfuncs; 109 int bus, dev, func; 110 char pcidev[PATH_MAX] = PCIDEV; 111 char *romfile = NULL; 112 const char *errstr; 113 int c, error = 0, dumpall = 1, domid = 0; 114 115 while ((c = getopt(argc, argv, "d:r:vx")) != -1) { 116 switch (c) { 117 case 'd': 118 strlcpy(pcidev, optarg, sizeof(pcidev)); 119 dumpall = 0; 120 break; 121 case 'r': 122 romfile = optarg; 123 dumpall = 0; 124 break; 125 case 'v': 126 verbose = 1; 127 break; 128 case 'x': 129 hex++; 130 break; 131 default: 132 usage(); 133 } 134 } 135 argc -= optind; 136 argv += optind; 137 138 if (argc > 1 || (romfile && argc != 1)) 139 usage(); 140 141 if (romfile) { 142 romfd = open(romfile, O_WRONLY|O_CREAT|O_TRUNC, 0777); 143 if (romfd == -1) 144 err(1, "%s", romfile); 145 } 146 147 if (hex > 1) 148 size = 256; 149 if (hex > 2) 150 size = 4096; 151 152 if (argc == 1) 153 dumpall = 0; 154 155 if (dumpall == 0) { 156 pcifd = open(pcidev, O_RDONLY, 0777); 157 if (pcifd == -1) 158 err(1, "%s", pcidev); 159 } else { 160 for (;;) { 161 snprintf(pcidev, 16, "/dev/pci%d", domid++); 162 pcifd = open(pcidev, O_RDONLY, 0777); 163 if (pcifd == -1) { 164 if (errno == ENXIO || errno == ENOENT) { 165 return 0; 166 } else { 167 err(1, "%s", pcidev); 168 } 169 } 170 printf("Domain %s:\n", pcidev); 171 scanpcidomain(); 172 close(pcifd); 173 } 174 } 175 176 if (argc == 1) { 177 errstr = str2busdevfunc(argv[0], &bus, &dev, &func); 178 if (errstr != NULL) 179 errx(1, "\"%s\": %s", argv[0], errstr); 180 181 nfuncs = pci_nfuncs(bus, dev); 182 if (nfuncs == -1 || func > nfuncs) 183 error = ENXIO; 184 else if (romfile) 185 error = dump_rom(bus, dev, func); 186 else 187 error = probe(bus, dev, func); 188 189 if (error != 0) 190 errc(1, error, "\"%s\"", argv[0]); 191 } else { 192 printf("Domain %s:\n", pcidev); 193 scanpcidomain(); 194 } 195 196 return (0); 197 } 198 199 void 200 scanpcidomain(void) 201 { 202 int nfuncs; 203 int bus, dev, func; 204 205 for (bus = 0; bus < 256; bus++) { 206 for (dev = 0; dev < 32; dev++) { 207 nfuncs = pci_nfuncs(bus, dev); 208 for (func = 0; func < nfuncs; func++) { 209 probe(bus, dev, func); 210 } 211 } 212 } 213 } 214 215 const char * 216 str2busdevfunc(const char *string, int *bus, int *dev, int *func) 217 { 218 const char *errstr; 219 char b[80], *d, *f; 220 221 strlcpy(b, string, sizeof(b)); 222 223 d = strchr(b, ':'); 224 if (d == NULL) 225 return("device not specified"); 226 *d++ = '\0'; 227 228 f = strchr(d, ':'); 229 if (f == NULL) 230 return("function not specified"); 231 *f++ = '\0'; 232 233 *bus = strtonum(b, 0, 255, &errstr); 234 if (errstr != NULL) 235 return (errstr); 236 *dev = strtonum(d, 0, 31, &errstr); 237 if (errstr != NULL) 238 return (errstr); 239 *func = strtonum(f, 0, 7, &errstr); 240 if (errstr != NULL) 241 return (errstr); 242 243 return (NULL); 244 } 245 246 int 247 probe(int bus, int dev, int func) 248 { 249 u_int32_t id_reg; 250 const struct pci_known_vendor *pkv; 251 const struct pci_known_product *pkp; 252 const char *vendor = NULL, *product = NULL; 253 254 if (pci_read(bus, dev, func, PCI_ID_REG, &id_reg) != 0) 255 return (errno); 256 257 if (PCI_VENDOR(id_reg) == PCI_VENDOR_INVALID || 258 PCI_VENDOR(id_reg) == 0) 259 return (ENXIO); 260 261 for (pkv = pci_known_vendors; pkv->vendorname != NULL; pkv++) { 262 if (pkv->vendor == PCI_VENDOR(id_reg)) { 263 vendor = pkv->vendorname; 264 break; 265 } 266 } 267 268 if (vendor != NULL) { 269 for (pkp = pci_known_products; pkp->productname != NULL; pkp++) 270 if (pkp->vendor == PCI_VENDOR(id_reg) && 271 pkp->product == PCI_PRODUCT(id_reg)) { 272 product = pkp->productname; 273 break; 274 } 275 } 276 277 printf(" %d:%d:%d: %s %s\n", bus, dev, func, 278 (vendor == NULL) ? "unknown" : vendor, 279 (product == NULL) ? "unknown" : product); 280 281 if (verbose) 282 dump(bus, dev, func); 283 if (hex > 0) 284 hexdump(bus, dev, func, size); 285 286 return (0); 287 } 288 289 void 290 dump_pci_powerstate(int bus, int dev, int func, uint8_t ptr) 291 { 292 u_int32_t pmcsr; 293 294 if (pci_read(bus, dev, func, ptr + PCI_PMCSR, &pmcsr) != 0) 295 return; 296 297 printf("\t State: D%d", pmcsr & PCI_PMCSR_STATE_MASK); 298 if (pmcsr & PCI_PMCSR_PME_EN) 299 printf(" PME# enabled"); 300 if (pmcsr & PCI_PMCSR_PME_STATUS) 301 printf(" PME# asserted"); 302 printf("\n"); 303 } 304 305 void 306 print_pcie_ls(uint8_t speed) 307 { 308 if (speed & 4) 309 printf("8.0"); 310 else if (speed & 2) 311 printf("5.0"); 312 else if (speed & 1) 313 printf("2.5"); 314 else 315 printf("unknown (%d)", speed); 316 } 317 318 void 319 dump_pcie_linkspeed(int bus, int dev, int func, uint8_t ptr) 320 { 321 u_int32_t lcap, sreg, lcap2 = 0, xcap; 322 u_int8_t cwidth, cspeed, swidth, sspeed; 323 324 if (pci_read(bus, dev, func, ptr + PCI_PCIE_XCAP, &xcap) != 0) 325 return; 326 327 if (PCI_PCIE_XCAP_VER(xcap) >= 2) { 328 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP2, &lcap2) != 0) 329 lcap2 = 0; 330 else 331 cspeed = (lcap2 & 0x0e) >> 1; 332 } 333 334 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP, &lcap) != 0) 335 return; 336 if (lcap2 == 0) 337 cspeed = lcap & 0x0f; 338 339 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCSR, &sreg) != 0) 340 return; 341 sreg = sreg >> 16; 342 343 cwidth = (lcap >> 4) & 0x3f; 344 if (cwidth == 0) 345 return; 346 347 swidth = (sreg >> 4) & 0x3f; 348 sspeed = sreg & 0x0f; 349 350 printf("\t Link Speed: "); 351 print_pcie_ls(sspeed); 352 printf(" / "); 353 print_pcie_ls(cspeed); 354 355 printf(" GT/s Link Width: x%d / x%d\n", swidth, cwidth); 356 } 357 358 void 359 dump_caplist(int bus, int dev, int func, u_int8_t ptr) 360 { 361 u_int32_t reg; 362 u_int8_t cap; 363 364 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, ®) != 0) 365 return; 366 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT)) 367 return; 368 369 if (pci_read(bus, dev, func, ptr, ®) != 0) 370 return; 371 ptr = PCI_CAPLIST_PTR(reg); 372 while (ptr != 0) { 373 if (pci_read(bus, dev, func, ptr, ®) != 0) 374 return; 375 cap = PCI_CAPLIST_CAP(reg); 376 printf("\t0x%04x: Capability 0x%02x: ", ptr, cap); 377 if (cap >= nitems(pci_capnames)) 378 cap = 0; 379 printf("%s\n", pci_capnames[cap]); 380 if (cap == PCI_CAP_PWRMGMT) 381 dump_pci_powerstate(bus, dev, func, ptr); 382 if (cap == PCI_CAP_PCIEXPRESS) 383 dump_pcie_linkspeed(bus, dev, func, ptr); 384 ptr = PCI_CAPLIST_NEXT(reg); 385 } 386 } 387 388 void 389 dump_type0(int bus, int dev, int func) 390 { 391 const char *memtype; 392 u_int64_t mem; 393 u_int64_t mask; 394 u_int32_t reg, reg1; 395 int bar; 396 397 for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 0x4) { 398 if (pci_read(bus, dev, func, bar, ®) != 0 || 399 pci_readmask(bus, dev, func, bar, ®1) != 0) 400 warn("unable to read PCI_MAPREG 0x%02x", bar); 401 402 printf("\t0x%04x: BAR ", bar); 403 404 if (reg == 0 && reg1 == 0) { 405 printf("empty (%08x)\n", reg); 406 continue; 407 } 408 409 switch (PCI_MAPREG_TYPE(reg)) { 410 case PCI_MAPREG_TYPE_MEM: 411 printf("mem "); 412 if (PCI_MAPREG_MEM_PREFETCHABLE(reg)) 413 printf("prefetchable "); 414 415 memtype = "32bit 1m"; 416 switch (PCI_MAPREG_MEM_TYPE(reg)) { 417 case PCI_MAPREG_MEM_TYPE_32BIT: 418 memtype = "32bit"; 419 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 420 printf("%s ", memtype); 421 422 printf("addr: 0x%08x/0x%08x\n", 423 PCI_MAPREG_MEM_ADDR(reg), 424 PCI_MAPREG_MEM_SIZE(reg1)); 425 426 break; 427 case PCI_MAPREG_MEM_TYPE_64BIT: 428 mem = reg; 429 mask = reg1; 430 bar += 0x04; 431 if (pci_read(bus, dev, func, bar, ®) != 0 || 432 pci_readmask(bus, dev, func, bar, ®1) != 0) 433 warn("unable to read 0x%02x", bar); 434 435 mem |= (u_int64_t)reg << 32; 436 mask |= (u_int64_t)reg1 << 32; 437 438 printf("64bit addr: 0x%016llx/0x%08llx\n", 439 PCI_MAPREG_MEM64_ADDR(mem), 440 PCI_MAPREG_MEM64_SIZE(mask)); 441 442 break; 443 } 444 break; 445 446 case PCI_MAPREG_TYPE_IO: 447 printf("io addr: 0x%08x/0x%04x\n", 448 PCI_MAPREG_IO_ADDR(reg), 449 PCI_MAPREG_IO_SIZE(reg1)); 450 break; 451 } 452 } 453 454 if (pci_read(bus, dev, func, PCI_CARDBUS_CIS_REG, ®) != 0) 455 warn("unable to read PCI_CARDBUS_CIS_REG"); 456 printf("\t0x%04x: Cardbus CIS: %08x\n", PCI_CARDBUS_CIS_REG, reg); 457 458 if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG, ®) != 0) 459 warn("unable to read PCI_SUBSYS_ID_REG"); 460 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n", 461 PCI_SUBSYS_ID_REG, PCI_VENDOR(reg), PCI_PRODUCT(reg)); 462 463 if (pci_read(bus, dev, func, PCI_ROM_REG, ®) != 0) 464 warn("unable to read PCI_ROM_REG"); 465 printf("\t0x%04x: Expansion ROM Base Address: %08x\n", 466 PCI_ROM_REG, reg); 467 468 if (pci_read(bus, dev, func, 0x38, ®) != 0) 469 warn("unable to read 0x38 (reserved)"); 470 printf("\t0x%04x: %08x\n", 0x38, reg); 471 472 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, ®) != 0) 473 warn("unable to read PCI_INTERRUPT_REG"); 474 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x Min Gnt: %02x" 475 " Max Lat: %02x\n", PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg), 476 PCI_INTERRUPT_LINE(reg), PCI_MIN_GNT(reg), PCI_MAX_LAT(reg)); 477 } 478 479 void 480 dump_type1(int bus, int dev, int func) 481 { 482 u_int32_t reg; 483 int bar; 484 485 for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_PPB_END; bar += 0x4) { 486 if (pci_read(bus, dev, func, bar, ®) != 0) 487 warn("unable to read PCI_MAPREG 0x%02x", bar); 488 printf("\t0x%04x: %08x\n", bar, reg); 489 } 490 491 if (pci_read(bus, dev, func, PCI_PRIBUS_1, ®) != 0) 492 warn("unable to read PCI_PRIBUS_1"); 493 printf("\t0x%04x: Primary Bus: %d Secondary Bus: %d " 494 "Subordinate Bus: %d \n\t Secondary Latency Timer: %02x\n", 495 PCI_PRIBUS_1, (reg >> 0) & 0xff, (reg >> 8) & 0xff, 496 (reg >> 16) & 0xff, (reg >> 24) & 0xff); 497 498 if (pci_read(bus, dev, func, PCI_IOBASEL_1, ®) != 0) 499 warn("unable to read PCI_IOBASEL_1"); 500 printf("\t0x%04x: I/O Base: %02x I/O Limit: %02x " 501 "Secondary Status: %04x\n", PCI_IOBASEL_1, (reg >> 0 ) & 0xff, 502 (reg >> 8) & 0xff, (reg >> 16) & 0xffff); 503 504 if (pci_read(bus, dev, func, PCI_MEMBASE_1, ®) != 0) 505 warn("unable to read PCI_MEMBASE_1"); 506 printf("\t0x%04x: Memory Base: %04x Memory Limit: %04x\n", 507 PCI_MEMBASE_1, (reg >> 0) & 0xffff, (reg >> 16) & 0xffff); 508 509 if (pci_read(bus, dev, func, PCI_PMBASEL_1, ®) != 0) 510 warn("unable to read PCI_PMBASEL_1"); 511 printf("\t0x%04x: Prefetch Memory Base: %04x " 512 "Prefetch Memory Limit: %04x\n", PCI_PMBASEL_1, 513 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff); 514 515 #undef PCI_PMBASEH_1 516 #define PCI_PMBASEH_1 0x28 517 if (pci_read(bus, dev, func, PCI_PMBASEH_1, ®) != 0) 518 warn("unable to read PCI_PMBASEH_1"); 519 printf("\t0x%04x: Prefetch Memory Base Upper 32 Bits: %08x\n", 520 PCI_PMBASEH_1, reg); 521 522 #undef PCI_PMLIMITH_1 523 #define PCI_PMLIMITH_1 0x2c 524 if (pci_read(bus, dev, func, PCI_PMLIMITH_1, ®) != 0) 525 warn("unable to read PCI_PMLIMITH_1"); 526 printf("\t0x%04x: Prefetch Memory Limit Upper 32 Bits: %08x\n", 527 PCI_PMLIMITH_1, reg); 528 529 #undef PCI_IOBASEH_1 530 #define PCI_IOBASEH_1 0x30 531 if (pci_read(bus, dev, func, PCI_IOBASEH_1, ®) != 0) 532 warn("unable to read PCI_IOBASEH_1"); 533 printf("\t0x%04x: I/O Base Upper 16 Bits: %04x " 534 "I/O Limit Upper 16 Bits: %04x\n", PCI_IOBASEH_1, 535 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff); 536 537 #define PCI_PPB_ROM_REG 0x38 538 if (pci_read(bus, dev, func, PCI_PPB_ROM_REG, ®) != 0) 539 warn("unable to read PCI_PPB_ROM_REG"); 540 printf("\t0x%04x: Expansion ROM Base Address: %08x\n", 541 PCI_PPB_ROM_REG, reg); 542 543 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, ®) != 0) 544 warn("unable to read PCI_INTERRUPT_REG"); 545 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x " 546 "Bridge Control: %04x\n", 547 PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg), 548 PCI_INTERRUPT_LINE(reg), reg >> 16); 549 } 550 551 void 552 dump_type2(int bus, int dev, int func) 553 { 554 u_int32_t reg; 555 556 if (pci_read(bus, dev, func, PCI_MAPREG_START, ®) != 0) 557 warn("unable to read PCI_MAPREG\n"); 558 printf("\t0x%04x: Cardbus Control Registers Base Address: %08x\n", 559 PCI_MAPREG_START, reg); 560 561 if (pci_read(bus, dev, func, PCI_PRIBUS_2, ®) != 0) 562 warn("unable to read PCI_PRIBUS_2"); 563 printf("\t0x%04x: Primary Bus: %d Cardbus Bus: %d " 564 "Subordinate Bus: %d \n\t Cardbus Latency Timer: %02x\n", 565 PCI_PRIBUS_2, (reg >> 0) & 0xff, (reg >> 8) & 0xff, 566 (reg >> 16) & 0xff, (reg >> 24) & 0xff); 567 568 if (pci_read(bus, dev, func, PCI_MEMBASE0_2, ®) != 0) 569 warn("unable to read PCI_MEMBASE0_2\n"); 570 printf("\t0x%04x: Memory Base 0: %08x\n", PCI_MEMBASE0_2, reg); 571 572 if (pci_read(bus, dev, func, PCI_MEMLIMIT0_2, ®) != 0) 573 warn("unable to read PCI_MEMLIMIT0_2\n"); 574 printf("\t0x%04x: Memory Limit 0: %08x\n", PCI_MEMLIMIT0_2, reg); 575 576 if (pci_read(bus, dev, func, PCI_MEMBASE1_2, ®) != 0) 577 warn("unable to read PCI_MEMBASE1_2\n"); 578 printf("\t0x%04x: Memory Base 1: %08x\n", PCI_MEMBASE1_2, reg); 579 580 if (pci_read(bus, dev, func, PCI_MEMLIMIT1_2, ®) != 0) 581 warn("unable to read PCI_MEMLIMIT1_2\n"); 582 printf("\t0x%04x: Memory Limit 1: %08x\n", PCI_MEMLIMIT1_2, reg); 583 584 if (pci_read(bus, dev, func, PCI_IOBASE0_2, ®) != 0) 585 warn("unable to read PCI_IOBASE0_2\n"); 586 printf("\t0x%04x: I/O Base 0: %08x\n", PCI_IOBASE0_2, reg); 587 588 if (pci_read(bus, dev, func, PCI_IOLIMIT0_2, ®) != 0) 589 warn("unable to read PCI_IOLIMIT0_2\n"); 590 printf("\t0x%04x: I/O Limit 0: %08x\n", PCI_IOLIMIT0_2, reg); 591 592 if (pci_read(bus, dev, func, PCI_IOBASE1_2, ®) != 0) 593 warn("unable to read PCI_IOBASE1_2\n"); 594 printf("\t0x%04x: I/O Base 1: %08x\n", PCI_IOBASE1_2, reg); 595 596 if (pci_read(bus, dev, func, PCI_IOLIMIT1_2, ®) != 0) 597 warn("unable to read PCI_IOLIMIT1_2\n"); 598 printf("\t0x%04x: I/O Limit 1: %08x\n", PCI_IOLIMIT1_2, reg); 599 600 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, ®) != 0) 601 warn("unable to read PCI_INTERRUPT_REG"); 602 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x " 603 "Bridge Control: %04x\n", 604 PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg), 605 PCI_INTERRUPT_LINE(reg), reg >> 16); 606 607 if (pci_read(bus, dev, func, PCI_SUBVEND_2, ®) != 0) 608 warn("unable to read PCI_SUBVEND_2"); 609 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n", 610 PCI_SUBVEND_2, PCI_VENDOR(reg), PCI_PRODUCT(reg)); 611 612 if (pci_read(bus, dev, func, PCI_PCCARDIF_2, ®) != 0) 613 warn("unable to read PCI_PCCARDIF_2\n"); 614 printf("\t0x%04x: 16-bit Legacy Mode Base Address: %08x\n", 615 PCI_PCCARDIF_2, reg); 616 } 617 618 void 619 dump(int bus, int dev, int func) 620 { 621 u_int32_t reg; 622 u_int8_t capptr = PCI_CAPLISTPTR_REG; 623 624 if (pci_read(bus, dev, func, PCI_ID_REG, ®) != 0) 625 warn("unable to read PCI_ID_REG"); 626 printf("\t0x%04x: Vendor ID: %04x Product ID: %04x\n", PCI_ID_REG, 627 PCI_VENDOR(reg), PCI_PRODUCT(reg)); 628 629 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, ®) != 0) 630 warn("unable to read PCI_COMMAND_STATUS_REG"); 631 printf("\t0x%04x: Command: %04x Status: %04x\n", 632 PCI_COMMAND_STATUS_REG, reg & 0xffff, (reg >> 16) & 0xffff); 633 634 if (pci_read(bus, dev, func, PCI_CLASS_REG, ®) != 0) 635 warn("unable to read PCI_CLASS_REG"); 636 printf("\t0x%04x: Class: %02x Subclass: %02x Interface: %02x " 637 "Revision: %02x\n", PCI_CLASS_REG, PCI_CLASS(reg), 638 PCI_SUBCLASS(reg), PCI_INTERFACE(reg), PCI_REVISION(reg)); 639 640 if (pci_read(bus, dev, func, PCI_BHLC_REG, ®) != 0) 641 warn("unable to read PCI_BHLC_REG"); 642 printf("\t0x%04x: BIST: %02x Header Type: %02x Latency Timer: %02x " 643 "Cache Line Size: %02x\n", PCI_BHLC_REG, PCI_BIST(reg), 644 PCI_HDRTYPE(reg), PCI_LATTIMER(reg), PCI_CACHELINE(reg)); 645 646 switch (PCI_HDRTYPE_TYPE(reg)) { 647 case 2: 648 dump_type2(bus, dev, func); 649 capptr = PCI_CARDBUS_CAPLISTPTR_REG; 650 break; 651 case 1: 652 dump_type1(bus, dev, func); 653 break; 654 case 0: 655 dump_type0(bus, dev, func); 656 break; 657 default: 658 break; 659 } 660 dump_caplist(bus, dev, func, capptr); 661 } 662 663 void 664 hexdump(int bus, int dev, int func, int size) 665 { 666 u_int32_t reg; 667 int i; 668 669 for (i = 0; i < size; i += 4) { 670 if (pci_read(bus, dev, func, i, ®) != 0) { 671 if (errno == EINVAL) 672 return; 673 warn("unable to read 0x%02x", i); 674 } 675 676 if ((i % 16) == 0) 677 printf("\t0x%04x:", i); 678 printf(" %08x", reg); 679 680 if ((i % 16) == 12) 681 printf("\n"); 682 } 683 } 684 685 int 686 pci_nfuncs(int bus, int dev) 687 { 688 u_int32_t hdr; 689 690 if (pci_read(bus, dev, 0, PCI_BHLC_REG, &hdr) != 0) 691 return (-1); 692 693 return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1); 694 } 695 696 int 697 pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val) 698 { 699 struct pci_io io; 700 int rv; 701 702 bzero(&io, sizeof(io)); 703 io.pi_sel.pc_bus = bus; 704 io.pi_sel.pc_dev = dev; 705 io.pi_sel.pc_func = func; 706 io.pi_reg = reg; 707 io.pi_width = 4; 708 709 rv = ioctl(pcifd, PCIOCREAD, &io); 710 if (rv != 0) 711 return (rv); 712 713 *val = io.pi_data; 714 715 return (0); 716 } 717 718 int 719 pci_readmask(int bus, int dev, int func, u_int32_t reg, u_int32_t *val) 720 { 721 struct pci_io io; 722 int rv; 723 724 bzero(&io, sizeof(io)); 725 io.pi_sel.pc_bus = bus; 726 io.pi_sel.pc_dev = dev; 727 io.pi_sel.pc_func = func; 728 io.pi_reg = reg; 729 io.pi_width = 4; 730 731 rv = ioctl(pcifd, PCIOCREADMASK, &io); 732 if (rv != 0) 733 return (rv); 734 735 *val = io.pi_data; 736 737 return (0); 738 } 739 740 int 741 dump_rom(int bus, int dev, int func) 742 { 743 struct pci_rom rom; 744 u_int32_t cr, addr; 745 746 if (pci_read(bus, dev, func, PCI_ROM_REG, &addr) != 0 || 747 pci_read(bus, dev, func, PCI_CLASS_REG, &cr) != 0) 748 return (errno); 749 750 if (addr == 0 && PCI_CLASS(cr) == PCI_CLASS_DISPLAY && 751 PCI_SUBCLASS(cr) == PCI_SUBCLASS_DISPLAY_VGA) 752 return dump_vga_bios(); 753 754 bzero(&rom, sizeof(rom)); 755 rom.pr_sel.pc_bus = bus; 756 rom.pr_sel.pc_dev = dev; 757 rom.pr_sel.pc_func = func; 758 if (ioctl(pcifd, PCIOCGETROMLEN, &rom)) 759 return (errno); 760 761 rom.pr_rom = malloc(rom.pr_romlen); 762 if (rom.pr_rom == NULL) 763 return (ENOMEM); 764 765 if (ioctl(pcifd, PCIOCGETROM, &rom)) 766 return (errno); 767 768 if (write(romfd, rom.pr_rom, rom.pr_romlen) == -1) 769 return (errno); 770 771 return (0); 772 } 773 774 #define VGA_BIOS_ADDR 0xc0000 775 #define VGA_BIOS_LEN 0x10000 776 777 int 778 dump_vga_bios(void) 779 { 780 #if defined(__amd64__) || defined(__i386__) 781 void *bios; 782 int fd; 783 784 fd = open(_PATH_MEM, O_RDONLY, 0777); 785 if (fd == -1) 786 err(1, "%s", _PATH_MEM); 787 788 bios = malloc(VGA_BIOS_LEN); 789 if (bios == NULL) 790 return (ENOMEM); 791 792 if (pread(fd, bios, VGA_BIOS_LEN, VGA_BIOS_ADDR) == -1) 793 err(1, "%s", _PATH_MEM); 794 795 if (write(romfd, bios, VGA_BIOS_LEN) == -1) { 796 free(bios); 797 return (errno); 798 } 799 800 free(bios); 801 802 return (0); 803 #else 804 return (ENODEV); 805 #endif 806 } 807