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