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