Bug Summary

File:src/usr.sbin/pcidump/pcidump.c
Warning:line 760, column 10
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pcidump.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/pcidump/pcidump.c
1/* $OpenBSD: pcidump.c,v 1.68 2021/10/25 19:54:29 kn 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)
22
Taking false branch
325 return (errno(*__errno()));
326
327 if (PCI_VENDOR(id_reg)(((id_reg) >> 0) & 0xffff) == PCI_VENDOR_INVALID0xffff ||
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 & 4)
532 printf("8.0");
533 else if (speed & 2)
534 printf("5.0");
535 else if (speed & 1)
536 printf("2.5");
537 else
538 printf("unknown (%d)", speed);
539}
540
541void
542dump_pcie_linkspeed(int bus, int dev, int func, uint8_t ptr)
543{
544 u_int32_t dcap, dcsr;
545 u_int32_t lcap, sreg, lcap2 = 0, xcap;
546 u_int8_t cwidth, cspeed, swidth, sspeed;
547
548 if (pci_read(bus, dev, func, ptr + PCI_PCIE_DCAP0x04, &dcap) != 0)
549 return;
550
551 if (pci_read(bus, dev, func, ptr + PCI_PCIE_DCSR0x08, &dcsr) != 0)
552 return;
553
554 printf("\t\tMax Payload Size: %u / %u bytes\n",
555 pcie_dcsr_mps(dcsr), pcie_dcap_mps(dcap));
556 printf("\t\tMax Read Request Size: %u bytes\n",
557 pcie_dcsr_mrrs(dcsr));
558
559 if (pci_read(bus, dev, func, ptr + PCI_PCIE_XCAP0x00, &xcap) != 0)
560 return;
561
562 if (PCI_PCIE_XCAP_VER(xcap)(((xcap) >> 16) & 0x0f) >= 2) {
563 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP20x2c, &lcap2) != 0)
564 lcap2 = 0;
565 else
566 cspeed = (lcap2 & 0x0e) >> 1;
567 }
568
569 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP0x0c, &lcap) != 0)
570 return;
571 if (lcap2 == 0)
572 cspeed = lcap & 0x0f;
573
574 if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCSR0x10, &sreg) != 0)
575 return;
576 sreg = sreg >> 16;
577
578 cwidth = (lcap >> 4) & 0x3f;
579 if (cwidth == 0)
580 return;
581
582 swidth = (sreg >> 4) & 0x3f;
583 sspeed = sreg & 0x0f;
584
585 printf("\t\tLink Speed: ");
586 print_pcie_ls(sspeed);
587 printf(" / ");
588 print_pcie_ls(cspeed);
589 printf(" GT/s\n");
590
591 printf("\t\tLink Width: x%d / x%d\n", swidth, cwidth);
592}
593
594void
595dump_pcie_devserial(int bus, int dev, int func, u_int16_t ptr)
596{
597 uint32_t lower, upper;
598 uint64_t serial;
599
600 if ((pci_read(bus, dev, func, ptr + 8, &upper) != 0) ||
601 (pci_read(bus, dev, func, ptr + 4, &lower) != 0))
602 return;
603
604 serial = ((uint64_t)upper << 32) | (uint64_t)lower;
605
606 printf("\t\tSerial Number: %016llx\n", serial);
607}
608
609void
610dump_msi(int bus, int dev, int func, u_int8_t ptr)
611{
612 u_int32_t reg;
613
614 if (pci_read(bus, dev, func, ptr, &reg) != 0)
615 return;
616
617 printf("\t\tEnabled: %s\n", reg & PCI_MSI_MC_MSIE0x00010000 ? "yes" : "no");
618}
619
620void
621dump_msix(int bus, int dev, int func, u_int8_t ptr)
622{
623 u_int32_t reg;
624 u_int32_t table;
625
626 if ((pci_read(bus, dev, func, ptr, &reg) != 0) ||
627 (pci_read(bus, dev, func, ptr + PCI_MSIX_TABLE0x04, &table) != 0))
628 return;
629
630 printf("\t\tEnabled: %s; table size %d (BAR %d:%d)\n",
631 reg & PCI_MSIX_MC_MSIXE0x80000000 ? "yes" : "no",
632 PCI_MSIX_MC_TBLSZ(reg)(((reg) & 0x07ff0000) >> 16) + 1,
633 (table & PCI_MSIX_TABLE_BIR0x00000007),
634 (table & PCI_MSIX_TABLE_OFF~(0x00000007)));
635}
636
637void
638dump_pcie_enhanced_caplist(int bus, int dev, int func)
639{
640 u_int32_t reg;
641 u_int32_t capidx;
642 u_int16_t ptr;
643 u_int16_t ecap;
644
645 ptr = PCI_PCIE_ECAP0x100;
646
647 do {
648 if (pci_read(bus, dev, func, ptr, &reg) != 0)
649 return;
650
651 if (PCI_PCIE_ECAP_ID(reg)(((reg) & 0x0000ffff)) == 0xffff &&
652 PCI_PCIE_ECAP_NEXT(reg)(((reg) >> 20) & 0xffc) == PCI_PCIE_ECAP_LAST0x0)
653 return;
654
655 ecap = PCI_PCIE_ECAP_ID(reg)(((reg) & 0x0000ffff));
656 if (ecap >= nitems(pci_enhanced_capnames)(sizeof((pci_enhanced_capnames)) / sizeof((pci_enhanced_capnames
)[0]))
)
657 capidx = 0;
658 else
659 capidx = ecap;
660
661 printf("\t0x%04x: Enhanced Capability 0x%02x: ", ptr, ecap);
662 printf("%s\n", pci_enhanced_capnames[capidx]);
663
664 switch (ecap) {
665 case 0x03:
666 dump_pcie_devserial(bus, dev, func, ptr);
667 break;
668 }
669
670 ptr = PCI_PCIE_ECAP_NEXT(reg)(((reg) >> 20) & 0xffc);
671
672 } while (ptr != PCI_PCIE_ECAP_LAST0x0);
673}
674
675void
676dump_caplist(int bus, int dev, int func, u_int8_t ptr)
677{
678 u_int32_t reg;
679 u_int8_t cap;
680
681 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG0x04, &reg) != 0)
682 return;
683 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT0x00100000))
684 return;
685
686 if (pci_read(bus, dev, func, ptr, &reg) != 0)
687 return;
688 ptr = PCI_CAPLIST_PTR(reg)((reg) & 0xff);
689 while (ptr != 0) {
690 if (pci_read(bus, dev, func, ptr, &reg) != 0)
691 return;
692 cap = PCI_CAPLIST_CAP(reg)((reg) & 0xff);
693 printf("\t0x%04x: Capability 0x%02x: ", ptr, cap);
694 if (cap >= nitems(pci_capnames)(sizeof((pci_capnames)) / sizeof((pci_capnames)[0])))
695 cap = 0;
696 printf("%s\n", pci_capnames[cap]);
697 switch (cap) {
698 case PCI_CAP_PWRMGMT0x01:
699 dump_pci_powerstate(bus, dev, func, ptr);
700 break;
701 case PCI_CAP_VPD0x03:
702 dump_vpd(bus, dev, func);
703 break;
704 case PCI_CAP_PCIEXPRESS0x10:
705 dump_pcie_linkspeed(bus, dev, func, ptr);
706 dump_pcie_enhanced_caplist(bus, dev, func);
707 break;
708 case PCI_CAP_MSI0x05:
709 dump_msi(bus, dev,func, ptr);
710 break;
711 case PCI_CAP_MSIX0x11:
712 dump_msix(bus, dev, func, ptr);
713 break;
714 }
715 ptr = PCI_CAPLIST_NEXT(reg)(((reg) >> 8) & 0xff);
716 }
717}
718
719void
720dump_bars(int bus, int dev, int func, int end)
721{
722 const char *memtype;
723 u_int64_t mem;
724 u_int64_t mask;
725 u_int32_t reg, reg1;
41
'reg1' declared without an initial value
726 int bar;
727
728 for (bar = PCI_MAPREG_START0x10; bar < end; bar += 0x4) {
42
Loop condition is true. Entering loop body
729 if (pci_read(bus, dev, func, bar, &reg) != 0 ||
43
Assuming the condition is true
730 pci_readmask(bus, dev, func, bar, &reg1) != 0)
731 warn("unable to read PCI_MAPREG 0x%02x", bar);
732
733 printf("\t0x%04x: BAR ", bar);
734
735 if (reg == 0 && reg1 == 0) {
44
Assuming 'reg' is not equal to 0
736 printf("empty (%08x)\n", reg);
737 continue;
738 }
739
740 switch (PCI_MAPREG_TYPE(reg)((reg) & 0x00000001)) {
45
Control jumps to 'case 0:' at line 741
741 case PCI_MAPREG_TYPE_MEM0x00000000:
742 printf("mem ");
743 if (PCI_MAPREG_MEM_PREFETCHABLE(reg)(((reg) & 0x00000008) != 0))
46
Assuming the condition is false
47
Taking false branch
744 printf("prefetchable ");
745
746 memtype = "32bit 1m";
747 switch (PCI_MAPREG_MEM_TYPE(reg)((reg) & 0x00000006)) {
48
Control jumps to 'case 4:' at line 758
748 case PCI_MAPREG_MEM_TYPE_32BIT0x00000000:
749 memtype = "32bit";
750 case PCI_MAPREG_MEM_TYPE_32BIT_1M0x00000002:
751 printf("%s ", memtype);
752
753 printf("addr: 0x%08x/0x%08x\n",
754 PCI_MAPREG_MEM_ADDR(reg)((reg) & 0xfffffff0),
755 PCI_MAPREG_MEM_SIZE(reg1)(((reg1) & 0xfffffff0) & -((reg1) & 0xfffffff0)));
756
757 break;
758 case PCI_MAPREG_MEM_TYPE_64BIT0x00000004:
759 mem = reg;
760 mask = reg1;
49
Assigned value is garbage or undefined
761 bar += 0x04;
762 if (pci_read(bus, dev, func, bar, &reg) != 0 ||
763 pci_readmask(bus, dev, func, bar, &reg1) != 0)
764 warn("unable to read 0x%02x", bar);
765
766 mem |= (u_int64_t)reg << 32;
767 mask |= (u_int64_t)reg1 << 32;
768
769 printf("64bit addr: 0x%016llx/0x%08llx\n",
770 PCI_MAPREG_MEM64_ADDR(mem)((mem) & 0xfffffffffffffff0ULL),
771 PCI_MAPREG_MEM64_SIZE(mask)(((mask) & 0xfffffffffffffff0ULL) & -((mask) & 0xfffffffffffffff0ULL
))
);
772
773 break;
774 }
775 break;
776
777 case PCI_MAPREG_TYPE_IO0x00000001:
778 printf("io addr: 0x%08x/0x%04x\n",
779 PCI_MAPREG_IO_ADDR(reg)((reg) & 0xfffffffe),
780 PCI_MAPREG_IO_SIZE(reg1)(((reg1) & 0xfffffffe) & -((reg1) & 0xfffffffe)));
781 break;
782 }
783 }
784}
785
786void
787dump_type0(int bus, int dev, int func)
788{
789 u_int32_t reg;
790
791 dump_bars(bus, dev, func, PCI_MAPREG_END0x28);
40
Calling 'dump_bars'
792
793 if (pci_read(bus, dev, func, PCI_CARDBUS_CIS_REG0x28, &reg) != 0)
794 warn("unable to read PCI_CARDBUS_CIS_REG");
795 printf("\t0x%04x: Cardbus CIS: %08x\n", PCI_CARDBUS_CIS_REG0x28, reg);
796
797 if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG0x2c, &reg) != 0)
798 warn("unable to read PCI_SUBSYS_ID_REG");
799 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n",
800 PCI_SUBSYS_ID_REG0x2c, PCI_VENDOR(reg)(((reg) >> 0) & 0xffff), PCI_PRODUCT(reg)(((reg) >> 16) & 0xffff));
801
802 if (pci_read(bus, dev, func, PCI_ROM_REG0x30, &reg) != 0)
803 warn("unable to read PCI_ROM_REG");
804 printf("\t0x%04x: Expansion ROM Base Address: %08x\n",
805 PCI_ROM_REG0x30, reg);
806
807 if (pci_read(bus, dev, func, 0x38, &reg) != 0)
808 warn("unable to read 0x38 (reserved)");
809 printf("\t0x%04x: %08x\n", 0x38, reg);
810
811 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG0x3c, &reg) != 0)
812 warn("unable to read PCI_INTERRUPT_REG");
813 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x Min Gnt: %02x"
814 " Max Lat: %02x\n", PCI_INTERRUPT_REG0x3c, PCI_INTERRUPT_PIN(reg)(((reg) >> 8) & 0xff),
815 PCI_INTERRUPT_LINE(reg)(((reg) >> 0) & 0xff), PCI_MIN_GNT(reg)(((reg) >> 16) & 0xff), PCI_MAX_LAT(reg)(((reg) >> 24) & 0xff));
816}
817
818void
819dump_type1(int bus, int dev, int func)
820{
821 u_int32_t reg;
822
823 dump_bars(bus, dev, func, PCI_MAPREG_PPB_END0x18);
824
825 if (pci_read(bus, dev, func, PCI_PRIBUS_10x18, &reg) != 0)
826 warn("unable to read PCI_PRIBUS_1");
827 printf("\t0x%04x: Primary Bus: %d, Secondary Bus: %d, "
828 "Subordinate Bus: %d,\n\t\tSecondary Latency Timer: %02x\n",
829 PCI_PRIBUS_10x18, (reg >> 0) & 0xff, (reg >> 8) & 0xff,
830 (reg >> 16) & 0xff, (reg >> 24) & 0xff);
831
832 if (pci_read(bus, dev, func, PCI_IOBASEL_10x1c, &reg) != 0)
833 warn("unable to read PCI_IOBASEL_1");
834 printf("\t0x%04x: I/O Base: %02x, I/O Limit: %02x, "
835 "Secondary Status: %04x\n", PCI_IOBASEL_10x1c, (reg >> 0 ) & 0xff,
836 (reg >> 8) & 0xff, (reg >> 16) & 0xffff);
837
838 if (pci_read(bus, dev, func, PCI_MEMBASE_10x20, &reg) != 0)
839 warn("unable to read PCI_MEMBASE_1");
840 printf("\t0x%04x: Memory Base: %04x, Memory Limit: %04x\n",
841 PCI_MEMBASE_10x20, (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
842
843 if (pci_read(bus, dev, func, PCI_PMBASEL_10x24, &reg) != 0)
844 warn("unable to read PCI_PMBASEL_1");
845 printf("\t0x%04x: Prefetch Memory Base: %04x, "
846 "Prefetch Memory Limit: %04x\n", PCI_PMBASEL_10x24,
847 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
848
849#undef PCI_PMBASEH_10x28
850#define PCI_PMBASEH_10x28 0x28
851 if (pci_read(bus, dev, func, PCI_PMBASEH_10x28, &reg) != 0)
852 warn("unable to read PCI_PMBASEH_1");
853 printf("\t0x%04x: Prefetch Memory Base Upper 32 Bits: %08x\n",
854 PCI_PMBASEH_10x28, reg);
855
856#undef PCI_PMLIMITH_10x2c
857#define PCI_PMLIMITH_10x2c 0x2c
858 if (pci_read(bus, dev, func, PCI_PMLIMITH_10x2c, &reg) != 0)
859 warn("unable to read PCI_PMLIMITH_1");
860 printf("\t0x%04x: Prefetch Memory Limit Upper 32 Bits: %08x\n",
861 PCI_PMLIMITH_10x2c, reg);
862
863#undef PCI_IOBASEH_10x30
864#define PCI_IOBASEH_10x30 0x30
865 if (pci_read(bus, dev, func, PCI_IOBASEH_10x30, &reg) != 0)
866 warn("unable to read PCI_IOBASEH_1");
867 printf("\t0x%04x: I/O Base Upper 16 Bits: %04x, "
868 "I/O Limit Upper 16 Bits: %04x\n", PCI_IOBASEH_10x30,
869 (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
870
871#define PCI_PPB_ROM_REG0x38 0x38
872 if (pci_read(bus, dev, func, PCI_PPB_ROM_REG0x38, &reg) != 0)
873 warn("unable to read PCI_PPB_ROM_REG");
874 printf("\t0x%04x: Expansion ROM Base Address: %08x\n",
875 PCI_PPB_ROM_REG0x38, reg);
876
877 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG0x3c, &reg) != 0)
878 warn("unable to read PCI_INTERRUPT_REG");
879 printf("\t0x%04x: Interrupt Pin: %02x, Line: %02x, "
880 "Bridge Control: %04x\n",
881 PCI_INTERRUPT_REG0x3c, PCI_INTERRUPT_PIN(reg)(((reg) >> 8) & 0xff),
882 PCI_INTERRUPT_LINE(reg)(((reg) >> 0) & 0xff), reg >> 16);
883}
884
885void
886dump_type2(int bus, int dev, int func)
887{
888 u_int32_t reg;
889
890 if (pci_read(bus, dev, func, PCI_MAPREG_START0x10, &reg) != 0)
891 warn("unable to read PCI_MAPREG\n");
892 printf("\t0x%04x: Cardbus Control Registers Base Address: %08x\n",
893 PCI_MAPREG_START0x10, reg);
894
895 if (pci_read(bus, dev, func, PCI_PRIBUS_20x18, &reg) != 0)
896 warn("unable to read PCI_PRIBUS_2");
897 printf("\t0x%04x: Primary Bus: %d Cardbus Bus: %d "
898 "Subordinate Bus: %d \n\t Cardbus Latency Timer: %02x\n",
899 PCI_PRIBUS_20x18, (reg >> 0) & 0xff, (reg >> 8) & 0xff,
900 (reg >> 16) & 0xff, (reg >> 24) & 0xff);
901
902 if (pci_read(bus, dev, func, PCI_MEMBASE0_20x1c, &reg) != 0)
903 warn("unable to read PCI_MEMBASE0_2\n");
904 printf("\t0x%04x: Memory Base 0: %08x\n", PCI_MEMBASE0_20x1c, reg);
905
906 if (pci_read(bus, dev, func, PCI_MEMLIMIT0_20x20, &reg) != 0)
907 warn("unable to read PCI_MEMLIMIT0_2\n");
908 printf("\t0x%04x: Memory Limit 0: %08x\n", PCI_MEMLIMIT0_20x20, reg);
909
910 if (pci_read(bus, dev, func, PCI_MEMBASE1_20x24, &reg) != 0)
911 warn("unable to read PCI_MEMBASE1_2\n");
912 printf("\t0x%04x: Memory Base 1: %08x\n", PCI_MEMBASE1_20x24, reg);
913
914 if (pci_read(bus, dev, func, PCI_MEMLIMIT1_20x28, &reg) != 0)
915 warn("unable to read PCI_MEMLIMIT1_2\n");
916 printf("\t0x%04x: Memory Limit 1: %08x\n", PCI_MEMLIMIT1_20x28, reg);
917
918 if (pci_read(bus, dev, func, PCI_IOBASE0_20x2c, &reg) != 0)
919 warn("unable to read PCI_IOBASE0_2\n");
920 printf("\t0x%04x: I/O Base 0: %08x\n", PCI_IOBASE0_20x2c, reg);
921
922 if (pci_read(bus, dev, func, PCI_IOLIMIT0_20x30, &reg) != 0)
923 warn("unable to read PCI_IOLIMIT0_2\n");
924 printf("\t0x%04x: I/O Limit 0: %08x\n", PCI_IOLIMIT0_20x30, reg);
925
926 if (pci_read(bus, dev, func, PCI_IOBASE1_20x34, &reg) != 0)
927 warn("unable to read PCI_IOBASE1_2\n");
928 printf("\t0x%04x: I/O Base 1: %08x\n", PCI_IOBASE1_20x34, reg);
929
930 if (pci_read(bus, dev, func, PCI_IOLIMIT1_20x38, &reg) != 0)
931 warn("unable to read PCI_IOLIMIT1_2\n");
932 printf("\t0x%04x: I/O Limit 1: %08x\n", PCI_IOLIMIT1_20x38, reg);
933
934 if (pci_read(bus, dev, func, PCI_INTERRUPT_REG0x3c, &reg) != 0)
935 warn("unable to read PCI_INTERRUPT_REG");
936 printf("\t0x%04x: Interrupt Pin: %02x Line: %02x "
937 "Bridge Control: %04x\n",
938 PCI_INTERRUPT_REG0x3c, PCI_INTERRUPT_PIN(reg)(((reg) >> 8) & 0xff),
939 PCI_INTERRUPT_LINE(reg)(((reg) >> 0) & 0xff), reg >> 16);
940
941 if (pci_read(bus, dev, func, PCI_SUBVEND_20x40, &reg) != 0)
942 warn("unable to read PCI_SUBVEND_2");
943 printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n",
944 PCI_SUBVEND_20x40, PCI_VENDOR(reg)(((reg) >> 0) & 0xffff), PCI_PRODUCT(reg)(((reg) >> 16) & 0xffff));
945
946 if (pci_read(bus, dev, func, PCI_PCCARDIF_20x44, &reg) != 0)
947 warn("unable to read PCI_PCCARDIF_2\n");
948 printf("\t0x%04x: 16-bit Legacy Mode Base Address: %08x\n",
949 PCI_PCCARDIF_20x44, reg);
950}
951
952void
953dump(int bus, int dev, int func)
954{
955 u_int32_t reg;
956 u_int8_t capptr = PCI_CAPLISTPTR_REG0x34;
957 pci_class_t class;
958 pci_subclass_t subclass;
959
960 if (pci_read(bus, dev, func, PCI_ID_REG0x00, &reg) != 0)
34
Taking false branch
961 warn("unable to read PCI_ID_REG");
962 printf("\t0x%04x: Vendor ID: %04x, Product ID: %04x\n", PCI_ID_REG0x00,
963 PCI_VENDOR(reg)(((reg) >> 0) & 0xffff), PCI_PRODUCT(reg)(((reg) >> 16) & 0xffff));
964
965 if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG0x04, &reg) != 0)
35
Taking true branch
966 warn("unable to read PCI_COMMAND_STATUS_REG");
967 printf("\t0x%04x: Command: %04x, Status: %04x\n",
968 PCI_COMMAND_STATUS_REG0x04, reg & 0xffff, (reg >> 16) & 0xffff);
969
970 if (pci_read(bus, dev, func, PCI_CLASS_REG0x08, &reg) != 0)
36
Taking false branch
971 warn("unable to read PCI_CLASS_REG");
972 class = PCI_CLASS(reg)(((reg) >> 24) & 0xff);
973 subclass = PCI_SUBCLASS(reg)(((reg) >> 16) & 0xff);
974 printf("\t0x%04x:\tClass: %02x %s,", PCI_CLASS_REG0x08, class,
975 pci_class_name(class));
976 printf(" Subclass: %02x %s,", subclass,
977 pci_subclass_name(class, subclass));
978 printf("\n\t\tInterface: %02x, Revision: %02x\n",
979 PCI_INTERFACE(reg)(((reg) >> 8) & 0xff), PCI_REVISION(reg)(((reg) >> 0) & 0xff));
980
981 if (pci_read(bus, dev, func, PCI_BHLC_REG0x0c, &reg) != 0)
37
Taking true branch
982 warn("unable to read PCI_BHLC_REG");
983 printf("\t0x%04x: BIST: %02x, Header Type: %02x, "
984 "Latency Timer: %02x,\n\t\tCache Line Size: %02x\n", PCI_BHLC_REG0x0c,
985 PCI_BIST(reg)(((reg) >> 24) & 0xff), PCI_HDRTYPE(reg)(((reg) >> 16) & 0xff),
986 PCI_LATTIMER(reg)(((reg) >> 8) & 0xff), PCI_CACHELINE(reg)(((reg) >> 0) & 0xff));
987
988 switch (PCI_HDRTYPE_TYPE(reg)((((reg) >> 16) & 0xff) & 0x7f)) {
38
Control jumps to 'case 0:' at line 996
989 case 2:
990 dump_type2(bus, dev, func);
991 capptr = PCI_CARDBUS_CAPLISTPTR_REG0x14;
992 break;
993 case 1:
994 dump_type1(bus, dev, func);
995 break;
996 case 0:
997 dump_type0(bus, dev, func);
39
Calling 'dump_type0'
998 break;
999 default:
1000 break;
1001 }
1002 dump_caplist(bus, dev, func, capptr);
1003}
1004
1005void
1006hexdump(int bus, int dev, int func, int size)
1007{
1008 u_int32_t reg;
1009 int i;
1010
1011 for (i = 0; i < size; i += 4) {
1012 if (pci_read(bus, dev, func, i, &reg) != 0) {
1013 if (errno(*__errno()) == EINVAL22)
1014 return;
1015 warn("unable to read 0x%02x", i);
1016 }
1017
1018 if ((i % 16) == 0)
1019 printf("\t0x%04x:", i);
1020 printf(" %08x", reg);
1021
1022 if ((i % 16) == 12)
1023 printf("\n");
1024 }
1025}
1026
1027int
1028pci_nfuncs(int bus, int dev)
1029{
1030 u_int32_t hdr;
1031
1032 if (pci_read(bus, dev, 0, PCI_BHLC_REG0x0c, &hdr) != 0)
1033 return (-1);
1034
1035 return (PCI_HDRTYPE_MULTIFN(hdr)(((((hdr) >> 16) & 0xff) & 0x80) != 0) ? 8 : 1);
1036}
1037
1038int
1039pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
1040{
1041 struct pci_io io;
1042 int rv;
1043
1044 bzero(&io, sizeof(io));
1045 io.pi_sel.pc_bus = bus;
1046 io.pi_sel.pc_dev = dev;
1047 io.pi_sel.pc_func = func;
1048 io.pi_reg = reg;
1049 io.pi_width = 4;
1050
1051 rv = ioctl(pcifd, PCIOCREAD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_io) & 0x1fff) << 16) | ((('p')) <<
8) | ((2)))
, &io);
1052 if (rv != 0)
1053 return (rv);
1054
1055 *val = io.pi_data;
1056
1057 return (0);
1058}
1059
1060int
1061pci_readmask(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
1062{
1063 struct pci_io io;
1064 int rv;
1065
1066 bzero(&io, sizeof(io));
1067 io.pi_sel.pc_bus = bus;
1068 io.pi_sel.pc_dev = dev;
1069 io.pi_sel.pc_func = func;
1070 io.pi_reg = reg;
1071 io.pi_width = 4;
1072
1073 rv = ioctl(pcifd, PCIOCREADMASK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_io) & 0x1fff) << 16) | ((('p')) <<
8) | ((8)))
, &io);
1074 if (rv != 0)
1075 return (rv);
1076
1077 *val = io.pi_data;
1078
1079 return (0);
1080}
1081
1082int
1083dump_rom(int bus, int dev, int func)
1084{
1085 struct pci_rom rom;
1086 u_int32_t cr, addr;
1087
1088 if (pci_read(bus, dev, func, PCI_ROM_REG0x30, &addr) != 0 ||
1089 pci_read(bus, dev, func, PCI_CLASS_REG0x08, &cr) != 0)
1090 return (errno(*__errno()));
1091
1092 if (addr == 0 && PCI_CLASS(cr)(((cr) >> 24) & 0xff) == PCI_CLASS_DISPLAY0x03 &&
1093 PCI_SUBCLASS(cr)(((cr) >> 16) & 0xff) == PCI_SUBCLASS_DISPLAY_VGA0x00)
1094 return dump_vga_bios();
1095
1096 bzero(&rom, sizeof(rom));
1097 rom.pr_sel.pc_bus = bus;
1098 rom.pr_sel.pc_dev = dev;
1099 rom.pr_sel.pc_func = func;
1100 if (ioctl(pcifd, PCIOCGETROMLEN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_rom) & 0x1fff) << 16) | ((('p')) <<
8) | ((4)))
, &rom) == -1)
1101 return (errno(*__errno()));
1102
1103 rom.pr_rom = malloc(rom.pr_romlen);
1104 if (rom.pr_rom == NULL((void *)0))
1105 return (ENOMEM12);
1106
1107 if (ioctl(pcifd, PCIOCGETROM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pci_rom) & 0x1fff) << 16) | ((('p')) <<
8) | ((5)))
, &rom) == -1)
1108 return (errno(*__errno()));
1109
1110 if (write(romfd, rom.pr_rom, rom.pr_romlen) == -1)
1111 return (errno(*__errno()));
1112
1113 return (0);
1114}
1115
1116#define VGA_BIOS_ADDR0xc0000 0xc0000
1117#define VGA_BIOS_LEN0x10000 0x10000
1118
1119int
1120dump_vga_bios(void)
1121{
1122#if defined(__amd64__1) || defined(__i386__)
1123 void *bios;
1124 int fd;
1125
1126 fd = open(_PATH_MEM"/dev/mem", O_RDONLY0x0000);
1127 if (fd == -1)
1128 err(1, "%s", _PATH_MEM"/dev/mem");
1129
1130 bios = malloc(VGA_BIOS_LEN0x10000);
1131 if (bios == NULL((void *)0))
1132 return (ENOMEM12);
1133
1134 if (pread(fd, bios, VGA_BIOS_LEN0x10000, VGA_BIOS_ADDR0xc0000) == -1)
1135 err(1, "%s", _PATH_MEM"/dev/mem");
1136
1137 if (write(romfd, bios, VGA_BIOS_LEN0x10000) == -1) {
1138 free(bios);
1139 return (errno(*__errno()));
1140 }
1141
1142 free(bios);
1143
1144 return (0);
1145#else
1146 return (ENODEV19);
1147#endif
1148}
1149
1150struct pci_subclass {
1151 pci_subclass_t subclass;
1152 const char *name;
1153};
1154
1155struct pci_class {
1156 pci_class_t class;
1157 const char *name;
1158 const struct pci_subclass
1159 *subclass;
1160 size_t nsubclass;
1161};
1162
1163static const struct pci_subclass pci_subclass_prehistoric[] = {
1164 { PCI_SUBCLASS_PREHISTORIC_MISC0x00, "Miscellaneous" },
1165 { PCI_SUBCLASS_PREHISTORIC_VGA0x01, "VGA" },
1166};
1167
1168static const struct pci_subclass pci_subclass_mass_storage[] = {
1169 { PCI_SUBCLASS_MASS_STORAGE_SCSI0x00, "SCSI" },
1170 { PCI_SUBCLASS_MASS_STORAGE_IDE0x01, "IDE" },
1171 { PCI_SUBCLASS_MASS_STORAGE_FLOPPY0x02, "Floppy" },
1172 { PCI_SUBCLASS_MASS_STORAGE_IPI0x03, "IPI" },
1173 { PCI_SUBCLASS_MASS_STORAGE_RAID0x04, "RAID" },
1174 { PCI_SUBCLASS_MASS_STORAGE_ATA0x05, "ATA" },
1175 { PCI_SUBCLASS_MASS_STORAGE_SATA0x06, "SATA" },
1176 { PCI_SUBCLASS_MASS_STORAGE_SAS0x07, "SAS" },
1177 { PCI_SUBCLASS_MASS_STORAGE_UFS0x09, "UFS" },
1178 { PCI_SUBCLASS_MASS_STORAGE_NVM0x08, "NVM" },
1179 { PCI_SUBCLASS_MASS_STORAGE_MISC0x80, "Miscellaneous" },
1180};
1181
1182static const struct pci_subclass pci_subclass_network[] = {
1183 { PCI_SUBCLASS_NETWORK_ETHERNET0x00, "Ethernet" },
1184 { PCI_SUBCLASS_NETWORK_TOKENRING0x01, "Token Ring" },
1185 { PCI_SUBCLASS_NETWORK_FDDI0x02, "FDDI" },
1186 { PCI_SUBCLASS_NETWORK_ATM0x03, "ATM" },
1187 { PCI_SUBCLASS_NETWORK_ISDN0x04, "ISDN" },
1188 { PCI_SUBCLASS_NETWORK_WORLDFIP0x05, "WorldFip" },
1189 { PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP0x06, "PCMIG Multi Computing" },
1190 { PCI_SUBCLASS_NETWORK_INFINIBAND0x07, "InfiniBand" },
1191 { PCI_SUBCLASS_NETWORK_MISC0x80, "Miscellaneous" },
1192};
1193
1194static const struct pci_subclass pci_subclass_display[] = {
1195 { PCI_SUBCLASS_DISPLAY_VGA0x00, "VGA" },
1196 { PCI_SUBCLASS_DISPLAY_XGA0x01, "XGA" },
1197 { PCI_SUBCLASS_DISPLAY_3D0x02, "3D" },
1198 { PCI_SUBCLASS_DISPLAY_MISC0x80, "Miscellaneous" },
1199};
1200
1201static const struct pci_subclass pci_subclass_multimedia[] = {
1202 { PCI_SUBCLASS_MULTIMEDIA_VIDEO0x00, "Video" },
1203 { PCI_SUBCLASS_MULTIMEDIA_AUDIO0x01, "Audio" },
1204 { PCI_SUBCLASS_MULTIMEDIA_TELEPHONY0x02, "Telephony" },
1205 { PCI_SUBCLASS_MULTIMEDIA_HDAUDIO0x03, "HD Audio" },
1206 { PCI_SUBCLASS_MULTIMEDIA_MISC0x80, "Miscellaneous" },
1207};
1208
1209static const struct pci_subclass pci_subclass_memory[] = {
1210 { PCI_SUBCLASS_MEMORY_RAM0x00, "RAM" },
1211 { PCI_SUBCLASS_MEMORY_FLASH0x01, "Flash" },
1212 { PCI_SUBCLASS_MEMORY_MISC0x80, "Miscellaneous" },
1213};
1214
1215static const struct pci_subclass pci_subclass_bridge[] = {
1216 { PCI_SUBCLASS_BRIDGE_HOST0x00, "Host" },
1217 { PCI_SUBCLASS_BRIDGE_ISA0x01, "ISA" },
1218 { PCI_SUBCLASS_BRIDGE_EISA0x02, "EISA" },
1219 { PCI_SUBCLASS_BRIDGE_MC0x03, "MicroChannel" },
1220 { PCI_SUBCLASS_BRIDGE_PCI0x04, "PCI" },
1221 { PCI_SUBCLASS_BRIDGE_PCMCIA0x05, "PCMCIA" },
1222 { PCI_SUBCLASS_BRIDGE_NUBUS0x06, "NuBus" },
1223 { PCI_SUBCLASS_BRIDGE_RACEWAY0x08, "RACEway" },
1224 { PCI_SUBCLASS_BRIDGE_STPCI0x09, "Semi-transparent PCI" },
1225 { PCI_SUBCLASS_BRIDGE_INFINIBAND0x0a, "InfiniBand" },
1226 { PCI_SUBCLASS_BRIDGE_MISC0x80, "Miscellaneous" },
1227 { PCI_SUBCLASS_BRIDGE_AS0x0b, "advanced switching" },
1228};
1229
1230static const struct pci_subclass pci_subclass_communications[] = {
1231 { PCI_SUBCLASS_COMMUNICATIONS_SERIAL0x00, "Serial" },
1232 { PCI_SUBCLASS_COMMUNICATIONS_PARALLEL0x01, "Parallel" },
1233 { PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL0x02, "Multi-port Serial" },
1234 { PCI_SUBCLASS_COMMUNICATIONS_MODEM0x03, "Modem" },
1235 { PCI_SUBCLASS_COMMUNICATIONS_GPIB0x04, "GPIB" },
1236 { PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD0x05,
1237 "Smartcard" },
1238 { PCI_SUBCLASS_COMMUNICATIONS_MISC0x80, "Miscellaneous" },
1239};
1240
1241static const struct pci_subclass pci_subclass_system[] = {
1242 { PCI_SUBCLASS_SYSTEM_PIC0x00, "Interrupt" },
1243 { PCI_SUBCLASS_SYSTEM_DMA0x01, "8237 DMA" },
1244 { PCI_SUBCLASS_SYSTEM_TIMER0x02, "8254 Timer" },
1245 { PCI_SUBCLASS_SYSTEM_RTC0x03, "RTC" },
1246 { PCI_SUBCLASS_SYSTEM_SDHC0x05, "SDHC" },
1247 { PCI_SUBCLASS_SYSTEM_IOMMU0x06, "IOMMU" },
1248 { PCI_SUBCLASS_SYSTEM_ROOTCOMPEVENT0x07, "Root Complex Event" },
1249 { PCI_SUBCLASS_SYSTEM_MISC0x80, "Miscellaneous" },
1250};
1251
1252static const struct pci_subclass pci_subclass_input[] = {
1253 { PCI_SUBCLASS_INPUT_KEYBOARD0x00, "Keyboard" },
1254 { PCI_SUBCLASS_INPUT_DIGITIZER0x01, "Digitizer" },
1255 { PCI_SUBCLASS_INPUT_MOUSE0x02, "Mouse" },
1256 { PCI_SUBCLASS_INPUT_SCANNER0x03, "Scanner" },
1257 { PCI_SUBCLASS_INPUT_GAMEPORT0x04, "Game Port" },
1258 { PCI_SUBCLASS_INPUT_MISC0x80, "Miscellaneous" },
1259};
1260
1261static const struct pci_subclass pci_subclass_dock[] = {
1262 { PCI_SUBCLASS_DOCK_GENERIC0x00, "Generic" },
1263 { PCI_SUBCLASS_DOCK_MISC0x80, "Miscellaneous" },
1264};
1265
1266static const struct pci_subclass pci_subclass_processor[] = {
1267 { PCI_SUBCLASS_PROCESSOR_3860x00, "386" },
1268 { PCI_SUBCLASS_PROCESSOR_4860x01, "486" },
1269 { PCI_SUBCLASS_PROCESSOR_PENTIUM0x02, "Pentium" },
1270 { PCI_SUBCLASS_PROCESSOR_ALPHA0x10, "Alpha" },
1271 { PCI_SUBCLASS_PROCESSOR_POWERPC0x20, "PowerPC" },
1272 { PCI_SUBCLASS_PROCESSOR_MIPS0x30, "MIPS" },
1273 { PCI_SUBCLASS_PROCESSOR_COPROC0x40, "Co-Processor" },
1274};
1275
1276static const struct pci_subclass pci_subclass_serialbus[] = {
1277 { PCI_SUBCLASS_SERIALBUS_FIREWIRE0x00, "FireWire" },
1278 { PCI_SUBCLASS_SERIALBUS_ACCESS0x01, "ACCESS.bus" },
1279 { PCI_SUBCLASS_SERIALBUS_SSA0x02, "SSA" },
1280 { PCI_SUBCLASS_SERIALBUS_USB0x03, "USB" },
1281 { PCI_SUBCLASS_SERIALBUS_FIBER0x04, "Fiber Channel" },
1282 { PCI_SUBCLASS_SERIALBUS_SMBUS0x05, "SMBus" },
1283 { PCI_SUBCLASS_SERIALBUS_INFINIBAND0x06, "InfiniBand" },
1284 { PCI_SUBCLASS_SERIALBUS_IPMI0x07, "IPMI" },
1285 { PCI_SUBCLASS_SERIALBUS_SERCOS0x08, "SERCOS" },
1286 { PCI_SUBCLASS_SERIALBUS_CANBUS0x09, "CANbus" },
1287};
1288
1289static const struct pci_subclass pci_subclass_wireless[] = {
1290 { PCI_SUBCLASS_WIRELESS_IRDA0x00, "IrDA" },
1291 { PCI_SUBCLASS_WIRELESS_CONSUMERIR0x01, "Consumer IR" },
1292 { PCI_SUBCLASS_WIRELESS_RF0x10, "RF" },
1293 { PCI_SUBCLASS_WIRELESS_BLUETOOTH0x11, "Bluetooth" },
1294 { PCI_SUBCLASS_WIRELESS_BROADBAND0x12, "Broadband" },
1295 { PCI_SUBCLASS_WIRELESS_802_11A0x20, "802.11a" },
1296 { PCI_SUBCLASS_WIRELESS_802_11B0x21, "802.11b" },
1297 { PCI_SUBCLASS_WIRELESS_MISC0x80, "Miscellaneous" },
1298};
1299
1300static const struct pci_subclass pci_subclass_i2o[] = {
1301 { PCI_SUBCLASS_I2O_STANDARD0x00, "Standard" },
1302};
1303
1304static const struct pci_subclass pci_subclass_satcom[] = {
1305 { PCI_SUBCLASS_SATCOM_TV0x01, "TV" },
1306 { PCI_SUBCLASS_SATCOM_AUDIO0x02, "Audio" },
1307 { PCI_SUBCLASS_SATCOM_VOICE0x03, "Voice" },
1308 { PCI_SUBCLASS_SATCOM_DATA0x04, "Data" },
1309};
1310
1311static const struct pci_subclass pci_subclass_crypto[] = {
1312 { PCI_SUBCLASS_CRYPTO_NETCOMP0x00, "Network/Computing" },
1313 { PCI_SUBCLASS_CRYPTO_ENTERTAINMENT0x10, "Entertainment" },
1314 { PCI_SUBCLASS_CRYPTO_MISC0x80, "Miscellaneous" },
1315};
1316
1317static const struct pci_subclass pci_subclass_dasp[] = {
1318 { PCI_SUBCLASS_DASP_DPIO0x00, "DPIO" },
1319 { PCI_SUBCLASS_DASP_TIMEFREQ0x01, "Time and Frequency" },
1320 { PCI_SUBCLASS_DASP_SYNC0x10, "Synchronization" },
1321 { PCI_SUBCLASS_DASP_MGMT0x20, "Management" },
1322 { PCI_SUBCLASS_DASP_MISC0x80, "Miscellaneous" },
1323};
1324
1325static const struct pci_subclass pci_subclass_accelerator[] = {};
1326static const struct pci_subclass pci_subclass_instrumentation[] = {};
1327
1328#define CLASS(_c, _n, _s){ .class = _c, .name = _n, .subclass = _s, .nsubclass = (sizeof
((_s)) / sizeof((_s)[0])), }
{ \
1329 .class = _c, \
1330 .name = _n, \
1331 .subclass = _s, \
1332 .nsubclass = nitems(_s)(sizeof((_s)) / sizeof((_s)[0])), \
1333}
1334
1335static const struct pci_class pci_classes[] = {
1336 CLASS(PCI_CLASS_PREHISTORIC, "Prehistoric",{ .class = 0x00, .name = "Prehistoric", .subclass = pci_subclass_prehistoric
, .nsubclass = (sizeof((pci_subclass_prehistoric)) / sizeof((
pci_subclass_prehistoric)[0])), }
1337 pci_subclass_prehistoric){ .class = 0x00, .name = "Prehistoric", .subclass = pci_subclass_prehistoric
, .nsubclass = (sizeof((pci_subclass_prehistoric)) / sizeof((
pci_subclass_prehistoric)[0])), }
,
1338 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])), }
1339 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])), }
,
1340 CLASS(PCI_CLASS_NETWORK, "Network",{ .class = 0x02, .name = "Network", .subclass = pci_subclass_network
, .nsubclass = (sizeof((pci_subclass_network)) / sizeof((pci_subclass_network
)[0])), }
1341 pci_subclass_network){ .class = 0x02, .name = "Network", .subclass = pci_subclass_network
, .nsubclass = (sizeof((pci_subclass_network)) / sizeof((pci_subclass_network
)[0])), }
,
1342 CLASS(PCI_CLASS_DISPLAY, "Display",{ .class = 0x03, .name = "Display", .subclass = pci_subclass_display
, .nsubclass = (sizeof((pci_subclass_display)) / sizeof((pci_subclass_display
)[0])), }
1343 pci_subclass_display){ .class = 0x03, .name = "Display", .subclass = pci_subclass_display
, .nsubclass = (sizeof((pci_subclass_display)) / sizeof((pci_subclass_display
)[0])), }
,
1344 CLASS(PCI_CLASS_MULTIMEDIA, "Multimedia",{ .class = 0x04, .name = "Multimedia", .subclass = pci_subclass_multimedia
, .nsubclass = (sizeof((pci_subclass_multimedia)) / sizeof((pci_subclass_multimedia
)[0])), }
1345 pci_subclass_multimedia){ .class = 0x04, .name = "Multimedia", .subclass = pci_subclass_multimedia
, .nsubclass = (sizeof((pci_subclass_multimedia)) / sizeof((pci_subclass_multimedia
)[0])), }
,
1346 CLASS(PCI_CLASS_MEMORY, "Memory",{ .class = 0x05, .name = "Memory", .subclass = pci_subclass_memory
, .nsubclass = (sizeof((pci_subclass_memory)) / sizeof((pci_subclass_memory
)[0])), }
1347 pci_subclass_memory){ .class = 0x05, .name = "Memory", .subclass = pci_subclass_memory
, .nsubclass = (sizeof((pci_subclass_memory)) / sizeof((pci_subclass_memory
)[0])), }
,
1348 CLASS(PCI_CLASS_BRIDGE, "Bridge",{ .class = 0x06, .name = "Bridge", .subclass = pci_subclass_bridge
, .nsubclass = (sizeof((pci_subclass_bridge)) / sizeof((pci_subclass_bridge
)[0])), }
1349 pci_subclass_bridge){ .class = 0x06, .name = "Bridge", .subclass = pci_subclass_bridge
, .nsubclass = (sizeof((pci_subclass_bridge)) / sizeof((pci_subclass_bridge
)[0])), }
,
1350 CLASS(PCI_CLASS_COMMUNICATIONS, "Communications",{ .class = 0x07, .name = "Communications", .subclass = pci_subclass_communications
, .nsubclass = (sizeof((pci_subclass_communications)) / sizeof
((pci_subclass_communications)[0])), }
1351 pci_subclass_communications){ .class = 0x07, .name = "Communications", .subclass = pci_subclass_communications
, .nsubclass = (sizeof((pci_subclass_communications)) / sizeof
((pci_subclass_communications)[0])), }
,
1352 CLASS(PCI_CLASS_SYSTEM, "System",{ .class = 0x08, .name = "System", .subclass = pci_subclass_system
, .nsubclass = (sizeof((pci_subclass_system)) / sizeof((pci_subclass_system
)[0])), }
1353 pci_subclass_system){ .class = 0x08, .name = "System", .subclass = pci_subclass_system
, .nsubclass = (sizeof((pci_subclass_system)) / sizeof((pci_subclass_system
)[0])), }
,
1354 CLASS(PCI_CLASS_INPUT, "Input",{ .class = 0x09, .name = "Input", .subclass = pci_subclass_input
, .nsubclass = (sizeof((pci_subclass_input)) / sizeof((pci_subclass_input
)[0])), }
1355 pci_subclass_input){ .class = 0x09, .name = "Input", .subclass = pci_subclass_input
, .nsubclass = (sizeof((pci_subclass_input)) / sizeof((pci_subclass_input
)[0])), }
,
1356 CLASS(PCI_CLASS_DOCK, "Dock",{ .class = 0x0a, .name = "Dock", .subclass = pci_subclass_dock
, .nsubclass = (sizeof((pci_subclass_dock)) / sizeof((pci_subclass_dock
)[0])), }
1357 pci_subclass_dock){ .class = 0x0a, .name = "Dock", .subclass = pci_subclass_dock
, .nsubclass = (sizeof((pci_subclass_dock)) / sizeof((pci_subclass_dock
)[0])), }
,
1358 CLASS(PCI_CLASS_PROCESSOR, "Processor",{ .class = 0x0b, .name = "Processor", .subclass = pci_subclass_processor
, .nsubclass = (sizeof((pci_subclass_processor)) / sizeof((pci_subclass_processor
)[0])), }
1359 pci_subclass_processor){ .class = 0x0b, .name = "Processor", .subclass = pci_subclass_processor
, .nsubclass = (sizeof((pci_subclass_processor)) / sizeof((pci_subclass_processor
)[0])), }
,
1360 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])), }
1361 pci_subclass_serialbus){ .class = 0x0c, .name = "Serial Bus", .subclass = pci_subclass_serialbus
, .nsubclass = (sizeof((pci_subclass_serialbus)) / sizeof((pci_subclass_serialbus
)[0])), }
,
1362 CLASS(PCI_CLASS_WIRELESS, "Wireless",{ .class = 0x0d, .name = "Wireless", .subclass = pci_subclass_wireless
, .nsubclass = (sizeof((pci_subclass_wireless)) / sizeof((pci_subclass_wireless
)[0])), }
1363 pci_subclass_wireless){ .class = 0x0d, .name = "Wireless", .subclass = pci_subclass_wireless
, .nsubclass = (sizeof((pci_subclass_wireless)) / sizeof((pci_subclass_wireless
)[0])), }
,
1364 CLASS(PCI_CLASS_I2O, "I2O",{ .class = 0x0e, .name = "I2O", .subclass = pci_subclass_i2o,
.nsubclass = (sizeof((pci_subclass_i2o)) / sizeof((pci_subclass_i2o
)[0])), }
1365 pci_subclass_i2o){ .class = 0x0e, .name = "I2O", .subclass = pci_subclass_i2o,
.nsubclass = (sizeof((pci_subclass_i2o)) / sizeof((pci_subclass_i2o
)[0])), }
,
1366 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])), }
1367 pci_subclass_satcom){ .class = 0x0f, .name = "Satellite Comm", .subclass = pci_subclass_satcom
, .nsubclass = (sizeof((pci_subclass_satcom)) / sizeof((pci_subclass_satcom
)[0])), }
,
1368 CLASS(PCI_CLASS_CRYPTO, "Crypto",{ .class = 0x10, .name = "Crypto", .subclass = pci_subclass_crypto
, .nsubclass = (sizeof((pci_subclass_crypto)) / sizeof((pci_subclass_crypto
)[0])), }
1369 pci_subclass_crypto){ .class = 0x10, .name = "Crypto", .subclass = pci_subclass_crypto
, .nsubclass = (sizeof((pci_subclass_crypto)) / sizeof((pci_subclass_crypto
)[0])), }
,
1370 CLASS(PCI_CLASS_DASP, "DASP",{ .class = 0x11, .name = "DASP", .subclass = pci_subclass_dasp
, .nsubclass = (sizeof((pci_subclass_dasp)) / sizeof((pci_subclass_dasp
)[0])), }
1371 pci_subclass_dasp){ .class = 0x11, .name = "DASP", .subclass = pci_subclass_dasp
, .nsubclass = (sizeof((pci_subclass_dasp)) / sizeof((pci_subclass_dasp
)[0])), }
,
1372 CLASS(PCI_CLASS_ACCELERATOR, "Accelerator",{ .class = 0x12, .name = "Accelerator", .subclass = pci_subclass_accelerator
, .nsubclass = (sizeof((pci_subclass_accelerator)) / sizeof((
pci_subclass_accelerator)[0])), }
1373 pci_subclass_accelerator){ .class = 0x12, .name = "Accelerator", .subclass = pci_subclass_accelerator
, .nsubclass = (sizeof((pci_subclass_accelerator)) / sizeof((
pci_subclass_accelerator)[0])), }
,
1374 CLASS(PCI_CLASS_INSTRUMENTATION, "Instrumentation",{ .class = 0x13, .name = "Instrumentation", .subclass = pci_subclass_instrumentation
, .nsubclass = (sizeof((pci_subclass_instrumentation)) / sizeof
((pci_subclass_instrumentation)[0])), }
1375 pci_subclass_instrumentation){ .class = 0x13, .name = "Instrumentation", .subclass = pci_subclass_instrumentation
, .nsubclass = (sizeof((pci_subclass_instrumentation)) / sizeof
((pci_subclass_instrumentation)[0])), }
,
1376};
1377
1378static const struct pci_class *
1379pci_class(pci_class_t class)
1380{
1381 const struct pci_class *pc;
1382 size_t i;
1383
1384 for (i = 0; i < nitems(pci_classes)(sizeof((pci_classes)) / sizeof((pci_classes)[0])); i++) {
1385 pc = &pci_classes[i];
1386 if (pc->class == class)
1387 return (pc);
1388 }
1389
1390 return (NULL((void *)0));
1391}
1392
1393static const struct pci_subclass *
1394pci_subclass(const struct pci_class *pc, pci_subclass_t subclass)
1395{
1396 const struct pci_subclass *ps;
1397 size_t i;
1398
1399 for (i = 0; i < pc->nsubclass; i++) {
1400 ps = &pc->subclass[i];
1401 if (ps->subclass == subclass)
1402 return (ps);
1403 }
1404
1405 return (NULL((void *)0));
1406}
1407
1408static const char *
1409pci_class_name(pci_class_t class)
1410{
1411 const struct pci_class *pc;
1412
1413 pc = pci_class(class);
1414 if (pc == NULL((void *)0))
1415 return ("(unknown)");
1416
1417 return (pc->name);
1418}
1419
1420static const char *
1421pci_subclass_name(pci_class_t class, pci_subclass_t subclass)
1422{
1423 const struct pci_class *pc;
1424 const struct pci_subclass *ps;
1425
1426 pc = pci_class(class);
1427 if (pc == NULL((void *)0))
1428 return ("(unknown)");
1429
1430 ps = pci_subclass(pc, subclass);
1431 if (ps == NULL((void *)0) || ps->name == NULL((void *)0))
1432 return ("(unknown)");
1433
1434 return (ps->name);
1435}