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