2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2007 Yahoo!, Inc.
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
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
33 #include <sys/types.h>
38 #include <sys/agpio.h>
39 #include <sys/pciio.h>
41 #include <dev/agp/agpreg.h>
42 #include <dev/pci/pcireg.h>
46 static void list_ecaps(int fd
, struct pci_conf
*p
);
51 cap_power(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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",
59 cap
& PCIM_PCAP_D1SUPP
? " D1" : "",
60 cap
& PCIM_PCAP_D2SUPP
? " D2" : "",
61 status
& PCIM_PSTAT_DMASK
);
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);
72 if (AGP_MODE_GET_MODE_3(status
)) {
74 if (AGP_MODE_GET_RATE(status
) & AGP_MODE_V3_RATE_8x
)
76 if (AGP_MODE_GET_RATE(status
) & AGP_MODE_V3_RATE_4x
)
79 if (AGP_MODE_GET_RATE(status
) & AGP_MODE_V2_RATE_4x
)
81 if (AGP_MODE_GET_RATE(status
) & AGP_MODE_V2_RATE_2x
)
83 if (AGP_MODE_GET_RATE(status
) & AGP_MODE_V2_RATE_1x
)
86 if (AGP_MODE_GET_SBA(status
))
88 if (AGP_MODE_GET_AGP(command
)) {
89 printf("enabled at ");
90 if (AGP_MODE_GET_MODE_3(command
)) {
92 switch (AGP_MODE_GET_RATE(command
)) {
93 case AGP_MODE_V3_RATE_8x
:
96 case AGP_MODE_V3_RATE_4x
:
101 switch (AGP_MODE_GET_RATE(command
)) {
102 case AGP_MODE_V2_RATE_4x
:
105 case AGP_MODE_V2_RATE_2x
:
108 case AGP_MODE_V2_RATE_1x
:
112 if (AGP_MODE_GET_SBA(command
))
119 cap_vpd(int fd __unused
, struct pci_conf
*p __unused
, uint8_t ptr __unused
)
126 cap_msi(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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");
145 cap_pcix(int fd
, struct pci_conf
*p
, uint8_t ptr
)
148 int comma
, max_splits
, max_burst_read
;
150 status
= read_config(fd
, &p
->pc_sel
, ptr
+ PCIXR_STATUS
, 4);
152 if (status
& PCIXM_STATUS_64BIT
)
154 if ((p
->pc_hdr
& PCIM_HDRTYPE
) == 1)
156 if ((p
->pc_hdr
& PCIM_HDRTYPE
) != 1 || (status
& (PCIXM_STATUS_133CAP
|
157 PCIXM_STATUS_266CAP
| PCIXM_STATUS_533CAP
)) != 0)
160 if (status
& PCIXM_STATUS_133CAP
) {
164 if (status
& PCIXM_STATUS_266CAP
) {
165 printf("%s 266MHz", comma
? "," : "");
168 if (status
& PCIXM_STATUS_533CAP
) {
169 printf("%s 533MHz", comma
? "," : "");
172 if ((p
->pc_hdr
& PCIM_HDRTYPE
) == 1)
175 switch (status
& PCIXM_STATUS_MAX_READ
) {
176 case PCIXM_STATUS_MAX_READ_512
:
177 max_burst_read
= 512;
179 case PCIXM_STATUS_MAX_READ_1024
:
180 max_burst_read
= 1024;
182 case PCIXM_STATUS_MAX_READ_2048
:
183 max_burst_read
= 2048;
185 case PCIXM_STATUS_MAX_READ_4096
:
186 max_burst_read
= 4096;
190 switch (status
& PCIXM_STATUS_MAX_SPLITS
) {
191 case PCIXM_STATUS_MAX_SPLITS_1
:
194 case PCIXM_STATUS_MAX_SPLITS_2
:
197 case PCIXM_STATUS_MAX_SPLITS_3
:
200 case PCIXM_STATUS_MAX_SPLITS_4
:
203 case PCIXM_STATUS_MAX_SPLITS_8
:
206 case PCIXM_STATUS_MAX_SPLITS_12
:
209 case PCIXM_STATUS_MAX_SPLITS_16
:
212 case PCIXM_STATUS_MAX_SPLITS_32
:
216 printf("%s %d burst read, %d split transaction%s", comma
? "," : "",
217 max_burst_read
, max_splits
, max_splits
== 1 ? "" : "s");
221 cap_ht(int fd
, struct pci_conf
*p
, uint8_t ptr
)
226 command
= read_config(fd
, &p
->pc_sel
, ptr
+ PCIR_HT_COMMAND
, 2);
228 if ((command
& 0xe000) == PCIM_HTCAP_SLAVE
)
230 else if ((command
& 0xe000) == PCIM_HTCAP_HOST
)
233 switch (command
& PCIM_HTCMD_CAP_MASK
) {
234 case PCIM_HTCAP_SWITCH
:
237 case PCIM_HTCAP_INTERRUPT
:
240 case PCIM_HTCAP_REVISION_ID
:
241 printf("revision ID");
243 case PCIM_HTCAP_UNITID_CLUMPING
:
244 printf("unit ID clumping");
246 case PCIM_HTCAP_EXT_CONFIG_SPACE
:
247 printf("extended config space");
249 case PCIM_HTCAP_ADDRESS_MAPPING
:
250 printf("address mapping");
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" :
257 if (command
& PCIM_HTCMD_MSI_FIXED
)
260 reg
= read_config(fd
, &p
->pc_sel
,
261 ptr
+ PCIR_HTMSI_ADDRESS_HI
, 4);
264 reg
= read_config(fd
, &p
->pc_sel
,
265 ptr
+ PCIR_HTMSI_ADDRESS_LO
, 4);
269 case PCIM_HTCAP_DIRECT_ROUTE
:
270 printf("direct route");
272 case PCIM_HTCAP_VCSET
:
275 case PCIM_HTCAP_RETRY_MODE
:
276 printf("retry mode");
278 case PCIM_HTCAP_X86_ENCODING
:
279 printf("X86 encoding");
281 case PCIM_HTCAP_GEN3
:
285 printf("function-level extension");
288 printf("power management");
290 case PCIM_HTCAP_HIGH_NODE_COUNT
:
291 printf("high node count");
294 printf("unknown %02x", command
);
300 cap_vendor(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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) {
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 */
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)) {
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
? "," : "");
332 if (fvec
& (1 << 18)) {
333 printf("%s SATA RAID-5", comma
? "," : "");
336 if (fvec
& (1 << 9)) {
337 printf("%s Mobile", comma
? "," : "");
340 if (fvec
& (1 << 7)) {
341 printf("%s 6 PCI-e x1 slots", comma
? "," : "");
344 printf("%s 4 PCI-e x1 slots", comma
? "," : "");
347 if (fvec
& (1 << 5)) {
348 printf("%s SATA RAID-0/1/10", comma
? "," : "");
352 printf(", SATA AHCI");
358 cap_debug(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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));
368 cap_subvendor(int fd
, struct pci_conf
*p
, uint8_t ptr
)
371 uint16_t ssid
, ssvid
;
373 id
= read_config(fd
, &p
->pc_sel
, ptr
+ PCIR_SUBVENDCAP_ID
, 4);
376 printf("PCI Bridge subvendor=0x%04x subdevice=0x%04x", ssvid
, ssid
);
380 cap_secdev_amdiommu_decode_vasize(uint32_t misc0
)
382 switch (misc0
& PCIM_AMDIOMMU_MISC0_VASIZE_MASK
) {
383 case PCIM_AMDIOMMU_MISC0_VASIZE_32
:
385 case PCIM_AMDIOMMU_MISC0_VASIZE_40
:
387 case PCIM_AMDIOMMU_MISC0_VASIZE_48
:
389 case PCIM_AMDIOMMU_MISC0_VASIZE_64
:
397 cap_secdev_amdiommu_decode_pasize(uint32_t misc0
)
399 switch (misc0
& PCIM_AMDIOMMU_MISC0_PASIZE_MASK
) {
400 case PCIM_AMDIOMMU_MISC0_PASIZE_40
:
402 case PCIM_AMDIOMMU_MISC0_PASIZE_48
:
404 case PCIM_AMDIOMMU_MISC0_PASIZE_52
:
412 cap_secdev_amdiommu_decode_gvasize(uint32_t misc0
)
414 switch (misc0
& PCIM_AMDIOMMU_MISC0_GVASIZE_MASK
) {
415 case PCIM_AMDIOMMU_MISC0_GVASIZE_48
:
417 case PCIM_AMDIOMMU_MISC0_GVASIZE_57
:
425 cap_secdev(int fd
, struct pci_conf
*p
, uint8_t ptr
)
428 uint32_t cap_type
, cap_rev
;
429 uint32_t base_low
, base_high
;
431 uint32_t misc0
, misc1
;
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);
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");
453 #define PRINTCAP(bit, name) \
454 if ((cap_h & PCIM_AMDIOMMU_CAP_ ##bit) != 0) { \
455 printf("%s%s", delim, #name); \
458 PRINTCAP(CAPEXT
, CapExt
);
459 PRINTCAP(EFR
, EFRSup
);
460 PRINTCAP(NPCACHE
, NpCache
);
461 PRINTCAP(HTTUN
, HtTunnel
);
462 PRINTCAP(IOTLB
, IotlbSup
);
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))
494 link_speed_string(uint8_t speed
)
516 max_read_string(u_int max_read
)
538 aspm_string(uint8_t aspm
)
554 slot_power(uint32_t cap
)
558 mwatts
= (cap
& PCIEM_SLOT_CAP_SPLV
) >> 7;
559 switch (cap
& PCIEM_SLOT_CAP_SPLS
) {
576 cap_express(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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
:
589 case PCIEM_TYPE_LEGACY_ENDPOINT
:
590 printf("legacy endpoint");
592 case PCIEM_TYPE_ROOT_PORT
:
595 case PCIEM_TYPE_UPSTREAM_PORT
:
596 printf("upstream port");
598 case PCIEM_TYPE_DOWNSTREAM_PORT
:
599 printf("downstream port");
601 case PCIEM_TYPE_PCI_BRIDGE
:
602 printf("PCI bridge");
604 case PCIEM_TYPE_PCIE_BRIDGE
:
605 printf("PCI to PCIe bridge");
607 case PCIEM_TYPE_ROOT_INT_EP
:
608 printf("root endpoint");
610 case PCIEM_TYPE_ROOT_EC
:
611 printf("event collector");
614 printf("type %d", (flags
& PCIEM_FLAGS_TYPE
) >> 4);
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)
626 if (ctl
& PCIEM_CTL_RELAXED_ORD_ENABLE
)
628 if (ctl
& PCIEM_CTL_NOSNOOP_ENABLE
)
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);
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)
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
))
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);
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" :
674 if (cap
& PCIEM_SLOT_CAP_HPS
)
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" :
683 if (cap
& PCIEM_SLOT_CAP_EIP
)
684 printf(" EI(%s)", sta
& PCIEM_SLOT_STA_EIS
? "engaged" :
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
;
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" : "");
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
);
716 cap_sata(int fd __unused
, struct pci_conf
*p __unused
, uint8_t ptr __unused
)
719 printf("SATA Index-Data Pair");
723 cap_pciaf(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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" : "");
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
]);
749 case PCIM_EA_BEI_BRIDGE
:
751 case PCIM_EA_BEI_ENI
:
753 case PCIM_EA_BEI_ROM
:
755 case PCIM_EA_BEI_RESERVED
:
762 ea_prop_to_name(uint8_t prop
)
767 return "Non-Prefetchable Memory";
768 case PCIM_EA_P_MEM_PREFETCH
:
769 return "Prefetchable Memory";
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";
794 cap_ea(int fd
, struct pci_conf
*p
, uint8_t ptr
)
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
);
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);
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);
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
;
846 if (((dw
[0] & PCIM_EA_IS_64
) != 0) && (b
< ent_size
)) {
847 base
|= (uint64_t)dw
[b
] << 32UL;
850 if (((dw
[1] & PCIM_EA_IS_64
) != 0)
852 max_offset
|= (uint64_t)dw
[b
] << 32UL;
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
));
869 list_caps(int fd
, struct pci_conf
*p
, int level
)
875 /* Are capabilities present for this device? */
876 sta
= read_config(fd
, &p
->pc_sel
, PCIR_STATUS
, 2);
877 if (!(sta
& PCIM_STATUS_CAPPRESENT
))
882 switch (p
->pc_hdr
& PCIM_HDRTYPE
) {
883 case PCIM_HDRTYPE_NORMAL
:
884 case PCIM_HDRTYPE_BRIDGE
:
887 case PCIM_HDRTYPE_CARDBUS
:
888 ptr
= PCIR_CAP_PTR_2
;
891 errx(1, "list_caps: bad header type");
894 /* Walk the capability list. */
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
);
902 cap_power(fd
, p
, ptr
);
914 cap_pcix(fd
, p
, ptr
);
920 cap_vendor(fd
, p
, ptr
);
923 cap_debug(fd
, p
, ptr
);
926 cap_subvendor(fd
, p
, ptr
);
929 cap_secdev(fd
, p
, ptr
);
933 cap_express(fd
, p
, ptr
);
936 cap_msix(fd
, p
, ptr
);
939 cap_sata(fd
, p
, ptr
);
942 cap_pciaf(fd
, p
, ptr
);
952 ptr
= read_config(fd
, &p
->pc_sel
, ptr
+ PCICAP_NEXTPTR
, 1);
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;
968 x
= (x
+ (x
>> 16)) & 0x000000ff;
973 ecap_aer(int fd
, struct pci_conf
*p
, uint16_t ptr
, uint8_t ver
)
977 printf("AER %d", ver
);
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
));
991 ecap_vc(int fd
, struct pci_conf
*p
, uint16_t ptr
, uint8_t ver
)
995 printf("VC %d", ver
);
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);
1009 ecap_sernum(int fd
, struct pci_conf
*p
, uint16_t ptr
, uint8_t ver
)
1013 printf("Serial %d", ver
);
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
);
1024 ecap_vendor(int fd
, struct pci_conf
*p
, uint16_t ptr
, uint8_t ver
)
1027 uint16_t nextptr
, len
;
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
);
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))
1044 for (i
= 0; i
< len
; i
+= 4) {
1045 val
= read_config(fd
, &p
->pc_sel
, ptr
+ i
, 4);
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
))
1058 ecap_sec_pcie(int fd
, struct pci_conf
*p
, uint16_t ptr
, uint8_t ver
)
1062 printf("PCIe Sec %d", ver
);
1067 val
= read_config(fd
, &p
->pc_sel
, ptr
+ 8, 4);
1068 printf(" lane errors %#x\n", val
);
1072 check_enabled(int value
)
1075 return (value
? "enabled" : "disabled");
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
;
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);
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);
1102 printf("First VF RID Offset 0x%04x, VF RID Stride 0x%04x\n", vf_offset
,
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);
1111 printf("Page Sizes: ");
1113 while (page_caps
!= 0) {
1114 page_shift
= ffs(page_caps
) - 1;
1116 if (page_caps
& page_size
)
1117 enabled
= " (enabled)";
1121 size
= (1 << (page_shift
+ PCI_SRIOV_BASE_PAGE_SHIFT
));
1122 printf("%s%d%s", comma
, size
, enabled
);
1125 page_caps
&= ~(1 << page_shift
);
1129 for (i
= 0; i
<= PCIR_MAX_BAR_0
; i
++)
1130 print_bar(fd
, p
, "iov bar ", ptr
+ PCIR_SRIOV_BAR(i
));
1134 check_avail_and_state(u_int cap
, u_int capbit
, u_int ctl
, u_int ctlbit
)
1138 return (ctl
& ctlbit
? "enabled" : "disabled");
1140 return "unavailable";
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
);
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
));
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
));
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
));
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
) {
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
));
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]);
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" },
1242 list_ecaps(int fd
, struct pci_conf
*p
)
1250 ecap
= read_config(fd
, &p
->pc_sel
, ptr
, 4);
1251 if (ecap
== 0xffffffff || ecap
== 0)
1254 printf(" ecap %04x[%03x] = ", PCI_EXTCAP_ID(ecap
), ptr
);
1255 switch (PCI_EXTCAP_ID(ecap
)) {
1257 ecap_aer(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
1260 ecap_vc(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
1263 ecap_sernum(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
1266 ecap_vendor(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
1269 ecap_sec_pcie(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
1272 ecap_sriov(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
1275 ecap_acs(fd
, p
, ptr
, PCI_EXTCAP_VER(ecap
));
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
;
1284 printf("%s %d\n", name
, PCI_EXTCAP_VER(ecap
));
1287 ptr
= PCI_EXTCAP_NEXTPTR(ecap
);
1290 ecap
= read_config(fd
, &p
->pc_sel
, ptr
, 4);
1294 /* Find offset of a specific capability. Returns 0 on failure. */
1296 pci_find_cap(int fd
, struct pci_conf
*p
, uint8_t id
)
1301 /* Are capabilities present for this device? */
1302 sta
= read_config(fd
, &p
->pc_sel
, PCIR_STATUS
, 2);
1303 if (!(sta
& PCIM_STATUS_CAPPRESENT
))
1306 switch (p
->pc_hdr
& PCIM_HDRTYPE
) {
1307 case PCIM_HDRTYPE_NORMAL
:
1308 case PCIM_HDRTYPE_BRIDGE
:
1311 case PCIM_HDRTYPE_CARDBUS
:
1312 ptr
= PCIR_CAP_PTR_2
;
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);
1323 ptr
= read_config(fd
, &p
->pc_sel
, ptr
+ PCICAP_NEXTPTR
, 1);
1328 /* Find offset of a specific extended capability. Returns 0 on failure. */
1330 pcie_find_cap(int fd
, struct pci_conf
*p
, uint16_t id
)
1336 ecap
= read_config(fd
, &p
->pc_sel
, ptr
, 4);
1337 if (ecap
== 0xffffffff || ecap
== 0)
1340 if (PCI_EXTCAP_ID(ecap
) == id
)
1342 ptr
= PCI_EXTCAP_NEXTPTR(ecap
);
1345 ecap
= read_config(fd
, &p
->pc_sel
, ptr
, 4);