unix: remove always true check from uipc_attach
[freebsd/src.git] / usr.sbin / pciconf / cap.c
blobe252926ab9bec44eae7a7e5068344680c1218279
1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2007 Yahoo!, Inc.
5 * All rights reserved.
6 * Written by: John Baldwin <jhb@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <sys/types.h>
35 #include <err.h>
36 #include <stdio.h>
37 #include <strings.h>
38 #include <sys/agpio.h>
39 #include <sys/pciio.h>
41 #include <dev/agp/agpreg.h>
42 #include <dev/pci/pcireg.h>
44 #include "pciconf.h"
46 static void list_ecaps(int fd, struct pci_conf *p);
48 static int cap_level;
50 static void
51 cap_power(int fd, struct pci_conf *p, uint8_t ptr)
53 uint16_t cap, status;
55 cap = read_config(fd, &p->pc_sel, ptr + PCIR_POWER_CAP, 2);
56 status = read_config(fd, &p->pc_sel, ptr + PCIR_POWER_STATUS, 2);
57 printf("powerspec %d supports D0%s%s D3 current D%d",
58 cap & PCIM_PCAP_SPEC,
59 cap & PCIM_PCAP_D1SUPP ? " D1" : "",
60 cap & PCIM_PCAP_D2SUPP ? " D2" : "",
61 status & PCIM_PSTAT_DMASK);
64 static void
65 cap_agp(int fd, struct pci_conf *p, uint8_t ptr)
67 uint32_t status, command;
69 status = read_config(fd, &p->pc_sel, ptr + AGP_STATUS, 4);
70 command = read_config(fd, &p->pc_sel, ptr + AGP_CAPID, 4);
71 printf("AGP ");
72 if (AGP_MODE_GET_MODE_3(status)) {
73 printf("v3 ");
74 if (AGP_MODE_GET_RATE(status) & AGP_MODE_V3_RATE_8x)
75 printf("8x ");
76 if (AGP_MODE_GET_RATE(status) & AGP_MODE_V3_RATE_4x)
77 printf("4x ");
78 } else {
79 if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_4x)
80 printf("4x ");
81 if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_2x)
82 printf("2x ");
83 if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_1x)
84 printf("1x ");
86 if (AGP_MODE_GET_SBA(status))
87 printf("SBA ");
88 if (AGP_MODE_GET_AGP(command)) {
89 printf("enabled at ");
90 if (AGP_MODE_GET_MODE_3(command)) {
91 printf("v3 ");
92 switch (AGP_MODE_GET_RATE(command)) {
93 case AGP_MODE_V3_RATE_8x:
94 printf("8x ");
95 break;
96 case AGP_MODE_V3_RATE_4x:
97 printf("4x ");
98 break;
100 } else
101 switch (AGP_MODE_GET_RATE(command)) {
102 case AGP_MODE_V2_RATE_4x:
103 printf("4x ");
104 break;
105 case AGP_MODE_V2_RATE_2x:
106 printf("2x ");
107 break;
108 case AGP_MODE_V2_RATE_1x:
109 printf("1x ");
110 break;
112 if (AGP_MODE_GET_SBA(command))
113 printf("SBA ");
114 } else
115 printf("disabled");
118 static void
119 cap_vpd(int fd __unused, struct pci_conf *p __unused, uint8_t ptr __unused)
122 printf("VPD");
125 static void
126 cap_msi(int fd, struct pci_conf *p, uint8_t ptr)
128 uint16_t ctrl;
129 int msgnum;
131 ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSI_CTRL, 2);
132 msgnum = 1 << ((ctrl & PCIM_MSICTRL_MMC_MASK) >> 1);
133 printf("MSI supports %d message%s%s%s ", msgnum,
134 (msgnum == 1) ? "" : "s",
135 (ctrl & PCIM_MSICTRL_64BIT) ? ", 64 bit" : "",
136 (ctrl & PCIM_MSICTRL_VECTOR) ? ", vector masks" : "");
137 if (ctrl & PCIM_MSICTRL_MSI_ENABLE) {
138 msgnum = 1 << ((ctrl & PCIM_MSICTRL_MME_MASK) >> 4);
139 printf("enabled with %d message%s", msgnum,
140 (msgnum == 1) ? "" : "s");
144 static void
145 cap_pcix(int fd, struct pci_conf *p, uint8_t ptr)
147 uint32_t status;
148 int comma, max_splits, max_burst_read;
150 status = read_config(fd, &p->pc_sel, ptr + PCIXR_STATUS, 4);
151 printf("PCI-X ");
152 if (status & PCIXM_STATUS_64BIT)
153 printf("64-bit ");
154 if ((p->pc_hdr & PCIM_HDRTYPE) == 1)
155 printf("bridge ");
156 if ((p->pc_hdr & PCIM_HDRTYPE) != 1 || (status & (PCIXM_STATUS_133CAP |
157 PCIXM_STATUS_266CAP | PCIXM_STATUS_533CAP)) != 0)
158 printf("supports");
159 comma = 0;
160 if (status & PCIXM_STATUS_133CAP) {
161 printf(" 133MHz");
162 comma = 1;
164 if (status & PCIXM_STATUS_266CAP) {
165 printf("%s 266MHz", comma ? "," : "");
166 comma = 1;
168 if (status & PCIXM_STATUS_533CAP) {
169 printf("%s 533MHz", comma ? "," : "");
170 comma = 1;
172 if ((p->pc_hdr & PCIM_HDRTYPE) == 1)
173 return;
174 max_burst_read = 0;
175 switch (status & PCIXM_STATUS_MAX_READ) {
176 case PCIXM_STATUS_MAX_READ_512:
177 max_burst_read = 512;
178 break;
179 case PCIXM_STATUS_MAX_READ_1024:
180 max_burst_read = 1024;
181 break;
182 case PCIXM_STATUS_MAX_READ_2048:
183 max_burst_read = 2048;
184 break;
185 case PCIXM_STATUS_MAX_READ_4096:
186 max_burst_read = 4096;
187 break;
189 max_splits = 0;
190 switch (status & PCIXM_STATUS_MAX_SPLITS) {
191 case PCIXM_STATUS_MAX_SPLITS_1:
192 max_splits = 1;
193 break;
194 case PCIXM_STATUS_MAX_SPLITS_2:
195 max_splits = 2;
196 break;
197 case PCIXM_STATUS_MAX_SPLITS_3:
198 max_splits = 3;
199 break;
200 case PCIXM_STATUS_MAX_SPLITS_4:
201 max_splits = 4;
202 break;
203 case PCIXM_STATUS_MAX_SPLITS_8:
204 max_splits = 8;
205 break;
206 case PCIXM_STATUS_MAX_SPLITS_12:
207 max_splits = 12;
208 break;
209 case PCIXM_STATUS_MAX_SPLITS_16:
210 max_splits = 16;
211 break;
212 case PCIXM_STATUS_MAX_SPLITS_32:
213 max_splits = 32;
214 break;
216 printf("%s %d burst read, %d split transaction%s", comma ? "," : "",
217 max_burst_read, max_splits, max_splits == 1 ? "" : "s");
220 static void
221 cap_ht(int fd, struct pci_conf *p, uint8_t ptr)
223 uint32_t reg;
224 uint16_t command;
226 command = read_config(fd, &p->pc_sel, ptr + PCIR_HT_COMMAND, 2);
227 printf("HT ");
228 if ((command & 0xe000) == PCIM_HTCAP_SLAVE)
229 printf("slave");
230 else if ((command & 0xe000) == PCIM_HTCAP_HOST)
231 printf("host");
232 else
233 switch (command & PCIM_HTCMD_CAP_MASK) {
234 case PCIM_HTCAP_SWITCH:
235 printf("switch");
236 break;
237 case PCIM_HTCAP_INTERRUPT:
238 printf("interrupt");
239 break;
240 case PCIM_HTCAP_REVISION_ID:
241 printf("revision ID");
242 break;
243 case PCIM_HTCAP_UNITID_CLUMPING:
244 printf("unit ID clumping");
245 break;
246 case PCIM_HTCAP_EXT_CONFIG_SPACE:
247 printf("extended config space");
248 break;
249 case PCIM_HTCAP_ADDRESS_MAPPING:
250 printf("address mapping");
251 break;
252 case PCIM_HTCAP_MSI_MAPPING:
253 printf("MSI %saddress window %s at 0x",
254 command & PCIM_HTCMD_MSI_FIXED ? "fixed " : "",
255 command & PCIM_HTCMD_MSI_ENABLE ? "enabled" :
256 "disabled");
257 if (command & PCIM_HTCMD_MSI_FIXED)
258 printf("fee00000");
259 else {
260 reg = read_config(fd, &p->pc_sel,
261 ptr + PCIR_HTMSI_ADDRESS_HI, 4);
262 if (reg != 0)
263 printf("%08x", reg);
264 reg = read_config(fd, &p->pc_sel,
265 ptr + PCIR_HTMSI_ADDRESS_LO, 4);
266 printf("%08x", reg);
268 break;
269 case PCIM_HTCAP_DIRECT_ROUTE:
270 printf("direct route");
271 break;
272 case PCIM_HTCAP_VCSET:
273 printf("VC set");
274 break;
275 case PCIM_HTCAP_RETRY_MODE:
276 printf("retry mode");
277 break;
278 case PCIM_HTCAP_X86_ENCODING:
279 printf("X86 encoding");
280 break;
281 case PCIM_HTCAP_GEN3:
282 printf("Gen3");
283 break;
284 case PCIM_HTCAP_FLE:
285 printf("function-level extension");
286 break;
287 case PCIM_HTCAP_PM:
288 printf("power management");
289 break;
290 case PCIM_HTCAP_HIGH_NODE_COUNT:
291 printf("high node count");
292 break;
293 default:
294 printf("unknown %02x", command);
295 break;
299 static void
300 cap_vendor(int fd, struct pci_conf *p, uint8_t ptr)
302 uint8_t length;
304 length = read_config(fd, &p->pc_sel, ptr + PCIR_VENDOR_LENGTH, 1);
305 printf("vendor (length %d)", length);
306 if (p->pc_vendor == 0x8086) {
307 /* Intel */
308 uint8_t version;
310 version = read_config(fd, &p->pc_sel, ptr + PCIR_VENDOR_DATA,
312 printf(" Intel cap %d version %d", version >> 4, version & 0xf);
313 if (version >> 4 == 1 && length == 12) {
314 /* Feature Detection */
315 uint32_t fvec;
316 int comma;
318 comma = 0;
319 fvec = read_config(fd, &p->pc_sel, ptr +
320 PCIR_VENDOR_DATA + 5, 4);
321 printf("\n\t\t features:");
322 if (fvec & (1 << 0)) {
323 printf(" AMT");
324 comma = 1;
326 fvec = read_config(fd, &p->pc_sel, ptr +
327 PCIR_VENDOR_DATA + 1, 4);
328 if (fvec & (1 << 21)) {
329 printf("%s Quick Resume", comma ? "," : "");
330 comma = 1;
332 if (fvec & (1 << 18)) {
333 printf("%s SATA RAID-5", comma ? "," : "");
334 comma = 1;
336 if (fvec & (1 << 9)) {
337 printf("%s Mobile", comma ? "," : "");
338 comma = 1;
340 if (fvec & (1 << 7)) {
341 printf("%s 6 PCI-e x1 slots", comma ? "," : "");
342 comma = 1;
343 } else {
344 printf("%s 4 PCI-e x1 slots", comma ? "," : "");
345 comma = 1;
347 if (fvec & (1 << 5)) {
348 printf("%s SATA RAID-0/1/10", comma ? "," : "");
349 comma = 1;
351 if (fvec & (1 << 3))
352 printf(", SATA AHCI");
357 static void
358 cap_debug(int fd, struct pci_conf *p, uint8_t ptr)
360 uint16_t debug_port;
362 debug_port = read_config(fd, &p->pc_sel, ptr + PCIR_DEBUG_PORT, 2);
363 printf("EHCI Debug Port at offset 0x%x in map 0x%x", debug_port &
364 PCIM_DEBUG_PORT_OFFSET, PCIR_BAR(debug_port >> 13));
367 static void
368 cap_subvendor(int fd, struct pci_conf *p, uint8_t ptr)
370 uint32_t id;
371 uint16_t ssid, ssvid;
373 id = read_config(fd, &p->pc_sel, ptr + PCIR_SUBVENDCAP_ID, 4);
374 ssid = id >> 16;
375 ssvid = id & 0xffff;
376 printf("PCI Bridge subvendor=0x%04x subdevice=0x%04x", ssvid, ssid);
379 static const char *
380 cap_secdev_amdiommu_decode_vasize(uint32_t misc0)
382 switch (misc0 & PCIM_AMDIOMMU_MISC0_VASIZE_MASK) {
383 case PCIM_AMDIOMMU_MISC0_VASIZE_32:
384 return ("32bit");
385 case PCIM_AMDIOMMU_MISC0_VASIZE_40:
386 return ("40bit");
387 case PCIM_AMDIOMMU_MISC0_VASIZE_48:
388 return ("48bit");
389 case PCIM_AMDIOMMU_MISC0_VASIZE_64:
390 return ("64bit");
391 default:
392 return ("unknown");
396 static const char *
397 cap_secdev_amdiommu_decode_pasize(uint32_t misc0)
399 switch (misc0 & PCIM_AMDIOMMU_MISC0_PASIZE_MASK) {
400 case PCIM_AMDIOMMU_MISC0_PASIZE_40:
401 return ("40bit");
402 case PCIM_AMDIOMMU_MISC0_PASIZE_48:
403 return ("48bit");
404 case PCIM_AMDIOMMU_MISC0_PASIZE_52:
405 return ("52bit");
406 default:
407 return ("unknown");
411 static const char *
412 cap_secdev_amdiommu_decode_gvasize(uint32_t misc0)
414 switch (misc0 & PCIM_AMDIOMMU_MISC0_GVASIZE_MASK) {
415 case PCIM_AMDIOMMU_MISC0_GVASIZE_48:
416 return ("48bit");
417 case PCIM_AMDIOMMU_MISC0_GVASIZE_57:
418 return ("57bit");
419 default:
420 return ("unknown");
424 static void
425 cap_secdev(int fd, struct pci_conf *p, uint8_t ptr)
427 uint32_t cap_h;
428 uint32_t cap_type, cap_rev;
429 uint32_t base_low, base_high;
430 uint32_t range;
431 uint32_t misc0, misc1;
432 const char *delim;
434 cap_h = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_CAP_HEADER, 4);
435 cap_type = cap_h & PCIM_AMDIOMMU_CAP_TYPE_MASK;
436 cap_rev = cap_h & PCIM_AMDIOMMU_CAP_REV_MASK;
437 if (cap_type != PCIM_AMDIOMMU_CAP_TYPE_VAL ||
438 cap_rev != PCIM_AMDIOMMU_CAP_REV_VAL) {
439 printf("Secure Device Type=0x%1x Rev=0x%02x\n",
440 cap_type >> 16, cap_rev >> 19);
441 return;
443 base_low = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_BASE_LOW,
445 base_high = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_BASE_HIGH,
447 printf("AMD IOMMU Base Capability Base=%#018jx/%sabled",
448 (uintmax_t)(base_low & PCIM_AMDIOMMU_BASE_LOW_ADDRM) +
449 ((uintmax_t)base_high << 32),
450 (base_low & PCIM_AMDIOMMU_BASE_LOW_EN) != 0 ? "En" : "Dis");
452 delim = "\n\t\t";
453 #define PRINTCAP(bit, name) \
454 if ((cap_h & PCIM_AMDIOMMU_CAP_ ##bit) != 0) { \
455 printf("%s%s", delim, #name); \
456 delim = ","; \
458 PRINTCAP(CAPEXT, CapExt);
459 PRINTCAP(EFR, EFRSup);
460 PRINTCAP(NPCACHE, NpCache);
461 PRINTCAP(HTTUN, HtTunnel);
462 PRINTCAP(IOTLB, IotlbSup);
463 #undef PRINTCAP
465 range = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_RANGE, 4);
466 printf("\n\t\tUnitId=%d", range & PCIM_AMDIOMMU_RANGE_UNITID_MASK);
467 if ((range & PCIM_AMDIOMMU_RANGE_RNGVALID) != 0) {
468 printf(" BusNum=%#06x FirstDev=%#06x LastDev=%#06x",
469 (range & PCIM_AMDIOMMU_RANGE_BUSNUM_MASK) >> 8,
470 (range & PCIM_AMDIOMMU_RANGE_FIRSTDEV_MASK) >> 16,
471 (range & PCIM_AMDIOMMU_RANGE_LASTDEV_MASK) >> 24);
474 misc0 = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_MISC0, 4);
475 printf("\n\t\tMsiNum=%d MsiNumPPR=%d HtAtsResv=%d",
476 misc0 & PCIM_AMDIOMMU_MISC0_MSINUM_MASK,
477 (misc0 & PCIM_AMDIOMMU_MISC0_MSINUMPPR_MASK) >> 27,
478 (misc0 & PCIM_AMDIOMMU_MISC0_HTATSRESV) != 0);
479 if ((cap_h & PCIM_AMDIOMMU_CAP_CAPEXT) != 0) {
480 misc1 = read_config(fd, &p->pc_sel,
481 ptr + PCIR_AMDIOMMU_MISC1, 4);
482 printf(" MsiNumGA=%d",
483 misc1 & PCIM_AMDIOMMU_MISC1_MSINUMGA_MASK);
485 printf("\n\t\tVAsize=%s PAsize=%s GVAsize=%s",
486 cap_secdev_amdiommu_decode_vasize(misc0),
487 cap_secdev_amdiommu_decode_pasize(misc0),
488 cap_secdev_amdiommu_decode_gvasize(misc0));
491 #define MAX_PAYLOAD(field) (128 << (field))
493 static const char *
494 link_speed_string(uint8_t speed)
497 switch (speed) {
498 case 1:
499 return ("2.5");
500 case 2:
501 return ("5.0");
502 case 3:
503 return ("8.0");
504 case 4:
505 return ("16.0");
506 case 5:
507 return ("32.0");
508 case 6:
509 return ("64.0");
510 default:
511 return ("undef");
515 static const char *
516 max_read_string(u_int max_read)
519 switch (max_read) {
520 case 0x0:
521 return ("128");
522 case 0x1:
523 return ("256");
524 case 0x2:
525 return ("512");
526 case 0x3:
527 return ("1024");
528 case 0x4:
529 return ("2048");
530 case 0x5:
531 return ("4096");
532 default:
533 return ("undef");
537 static const char *
538 aspm_string(uint8_t aspm)
541 switch (aspm) {
542 case 1:
543 return ("L0s");
544 case 2:
545 return ("L1");
546 case 3:
547 return ("L0s/L1");
548 default:
549 return ("disabled");
553 static int
554 slot_power(uint32_t cap)
556 int mwatts;
558 mwatts = (cap & PCIEM_SLOT_CAP_SPLV) >> 7;
559 switch (cap & PCIEM_SLOT_CAP_SPLS) {
560 case 0x0:
561 mwatts *= 1000;
562 break;
563 case 0x1:
564 mwatts *= 100;
565 break;
566 case 0x2:
567 mwatts *= 10;
568 break;
569 default:
570 break;
572 return (mwatts);
575 static void
576 cap_express(int fd, struct pci_conf *p, uint8_t ptr)
578 uint32_t cap;
579 uint16_t ctl, flags, sta;
580 unsigned int version;
582 flags = read_config(fd, &p->pc_sel, ptr + PCIER_FLAGS, 2);
583 version = flags & PCIEM_FLAGS_VERSION;
584 printf("PCI-Express %u ", version);
585 switch (flags & PCIEM_FLAGS_TYPE) {
586 case PCIEM_TYPE_ENDPOINT:
587 printf("endpoint");
588 break;
589 case PCIEM_TYPE_LEGACY_ENDPOINT:
590 printf("legacy endpoint");
591 break;
592 case PCIEM_TYPE_ROOT_PORT:
593 printf("root port");
594 break;
595 case PCIEM_TYPE_UPSTREAM_PORT:
596 printf("upstream port");
597 break;
598 case PCIEM_TYPE_DOWNSTREAM_PORT:
599 printf("downstream port");
600 break;
601 case PCIEM_TYPE_PCI_BRIDGE:
602 printf("PCI bridge");
603 break;
604 case PCIEM_TYPE_PCIE_BRIDGE:
605 printf("PCI to PCIe bridge");
606 break;
607 case PCIEM_TYPE_ROOT_INT_EP:
608 printf("root endpoint");
609 break;
610 case PCIEM_TYPE_ROOT_EC:
611 printf("event collector");
612 break;
613 default:
614 printf("type %d", (flags & PCIEM_FLAGS_TYPE) >> 4);
615 break;
617 if (flags & PCIEM_FLAGS_IRQ)
618 printf(" MSI %d", (flags & PCIEM_FLAGS_IRQ) >> 9);
619 cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP, 4);
620 ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL, 2);
621 printf(" max data %d(%d)",
622 MAX_PAYLOAD((ctl & PCIEM_CTL_MAX_PAYLOAD) >> 5),
623 MAX_PAYLOAD(cap & PCIEM_CAP_MAX_PAYLOAD));
624 if ((cap & PCIEM_CAP_FLR) != 0)
625 printf(" FLR");
626 if (ctl & PCIEM_CTL_RELAXED_ORD_ENABLE)
627 printf(" RO");
628 if (ctl & PCIEM_CTL_NOSNOOP_ENABLE)
629 printf(" NS");
630 if (version >= 2) {
631 cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP2, 4);
632 if ((cap & PCIEM_CAP2_ARI) != 0) {
633 ctl = read_config(fd, &p->pc_sel,
634 ptr + PCIER_DEVICE_CTL2, 4);
635 printf(" ARI %s",
636 (ctl & PCIEM_CTL2_ARI) ? "enabled" : "disabled");
639 printf("\n max read %s", max_read_string((ctl &
640 PCIEM_CTL_MAX_READ_REQUEST) >> 12));
641 cap = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CAP, 4);
642 sta = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_STA, 2);
643 if (cap == 0 && sta == 0)
644 return;
645 printf("\n ");
646 printf(" link x%d(x%d)", (sta & PCIEM_LINK_STA_WIDTH) >> 4,
647 (cap & PCIEM_LINK_CAP_MAX_WIDTH) >> 4);
648 if ((cap & PCIEM_LINK_CAP_MAX_WIDTH) != 0) {
649 printf(" speed %s(%s)", (sta & PCIEM_LINK_STA_WIDTH) == 0 ?
650 "0.0" : link_speed_string(sta & PCIEM_LINK_STA_SPEED),
651 link_speed_string(cap & PCIEM_LINK_CAP_MAX_SPEED));
653 if ((cap & PCIEM_LINK_CAP_ASPM) != 0) {
654 ctl = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CTL, 2);
655 printf(" ASPM %s(%s)", aspm_string(ctl & PCIEM_LINK_CTL_ASPMC),
656 aspm_string((cap & PCIEM_LINK_CAP_ASPM) >> 10));
658 if ((cap & PCIEM_LINK_CAP_CLOCK_PM) != 0) {
659 ctl = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CTL, 2);
660 printf(" ClockPM %s", (ctl & PCIEM_LINK_CTL_ECPM) ?
661 "enabled" : "disabled");
663 if (!(flags & PCIEM_FLAGS_SLOT))
664 return;
665 cap = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_CAP, 4);
666 sta = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_STA, 2);
667 ctl = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_CTL, 2);
668 printf("\n ");
669 printf(" slot %d", (cap & PCIEM_SLOT_CAP_PSN) >> 19);
670 printf(" power limit %d mW", slot_power(cap));
671 if (cap & PCIEM_SLOT_CAP_HPC)
672 printf(" HotPlug(%s)", sta & PCIEM_SLOT_STA_PDS ? "present" :
673 "empty");
674 if (cap & PCIEM_SLOT_CAP_HPS)
675 printf(" surprise");
676 if (cap & PCIEM_SLOT_CAP_APB)
677 printf(" Attn Button");
678 if (cap & PCIEM_SLOT_CAP_PCP)
679 printf(" PC(%s)", ctl & PCIEM_SLOT_CTL_PCC ? "off" : "on");
680 if (cap & PCIEM_SLOT_CAP_MRLSP)
681 printf(" MRL(%s)", sta & PCIEM_SLOT_STA_MRLSS ? "open" :
682 "closed");
683 if (cap & PCIEM_SLOT_CAP_EIP)
684 printf(" EI(%s)", sta & PCIEM_SLOT_STA_EIS ? "engaged" :
685 "disengaged");
688 static void
689 cap_msix(int fd, struct pci_conf *p, uint8_t ptr)
691 uint32_t pba_offset, table_offset, val;
692 int msgnum, pba_bar, table_bar;
693 uint16_t ctrl;
695 ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_CTRL, 2);
696 msgnum = (ctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1;
698 val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_TABLE, 4);
699 table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
700 table_offset = val & ~PCIM_MSIX_BIR_MASK;
702 val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_PBA, 4);
703 pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
704 pba_offset = val & ~PCIM_MSIX_BIR_MASK;
706 printf("MSI-X supports %d message%s%s\n", msgnum,
707 (msgnum == 1) ? "" : "s",
708 (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE) ? ", enabled" : "");
710 printf(" ");
711 printf("Table in map 0x%x[0x%x], PBA in map 0x%x[0x%x]",
712 table_bar, table_offset, pba_bar, pba_offset);
715 static void
716 cap_sata(int fd __unused, struct pci_conf *p __unused, uint8_t ptr __unused)
719 printf("SATA Index-Data Pair");
722 static void
723 cap_pciaf(int fd, struct pci_conf *p, uint8_t ptr)
725 uint8_t cap;
727 cap = read_config(fd, &p->pc_sel, ptr + PCIR_PCIAF_CAP, 1);
728 printf("PCI Advanced Features:%s%s",
729 cap & PCIM_PCIAFCAP_FLR ? " FLR" : "",
730 cap & PCIM_PCIAFCAP_TP ? " TP" : "");
733 static const char *
734 ea_bei_to_name(int bei)
736 static const char *barstr[] = {
737 "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5"
739 static const char *vfbarstr[] = {
740 "VFBAR0", "VFBAR1", "VFBAR2", "VFBAR3", "VFBAR4", "VFBAR5"
743 if ((bei >= PCIM_EA_BEI_BAR_0) && (bei <= PCIM_EA_BEI_BAR_5))
744 return (barstr[bei - PCIM_EA_BEI_BAR_0]);
745 if ((bei >= PCIM_EA_BEI_VF_BAR_0) && (bei <= PCIM_EA_BEI_VF_BAR_5))
746 return (vfbarstr[bei - PCIM_EA_BEI_VF_BAR_0]);
748 switch (bei) {
749 case PCIM_EA_BEI_BRIDGE:
750 return "BRIDGE";
751 case PCIM_EA_BEI_ENI:
752 return "ENI";
753 case PCIM_EA_BEI_ROM:
754 return "ROM";
755 case PCIM_EA_BEI_RESERVED:
756 default:
757 return "RSVD";
761 static const char *
762 ea_prop_to_name(uint8_t prop)
765 switch (prop) {
766 case PCIM_EA_P_MEM:
767 return "Non-Prefetchable Memory";
768 case PCIM_EA_P_MEM_PREFETCH:
769 return "Prefetchable Memory";
770 case PCIM_EA_P_IO:
771 return "I/O Space";
772 case PCIM_EA_P_VF_MEM_PREFETCH:
773 return "VF Prefetchable Memory";
774 case PCIM_EA_P_VF_MEM:
775 return "VF Non-Prefetchable Memory";
776 case PCIM_EA_P_BRIDGE_MEM:
777 return "Bridge Non-Prefetchable Memory";
778 case PCIM_EA_P_BRIDGE_MEM_PREFETCH:
779 return "Bridge Prefetchable Memory";
780 case PCIM_EA_P_BRIDGE_IO:
781 return "Bridge I/O Space";
782 case PCIM_EA_P_MEM_RESERVED:
783 return "Reserved Memory";
784 case PCIM_EA_P_IO_RESERVED:
785 return "Reserved I/O Space";
786 case PCIM_EA_P_UNAVAILABLE:
787 return "Unavailable";
788 default:
789 return "Reserved";
793 static void
794 cap_ea(int fd, struct pci_conf *p, uint8_t ptr)
796 int num_ent;
797 int a, b;
798 uint32_t bei;
799 uint32_t val;
800 int ent_size;
801 uint32_t dw[4];
802 uint32_t flags, flags_pp, flags_sp;
803 uint64_t base, max_offset;
804 uint8_t fixed_sub_bus_nr, fixed_sec_bus_nr;
806 /* Determine the number of entries */
807 num_ent = read_config(fd, &p->pc_sel, ptr + PCIR_EA_NUM_ENT, 2);
808 num_ent &= PCIM_EA_NUM_ENT_MASK;
810 printf("PCI Enhanced Allocation (%d entries)", num_ent);
812 /* Find the first entry to care of */
813 ptr += PCIR_EA_FIRST_ENT;
815 /* Print BUS numbers for bridges */
816 if ((p->pc_hdr & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) {
817 val = read_config(fd, &p->pc_sel, ptr, 4);
819 fixed_sec_bus_nr = PCIM_EA_SEC_NR(val);
820 fixed_sub_bus_nr = PCIM_EA_SUB_NR(val);
822 printf("\n\t\t BRIDGE, sec bus [%d], sub bus [%d]",
823 fixed_sec_bus_nr, fixed_sub_bus_nr);
824 ptr += 4;
827 for (a = 0; a < num_ent; a++) {
828 /* Read a number of dwords in the entry */
829 val = read_config(fd, &p->pc_sel, ptr, 4);
830 ptr += 4;
831 ent_size = (val & PCIM_EA_ES);
833 for (b = 0; b < ent_size; b++) {
834 dw[b] = read_config(fd, &p->pc_sel, ptr, 4);
835 ptr += 4;
838 flags = val;
839 flags_pp = (flags & PCIM_EA_PP) >> PCIM_EA_PP_OFFSET;
840 flags_sp = (flags & PCIM_EA_SP) >> PCIM_EA_SP_OFFSET;
841 bei = (PCIM_EA_BEI & val) >> PCIM_EA_BEI_OFFSET;
843 base = dw[0] & PCIM_EA_FIELD_MASK;
844 max_offset = dw[1] | ~PCIM_EA_FIELD_MASK;
845 b = 2;
846 if (((dw[0] & PCIM_EA_IS_64) != 0) && (b < ent_size)) {
847 base |= (uint64_t)dw[b] << 32UL;
848 b++;
850 if (((dw[1] & PCIM_EA_IS_64) != 0)
851 && (b < ent_size)) {
852 max_offset |= (uint64_t)dw[b] << 32UL;
853 b++;
856 printf("\n\t\t [%d] %s, %s, %s, base [0x%jx], size [0x%jx]"
857 "\n\t\t\tPrimary properties [0x%x] (%s)"
858 "\n\t\t\tSecondary properties [0x%x] (%s)",
859 bei, ea_bei_to_name(bei),
860 (flags & PCIM_EA_ENABLE ? "Enabled" : "Disabled"),
861 (flags & PCIM_EA_WRITABLE ? "Writable" : "Read-only"),
862 (uintmax_t)base, (uintmax_t)(max_offset + 1),
863 flags_pp, ea_prop_to_name(flags_pp),
864 flags_sp, ea_prop_to_name(flags_sp));
868 void
869 list_caps(int fd, struct pci_conf *p, int level)
871 int express;
872 uint16_t sta;
873 uint8_t ptr, cap;
875 /* Are capabilities present for this device? */
876 sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2);
877 if (!(sta & PCIM_STATUS_CAPPRESENT))
878 return;
880 cap_level = level;
882 switch (p->pc_hdr & PCIM_HDRTYPE) {
883 case PCIM_HDRTYPE_NORMAL:
884 case PCIM_HDRTYPE_BRIDGE:
885 ptr = PCIR_CAP_PTR;
886 break;
887 case PCIM_HDRTYPE_CARDBUS:
888 ptr = PCIR_CAP_PTR_2;
889 break;
890 default:
891 errx(1, "list_caps: bad header type");
894 /* Walk the capability list. */
895 express = 0;
896 ptr = read_config(fd, &p->pc_sel, ptr, 1);
897 while (ptr != 0 && ptr != 0xff) {
898 cap = read_config(fd, &p->pc_sel, ptr + PCICAP_ID, 1);
899 printf(" cap %02x[%02x] = ", cap, ptr);
900 switch (cap) {
901 case PCIY_PMG:
902 cap_power(fd, p, ptr);
903 break;
904 case PCIY_AGP:
905 cap_agp(fd, p, ptr);
906 break;
907 case PCIY_VPD:
908 cap_vpd(fd, p, ptr);
909 break;
910 case PCIY_MSI:
911 cap_msi(fd, p, ptr);
912 break;
913 case PCIY_PCIX:
914 cap_pcix(fd, p, ptr);
915 break;
916 case PCIY_HT:
917 cap_ht(fd, p, ptr);
918 break;
919 case PCIY_VENDOR:
920 cap_vendor(fd, p, ptr);
921 break;
922 case PCIY_DEBUG:
923 cap_debug(fd, p, ptr);
924 break;
925 case PCIY_SUBVENDOR:
926 cap_subvendor(fd, p, ptr);
927 break;
928 case PCIY_SECDEV:
929 cap_secdev(fd, p, ptr);
930 break;
931 case PCIY_EXPRESS:
932 express = 1;
933 cap_express(fd, p, ptr);
934 break;
935 case PCIY_MSIX:
936 cap_msix(fd, p, ptr);
937 break;
938 case PCIY_SATA:
939 cap_sata(fd, p, ptr);
940 break;
941 case PCIY_PCIAF:
942 cap_pciaf(fd, p, ptr);
943 break;
944 case PCIY_EA:
945 cap_ea(fd, p, ptr);
946 break;
947 default:
948 printf("unknown");
949 break;
951 printf("\n");
952 ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1);
955 if (express)
956 list_ecaps(fd, p);
959 /* From <sys/systm.h>. */
960 static __inline uint32_t
961 bitcount32(uint32_t x)
964 x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1);
965 x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2);
966 x = (x + (x >> 4)) & 0x0f0f0f0f;
967 x = (x + (x >> 8));
968 x = (x + (x >> 16)) & 0x000000ff;
969 return (x);
972 static void
973 ecap_aer(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
975 uint32_t sta, mask;
977 printf("AER %d", ver);
978 if (ver < 1) {
979 printf("\n");
980 return;
982 sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_STATUS, 4);
983 mask = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_SEVERITY, 4);
984 printf(" %d fatal", bitcount32(sta & mask));
985 printf(" %d non-fatal", bitcount32(sta & ~mask));
986 sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_COR_STATUS, 4);
987 printf(" %d corrected\n", bitcount32(sta));
990 static void
991 ecap_vc(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
993 uint32_t cap1;
995 printf("VC %d", ver);
996 if (ver < 1) {
997 printf("\n");
998 return;
1000 cap1 = read_config(fd, &p->pc_sel, ptr + PCIR_VC_CAP1, 4);
1001 printf(" max VC%d", cap1 & PCIM_VC_CAP1_EXT_COUNT);
1002 if ((cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) != 0)
1003 printf(" lowpri VC0-VC%d",
1004 (cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) >> 4);
1005 printf("\n");
1008 static void
1009 ecap_sernum(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1011 uint32_t high, low;
1013 printf("Serial %d", ver);
1014 if (ver < 1) {
1015 printf("\n");
1016 return;
1018 low = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_LOW, 4);
1019 high = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_HIGH, 4);
1020 printf(" %08x%08x\n", high, low);
1023 static void
1024 ecap_vendor(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1026 uint32_t val, hdr;
1027 uint16_t nextptr, len;
1028 int i;
1030 val = read_config(fd, &p->pc_sel, ptr, 4);
1031 nextptr = PCI_EXTCAP_NEXTPTR(val);
1032 hdr = read_config(fd, &p->pc_sel, ptr + PCIR_VSEC_HEADER, 4);
1033 len = PCIR_VSEC_LENGTH(hdr);
1034 if (len == 0) {
1035 if (nextptr == 0)
1036 nextptr = 0x1000;
1037 len = nextptr - ptr;
1040 printf("Vendor [%d] ID %04x Rev %d Length %d\n", ver,
1041 PCIR_VSEC_ID(hdr), PCIR_VSEC_REV(hdr), len);
1042 if ((ver < 1) || (cap_level <= 1))
1043 return;
1044 for (i = 0; i < len; i += 4) {
1045 val = read_config(fd, &p->pc_sel, ptr + i, 4);
1046 if ((i % 16) == 0)
1047 printf(" ");
1048 printf("%02x %02x %02x %02x", val & 0xff, (val >> 8) & 0xff,
1049 (val >> 16) & 0xff, (val >> 24) & 0xff);
1050 if ((((i + 4) % 16) == 0 ) || ((i + 4) >= len))
1051 printf("\n");
1052 else
1053 printf(" ");
1057 static void
1058 ecap_sec_pcie(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1060 uint32_t val;
1062 printf("PCIe Sec %d", ver);
1063 if (ver < 1) {
1064 printf("\n");
1065 return;
1067 val = read_config(fd, &p->pc_sel, ptr + 8, 4);
1068 printf(" lane errors %#x\n", val);
1071 static const char *
1072 check_enabled(int value)
1075 return (value ? "enabled" : "disabled");
1078 static void
1079 ecap_sriov(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1081 const char *comma, *enabled;
1082 uint16_t iov_ctl, total_vfs, num_vfs, vf_offset, vf_stride, vf_did;
1083 uint32_t page_caps, page_size, page_shift, size;
1084 int i;
1086 printf("SR-IOV %d ", ver);
1088 iov_ctl = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_CTL, 2);
1089 printf("IOV %s, Memory Space %s, ARI %s\n",
1090 check_enabled(iov_ctl & PCIM_SRIOV_VF_EN),
1091 check_enabled(iov_ctl & PCIM_SRIOV_VF_MSE),
1092 check_enabled(iov_ctl & PCIM_SRIOV_ARI_EN));
1094 total_vfs = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_TOTAL_VFS, 2);
1095 num_vfs = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_NUM_VFS, 2);
1096 printf(" ");
1097 printf("%d VFs configured out of %d supported\n", num_vfs, total_vfs);
1099 vf_offset = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_VF_OFF, 2);
1100 vf_stride = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_VF_STRIDE, 2);
1101 printf(" ");
1102 printf("First VF RID Offset 0x%04x, VF RID Stride 0x%04x\n", vf_offset,
1103 vf_stride);
1105 vf_did = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_VF_DID, 2);
1106 printf(" VF Device ID 0x%04x\n", vf_did);
1108 page_caps = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_PAGE_CAP, 4);
1109 page_size = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_PAGE_SIZE, 4);
1110 printf(" ");
1111 printf("Page Sizes: ");
1112 comma = "";
1113 while (page_caps != 0) {
1114 page_shift = ffs(page_caps) - 1;
1116 if (page_caps & page_size)
1117 enabled = " (enabled)";
1118 else
1119 enabled = "";
1121 size = (1 << (page_shift + PCI_SRIOV_BASE_PAGE_SHIFT));
1122 printf("%s%d%s", comma, size, enabled);
1123 comma = ", ";
1125 page_caps &= ~(1 << page_shift);
1127 printf("\n");
1129 for (i = 0; i <= PCIR_MAX_BAR_0; i++)
1130 print_bar(fd, p, "iov bar ", ptr + PCIR_SRIOV_BAR(i));
1133 static const char *
1134 check_avail_and_state(u_int cap, u_int capbit, u_int ctl, u_int ctlbit)
1137 if (cap & capbit)
1138 return (ctl & ctlbit ? "enabled" : "disabled");
1139 else
1140 return "unavailable";
1143 static void
1144 ecap_acs(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1146 uint16_t acs_cap, acs_ctl;
1147 static const char *const acc[] = { "access enabled", "blocking enabled",
1148 "redirect enabled", "reserved" };
1150 printf("ACS %d ", ver);
1151 if (ver != 1) {
1152 printf("\n");
1153 return;
1156 #define CHECK_AVAIL_STATE(bit) \
1157 check_avail_and_state(acs_cap, bit, acs_ctl, bit##_ENABLE)
1159 acs_cap = read_config(fd, &p->pc_sel, ptr + PCIR_ACS_CAP, 2);
1160 acs_ctl = read_config(fd, &p->pc_sel, ptr + PCIR_ACS_CTL, 2);
1161 printf("Source Validation %s, Translation Blocking %s\n",
1162 CHECK_AVAIL_STATE(PCIM_ACS_SOURCE_VALIDATION),
1163 CHECK_AVAIL_STATE(PCIM_ACS_TRANSLATION_BLOCKING));
1165 printf(" ");
1166 printf("P2P Req Redirect %s, P2P Cmpl Redirect %s\n",
1167 CHECK_AVAIL_STATE(PCIM_ACS_P2P_REQ_REDIRECT),
1168 CHECK_AVAIL_STATE(PCIM_ACS_P2P_CMP_REDIRECT));
1169 printf(" ");
1170 printf("P2P Upstream Forwarding %s, P2P Egress Control %s\n",
1171 CHECK_AVAIL_STATE(PCIM_ACS_P2P_UPSTREAM_FORWARDING),
1172 CHECK_AVAIL_STATE(PCIM_ACS_P2P_EGRESS_CTL));
1173 printf(" ");
1174 printf("P2P Direct Translated %s, Enhanced Capability %s\n",
1175 CHECK_AVAIL_STATE(PCIM_ACS_P2P_DIRECT_TRANSLATED),
1176 acs_ctl & PCIM_ACS_ENHANCED_CAP ? "available" : "unavailable");
1177 #undef CHECK_AVAIL_STATE
1179 if (acs_cap & PCIM_ACS_ENHANCED_CAP) {
1180 printf(" ");
1181 printf("I/O Req Blocking %s, Unclaimed Req Redirect Control %s\n",
1182 check_enabled(acs_ctl & PCIM_ACS_IO_REQ_BLOCKING_ENABLE),
1183 check_enabled(acs_ctl & PCIM_ACS_UNCLAIMED_REQ_REDIRECT_CTL));
1184 printf(" ");
1185 printf("DSP BAR %s, USP BAR %s\n",
1186 acc[(acs_cap & PCIM_ACS_DSP_MEM_TGT_ACC_CTL) >> 8],
1187 acc[(acs_cap & PCIM_ACS_USP_MEM_TGT_ACC_CTL) >> 10]);
1191 static struct {
1192 uint16_t id;
1193 const char *name;
1194 } ecap_names[] = {
1195 { PCIZ_AER, "AER" },
1196 { PCIZ_VC, "Virtual Channel" },
1197 { PCIZ_SERNUM, "Device Serial Number" },
1198 { PCIZ_PWRBDGT, "Power Budgeting" },
1199 { PCIZ_RCLINK_DCL, "Root Complex Link Declaration" },
1200 { PCIZ_RCLINK_CTL, "Root Complex Internal Link Control" },
1201 { PCIZ_RCEC_ASSOC, "Root Complex Event Collector ASsociation" },
1202 { PCIZ_MFVC, "MFVC" },
1203 { PCIZ_VC2, "Virtual Channel 2" },
1204 { PCIZ_RCRB, "RCRB" },
1205 { PCIZ_CAC, "Configuration Access Correction" },
1206 { PCIZ_ACS, "ACS" },
1207 { PCIZ_ARI, "ARI" },
1208 { PCIZ_ATS, "ATS" },
1209 { PCIZ_SRIOV, "SRIOV" },
1210 { PCIZ_MRIOV, "MRIOV" },
1211 { PCIZ_MULTICAST, "Multicast" },
1212 { PCIZ_PAGE_REQ, "Page Page Request" },
1213 { PCIZ_AMD, "AMD proprietary "},
1214 { PCIZ_RESIZE_BAR, "Resizable BAR" },
1215 { PCIZ_DPA, "DPA" },
1216 { PCIZ_TPH_REQ, "TPH Requester" },
1217 { PCIZ_LTR, "LTR" },
1218 { PCIZ_SEC_PCIE, "Secondary PCI Express" },
1219 { PCIZ_PMUX, "Protocol Multiplexing" },
1220 { PCIZ_PASID, "Process Address Space ID" },
1221 { PCIZ_LN_REQ, "LN Requester" },
1222 { PCIZ_DPC, "Downstream Port Containment" },
1223 { PCIZ_L1PM, "L1 PM Substates" },
1224 { PCIZ_PTM, "Precision Time Measurement" },
1225 { PCIZ_M_PCIE, "PCIe over M-PHY" },
1226 { PCIZ_FRS, "FRS Queuing" },
1227 { PCIZ_RTR, "Readiness Time Reporting" },
1228 { PCIZ_DVSEC, "Designated Vendor-Specific" },
1229 { PCIZ_VF_REBAR, "VF Resizable BAR" },
1230 { PCIZ_DLNK, "Data Link Feature" },
1231 { PCIZ_16GT, "Physical Layer 16.0 GT/s" },
1232 { PCIZ_LMR, "Lane Margining at Receiver" },
1233 { PCIZ_HIER_ID, "Hierarchy ID" },
1234 { PCIZ_NPEM, "Native PCIe Enclosure Management" },
1235 { PCIZ_PL32, "Physical Layer 32.0 GT/s" },
1236 { PCIZ_AP, "Alternate Protocol" },
1237 { PCIZ_SFI, "System Firmware Intermediary" },
1238 { 0, NULL }
1241 static void
1242 list_ecaps(int fd, struct pci_conf *p)
1244 const char *name;
1245 uint32_t ecap;
1246 uint16_t ptr;
1247 int i;
1249 ptr = PCIR_EXTCAP;
1250 ecap = read_config(fd, &p->pc_sel, ptr, 4);
1251 if (ecap == 0xffffffff || ecap == 0)
1252 return;
1253 for (;;) {
1254 printf(" ecap %04x[%03x] = ", PCI_EXTCAP_ID(ecap), ptr);
1255 switch (PCI_EXTCAP_ID(ecap)) {
1256 case PCIZ_AER:
1257 ecap_aer(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1258 break;
1259 case PCIZ_VC:
1260 ecap_vc(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1261 break;
1262 case PCIZ_SERNUM:
1263 ecap_sernum(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1264 break;
1265 case PCIZ_VENDOR:
1266 ecap_vendor(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1267 break;
1268 case PCIZ_SEC_PCIE:
1269 ecap_sec_pcie(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1270 break;
1271 case PCIZ_SRIOV:
1272 ecap_sriov(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1273 break;
1274 case PCIZ_ACS:
1275 ecap_acs(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1276 break;
1277 default:
1278 name = "unknown";
1279 for (i = 0; ecap_names[i].name != NULL; i++)
1280 if (ecap_names[i].id == PCI_EXTCAP_ID(ecap)) {
1281 name = ecap_names[i].name;
1282 break;
1284 printf("%s %d\n", name, PCI_EXTCAP_VER(ecap));
1285 break;
1287 ptr = PCI_EXTCAP_NEXTPTR(ecap);
1288 if (ptr == 0)
1289 break;
1290 ecap = read_config(fd, &p->pc_sel, ptr, 4);
1294 /* Find offset of a specific capability. Returns 0 on failure. */
1295 uint8_t
1296 pci_find_cap(int fd, struct pci_conf *p, uint8_t id)
1298 uint16_t sta;
1299 uint8_t ptr, cap;
1301 /* Are capabilities present for this device? */
1302 sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2);
1303 if (!(sta & PCIM_STATUS_CAPPRESENT))
1304 return (0);
1306 switch (p->pc_hdr & PCIM_HDRTYPE) {
1307 case PCIM_HDRTYPE_NORMAL:
1308 case PCIM_HDRTYPE_BRIDGE:
1309 ptr = PCIR_CAP_PTR;
1310 break;
1311 case PCIM_HDRTYPE_CARDBUS:
1312 ptr = PCIR_CAP_PTR_2;
1313 break;
1314 default:
1315 return (0);
1318 ptr = read_config(fd, &p->pc_sel, ptr, 1);
1319 while (ptr != 0 && ptr != 0xff) {
1320 cap = read_config(fd, &p->pc_sel, ptr + PCICAP_ID, 1);
1321 if (cap == id)
1322 return (ptr);
1323 ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1);
1325 return (0);
1328 /* Find offset of a specific extended capability. Returns 0 on failure. */
1329 uint16_t
1330 pcie_find_cap(int fd, struct pci_conf *p, uint16_t id)
1332 uint32_t ecap;
1333 uint16_t ptr;
1335 ptr = PCIR_EXTCAP;
1336 ecap = read_config(fd, &p->pc_sel, ptr, 4);
1337 if (ecap == 0xffffffff || ecap == 0)
1338 return (0);
1339 for (;;) {
1340 if (PCI_EXTCAP_ID(ecap) == id)
1341 return (ptr);
1342 ptr = PCI_EXTCAP_NEXTPTR(ecap);
1343 if (ptr == 0)
1344 break;
1345 ecap = read_config(fd, &p->pc_sel, ptr, 4);
1347 return (0);