Bug Summary

File:src/usr.sbin/pcidump/pcidump.c
Warning:line 821, column 25
The left operand of '>>' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pcidump.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/pcidump/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/pcidump/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/pcidump/pcidump.c
1/* $OpenBSD: pcidump.c,v 1.69 2023/04/16 17:26:14 kettenis 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(*__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" "/dev/pci"
40
41#ifndef nitems
42#define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0]))
43#endif
44
45__dead__attribute__((__noreturn__)) void usage(void);
46void scanpcidomain(void);
47int probe(int, int, int);
48void dump(int, int, int);
49void hexdump(int, int, int, int);
50const char *str2busdevfunc(const char *, int *, int *, int *);
51int pci_nfuncs(int, int);
52int pci_read(int, int, int, u_int32_t, u_int32_t *);
53int pci_readmask(int, int, int, u_int32_t, u_int32_t *);
54void dump_bars(int, int, int, int);
55void dump_caplist(int, int, int, u_int8_t);
56void dump_vpd(int, int, int);
57void dump_pci_powerstate(int, int, int, uint8_t);
58void dump_pcie_linkspeed(int, int, int, uint8_t);
59void dump_pcie_devserial(int, int, int, uint16_t);
60void dump_msi(int, int, int, uint8_t);
61void dump_msix(int, int, int, uint8_t);
62void print_pcie_ls(uint8_t);
63int dump_rom(int, int, int);
64int dump_vga_bios(void);
65
66static const char *
67 pci_class_name(pci_class_t);
68static const char *
69 pci_subclass_name(pci_class_t, pci_subclass_t);
70
71void dump_type0(int bus, int dev, int func);
72void dump_type1(int bus, int dev, int func);
73void dump_type2(int bus, int dev, int func);
74
75__dead__attribute__((__noreturn__)) void
76usage(void)
77{
78 extern char *__progname;
79
80 fprintf(stderr(&__sF[2]),
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
87int pcifd;
88int romfd;
89int verbose = 0;
90int hex = 0;
91int size = 64;
92
93const 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
118const 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
170int
171main(int argc, char *argv[])
172{
173 int nfuncs;
174 int bus, dev, func;
175 char pcidev[PATH_MAX1024] = PCIDEV"/dev/pci";
176 char *romfile = NULL((void *)0);
177 const char *errstr;
178 int c, error = 0, dumpall = 1, domid = 0;
179
180 while ((c = getopt(argc, argv, "d:r:vx")) != -1) {
1
Assuming the condition is false
2
Loop condition is false. Execution continues on line 200
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
3.1
'romfile' is null
&& argc != 1))
3
Assuming 'argc' is <= 1
204 usage();
205
206 if (romfile
3.2
'romfile' is null
) {
4
Taking false branch
207 romfd = open(romfile, O_WRONLY0x0001|O_CREAT0x0200|O_TRUNC0x0400, 0777);
208 if (romfd == -1)
209 err(1, "%s", romfile);
210 }
211
212 if (unveil("/dev", "r") == -1)
5
Assuming the condition is false
6
Taking false branch
213 err(1, "unveil /dev");
214 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
7
Assuming the condition is false
8
Taking false branch
215 err(1, "unveil");
216
217 if (hex
8.1
'hex' is <= 1
> 1)
9
Taking false branch
218 size = 256;
219 if (hex
9.1
'hex' is <= 2
> 2)
10
Taking false branch
220 size = 4096;
221
222 if (argc == 1)
11
Assuming 'argc' is equal to 1
12
Taking true branch
223 dumpall = 0;
224
225 if (dumpall
12.1
'dumpall' is equal to 0
== 0) {
13
Taking true branch
226 pcifd = open(pcidev, O_RDONLY0x0000);
227 if (pcifd == -1)
14
Assuming the condition is false
15
Taking false branch
228 err(1, "%s", pcidev);
229 } else {
230 for (;;) {
231 snprintf(pcidev, 16, "/dev/pci%d", domid++);
232 pcifd = open(pcidev, O_RDONLY0x0000);
233 if (pcifd == -1) {
234 if (errno(*__errno()) == ENXIO6 || errno(*__errno()) == ENOENT2) {
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
15.1
'argc' is equal to 1
== 1) {
16
Taking true branch
247 errstr = str2busdevfunc(argv[0], &bus, &dev, &func);
248 if (errstr
16.1
'errstr' is equal to NULL
!= NULL((void *)0))
17
Taking false branch
249 errx(1, "\"%s\": %s", argv[0], errstr);
250
251 nfuncs = pci_nfuncs(bus, dev);
252 if (nfuncs == -1 || func > nfuncs)
18
Assuming 'func' is <= 'nfuncs'
19
Taking false branch
253 error = ENXIO6;
254 else if (romfile
19.1
'romfile' is null
)
20
Taking false branch
255 error = dump_rom(bus, dev, func);
256 else
257 error = probe(bus, dev, func);
21
Calling 'probe'
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
269void
270scanpcidomain(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
285const char *
286str2busdevfunc(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((void *)0))
295 return("device not specified");
296 *d++ = '\0';
297
298 f = strchr(d, ':');
299 if (f == NULL((void *)0))
300 return("function not specified");
301 *f++ = '\0';
302
303 *bus = strtonum(b, 0, 255, &errstr);
304 if (errstr != NULL((void *)0))
305 return (errstr);
306 *dev = strtonum(d, 0, 31, &errstr);
307 if (errstr != NULL((void *)0))
308 return (errstr);
309 *func = strtonum(f, 0, 7, &errstr);
310 if (errstr != NULL((void *)0))
311 return (errstr);
312
313 return (NULL((void *)0));
314}
315
316int
317probe(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((void *)0), *product = NULL((void *)0);
323
324 if (pci_read(bus, dev, func, PCI_ID_REG0x00, &id_reg) != 0)
325 return (errno(*__errno()));
326
327 if (PCI_VENDOR(id_reg)(((id_reg) >> 0) & 0xffff) == PCI_VENDOR_INVALID0xffff ||
22
Taking false branch
23
Assuming the condition is false
25
Taking false branch
328 PCI_VENDOR(id_reg)(((id_reg) >> 0) & 0xffff) == 0)
24
Assuming the condition is false
329 return (ENXIO6);
330
331 for (pkv = pci_known_vendors; pkv->vendorname != NULL((void *)0); pkv++) {
26
Assuming field 'vendorname' is equal to NULL
27
Loop condition is false. Execution continues on line 338
332 if (pkv->vendor == PCI_VENDOR(id_reg)(((id_reg) >> 0) & 0xffff)) {
333 vendor = pkv->vendorname;
334 break;
335 }
336 }
337
338 if (vendor
27.1
'vendor' is equal to NULL
!= NULL((void *)0)) {
28
Taking false branch
339 for (pkp = pci_known_products; pkp->productname != NULL((void *)0); pkp++)
340 if (pkp->vendor == PCI_VENDOR(id_reg)(((id_reg) >> 0) & 0xffff) &&
341 pkp->product == PCI_PRODUCT(id_reg)(((id_reg) >> 16) & 0xffff)) {
342 product = pkp->productname;
343 break;
344 }
345 }
346
347 printf(" %d:%d:%d: %s %s\n", bus, dev, func,
348 (vendor
28.1
'vendor' is equal to NULL
== NULL((void *)0)) ? "unknown" : vendor,
29
'?' condition is true
349 (product
29.1
'product' is equal to NULL
== NULL((void *)0)) ? "unknown" : product);
30
'?' condition is true
350
351 if (verbose)
31
Assuming 'verbose' is not equal to 0
32
Taking true branch
352 dump(bus, dev, func);
33
Calling 'dump'
353 if (hex > 0)
354 hexdump(bus, dev, func, size);
355
356 return (0);
357}
358
359int
360print_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_TAB0x08|VIS_NL0x10, 0);
367 printf("%s", dst);
368 }
369 printf("\n");
370
371 return (0);
372}
373
374int
375print_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_TAB0x08|VIS_NL0x10, 0);
388 vis(key1, vpd->vpd_key1, VIS_TAB0x08|VIS_NL0x10, 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
407void
408dump_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)(sizeof((data)) / sizeof((data)[0]));
421 io.pv_data = data;
422
423 if (ioctl(pcifd, PCIOCGETVPD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_vpd_req) & 0x1fff) << 16) | ((('p')) <<
8) | ((9)))
, &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)((vpd) & 0x80)) {
435 struct pci_vpd_largeres *res;
436 type = PCI_VPDRES_LARGE_NAME(vpd)((vpd) & 0x7f);
437
438 switch (type) {
439 case PCI_VPDRES_TYPE_IDENTIFIER_STRING0x02:
440 printf("\t\tProduct Name: ");
441 break;
442 case PCI_VPDRES_TYPE_VPD0x10:
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)(((vpd) >> 3) & 0xf);
459 if (type == PCI_VPDRES_TYPE_END_TAG0xf)
460 break;
461
462 printf("\t\t");
463 switch (type) {
464 case PCI_VPDRES_TYPE_COMPATIBLE_DEVICE_ID0x3:
465 case PCI_VPDRES_TYPE_VENDOR_DEFINED0xe:
466 default:
467 printf("%02x", type);
468 break;
469 }
470
471 hlen = sizeof(vpd);
472 vlen = PCI_VPDRES_SMALL_LENGTH(vpd)((vpd) & 0x7);
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;
486trunc:
487 /* i have spent too much time in tcpdump - dlg */
488 printf("[|vpd]\n");
489}
490
491void
492dump_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_PMCSR0x04, &pmcsr) != 0)
497 return;
498
499 printf("\t\tState: D%d", pmcsr & PCI_PMCSR_STATE_MASK0x0003);
500 if (pmcsr & PCI_PMCSR_PME_EN0x0100)
501 printf(" PME# enabled");
502 if (pmcsr & PCI_PMCSR_PME_STATUS0x8000)
503 printf(" PME# asserted");
504 printf("\n");
505}
506
507static unsigned int
508pcie_dcap_mps(uint32_t dcap)
509{
510 uint32_t shift = dcap & 0x7;
511 return (128 << shift);
512}
513
514static unsigned int
515pcie_dcsr_mps(uint32_t dcsr)
516{
517 uint32_t shift = (dcsr >> 5) & 0x7;
518 return (128 << shift);
519}
520
521static unsigned int
522pcie_dcsr_mrrs(uint32_t dcsr)
523{
524 uint32_t shift = (dcsr >> 12) & 0x7;
525 return (128 << shift);
526}
527
528void
529print_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
547void
548dump_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_DCAP0x04, &dcap) != 0)
555 return;
556
557 if (pci_read(bus, dev, func, ptr + PCI_PCIE_DCSR0x08, &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_LCAP0x0c, &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_LCSR0x10, &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
586void
587dump_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
601void
602dump_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\n", reg & PCI_MSI_MC_MSIE0x00010000 ? "yes" : "no");
610}
611
612void
613dump_msix(int bus, int dev, int func, u_int8_t ptr)
614{
615 u_int32_t reg;
616 u_int32_t table;
617
618 if ((pci_read(bus, dev, func, ptr, &reg) != 0) ||
619 (pci_read(bus, dev, func, ptr + PCI_MSIX_TABLE0x04, &table) != 0))
620 return;
621
622 printf("\t\tEnabled: %s; table size %d (BAR %d:%d)\n",
623 reg & PCI_MSIX_MC_MSIXE0x80000000 ? "yes" : "no",
624 PCI_MSIX_MC_TBLSZ(reg)(((reg) & 0x07ff0000) >> 16) + 1,
625 (table & PCI_MSIX_TABLE_BIR0x00000007),
626 (table & PCI_MSIX_TABLE_OFF~(0x00000007)));
627}
628
629void
630dump_pcie_enhanced_caplist(int bus, int dev, int func)
631{
632 u_int32_t reg;
633 u_int32_t capidx;
634 u_int16_t ptr;
635 u_int16_t ecap;
636
637 ptr = PCI_PCIE_ECAP0x100;
638
639 do {
640 if (pci_read(bus, dev, func, ptr, &reg) != 0)
641 return;
642
643 if (PCI_PCIE_ECAP_ID(reg)(((reg) & 0x0000ffff)) == 0xffff &&
644 PCI_PCIE_ECAP_NEXT(reg)(((reg) >> 20) & 0xffc) == PCI_PCIE_ECAP_LAST0x0)
645 return;
646
647 ecap = PCI_PCIE_ECAP_ID(reg)(((reg) & 0x0000ffff));
648 if (ecap >= nitems(pci_enhanced_capnames)(sizeof((pci_enhanced_capnames)) / sizeof((pci_enhanced_capnames
)[0]))
)
649 capidx = 0;
650 else
651 capidx = ecap;
652
653 printf("\t0x%04x: Enhanced Capability 0x%02x: ", ptr, ecap);
654 printf("%s\n", pci_enhanced_capnames[capidx]);
655
656 switch (ecap) {
657 case 0x03:
658 dump_pcie_devserial(bus, dev, func, ptr);
659 break;
660 }
661
662 ptr = PCI_PCIE_ECAP_NEXT(reg)(((reg) >> 20) & 0xffc);
663
664 } while (ptr != PCI_PCIE_ECAP_LAST0x0);
665}
666
667void
668dump_caplist(int bus, int dev, int func, u_int8_t ptr)
669{
670 u_int32_t reg;
671 u_int8_t cap;
672
673 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG0x04, &reg) != 0)
674 return;
675 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT0x00100000))
676 return;
677
678 if (pci_read(bus, dev, func, ptr, &reg) != 0)
679 return;
680 ptr = PCI_CAPLIST_PTR(reg)((reg) & 0xff);
681 while (ptr != 0) {
682 if (pci_read(bus, dev, func, ptr, &reg) != 0)
683 return;
684 cap = PCI_CAPLIST_CAP(reg)((reg) & 0xff);
685 printf("\t0x%04x: Capability 0x%02x: ", ptr, cap);
686 if (cap >= nitems(pci_capnames)(sizeof((pci_capnames)) / sizeof((pci_capnames)[0])))
687 cap = 0;
688 printf("%s\n", pci_capnames[cap]);
689 switch (cap) {
690 case PCI_CAP_PWRMGMT0x01:
691 dump_pci_powerstate(bus, dev, func, ptr);
692 break;
693 case PCI_CAP_VPD0x03:
694 dump_vpd(bus, dev, func);
695 break;
696 case PCI_CAP_PCIEXPRESS0x10:
697 dump_pcie_linkspeed(bus, dev, func, ptr);
698 dump_pcie_enhanced_caplist(bus, dev, func);
699 break;
700 case PCI_CAP_MSI0x05:
701 dump_msi(bus, dev,func, ptr);
702 break;
703 case PCI_CAP_MSIX0x11:
704 dump_msix(bus, dev, func, ptr);
705 break;
706 }
707 ptr = PCI_CAPLIST_NEXT(reg)(((reg) >> 8) & 0xff);
708 }
709}
710
711void
712dump_bars(int bus, int dev, int func, int end)
713{
714 const char *memtype;
715 u_int64_t mem;
716 u_int64_t mask;
717 u_int32_t reg, reg1;
718 int bar;
719
720 for (bar = PCI_MAPREG_START0x10; bar < end; bar += 0x4) {
721 if (pci_read(bus, dev, func, bar, &reg) != 0 ||
722 pci_readmask(bus, dev, func, bar, &reg1) != 0)
723 warn("unable to read PCI_MAPREG 0x%02x", bar);
724
725 printf("\t0x%04x: BAR ", bar);
726
727 if (reg == 0 && reg1 == 0) {
728 printf("empty (%08x)\n", reg);
729 continue;
730 }
731
732 switch (PCI_MAPREG_TYPE(reg)((reg) & 0x00000001)) {
733 case PCI_MAPREG_TYPE_MEM0x00000000:
734 printf("mem ");
735 if (PCI_MAPREG_MEM_PREFETCHABLE(reg)(((reg) & 0x00000008) != 0))
736 printf("prefetchable ");
737
738 memtype = "32bit 1m";
739 switch (PCI_MAPREG_MEM_TYPE(reg)((reg) & 0x00000006)) {
740 case PCI_MAPREG_MEM_TYPE_32BIT0x00000000:
741 memtype = "32bit";
742 case PCI_MAPREG_MEM_TYPE_32BIT_1M0x00000002:
743 printf("%s ", memtype);
744
745 printf("addr: 0x%08x/0x%08x\n",
746 PCI_MAPREG_MEM_ADDR(reg)((reg) & 0xfffffff0),
747 PCI_MAPREG_MEM_SIZE(reg1)(((reg1) & 0xfffffff0) & -((reg1) & 0xfffffff0)));
748
749 break;
750 case PCI_MAPREG_MEM_TYPE_64BIT0x00000004:
751 mem = reg;
752 mask = reg1;
753 bar += 0x04;
754 if (pci_read(bus, dev, func, bar, &reg) != 0 ||
755 pci_readmask(bus, dev, func, bar, &reg1) != 0)
756 warn("unable to read 0x%02x", bar);
757
758 mem |= (u_int64_t)reg << 32;
759 mask |= (u_int64_t)reg1 << 32;
760
761 printf("64bit addr: 0x%016llx/0x%08llx\n",
762 PCI_MAPREG_MEM64_ADDR(mem)((mem) & 0xfffffffffffffff0ULL),
763 PCI_MAPREG_MEM64_SIZE(mask)(((mask) & 0xfffffffffffffff0ULL) & -((mask) & 0xfffffffffffffff0ULL
))
);
764
765 break;
766 }
767 break;
768
769 case PCI_MAPREG_TYPE_IO0x00000001:
770 printf("io addr: 0x%08x/0x%04x\n",
771 PCI_MAPREG_IO_ADDR(reg)((reg) & 0xfffffffe),
772 PCI_MAPREG_IO_SIZE(reg1)(((reg1) & 0xfffffffe) & -((reg1) & 0xfffffffe)));
773 break;
774 }
775 }
776}
777
778void
779dump_type0(int bus, int dev, int func)
780{
781 u_int32_t reg;
782
783 dump_bars(bus, dev, func, PCI_MAPREG_END0x28);
784
785 if (pci_read(bus, dev, func, PCI_CARDBUS_CIS_REG0x28, &reg) != 0)
786 warn("unable to read PCI_CARDBUS_CIS_REG");
787 printf("\t0x%04x: Cardbus CIS: %08x\n", PCI_CARDBUS_CIS_REG0x28, reg);
788
789 if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG0x2c, &reg) != 0)
790 warn("unable to read PCI_SUBSYS_ID_REG");
791 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n",
792 PCI_SUBSYS_ID_REG0x2c, PCI_VENDOR(reg)(((reg) >> 0) & 0xffff), PCI_PRODUCT(reg)(((reg) >> 16) & 0xffff));
793
794 if (pci_read(bus, dev, func, PCI_ROM_REG0x30, &reg) != 0)
795 warn("unable to read PCI_ROM_REG");
796 printf("\t0x%04x: Expansion ROM Base Address: %08x\n",
797 PCI_ROM_REG0x30, reg);
798
799 if (pci_read(bus, dev, func, 0x38, &reg) != 0)
800 warn("unable to read 0x38 (reserved)");
801 printf("\t0x%04x: %08x\n", 0x38, reg);
802
803 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG0x3c, &reg) != 0)
804 warn("unable to read PCI_INTERRUPT_REG");
805 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x Min Gnt: %02x"
806 " Max Lat: %02x\n", PCI_INTERRUPT_REG0x3c, PCI_INTERRUPT_PIN(reg)(((reg) >> 8) & 0xff),
807 PCI_INTERRUPT_LINE(reg)(((reg) >> 0) & 0xff), PCI_MIN_GNT(reg)(((reg) >> 16) & 0xff), PCI_MAX_LAT(reg)(((reg) >> 24) & 0xff));
808}
809
810void
811dump_type1(int bus, int dev, int func)
812{
813 u_int32_t reg;
40
'reg' declared without an initial value
814
815 dump_bars(bus, dev, func, PCI_MAPREG_PPB_END0x18);
816
817 if (pci_read(bus, dev, func, PCI_PRIBUS_10x18, &reg) != 0)
41
Calling 'pci_read'
45
Returning from 'pci_read'
46
Taking true branch
818 warn("unable to read PCI_PRIBUS_1");
819 printf("\t0x%04x: Primary Bus: %d, Secondary Bus: %d, "
820 "Subordinate Bus: %d,\n\t\tSecondary Latency Timer: %02x\n",
821 PCI_PRIBUS_10x18, (reg >> 0) & 0xff, (reg >> 8) & 0xff,
47
The left operand of '>>' is a garbage value
822 (reg >> 16) & 0xff, (reg >> 24) & 0xff);
823
824 if (pci_read(bus, dev, func, PCI_IOBASEL_10x1c, &reg) != 0)
825 warn("unable to read PCI_IOBASEL_1");
826 printf("\t0x%04x: I/O Base: %02x, I/O Limit: %02x, "
827 "Secondary Status: %04x\n", PCI_IOBASEL_10x1c, (reg >> 0 ) & 0xff,
828 (reg >> 8) & 0xff, (reg >> 16) & 0xffff);
829
830 if (pci_read(bus, dev, func, PCI_MEMBASE_10x20, &reg) != 0)
831 warn("unable to read PCI_MEMBASE_1");
832 printf("\t0x%04x: Memory Base: %04x, Memory Limit: %04x\n",
833 PCI_MEMBASE_10x20, (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
834
835 if (pci_read(bus, dev, func, PCI_PMBASEL_10x24, &reg) != 0)
836 warn("unable to read PCI_PMBASEL_1");
837 printf("\t0x%04x: Prefetch Memory Base: %04x, "
838 "Prefetch Memory Limit: %04x\n", PCI_PMBASEL_10x24,
839 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
840
841#undef PCI_PMBASEH_10x28
842#define PCI_PMBASEH_10x28 0x28
843 if (pci_read(bus, dev, func, PCI_PMBASEH_10x28, &reg) != 0)
844 warn("unable to read PCI_PMBASEH_1");
845 printf("\t0x%04x: Prefetch Memory Base Upper 32 Bits: %08x\n",
846 PCI_PMBASEH_10x28, reg);
847
848#undef PCI_PMLIMITH_10x2c
849#define PCI_PMLIMITH_10x2c 0x2c
850 if (pci_read(bus, dev, func, PCI_PMLIMITH_10x2c, &reg) != 0)
851 warn("unable to read PCI_PMLIMITH_1");
852 printf("\t0x%04x: Prefetch Memory Limit Upper 32 Bits: %08x\n",
853 PCI_PMLIMITH_10x2c, reg);
854
855#undef PCI_IOBASEH_10x30
856#define PCI_IOBASEH_10x30 0x30
857 if (pci_read(bus, dev, func, PCI_IOBASEH_10x30, &reg) != 0)
858 warn("unable to read PCI_IOBASEH_1");
859 printf("\t0x%04x: I/O Base Upper 16 Bits: %04x, "
860 "I/O Limit Upper 16 Bits: %04x\n", PCI_IOBASEH_10x30,
861 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
862
863#define PCI_PPB_ROM_REG0x38 0x38
864 if (pci_read(bus, dev, func, PCI_PPB_ROM_REG0x38, &reg) != 0)
865 warn("unable to read PCI_PPB_ROM_REG");
866 printf("\t0x%04x: Expansion ROM Base Address: %08x\n",
867 PCI_PPB_ROM_REG0x38, reg);
868
869 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG0x3c, &reg) != 0)
870 warn("unable to read PCI_INTERRUPT_REG");
871 printf("\t0x%04x: Interrupt Pin: %02x, Line: %02x, "
872 "Bridge Control: %04x\n",
873 PCI_INTERRUPT_REG0x3c, PCI_INTERRUPT_PIN(reg)(((reg) >> 8) & 0xff),
874 PCI_INTERRUPT_LINE(reg)(((reg) >> 0) & 0xff), reg >> 16);
875}
876
877void
878dump_type2(int bus, int dev, int func)
879{
880 u_int32_t reg;
881
882 if (pci_read(bus, dev, func, PCI_MAPREG_START0x10, &reg) != 0)
883 warn("unable to read PCI_MAPREG\n");
884 printf("\t0x%04x: Cardbus Control Registers Base Address: %08x\n",
885 PCI_MAPREG_START0x10, reg);
886
887 if (pci_read(bus, dev, func, PCI_PRIBUS_20x18, &reg) != 0)
888 warn("unable to read PCI_PRIBUS_2");
889 printf("\t0x%04x: Primary Bus: %d Cardbus Bus: %d "
890 "Subordinate Bus: %d \n\t Cardbus Latency Timer: %02x\n",
891 PCI_PRIBUS_20x18, (reg >> 0) & 0xff, (reg >> 8) & 0xff,
892 (reg >> 16) & 0xff, (reg >> 24) & 0xff);
893
894 if (pci_read(bus, dev, func, PCI_MEMBASE0_20x1c, &reg) != 0)
895 warn("unable to read PCI_MEMBASE0_2\n");
896 printf("\t0x%04x: Memory Base 0: %08x\n", PCI_MEMBASE0_20x1c, reg);
897
898 if (pci_read(bus, dev, func, PCI_MEMLIMIT0_20x20, &reg) != 0)
899 warn("unable to read PCI_MEMLIMIT0_2\n");
900 printf("\t0x%04x: Memory Limit 0: %08x\n", PCI_MEMLIMIT0_20x20, reg);
901
902 if (pci_read(bus, dev, func, PCI_MEMBASE1_20x24, &reg) != 0)
903 warn("unable to read PCI_MEMBASE1_2\n");
904 printf("\t0x%04x: Memory Base 1: %08x\n", PCI_MEMBASE1_20x24, reg);
905
906 if (pci_read(bus, dev, func, PCI_MEMLIMIT1_20x28, &reg) != 0)
907 warn("unable to read PCI_MEMLIMIT1_2\n");
908 printf("\t0x%04x: Memory Limit 1: %08x\n", PCI_MEMLIMIT1_20x28, reg);
909
910 if (pci_read(bus, dev, func, PCI_IOBASE0_20x2c, &reg) != 0)
911 warn("unable to read PCI_IOBASE0_2\n");
912 printf("\t0x%04x: I/O Base 0: %08x\n", PCI_IOBASE0_20x2c, reg);
913
914 if (pci_read(bus, dev, func, PCI_IOLIMIT0_20x30, &reg) != 0)
915 warn("unable to read PCI_IOLIMIT0_2\n");
916 printf("\t0x%04x: I/O Limit 0: %08x\n", PCI_IOLIMIT0_20x30, reg);
917
918 if (pci_read(bus, dev, func, PCI_IOBASE1_20x34, &reg) != 0)
919 warn("unable to read PCI_IOBASE1_2\n");
920 printf("\t0x%04x: I/O Base 1: %08x\n", PCI_IOBASE1_20x34, reg);
921
922 if (pci_read(bus, dev, func, PCI_IOLIMIT1_20x38, &reg) != 0)
923 warn("unable to read PCI_IOLIMIT1_2\n");
924 printf("\t0x%04x: I/O Limit 1: %08x\n", PCI_IOLIMIT1_20x38, reg);
925
926 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG0x3c, &reg) != 0)
927 warn("unable to read PCI_INTERRUPT_REG");
928 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x "
929 "Bridge Control: %04x\n",
930 PCI_INTERRUPT_REG0x3c, PCI_INTERRUPT_PIN(reg)(((reg) >> 8) & 0xff),
931 PCI_INTERRUPT_LINE(reg)(((reg) >> 0) & 0xff), reg >> 16);
932
933 if (pci_read(bus, dev, func, PCI_SUBVEND_20x40, &reg) != 0)
934 warn("unable to read PCI_SUBVEND_2");
935 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n",
936 PCI_SUBVEND_20x40, PCI_VENDOR(reg)(((reg) >> 0) & 0xffff), PCI_PRODUCT(reg)(((reg) >> 16) & 0xffff));
937
938 if (pci_read(bus, dev, func, PCI_PCCARDIF_20x44, &reg) != 0)
939 warn("unable to read PCI_PCCARDIF_2\n");
940 printf("\t0x%04x: 16-bit Legacy Mode Base Address: %08x\n",
941 PCI_PCCARDIF_20x44, reg);
942}
943
944void
945dump(int bus, int dev, int func)
946{
947 u_int32_t reg;
948 u_int8_t capptr = PCI_CAPLISTPTR_REG0x34;
949 pci_class_t class;
950 pci_subclass_t subclass;
951
952 if (pci_read(bus, dev, func, PCI_ID_REG0x00, &reg) != 0)
34
Taking false branch
953 warn("unable to read PCI_ID_REG");
954 printf("\t0x%04x: Vendor ID: %04x, Product ID: %04x\n", PCI_ID_REG0x00,
955 PCI_VENDOR(reg)(((reg) >> 0) & 0xffff), PCI_PRODUCT(reg)(((reg) >> 16) & 0xffff));
956
957 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG0x04, &reg) != 0)
35
Taking true branch
958 warn("unable to read PCI_COMMAND_STATUS_REG");
959 printf("\t0x%04x: Command: %04x, Status: %04x\n",
960 PCI_COMMAND_STATUS_REG0x04, reg & 0xffff, (reg >> 16) & 0xffff);
961
962 if (pci_read(bus, dev, func, PCI_CLASS_REG0x08, &reg) != 0)
36
Taking false branch
963 warn("unable to read PCI_CLASS_REG");
964 class = PCI_CLASS(reg)(((reg) >> 24) & 0xff);
965 subclass = PCI_SUBCLASS(reg)(((reg) >> 16) & 0xff);
966 printf("\t0x%04x:\tClass: %02x %s,", PCI_CLASS_REG0x08, class,
967 pci_class_name(class));
968 printf(" Subclass: %02x %s,", subclass,
969 pci_subclass_name(class, subclass));
970 printf("\n\t\tInterface: %02x, Revision: %02x\n",
971 PCI_INTERFACE(reg)(((reg) >> 8) & 0xff), PCI_REVISION(reg)(((reg) >> 0) & 0xff));
972
973 if (pci_read(bus, dev, func, PCI_BHLC_REG0x0c, &reg) != 0)
37
Taking true branch
974 warn("unable to read PCI_BHLC_REG");
975 printf("\t0x%04x: BIST: %02x, Header Type: %02x, "
976 "Latency Timer: %02x,\n\t\tCache Line Size: %02x\n", PCI_BHLC_REG0x0c,
977 PCI_BIST(reg)(((reg) >> 24) & 0xff), PCI_HDRTYPE(reg)(((reg) >> 16) & 0xff),
978 PCI_LATTIMER(reg)(((reg) >> 8) & 0xff), PCI_CACHELINE(reg)(((reg) >> 0) & 0xff));
979
980 switch (PCI_HDRTYPE_TYPE(reg)((((reg) >> 16) & 0xff) & 0x7f)) {
38
Control jumps to 'case 1:' at line 985
981 case 2:
982 dump_type2(bus, dev, func);
983 capptr = PCI_CARDBUS_CAPLISTPTR_REG0x14;
984 break;
985 case 1:
986 dump_type1(bus, dev, func);
39
Calling 'dump_type1'
987 break;
988 case 0:
989 dump_type0(bus, dev, func);
990 break;
991 default:
992 break;
993 }
994 dump_caplist(bus, dev, func, capptr);
995}
996
997void
998hexdump(int bus, int dev, int func, int size)
999{
1000 u_int32_t reg;
1001 int i;
1002
1003 for (i = 0; i < size; i += 4) {
1004 if (pci_read(bus, dev, func, i, &reg) != 0) {
1005 if (errno(*__errno()) == EINVAL22)
1006 return;
1007 warn("unable to read 0x%02x", i);
1008 }
1009
1010 if ((i % 16) == 0)
1011 printf("\t0x%04x:", i);
1012 printf(" %08x", reg);
1013
1014 if ((i % 16) == 12)
1015 printf("\n");
1016 }
1017}
1018
1019int
1020pci_nfuncs(int bus, int dev)
1021{
1022 u_int32_t hdr;
1023
1024 if (pci_read(bus, dev, 0, PCI_BHLC_REG0x0c, &hdr) != 0)
1025 return (-1);
1026
1027 return (PCI_HDRTYPE_MULTIFN(hdr)(((((hdr) >> 16) & 0xff) & 0x80) != 0) ? 8 : 1);
1028}
1029
1030int
1031pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
1032{
1033 struct pci_io io;
1034 int rv;
1035
1036 bzero(&io, sizeof(io));
1037 io.pi_sel.pc_bus = bus;
1038 io.pi_sel.pc_dev = dev;
1039 io.pi_sel.pc_func = func;
1040 io.pi_reg = reg;
1041 io.pi_width = 4;
1042
1043 rv = ioctl(pcifd, PCIOCREAD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_io) & 0x1fff) << 16) | ((('p')) <<
8) | ((2)))
, &io);
1044 if (rv != 0)
42
Assuming 'rv' is not equal to 0
43
Taking true branch
1045 return (rv);
44
Returning without writing to '*'
1046
1047 *val = io.pi_data;
1048
1049 return (0);
1050}
1051
1052int
1053pci_readmask(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
1054{
1055 struct pci_io io;
1056 int rv;
1057
1058 bzero(&io, sizeof(io));
1059 io.pi_sel.pc_bus = bus;
1060 io.pi_sel.pc_dev = dev;
1061 io.pi_sel.pc_func = func;
1062 io.pi_reg = reg;
1063 io.pi_width = 4;
1064
1065 rv = ioctl(pcifd, PCIOCREADMASK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_io) & 0x1fff) << 16) | ((('p')) <<
8) | ((8)))
, &io);
1066 if (rv != 0)
1067 return (rv);
1068
1069 *val = io.pi_data;
1070
1071 return (0);
1072}
1073
1074int
1075dump_rom(int bus, int dev, int func)
1076{
1077 struct pci_rom rom;
1078 u_int32_t cr, addr;
1079
1080 if (pci_read(bus, dev, func, PCI_ROM_REG0x30, &addr) != 0 ||
1081 pci_read(bus, dev, func, PCI_CLASS_REG0x08, &cr) != 0)
1082 return (errno(*__errno()));
1083
1084 if (addr == 0 && PCI_CLASS(cr)(((cr) >> 24) & 0xff) == PCI_CLASS_DISPLAY0x03 &&
1085 PCI_SUBCLASS(cr)(((cr) >> 16) & 0xff) == PCI_SUBCLASS_DISPLAY_VGA0x00)
1086 return dump_vga_bios();
1087
1088 bzero(&rom, sizeof(rom));
1089 rom.pr_sel.pc_bus = bus;
1090 rom.pr_sel.pc_dev = dev;
1091 rom.pr_sel.pc_func = func;
1092 if (ioctl(pcifd, PCIOCGETROMLEN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_rom) & 0x1fff) << 16) | ((('p')) <<
8) | ((4)))
, &rom) == -1)
1093 return (errno(*__errno()));
1094
1095 rom.pr_rom = malloc(rom.pr_romlen);
1096 if (rom.pr_rom == NULL((void *)0))
1097 return (ENOMEM12);
1098
1099 if (ioctl(pcifd, PCIOCGETROM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_rom) & 0x1fff) << 16) | ((('p')) <<
8) | ((5)))
, &rom) == -1)
1100 return (errno(*__errno()));
1101
1102 if (write(romfd, rom.pr_rom, rom.pr_romlen) == -1)
1103 return (errno(*__errno()));
1104
1105 return (0);
1106}
1107
1108#define VGA_BIOS_ADDR0xc0000 0xc0000
1109#define VGA_BIOS_LEN0x10000 0x10000
1110
1111int
1112dump_vga_bios(void)
1113{
1114#if defined(__amd64__1) || defined(__i386__)
1115 void *bios;
1116 int fd;
1117
1118 fd = open(_PATH_MEM"/dev/mem", O_RDONLY0x0000);
1119 if (fd == -1)
1120 err(1, "%s", _PATH_MEM"/dev/mem");
1121
1122 bios = malloc(VGA_BIOS_LEN0x10000);
1123 if (bios == NULL((void *)0))
1124 return (ENOMEM12);
1125
1126 if (pread(fd, bios, VGA_BIOS_LEN0x10000, VGA_BIOS_ADDR0xc0000) == -1)
1127 err(1, "%s", _PATH_MEM"/dev/mem");
1128
1129 if (write(romfd, bios, VGA_BIOS_LEN0x10000) == -1) {
1130 free(bios);
1131 return (errno(*__errno()));
1132 }
1133
1134 free(bios);
1135
1136 return (0);
1137#else
1138 return (ENODEV19);
1139#endif
1140}
1141
1142struct pci_subclass {
1143 pci_subclass_t subclass;
1144 const char *name;
1145};
1146
1147struct pci_class {
1148 pci_class_t class;
1149 const char *name;
1150 const struct pci_subclass
1151 *subclass;
1152 size_t nsubclass;
1153};
1154
1155static const struct pci_subclass pci_subclass_prehistoric[] = {
1156 { PCI_SUBCLASS_PREHISTORIC_MISC0x00, "Miscellaneous" },
1157 { PCI_SUBCLASS_PREHISTORIC_VGA0x01, "VGA" },
1158};
1159
1160static const struct pci_subclass pci_subclass_mass_storage[] = {
1161 { PCI_SUBCLASS_MASS_STORAGE_SCSI0x00, "SCSI" },
1162 { PCI_SUBCLASS_MASS_STORAGE_IDE0x01, "IDE" },
1163 { PCI_SUBCLASS_MASS_STORAGE_FLOPPY0x02, "Floppy" },
1164 { PCI_SUBCLASS_MASS_STORAGE_IPI0x03, "IPI" },
1165 { PCI_SUBCLASS_MASS_STORAGE_RAID0x04, "RAID" },
1166 { PCI_SUBCLASS_MASS_STORAGE_ATA0x05, "ATA" },
1167 { PCI_SUBCLASS_MASS_STORAGE_SATA0x06, "SATA" },
1168 { PCI_SUBCLASS_MASS_STORAGE_SAS0x07, "SAS" },
1169 { PCI_SUBCLASS_MASS_STORAGE_UFS0x09, "UFS" },
1170 { PCI_SUBCLASS_MASS_STORAGE_NVM0x08, "NVM" },
1171 { PCI_SUBCLASS_MASS_STORAGE_MISC0x80, "Miscellaneous" },
1172};
1173
1174static const struct pci_subclass pci_subclass_network[] = {
1175 { PCI_SUBCLASS_NETWORK_ETHERNET0x00, "Ethernet" },
1176 { PCI_SUBCLASS_NETWORK_TOKENRING0x01, "Token Ring" },
1177 { PCI_SUBCLASS_NETWORK_FDDI0x02, "FDDI" },
1178 { PCI_SUBCLASS_NETWORK_ATM0x03, "ATM" },
1179 { PCI_SUBCLASS_NETWORK_ISDN0x04, "ISDN" },
1180 { PCI_SUBCLASS_NETWORK_WORLDFIP0x05, "WorldFip" },
1181 { PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP0x06, "PCMIG Multi Computing" },
1182 { PCI_SUBCLASS_NETWORK_INFINIBAND0x07, "InfiniBand" },
1183 { PCI_SUBCLASS_NETWORK_MISC0x80, "Miscellaneous" },
1184};
1185
1186static const struct pci_subclass pci_subclass_display[] = {
1187 { PCI_SUBCLASS_DISPLAY_VGA0x00, "VGA" },
1188 { PCI_SUBCLASS_DISPLAY_XGA0x01, "XGA" },
1189 { PCI_SUBCLASS_DISPLAY_3D0x02, "3D" },
1190 { PCI_SUBCLASS_DISPLAY_MISC0x80, "Miscellaneous" },
1191};
1192
1193static const struct pci_subclass pci_subclass_multimedia[] = {
1194 { PCI_SUBCLASS_MULTIMEDIA_VIDEO0x00, "Video" },
1195 { PCI_SUBCLASS_MULTIMEDIA_AUDIO0x01, "Audio" },
1196 { PCI_SUBCLASS_MULTIMEDIA_TELEPHONY0x02, "Telephony" },
1197 { PCI_SUBCLASS_MULTIMEDIA_HDAUDIO0x03, "HD Audio" },
1198 { PCI_SUBCLASS_MULTIMEDIA_MISC0x80, "Miscellaneous" },
1199};
1200
1201static const struct pci_subclass pci_subclass_memory[] = {
1202 { PCI_SUBCLASS_MEMORY_RAM0x00, "RAM" },
1203 { PCI_SUBCLASS_MEMORY_FLASH0x01, "Flash" },
1204 { PCI_SUBCLASS_MEMORY_MISC0x80, "Miscellaneous" },
1205};
1206
1207static const struct pci_subclass pci_subclass_bridge[] = {
1208 { PCI_SUBCLASS_BRIDGE_HOST0x00, "Host" },
1209 { PCI_SUBCLASS_BRIDGE_ISA0x01, "ISA" },
1210 { PCI_SUBCLASS_BRIDGE_EISA0x02, "EISA" },
1211 { PCI_SUBCLASS_BRIDGE_MC0x03, "MicroChannel" },
1212 { PCI_SUBCLASS_BRIDGE_PCI0x04, "PCI" },
1213 { PCI_SUBCLASS_BRIDGE_PCMCIA0x05, "PCMCIA" },
1214 { PCI_SUBCLASS_BRIDGE_NUBUS0x06, "NuBus" },
1215 { PCI_SUBCLASS_BRIDGE_RACEWAY0x08, "RACEway" },
1216 { PCI_SUBCLASS_BRIDGE_STPCI0x09, "Semi-transparent PCI" },
1217 { PCI_SUBCLASS_BRIDGE_INFINIBAND0x0a, "InfiniBand" },
1218 { PCI_SUBCLASS_BRIDGE_MISC0x80, "Miscellaneous" },
1219 { PCI_SUBCLASS_BRIDGE_AS0x0b, "advanced switching" },
1220};
1221
1222static const struct pci_subclass pci_subclass_communications[] = {
1223 { PCI_SUBCLASS_COMMUNICATIONS_SERIAL0x00, "Serial" },
1224 { PCI_SUBCLASS_COMMUNICATIONS_PARALLEL0x01, "Parallel" },
1225 { PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL0x02, "Multi-port Serial" },
1226 { PCI_SUBCLASS_COMMUNICATIONS_MODEM0x03, "Modem" },
1227 { PCI_SUBCLASS_COMMUNICATIONS_GPIB0x04, "GPIB" },
1228 { PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD0x05,
1229 "Smartcard" },
1230 { PCI_SUBCLASS_COMMUNICATIONS_MISC0x80, "Miscellaneous" },
1231};
1232
1233static const struct pci_subclass pci_subclass_system[] = {
1234 { PCI_SUBCLASS_SYSTEM_PIC0x00, "Interrupt" },
1235 { PCI_SUBCLASS_SYSTEM_DMA0x01, "8237 DMA" },
1236 { PCI_SUBCLASS_SYSTEM_TIMER0x02, "8254 Timer" },
1237 { PCI_SUBCLASS_SYSTEM_RTC0x03, "RTC" },
1238 { PCI_SUBCLASS_SYSTEM_SDHC0x05, "SDHC" },
1239 { PCI_SUBCLASS_SYSTEM_IOMMU0x06, "IOMMU" },
1240 { PCI_SUBCLASS_SYSTEM_ROOTCOMPEVENT0x07, "Root Complex Event" },
1241 { PCI_SUBCLASS_SYSTEM_MISC0x80, "Miscellaneous" },
1242};
1243
1244static const struct pci_subclass pci_subclass_input[] = {
1245 { PCI_SUBCLASS_INPUT_KEYBOARD0x00, "Keyboard" },
1246 { PCI_SUBCLASS_INPUT_DIGITIZER0x01, "Digitizer" },
1247 { PCI_SUBCLASS_INPUT_MOUSE0x02, "Mouse" },
1248 { PCI_SUBCLASS_INPUT_SCANNER0x03, "Scanner" },
1249 { PCI_SUBCLASS_INPUT_GAMEPORT0x04, "Game Port" },
1250 { PCI_SUBCLASS_INPUT_MISC0x80, "Miscellaneous" },
1251};
1252
1253static const struct pci_subclass pci_subclass_dock[] = {
1254 { PCI_SUBCLASS_DOCK_GENERIC0x00, "Generic" },
1255 { PCI_SUBCLASS_DOCK_MISC0x80, "Miscellaneous" },
1256};
1257
1258static const struct pci_subclass pci_subclass_processor[] = {
1259 { PCI_SUBCLASS_PROCESSOR_3860x00, "386" },
1260 { PCI_SUBCLASS_PROCESSOR_4860x01, "486" },
1261 { PCI_SUBCLASS_PROCESSOR_PENTIUM0x02, "Pentium" },
1262 { PCI_SUBCLASS_PROCESSOR_ALPHA0x10, "Alpha" },
1263 { PCI_SUBCLASS_PROCESSOR_POWERPC0x20, "PowerPC" },
1264 { PCI_SUBCLASS_PROCESSOR_MIPS0x30, "MIPS" },
1265 { PCI_SUBCLASS_PROCESSOR_COPROC0x40, "Co-Processor" },
1266};
1267
1268static const struct pci_subclass pci_subclass_serialbus[] = {
1269 { PCI_SUBCLASS_SERIALBUS_FIREWIRE0x00, "FireWire" },
1270 { PCI_SUBCLASS_SERIALBUS_ACCESS0x01, "ACCESS.bus" },
1271 { PCI_SUBCLASS_SERIALBUS_SSA0x02, "SSA" },
1272 { PCI_SUBCLASS_SERIALBUS_USB0x03, "USB" },
1273 { PCI_SUBCLASS_SERIALBUS_FIBER0x04, "Fiber Channel" },
1274 { PCI_SUBCLASS_SERIALBUS_SMBUS0x05, "SMBus" },
1275 { PCI_SUBCLASS_SERIALBUS_INFINIBAND0x06, "InfiniBand" },
1276 { PCI_SUBCLASS_SERIALBUS_IPMI0x07, "IPMI" },
1277 { PCI_SUBCLASS_SERIALBUS_SERCOS0x08, "SERCOS" },
1278 { PCI_SUBCLASS_SERIALBUS_CANBUS0x09, "CANbus" },
1279};
1280
1281static const struct pci_subclass pci_subclass_wireless[] = {
1282 { PCI_SUBCLASS_WIRELESS_IRDA0x00, "IrDA" },
1283 { PCI_SUBCLASS_WIRELESS_CONSUMERIR0x01, "Consumer IR" },
1284 { PCI_SUBCLASS_WIRELESS_RF0x10, "RF" },
1285 { PCI_SUBCLASS_WIRELESS_BLUETOOTH0x11, "Bluetooth" },
1286 { PCI_SUBCLASS_WIRELESS_BROADBAND0x12, "Broadband" },
1287 { PCI_SUBCLASS_WIRELESS_802_11A0x20, "802.11a" },
1288 { PCI_SUBCLASS_WIRELESS_802_11B0x21, "802.11b" },
1289 { PCI_SUBCLASS_WIRELESS_MISC0x80, "Miscellaneous" },
1290};
1291
1292static const struct pci_subclass pci_subclass_i2o[] = {
1293 { PCI_SUBCLASS_I2O_STANDARD0x00, "Standard" },
1294};
1295
1296static const struct pci_subclass pci_subclass_satcom[] = {
1297 { PCI_SUBCLASS_SATCOM_TV0x01, "TV" },
1298 { PCI_SUBCLASS_SATCOM_AUDIO0x02, "Audio" },
1299 { PCI_SUBCLASS_SATCOM_VOICE0x03, "Voice" },
1300 { PCI_SUBCLASS_SATCOM_DATA0x04, "Data" },
1301};
1302
1303static const struct pci_subclass pci_subclass_crypto[] = {
1304 { PCI_SUBCLASS_CRYPTO_NETCOMP0x00, "Network/Computing" },
1305 { PCI_SUBCLASS_CRYPTO_ENTERTAINMENT0x10, "Entertainment" },
1306 { PCI_SUBCLASS_CRYPTO_MISC0x80, "Miscellaneous" },
1307};
1308
1309static const struct pci_subclass pci_subclass_dasp[] = {
1310 { PCI_SUBCLASS_DASP_DPIO0x00, "DPIO" },
1311 { PCI_SUBCLASS_DASP_TIMEFREQ0x01, "Time and Frequency" },
1312 { PCI_SUBCLASS_DASP_SYNC0x10, "Synchronization" },
1313 { PCI_SUBCLASS_DASP_MGMT0x20, "Management" },
1314 { PCI_SUBCLASS_DASP_MISC0x80, "Miscellaneous" },
1315};
1316
1317static const struct pci_subclass pci_subclass_accelerator[] = {};
1318static const struct pci_subclass pci_subclass_instrumentation[] = {};
1319
1320#define CLASS(_c, _n, _s){ .class = _c, .name = _n, .subclass = _s, .nsubclass = (sizeof
((_s)) / sizeof((_s)[0])), }
{ \
1321 .class = _c, \
1322 .name = _n, \
1323 .subclass = _s, \
1324 .nsubclass = nitems(_s)(sizeof((_s)) / sizeof((_s)[0])), \
1325}
1326
1327static const struct pci_class pci_classes[] = {
1328 CLASS(PCI_CLASS_PREHISTORIC, "Prehistoric",{ .class = 0x00, .name = "Prehistoric", .subclass = pci_subclass_prehistoric
, .nsubclass = (sizeof((pci_subclass_prehistoric)) / sizeof((
pci_subclass_prehistoric)[0])), }
1329 pci_subclass_prehistoric){ .class = 0x00, .name = "Prehistoric", .subclass = pci_subclass_prehistoric
, .nsubclass = (sizeof((pci_subclass_prehistoric)) / sizeof((
pci_subclass_prehistoric)[0])), }
,
1330 CLASS(PCI_CLASS_MASS_STORAGE, "Mass Storage",{ .class = 0x01, .name = "Mass Storage", .subclass = pci_subclass_mass_storage
, .nsubclass = (sizeof((pci_subclass_mass_storage)) / sizeof(
(pci_subclass_mass_storage)[0])), }
1331 pci_subclass_mass_storage){ .class = 0x01, .name = "Mass Storage", .subclass = pci_subclass_mass_storage
, .nsubclass = (sizeof((pci_subclass_mass_storage)) / sizeof(
(pci_subclass_mass_storage)[0])), }
,
1332 CLASS(PCI_CLASS_NETWORK, "Network",{ .class = 0x02, .name = "Network", .subclass = pci_subclass_network
, .nsubclass = (sizeof((pci_subclass_network)) / sizeof((pci_subclass_network
)[0])), }
1333 pci_subclass_network){ .class = 0x02, .name = "Network", .subclass = pci_subclass_network
, .nsubclass = (sizeof((pci_subclass_network)) / sizeof((pci_subclass_network
)[0])), }
,
1334 CLASS(PCI_CLASS_DISPLAY, "Display",{ .class = 0x03, .name = "Display", .subclass = pci_subclass_display
, .nsubclass = (sizeof((pci_subclass_display)) / sizeof((pci_subclass_display
)[0])), }
1335 pci_subclass_display){ .class = 0x03, .name = "Display", .subclass = pci_subclass_display
, .nsubclass = (sizeof((pci_subclass_display)) / sizeof((pci_subclass_display
)[0])), }
,
1336 CLASS(PCI_CLASS_MULTIMEDIA, "Multimedia",{ .class = 0x04, .name = "Multimedia", .subclass = pci_subclass_multimedia
, .nsubclass = (sizeof((pci_subclass_multimedia)) / sizeof((pci_subclass_multimedia
)[0])), }
1337 pci_subclass_multimedia){ .class = 0x04, .name = "Multimedia", .subclass = pci_subclass_multimedia
, .nsubclass = (sizeof((pci_subclass_multimedia)) / sizeof((pci_subclass_multimedia
)[0])), }
,
1338 CLASS(PCI_CLASS_MEMORY, "Memory",{ .class = 0x05, .name = "Memory", .subclass = pci_subclass_memory
, .nsubclass = (sizeof((pci_subclass_memory)) / sizeof((pci_subclass_memory
)[0])), }
1339 pci_subclass_memory){ .class = 0x05, .name = "Memory", .subclass = pci_subclass_memory
, .nsubclass = (sizeof((pci_subclass_memory)) / sizeof((pci_subclass_memory
)[0])), }
,
1340 CLASS(PCI_CLASS_BRIDGE, "Bridge",{ .class = 0x06, .name = "Bridge", .subclass = pci_subclass_bridge
, .nsubclass = (sizeof((pci_subclass_bridge)) / sizeof((pci_subclass_bridge
)[0])), }
1341 pci_subclass_bridge){ .class = 0x06, .name = "Bridge", .subclass = pci_subclass_bridge
, .nsubclass = (sizeof((pci_subclass_bridge)) / sizeof((pci_subclass_bridge
)[0])), }
,
1342 CLASS(PCI_CLASS_COMMUNICATIONS, "Communications",{ .class = 0x07, .name = "Communications", .subclass = pci_subclass_communications
, .nsubclass = (sizeof((pci_subclass_communications)) / sizeof
((pci_subclass_communications)[0])), }
1343 pci_subclass_communications){ .class = 0x07, .name = "Communications", .subclass = pci_subclass_communications
, .nsubclass = (sizeof((pci_subclass_communications)) / sizeof
((pci_subclass_communications)[0])), }
,
1344 CLASS(PCI_CLASS_SYSTEM, "System",{ .class = 0x08, .name = "System", .subclass = pci_subclass_system
, .nsubclass = (sizeof((pci_subclass_system)) / sizeof((pci_subclass_system
)[0])), }
1345 pci_subclass_system){ .class = 0x08, .name = "System", .subclass = pci_subclass_system
, .nsubclass = (sizeof((pci_subclass_system)) / sizeof((pci_subclass_system
)[0])), }
,
1346 CLASS(PCI_CLASS_INPUT, "Input",{ .class = 0x09, .name = "Input", .subclass = pci_subclass_input
, .nsubclass = (sizeof((pci_subclass_input)) / sizeof((pci_subclass_input
)[0])), }
1347 pci_subclass_input){ .class = 0x09, .name = "Input", .subclass = pci_subclass_input
, .nsubclass = (sizeof((pci_subclass_input)) / sizeof((pci_subclass_input
)[0])), }
,
1348 CLASS(PCI_CLASS_DOCK, "Dock",{ .class = 0x0a, .name = "Dock", .subclass = pci_subclass_dock
, .nsubclass = (sizeof((pci_subclass_dock)) / sizeof((pci_subclass_dock
)[0])), }
1349 pci_subclass_dock){ .class = 0x0a, .name = "Dock", .subclass = pci_subclass_dock
, .nsubclass = (sizeof((pci_subclass_dock)) / sizeof((pci_subclass_dock
)[0])), }
,
1350 CLASS(PCI_CLASS_PROCESSOR, "Processor",{ .class = 0x0b, .name = "Processor", .subclass = pci_subclass_processor
, .nsubclass = (sizeof((pci_subclass_processor)) / sizeof((pci_subclass_processor
)[0])), }
1351 pci_subclass_processor){ .class = 0x0b, .name = "Processor", .subclass = pci_subclass_processor
, .nsubclass = (sizeof((pci_subclass_processor)) / sizeof((pci_subclass_processor
)[0])), }
,
1352 CLASS(PCI_CLASS_SERIALBUS, "Serial Bus",{ .class = 0x0c, .name = "Serial Bus", .subclass = pci_subclass_serialbus
, .nsubclass = (sizeof((pci_subclass_serialbus)) / sizeof((pci_subclass_serialbus
)[0])), }
1353 pci_subclass_serialbus){ .class = 0x0c, .name = "Serial Bus", .subclass = pci_subclass_serialbus
, .nsubclass = (sizeof((pci_subclass_serialbus)) / sizeof((pci_subclass_serialbus
)[0])), }
,
1354 CLASS(PCI_CLASS_WIRELESS, "Wireless",{ .class = 0x0d, .name = "Wireless", .subclass = pci_subclass_wireless
, .nsubclass = (sizeof((pci_subclass_wireless)) / sizeof((pci_subclass_wireless
)[0])), }
1355 pci_subclass_wireless){ .class = 0x0d, .name = "Wireless", .subclass = pci_subclass_wireless
, .nsubclass = (sizeof((pci_subclass_wireless)) / sizeof((pci_subclass_wireless
)[0])), }
,
1356 CLASS(PCI_CLASS_I2O, "I2O",{ .class = 0x0e, .name = "I2O", .subclass = pci_subclass_i2o,
.nsubclass = (sizeof((pci_subclass_i2o)) / sizeof((pci_subclass_i2o
)[0])), }
1357 pci_subclass_i2o){ .class = 0x0e, .name = "I2O", .subclass = pci_subclass_i2o,
.nsubclass = (sizeof((pci_subclass_i2o)) / sizeof((pci_subclass_i2o
)[0])), }
,
1358 CLASS(PCI_CLASS_SATCOM, "Satellite Comm",{ .class = 0x0f, .name = "Satellite Comm", .subclass = pci_subclass_satcom
, .nsubclass = (sizeof((pci_subclass_satcom)) / sizeof((pci_subclass_satcom
)[0])), }
1359 pci_subclass_satcom){ .class = 0x0f, .name = "Satellite Comm", .subclass = pci_subclass_satcom
, .nsubclass = (sizeof((pci_subclass_satcom)) / sizeof((pci_subclass_satcom
)[0])), }
,
1360 CLASS(PCI_CLASS_CRYPTO, "Crypto",{ .class = 0x10, .name = "Crypto", .subclass = pci_subclass_crypto
, .nsubclass = (sizeof((pci_subclass_crypto)) / sizeof((pci_subclass_crypto
)[0])), }
1361 pci_subclass_crypto){ .class = 0x10, .name = "Crypto", .subclass = pci_subclass_crypto
, .nsubclass = (sizeof((pci_subclass_crypto)) / sizeof((pci_subclass_crypto
)[0])), }
,
1362 CLASS(PCI_CLASS_DASP, "DASP",{ .class = 0x11, .name = "DASP", .subclass = pci_subclass_dasp
, .nsubclass = (sizeof((pci_subclass_dasp)) / sizeof((pci_subclass_dasp
)[0])), }
1363 pci_subclass_dasp){ .class = 0x11, .name = "DASP", .subclass = pci_subclass_dasp
, .nsubclass = (sizeof((pci_subclass_dasp)) / sizeof((pci_subclass_dasp
)[0])), }
,
1364 CLASS(PCI_CLASS_ACCELERATOR, "Accelerator",{ .class = 0x12, .name = "Accelerator", .subclass = pci_subclass_accelerator
, .nsubclass = (sizeof((pci_subclass_accelerator)) / sizeof((
pci_subclass_accelerator)[0])), }
1365 pci_subclass_accelerator){ .class = 0x12, .name = "Accelerator", .subclass = pci_subclass_accelerator
, .nsubclass = (sizeof((pci_subclass_accelerator)) / sizeof((
pci_subclass_accelerator)[0])), }
,
1366 CLASS(PCI_CLASS_INSTRUMENTATION, "Instrumentation",{ .class = 0x13, .name = "Instrumentation", .subclass = pci_subclass_instrumentation
, .nsubclass = (sizeof((pci_subclass_instrumentation)) / sizeof
((pci_subclass_instrumentation)[0])), }
1367 pci_subclass_instrumentation){ .class = 0x13, .name = "Instrumentation", .subclass = pci_subclass_instrumentation
, .nsubclass = (sizeof((pci_subclass_instrumentation)) / sizeof
((pci_subclass_instrumentation)[0])), }
,
1368};
1369
1370static const struct pci_class *
1371pci_class(pci_class_t class)
1372{
1373 const struct pci_class *pc;
1374 size_t i;
1375
1376 for (i = 0; i < nitems(pci_classes)(sizeof((pci_classes)) / sizeof((pci_classes)[0])); i++) {
1377 pc = &pci_classes[i];
1378 if (pc->class == class)
1379 return (pc);
1380 }
1381
1382 return (NULL((void *)0));
1383}
1384
1385static const struct pci_subclass *
1386pci_subclass(const struct pci_class *pc, pci_subclass_t subclass)
1387{
1388 const struct pci_subclass *ps;
1389 size_t i;
1390
1391 for (i = 0; i < pc->nsubclass; i++) {
1392 ps = &pc->subclass[i];
1393 if (ps->subclass == subclass)
1394 return (ps);
1395 }
1396
1397 return (NULL((void *)0));
1398}
1399
1400static const char *
1401pci_class_name(pci_class_t class)
1402{
1403 const struct pci_class *pc;
1404
1405 pc = pci_class(class);
1406 if (pc == NULL((void *)0))
1407 return ("(unknown)");
1408
1409 return (pc->name);
1410}
1411
1412static const char *
1413pci_subclass_name(pci_class_t class, pci_subclass_t subclass)
1414{
1415 const struct pci_class *pc;
1416 const struct pci_subclass *ps;
1417
1418 pc = pci_class(class);
1419 if (pc == NULL((void *)0))
1420 return ("(unknown)");
1421
1422 ps = pci_subclass(pc, subclass);
1423 if (ps == NULL((void *)0) || ps->name == NULL((void *)0))
1424 return ("(unknown)");
1425
1426 return (ps->name);
1427}