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, ®) != 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, ®) != 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, ®) != 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, ®) != 0)
677 return;
678 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
679 return;
680
681 if (pci_read(bus, dev, func, ptr, ®) != 0)
682 return;
683 ptr = PCI_CAPLIST_PTR(reg);
684 while (ptr != 0) {
685 if (pci_read(bus, dev, func, ptr, ®) != 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, ®) != 0 ||
725 pci_readmask(bus, dev, func, bar, ®1) != 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, ®) != 0 ||
758 pci_readmask(bus, dev, func, bar, ®1) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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, ®) != 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