xref: /openbsd-src/usr.sbin/pcidump/pcidump.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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, &reg) != 0)
365 		return;
366 	if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
367 		return;
368 
369 	if (pci_read(bus, dev, func, ptr, &reg) != 0)
370 		return;
371 	ptr = PCI_CAPLIST_PTR(reg);
372 	while (ptr != 0) {
373 		if (pci_read(bus, dev, func, ptr, &reg) != 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, &reg) != 0 ||
399 		    pci_readmask(bus, dev, func, bar, &reg1) != 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, &reg) != 0 ||
432 				    pci_readmask(bus, dev, func, bar, &reg1) != 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, &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, &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, &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, &reg) != 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, &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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &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, &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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &reg) != 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, &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, &reg) != 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, &reg) != 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, &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, &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, &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, &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, &reg) != 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