Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/pci/pci_subr.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/pci/pci_subr.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.183 retrieving revision 1.183.2.11 diff -u -p -r1.183 -r1.183.2.11 --- src/sys/dev/pci/pci_subr.c 2017/05/29 07:09:20 1.183 +++ src/sys/dev/pci/pci_subr.c 2019/07/17 15:55:31 1.183.2.11 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_subr.c,v 1.183 2017/05/29 07:09:20 msaitoh Exp $ */ +/* $NetBSD: pci_subr.c,v 1.183.2.11 2019/07/17 15:55:31 martin Exp $ */ /* * Copyright (c) 1997 Zubin D. Dittia. All rights reserved. @@ -40,7 +40,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.183 2017/05/29 07:09:20 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.183.2.11 2019/07/17 15:55:31 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_pci.h" @@ -70,7 +70,8 @@ __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v #include #endif -static int pci_conf_find_cap(const pcireg_t *, int, unsigned int, int *); +static int pci_conf_find_cap(const pcireg_t *, unsigned int, int *); +static int pci_conf_find_extcap(const pcireg_t *, unsigned int, int *); static void pci_conf_print_pcie_power(uint8_t, unsigned int); /* @@ -831,8 +832,7 @@ pci_conf_print_common( int pcie_capoff; pcireg_t reg; - if (pci_conf_find_cap(regs, PCI_CAPLISTPTR_REG, - PCI_CAP_PCIEXPRESS, &pcie_capoff)) { + if (pci_conf_find_cap(regs, PCI_CAP_PCIEXPRESS, &pcie_capoff)) { reg = regs[o2i(pcie_capoff + PCIE_XCAP)]; if (PCIE_XCAP_TYPE(reg) == PCIE_XCAP_TYPE_ROOT_EVNTC) subclass = PCI_SUBCLASS_SYSTEM_RCEC; @@ -1172,11 +1172,9 @@ static void pci_conf_print_pcipm_cap(const pcireg_t *regs, int capoff) { uint16_t caps, pmcsr; - pcireg_t reg; caps = regs[o2i(capoff)] >> PCI_PMCR_SHIFT; - reg = regs[o2i(capoff + PCI_PMCSR)]; - pmcsr = reg & 0xffff; + pmcsr = regs[o2i(capoff + PCI_PMCSR)]; printf("\n PCI Power Management Capabilities Register\n"); @@ -1195,7 +1193,7 @@ pci_conf_print_pcipm_cap(const pcireg_t onoff("PME# support D3 hot", caps, PCI_PMCR_PME_D3HOT); onoff("PME# support D3 cold", caps, PCI_PMCR_PME_D3COLD); - printf(" Control/status register: 0x%04x\n", pmcsr); + printf(" Control/status register: 0x%08x\n", pmcsr); printf(" Power state: D%d\n", pmcsr & PCI_PMCSR_STATE_MASK); onoff("PCI Express reserved", (pmcsr >> 2), 1); onoff("No soft reset", pmcsr, PCI_PMCSR_NO_SOFTRST); @@ -1207,11 +1205,11 @@ pci_conf_print_pcipm_cap(const pcireg_t __SHIFTOUT(pmcsr, PCI_PMCSR_DATASCL_MASK)); onoff("PME# status", pmcsr, PCI_PMCSR_PME_STS); printf(" Bridge Support Extensions register: 0x%02x\n", - (reg >> 16) & 0xff); - onoff("B2/B3 support", reg, PCI_PMCSR_B2B3_SUPPORT); - onoff("Bus Power/Clock Control Enable", reg, PCI_PMCSR_BPCC_EN); - printf(" Data register: 0x%02x\n", __SHIFTOUT(reg, PCI_PMCSR_DATA)); - + (pmcsr >> 16) & 0xff); + onoff("B2/B3 support", pmcsr, PCI_PMCSR_B2B3_SUPPORT); + onoff("Bus Power/Clock Control Enable", pmcsr, PCI_PMCSR_BPCC_EN); + printf(" Data register: 0x%02x\n", + __SHIFTOUT(pmcsr, PCI_PMCSR_DATA)); } /* XXX pci_conf_print_vpd_cap */ @@ -1530,7 +1528,91 @@ pci_conf_print_subsystem_cap(const pcire } /* XXX pci_conf_print_agp8_cap */ -/* XXX pci_conf_print_secure_cap */ +static void +pci_conf_print_secure_cap(const pcireg_t *regs, int capoff) +{ + pcireg_t reg, reg2, val; + bool havemisc1; + + printf("\n Secure Capability Register\n"); + reg = regs[o2i(capoff + PCI_SECURE_CAP)]; + printf(" Capability Register: 0x%04x\n", reg >> 16); + val = __SHIFTOUT(reg, PCI_SECURE_CAP_TYPE); + printf(" Capability block type: "); + /* I know IOMMU Only */ + if (val == PCI_SECURE_CAP_TYPE_IOMMU) + printf("IOMMU\n"); + else { + printf("0x%x(unknown)\n", val); + return; + } + + val = __SHIFTOUT(reg, PCI_SECURE_CAP_REV); + printf(" Capability revision: 0x%02x ", val); + if (val == PCI_SECURE_CAP_REV_IOMMU) + printf("(IOMMU)\n"); + else { + printf("(unknown)\n"); + return; + } + onoff("IOTLB support", reg, PCI_SECURE_CAP_IOTLBSUP); + onoff("HyperTransport tunnel translation support", reg, + PCI_SECURE_CAP_HTTUNNEL); + onoff("Not present table entries cached", reg, PCI_SECURE_CAP_NPCACHE); + onoff("IOMMU Extended Feature Register support", reg, + PCI_SECURE_CAP_EFRSUP); + onoff("IOMMU Miscellaneous Information Register 1", reg, + PCI_SECURE_CAP_EXT); + havemisc1 = reg & PCI_SECURE_CAP_EXT; + + reg = regs[o2i(capoff + PCI_SECURE_IOMMU_BAL)]; + printf(" Base Address Low Register: 0x%08x\n", reg); + onoff("Enable", reg, PCI_SECURE_IOMMU_BAL_EN); + reg2 = regs[o2i(capoff + PCI_SECURE_IOMMU_BAH)]; + printf(" Base Address High Register: 0x%08x\n", reg2); + printf(" Base Address : 0x%016" PRIx64 "\n", + ((uint64_t)reg2 << 32) + | (reg & (PCI_SECURE_IOMMU_BAL_H | PCI_SECURE_IOMMU_BAL_L))); + + reg = regs[o2i(capoff + PCI_SECURE_IOMMU_RANGE)]; + printf(" IOMMU Range Register: 0x%08x\n", reg); + printf(" HyperTransport UnitID: 0x%02x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_RANGE_UNITID)); + onoff("Range valid", reg, PCI_SECURE_IOMMU_RANGE_RNGVALID); + printf(" Device range bus number: 0x%02x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_RANGE_BUSNUM)); + printf(" First device: 0x%04x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_RANGE_FIRSTDEV)); + printf(" Last device: 0x%04x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_RANGE_LASTDEV)); + + reg = regs[o2i(capoff + PCI_SECURE_IOMMU_MISC0)]; + printf(" Miscellaneous Information Register 0: 0x%08x\n", reg); + printf(" MSI Message number: 0x%02x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_MISC0_MSINUM)); + val = __SHIFTOUT(reg, PCI_SECURE_IOMMU_MISC0_GVASIZE); + printf(" Guest Virtual Address size: "); + if (val == PCI_SECURE_IOMMU_MISC0_GVASIZE_48B) + printf("48bits\n"); + else + printf("0x%x(unknown)\n", val); + val = __SHIFTOUT(reg, PCI_SECURE_IOMMU_MISC0_PASIZE); + printf(" Physical Address size: %dbits\n", val); + val = __SHIFTOUT(reg, PCI_SECURE_IOMMU_MISC0_VASIZE); + printf(" Virtual Address size: %dbits\n", val); + onoff("ATS response address range reserved", reg, + PCI_SECURE_IOMMU_MISC0_ATSRESV); + printf(" Peripheral Page Request MSI Message number: 0x%02x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_MISC0_MISNPPR)); + + if (!havemisc1) + return; + + reg = regs[o2i(capoff + PCI_SECURE_IOMMU_MISC1)]; + printf(" Miscellaneous Information Register 1: 0x%08x\n", reg); + printf(" MSI Message number (GA): 0x%02x\n", + (uint32_t)__SHIFTOUT(reg, PCI_SECURE_IOMMU_MISC1_MSINUM)); +} static void pci_print_pcie_L0s_latency(uint32_t val) @@ -1606,18 +1688,39 @@ pci_print_pcie_compl_timeout(uint32_t va } } -static const char * const pcie_linkspeeds[] = {"2.5", "2.5", "5.0", "8.0"}; +static const char * const pcie_linkspeeds[] = {"2.5", "5.0", "8.0", "16.0"}; +/* + * Print link speed. This function is used for the following register bits: + * Maximum Link Speed in LCAP + * Current Link Speed in LCSR + * Target Link Speed in LCSR2 + * All of above bitfield's values start from 1. + * For LCSR2, 0 is allowed for a device which supports 2.5GT/s only (and + * this check also works for devices which compliant to versions of the base + * specification prior to 3.0. + */ static void -pci_print_pcie_linkspeed(pcireg_t val) +pci_print_pcie_linkspeed(int regnum, pcireg_t val) { - if (val > __arraycount(pcie_linkspeeds)) + if ((regnum == PCIE_LCSR2) && (val == 0)) + printf("2.5GT/s\n"); + else if ((val < 1) || (val > __arraycount(pcie_linkspeeds))) printf("unknown value (%u)\n", val); else - printf("%sGT/s\n", pcie_linkspeeds[val]); + printf("%sGT/s\n", pcie_linkspeeds[val - 1]); } +/* + * Print link speed "vector". + * This function is used for the following register bits: + * Supported Link Speeds Vector in LCAP2 + * Lower SKP OS Generation Supported Speed Vector in LCAP2 + * Lower SKP OS Reception Supported Speed Vector in LCAP2 + * Enable Lower SKP OS Generation Vector in LCTL3 + * All of above bitfield's values start from 0. + */ static void pci_print_pcie_linkspeedvector(pcireg_t val) { @@ -1653,9 +1756,8 @@ pci_conf_print_pcie_cap(const pcireg_t * { pcireg_t reg; /* for each register */ pcireg_t val; /* for each bitfield */ - bool check_link = true; bool check_slot = false; - bool check_rootport = false; + unsigned int pcie_devtype; bool check_upstreamport = false; unsigned int pciever; unsigned int i; @@ -1664,10 +1766,11 @@ pci_conf_print_pcie_cap(const pcireg_t * /* Capability Register */ reg = regs[o2i(capoff)]; printf(" Capability register: 0x%04x\n", reg >> 16); - pciever = (unsigned int)((reg & 0x000f0000) >> 16); + pciever = (unsigned int)(PCIE_XCAP_VER(reg)); printf(" Capability version: %u\n", pciever); printf(" Device type: "); - switch ((reg & 0x00f00000) >> 20) { + pcie_devtype = PCIE_XCAP_TYPE(reg); + switch (pcie_devtype) { case PCIE_XCAP_TYPE_PCIE_DEV: /* 0x0 */ printf("PCI Express Endpoint device\n"); check_upstreamport = true; @@ -1679,7 +1782,6 @@ pci_conf_print_pcie_cap(const pcireg_t * case PCIE_XCAP_TYPE_ROOT: /* 0x4 */ printf("Root Port of PCI Express Root Complex\n"); check_slot = true; - check_rootport = true; break; case PCIE_XCAP_TYPE_UP: /* 0x5 */ printf("Upstream Port of PCI Express Switch\n"); @@ -1688,7 +1790,6 @@ pci_conf_print_pcie_cap(const pcireg_t * case PCIE_XCAP_TYPE_DOWN: /* 0x6 */ printf("Downstream Port of PCI Express Switch\n"); check_slot = true; - check_rootport = true; break; case PCIE_XCAP_TYPE_PCIE2PCI: /* 0x7 */ printf("PCI Express to PCI/PCI-X Bridge\n"); @@ -1701,12 +1802,9 @@ pci_conf_print_pcie_cap(const pcireg_t * break; case PCIE_XCAP_TYPE_ROOT_INTEP: /* 0x9 */ printf("Root Complex Integrated Endpoint\n"); - check_link = false; break; case PCIE_XCAP_TYPE_ROOT_EVNTC: /* 0xa */ printf("Root Complex Event Collector\n"); - check_link = false; - check_rootport = true; break; default: printf("unknown\n"); @@ -1783,12 +1881,12 @@ pci_conf_print_pcie_cap(const pcireg_t * onoff("Transaction Pending", reg, PCIE_DCSR_TRANSACTION_PND); onoff("Emergency Power Reduction Detected", reg, PCIE_DCSR_EMGPWRREDD); - if (check_link) { + if (PCIE_HAS_LINKREGS(pcie_devtype)) { /* Link Capability Register */ reg = regs[o2i(capoff + PCIE_LCAP)]; printf(" Link Capabilities Register: 0x%08x\n", reg); printf(" Maximum Link Speed: "); - pci_print_pcie_linkspeed(reg & PCIE_LCAP_MAX_SPEED); + pci_print_pcie_linkspeed(PCIE_LCAP, reg & PCIE_LCAP_MAX_SPEED); printf(" Maximum Link Width: x%u lanes\n", (unsigned int)__SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH)); printf(" Active State PM Support: "); @@ -1871,7 +1969,8 @@ pci_conf_print_pcie_cap(const pcireg_t * reg = regs[o2i(capoff + PCIE_LCSR)]; printf(" Link Status Register: 0x%04x\n", reg >> 16); printf(" Negotiated Link Speed: "); - pci_print_pcie_linkspeed(__SHIFTOUT(reg, PCIE_LCSR_LINKSPEED)); + pci_print_pcie_linkspeed(PCIE_LCSR, + __SHIFTOUT(reg, PCIE_LCSR_LINKSPEED)); printf(" Negotiated Link Width: x%u lanes\n", (unsigned int)__SHIFTOUT(reg, PCIE_LCSR_NLW)); onoff("Training Error", reg, PCIE_LCSR_LINKTRAIN_ERR); @@ -1885,8 +1984,10 @@ pci_conf_print_pcie_cap(const pcireg_t * } if (check_slot == true) { + pcireg_t slcap; + /* Slot Capability Register */ - reg = regs[o2i(capoff + PCIE_SLCAP)]; + slcap = reg = regs[o2i(capoff + PCIE_SLCAP)]; printf(" Slot Capability Register: 0x%08x\n", reg); onoff("Attention Button Present", reg, PCIE_SLCAP_ABP); onoff("Power Controller Present", reg, PCIE_SLCAP_PCP); @@ -1914,35 +2015,44 @@ pci_conf_print_pcie_cap(const pcireg_t * onoff("Command Completed Interrupt Enabled", reg, PCIE_SLCSR_CCE); onoff("Hot-Plug Interrupt Enabled", reg, PCIE_SLCSR_HPE); - printf(" Attention Indicator Control: "); - switch ((reg & PCIE_SLCSR_AIC) >> 6) { - case 0x0: - printf("reserved\n"); - break; - case PCIE_SLCSR_IND_ON: - printf("on\n"); - break; - case PCIE_SLCSR_IND_BLINK: - printf("blink\n"); - break; - case PCIE_SLCSR_IND_OFF: - printf("off\n"); - break; + /* + * For Attention Indicator Control and Power Indicator Control, + * it's allowed to be a read only value 0 if corresponding + * capability register bit is 0. + */ + if (slcap & PCIE_SLCAP_AIP) { + printf(" Attention Indicator Control: "); + switch ((reg & PCIE_SLCSR_AIC) >> 6) { + case 0x0: + printf("reserved\n"); + break; + case PCIE_SLCSR_IND_ON: + printf("on\n"); + break; + case PCIE_SLCSR_IND_BLINK: + printf("blink\n"); + break; + case PCIE_SLCSR_IND_OFF: + printf("off\n"); + break; + } } - printf(" Power Indicator Control: "); - switch ((reg & PCIE_SLCSR_PIC) >> 8) { - case 0x0: - printf("reserved\n"); - break; - case PCIE_SLCSR_IND_ON: - printf("on\n"); - break; - case PCIE_SLCSR_IND_BLINK: - printf("blink\n"); - break; - case PCIE_SLCSR_IND_OFF: - printf("off\n"); - break; + if (slcap & PCIE_SLCAP_PIP) { + printf(" Power Indicator Control: "); + switch ((reg & PCIE_SLCSR_PIC) >> 8) { + case 0x0: + printf("reserved\n"); + break; + case PCIE_SLCSR_IND_ON: + printf("on\n"); + break; + case PCIE_SLCSR_IND_BLINK: + printf("blink\n"); + break; + case PCIE_SLCSR_IND_OFF: + printf("off\n"); + break; + } } printf(" Power Controller Control: Power %s\n", reg & PCIE_SLCSR_PCC ? "off" : "on"); @@ -1967,7 +2077,7 @@ pci_conf_print_pcie_cap(const pcireg_t * onoff("Data Link Layer State Changed", reg, PCIE_SLCSR_LACS); } - if (check_rootport == true) { + if (PCIE_HAS_ROOTREGS(pcie_devtype)) { /* Root Control Register */ reg = regs[o2i(capoff + PCIE_RCR)]; printf(" Root Control Register: 0x%04x\n", reg & 0xffff); @@ -2054,7 +2164,7 @@ pci_conf_print_pcie_cap(const pcireg_t * break; } printf(" OBFF Supported: "); - switch ((reg & PCIE_DCAP2_OBFF) >> 18) { + switch (__SHIFTOUT(reg, PCIE_DCAP2_OBFF)) { case 0x0: printf("Not supported\n"); break; @@ -2106,7 +2216,7 @@ pci_conf_print_pcie_cap(const pcireg_t * onoff("Emergency Power Reduction Request", reg, PCIE_DCSR2_EMGPWRRED_REQ); printf(" OBFF: "); - switch ((reg & PCIE_DCSR2_OBFF_EN) >> 13) { + switch (__SHIFTOUT(reg, PCIE_DCSR2_OBFF_EN)) { case 0x0: printf("Disabled\n"); break; @@ -2122,7 +2232,7 @@ pci_conf_print_pcie_cap(const pcireg_t * } onoff("End-End TLP Prefix Blocking on", reg, PCIE_DCSR2_EETLP); - if (check_link) { + if (PCIE_HAS_LINKREGS(pcie_devtype)) { bool drs_supported = false; /* Link Capability 2 */ @@ -2151,10 +2261,11 @@ pci_conf_print_pcie_cap(const pcireg_t * /* Link Control 2 */ reg = regs[o2i(capoff + PCIE_LCSR2)]; + /* If the vector is 0, LCAP2 is not implemented */ printf(" Link Control 2: 0x%04x\n", reg & 0xffff); printf(" Target Link Speed: "); - pci_print_pcie_linkspeed(__SHIFTOUT(reg, - PCIE_LCSR2_TGT_LSPEED)); + pci_print_pcie_linkspeed(PCIE_LCSR2, + __SHIFTOUT(reg, PCIE_LCSR2_TGT_LSPEED)); onoff("Enter Compliance Enabled", reg, PCIE_LCSR2_ENT_COMPL); onoff("HW Autonomous Speed Disabled", reg, PCIE_LCSR2_HW_AS_DIS); @@ -2293,7 +2404,167 @@ pci_conf_print_pciaf_cap(const pcireg_t onoff("Transaction Pending", reg, PCI_AFSR_TP); } -/* XXX pci_conf_print_ea_cap */ +static void +pci_conf_print_ea_cap_prop(unsigned int prop) +{ + + switch (prop) { + case PCI_EA_PROP_MEM_NONPREF: + printf("Memory Space, Non-Prefetchable\n"); + break; + case PCI_EA_PROP_MEM_PREF: + printf("Memory Space, Prefetchable\n"); + break; + case PCI_EA_PROP_IO: + printf("I/O Space\n"); + break; + case PCI_EA_PROP_VF_MEM_NONPREF: + printf("Resorce for VF use, Memory Space, Non-Prefetchable\n"); + break; + case PCI_EA_PROP_VF_MEM_PREF: + printf("Resorce for VF use, Memory Space, Prefetch\n"); + break; + case PCI_EA_PROP_BB_MEM_NONPREF: + printf("Behind the Bridge, Memory Space, Non-Pref\n"); + break; + case PCI_EA_PROP_BB_MEM_PREF: + printf("Behind the Bridge, Memory Space. Prefetchable\n"); + break; + case PCI_EA_PROP_BB_IO: + printf("Behind Bridge, I/O Space\n"); + break; + case PCI_EA_PROP_MEM_UNAVAIL: + printf("Memory Space Unavailable\n"); + break; + case PCI_EA_PROP_IO_UNAVAIL: + printf("IO Space Unavailable\n"); + break; + case PCI_EA_PROP_UNAVAIL: + printf("Entry Unavailable for use\n"); + break; + default: + printf("Reserved\n"); + break; + } +} + +static void +pci_conf_print_ea_cap(const pcireg_t *regs, int capoff) +{ + pcireg_t reg, reg2; + unsigned int entries, entoff, i; + + printf("\n Enhanced Allocation Capability Register\n"); + + reg = regs[o2i(capoff + PCI_EA_CAP1)]; + printf(" EA Num Entries register: 0x%04x\n", reg >> 16); + entries = __SHIFTOUT(reg, PCI_EA_CAP1_NUMENTRIES); + printf(" EA Num Entries: %u\n", entries); + + /* Type 1 only */ + if (PCI_HDRTYPE_TYPE(regs[o2i(PCI_BHLC_REG)]) == PCI_HDRTYPE_PPB) { + reg = regs[o2i(capoff + PCI_EA_CAP2)]; + printf(" EA Capability Second register: 0x%08x\n", reg); + printf(" Fixed Secondary Bus Number: %hhu\n", + (unsigned char)__SHIFTOUT(reg, PCI_EA_CAP2_SECONDARY)); + printf(" Fixed Subordinate Bus Number: %hhu\n", + (unsigned char)__SHIFTOUT(reg, PCI_EA_CAP2_SUBORDINATE)); + entoff = capoff + 8; + } else + entoff = capoff + 4; + + for (i = 0; i < entries; i++) { + uint64_t base, offset; + bool baseis64, offsetis64; + unsigned int bei, entry_size; + + printf(" Entry %u:\n", i); + /* The first DW */ + reg = regs[o2i(entoff)]; + printf(" The first register: 0x%08x\n", reg); + entry_size = __SHIFTOUT(reg, PCI_EA_ES); + printf(" Entry size: %u\n", entry_size); + printf(" BAR Equivalent Indicator: "); + bei = __SHIFTOUT(reg, PCI_EA_BEI); + switch (bei) { + case PCI_EA_BEI_BAR0: + case PCI_EA_BEI_BAR1: + case PCI_EA_BEI_BAR2: + case PCI_EA_BEI_BAR3: + case PCI_EA_BEI_BAR4: + case PCI_EA_BEI_BAR5: + printf("BAR %u\n", bei - PCI_EA_BEI_BAR0); + break; + case PCI_EA_BEI_BEHIND: + printf("Behind the function\n"); + break; + case PCI_EA_BEI_NOTIND: + printf("Not Indicated\n"); + break; + case PCI_EA_BEI_EXPROM: + printf("Expansion ROM\n"); + break; + case PCI_EA_BEI_VFBAR0: + case PCI_EA_BEI_VFBAR1: + case PCI_EA_BEI_VFBAR2: + case PCI_EA_BEI_VFBAR3: + case PCI_EA_BEI_VFBAR4: + case PCI_EA_BEI_VFBAR5: + printf("VF BAR %u\n", bei - PCI_EA_BEI_VFBAR0); + break; + case PCI_EA_BEI_RESERVED: + default: + printf("Reserved\n"); + break; + } + + printf(" Primary Properties: "); + pci_conf_print_ea_cap_prop(__SHIFTOUT(reg, PCI_EA_PP)); + printf(" Secondary Properties: "); + pci_conf_print_ea_cap_prop(__SHIFTOUT(reg, PCI_EA_SP)); + onoff("Writable", reg, PCI_EA_W); + onoff("Enable for this entry", reg, PCI_EA_E); + + if (entry_size == 0) { + entoff += 4; + continue; + } + + /* Base addr */ + reg = regs[o2i(entoff + 4)]; + base = reg & PCI_EA_LOWMASK; + baseis64 = reg & PCI_EA_BASEMAXOFFSET_64BIT; + printf(" Base Address Register Low: 0x%08x\n", reg); + if (baseis64) { + /* 64bit */ + reg2 = regs[o2i(entoff + 12)]; + printf(" Base Address Register high: 0x%08x\n", + reg2); + base |= (uint64_t)reg2 << 32; + } + + /* Offset addr */ + reg = regs[o2i(entoff + 8)]; + offset = reg & PCI_EA_LOWMASK; + offsetis64 = reg & PCI_EA_BASEMAXOFFSET_64BIT; + printf(" Max Offset Register Low: 0x%08x\n", reg); + if (offsetis64) { + /* 64bit */ + reg2 = regs[o2i(entoff + (baseis64 ? 16 : 12))]; + printf(" Max Offset Register high: 0x%08x\n", + reg2); + offset |= (uint64_t)reg2 << 32; + } + + printf(" range: 0x%016" PRIx64 "-0x%016" PRIx64 + "\n", base, base + offset); + + entoff += 4; + entoff += baseis64 ? 8 : 4; + entoff += offsetis64 ? 8 : 4; + } +} + /* XXX pci_conf_print_fpb_cap */ static struct { @@ -2318,23 +2589,39 @@ static struct { { PCI_CAP_SUBVENDOR, "Subsystem vendor ID", pci_conf_print_subsystem_cap }, { PCI_CAP_AGP8, "AGP 8x", NULL }, - { PCI_CAP_SECURE, "Secure Device", NULL }, + { PCI_CAP_SECURE, "Secure Device", pci_conf_print_secure_cap }, { PCI_CAP_PCIEXPRESS, "PCI Express", pci_conf_print_pcie_cap }, { PCI_CAP_MSIX, "MSI-X", pci_conf_print_msix_cap }, { PCI_CAP_SATA, "SATA", pci_conf_print_sata_cap }, { PCI_CAP_PCIAF, "Advanced Features", pci_conf_print_pciaf_cap}, - { PCI_CAP_EA, "Enhanced Allocation", NULL }, + { PCI_CAP_EA, "Enhanced Allocation", pci_conf_print_ea_cap }, { PCI_CAP_FPB, "Flattening Portal Bridge", NULL } }; static int -pci_conf_find_cap(const pcireg_t *regs, int capoff, unsigned int capid, - int *offsetp) +pci_conf_find_cap(const pcireg_t *regs, unsigned int capid, int *offsetp) { pcireg_t rval; + unsigned int capptr; int off; - for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]); + if (!(regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)) + return 0; + + /* Determine the Capability List Pointer register to start with. */ + switch (PCI_HDRTYPE_TYPE(regs[o2i(PCI_BHLC_REG)])) { + case 0: /* standard device header */ + case 1: /* PCI-PCI bridge header */ + capptr = PCI_CAPLISTPTR_REG; + break; + case 2: /* PCI-CardBus Bridge header */ + capptr = PCI_CARDBUS_CAPLISTPTR_REG; + break; + default: + return 0; + } + + for (off = PCI_CAPLIST_PTR(regs[o2i(capptr)]); off != 0; off = PCI_CAPLIST_NEXT(rval)) { rval = regs[o2i(off)]; if (capid == PCI_CAPLIST_CAP(rval)) { @@ -2393,13 +2680,6 @@ pci_conf_print_caplist( * the same. This is required because some capabilities * appear multiple times (e.g. HyperTransport capability). */ -#if 0 - if (pci_conf_find_cap(regs, capoff, i, &off)) { - rval = regs[o2i(off)]; - if (pci_captab[i].printfunc != NULL) - pci_captab[i].printfunc(regs, off); - } -#else for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]); off != 0; off = PCI_CAPLIST_NEXT(regs[o2i(off)])) { rval = regs[o2i(off)]; @@ -2407,7 +2687,6 @@ pci_conf_print_caplist( && (pci_captab[i].printfunc != NULL)) pci_captab[i].printfunc(regs, off); } -#endif } } @@ -2515,14 +2794,14 @@ pci_conf_print_aer_cap_errsrc_id(pcireg_ } static void -pci_conf_print_aer_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_aer_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; int pcie_capoff; int pcie_devtype = -1; bool tlp_prefix_log = false; - if (pci_conf_find_cap(regs, capoff, PCI_CAP_PCIEXPRESS, &pcie_capoff)) { + if (pci_conf_find_cap(regs, PCI_CAP_PCIEXPRESS, &pcie_capoff)) { reg = regs[o2i(pcie_capoff)]; pcie_devtype = PCIE_XCAP_TYPE(reg); /* PCIe DW9 to DW14 is for PCIe 2.0 and newer */ @@ -2574,7 +2853,8 @@ pci_conf_print_aer_cap(const pcireg_t *r pci_conf_print_aer_cap_rooterr_status(reg); reg = regs[o2i(extcapoff + PCI_AER_ERRSRC_ID)]; - printf(" Error Source Identification: 0x%04x\n", reg); + printf(" Error Source Identification register: 0x%08x\n", + reg); pci_conf_print_aer_cap_errsrc_id(reg); break; } @@ -2608,7 +2888,7 @@ pci_conf_print_vc_cap_arbtab(const pcire } static void -pci_conf_print_vc_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_vc_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, n; int parbtab, parbsize; @@ -2737,10 +3017,11 @@ pci_conf_print_pcie_power(uint8_t base, s = "275W < x <= 300W"; break; default: - s = "reserved for above 300W"; + s = "reserved for greater than 300W"; break; } printf("%s\n", s); + return; } for (unsigned int i = scale; i > 0; i--) @@ -2798,7 +3079,7 @@ pci_conf_print_pwrbdgt_pwrrail(uint8_t r } static void -pci_conf_print_pwrbdgt_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_pwrbdgt_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; @@ -2847,7 +3128,7 @@ pci_conf_print_rclink_dcl_cap_elmtype(un } static void -pci_conf_print_rclink_dcl_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_rclink_dcl_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; unsigned char nent, linktype; @@ -2926,7 +3207,7 @@ pci_conf_print_rclink_dcl_cap(const pcir /* XXX pci_conf_print_rclink_ctl_cap */ static void -pci_conf_print_rcec_assoc_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_rcec_assoc_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; @@ -2935,6 +3216,18 @@ pci_conf_print_rcec_assoc_cap(const pcir reg = regs[o2i(extcapoff + PCI_RCEC_ASSOC_ASSOCBITMAP)]; printf(" Association Bitmap for Root Complex Integrated Devices:" " 0x%08x\n", reg); + + if (PCI_EXTCAPLIST_VERSION(regs[o2i(extcapoff)]) >= 2) { + reg = regs[o2i(extcapoff + PCI_RCEC_ASSOC_ASSOCBUSNUM)]; + printf(" RCEC Associated Bus Numbers register: 0x%08x\n", + reg); + printf(" RCEC Next Bus: %u\n", + (unsigned int)__SHIFTOUT(reg, + PCI_RCEC_ASSOCBUSNUM_RCECNEXT)); + printf(" RCEC Last Bus: %u\n", + (unsigned int)__SHIFTOUT(reg, + PCI_RCEC_ASSOCBUSNUM_RCECLAST)); + } } /* XXX pci_conf_print_mfvc_cap */ @@ -2944,7 +3237,7 @@ pci_conf_print_rcec_assoc_cap(const pcir /* XXX pci_conf_print_cac_cap */ static void -pci_conf_print_acs_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_acs_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl; unsigned int size, i; @@ -2987,7 +3280,7 @@ pci_conf_print_acs_cap(const pcireg_t *r } static void -pci_conf_print_ari_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_ari_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl; @@ -3009,7 +3302,7 @@ pci_conf_print_ari_cap(const pcireg_t *r } static void -pci_conf_print_ats_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_ats_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl; unsigned int num; @@ -3026,6 +3319,7 @@ pci_conf_print_ats_cap(const pcireg_t *r printf(" Invalidate Queue Depth: %u\n", num); onoff("Page Aligned Request", reg, PCI_ATS_CAP_PALIGNREQ); onoff("Global Invalidate", reg, PCI_ATS_CAP_GLOBALINVL); + onoff("Relaxed Ordering", reg, PCI_ATS_CAP_RELAXORD); printf(" Control register: 0x%04x\n", ctl); printf(" Smallest Translation Unit: %u\n", @@ -3034,7 +3328,7 @@ pci_conf_print_ats_cap(const pcireg_t *r } static void -pci_conf_print_sernum_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_sernum_cap(const pcireg_t *regs, int extcapoff) { pcireg_t lo, hi; @@ -3048,7 +3342,7 @@ pci_conf_print_sernum_cap(const pcireg_t } static void -pci_conf_print_sriov_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_sriov_cap(const pcireg_t *regs, int extcapoff) { char buf[sizeof("99999 MB")]; pcireg_t reg; @@ -3160,7 +3454,7 @@ pci_conf_print_sriov_cap(const pcireg_t /* XXX pci_conf_print_mriov_cap */ static void -pci_conf_print_multicast_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_multicast_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl; pcireg_t regl, regh; @@ -3228,7 +3522,7 @@ pci_conf_print_multicast_cap(const pcire } static void -pci_conf_print_page_req_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_page_req_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, ctl, sta; @@ -3259,7 +3553,7 @@ pci_conf_print_page_req_cap(const pcireg #define MEM_PBUFSIZE sizeof("999GB") static void -pci_conf_print_resizbar_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_resizbar_cap(const pcireg_t *regs, int extcapoff) { pcireg_t cap, ctl; unsigned int bars, i, n; @@ -3316,7 +3610,7 @@ pci_conf_print_resizbar_cap(const pcireg } static void -pci_conf_print_dpa_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_dpa_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; unsigned int substmax, i; @@ -3380,15 +3674,15 @@ pci_conf_print_dpa_cap(const pcireg_t *r } static const char * -pci_conf_print_tph_req_cap_sttabloc(unsigned char val) +pci_conf_print_tph_req_cap_sttabloc(uint8_t val) { switch (val) { - case 0x0: + case PCI_TPH_REQ_STTBLLOC_NONE: return "Not Present"; - case 0x1: + case PCI_TPH_REQ_STTBLLOC_TPHREQ: return "in the TPH Requester Capability Structure"; - case 0x2: + case PCI_TPH_REQ_STTBLLOC_MSIX: return "in the MSI-X Table"; default: return "Unknown"; @@ -3396,10 +3690,11 @@ pci_conf_print_tph_req_cap_sttabloc(unsi } static void -pci_conf_print_tph_req_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_tph_req_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; - int size, i, j; + int size = 0, i, j; + uint8_t sttbloc; printf("\n TPH Requester Extended Capability\n"); @@ -3409,11 +3704,13 @@ pci_conf_print_tph_req_cap(const pcireg_ onoff("Interrupt Vector Mode Supported", reg, PCI_TPH_REQ_CAP_INTVEC); onoff("Device Specific Mode Supported", reg, PCI_TPH_REQ_CAP_DEVSPEC); onoff("Extend TPH Reqester Supported", reg, PCI_TPH_REQ_CAP_XTPHREQ); + sttbloc = __SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLLOC); printf(" ST Table Location: %s\n", - pci_conf_print_tph_req_cap_sttabloc( - (unsigned char)__SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLLOC))); - size = __SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLSIZ) + 1; - printf(" ST Table Size: %d\n", size); + pci_conf_print_tph_req_cap_sttabloc(sttbloc)); + if (sttbloc == PCI_TPH_REQ_STTBLLOC_TPHREQ) { + size = __SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLSIZ) + 1; + printf(" ST Table Size: %d\n", size); + } reg = regs[o2i(extcapoff + PCI_TPH_REQ_CTL)]; printf(" TPH Requester Control register: 0x%08x\n", reg); @@ -3429,7 +3726,7 @@ pci_conf_print_tph_req_cap(const pcireg_ printf("Device Specific Mode\n"); break; default: - printf("(reserved vaule)\n"); + printf("(reserved value)\n"); break; } printf(" TPH Requester Enable: "); @@ -3444,10 +3741,13 @@ pci_conf_print_tph_req_cap(const pcireg_ printf("TPH and Extended TPH"); break; default: - printf("(reserved vaule)\n"); + printf("(reserved value)\n"); break; } - + + if (sttbloc != PCI_TPH_REQ_STTBLLOC_TPHREQ) + return; + for (i = 0; i < size ; i += 2) { reg = regs[o2i(extcapoff + PCI_TPH_REQ_STTBL + i / 2)]; for (j = 0; j < 2 ; j++) { @@ -3463,27 +3763,24 @@ pci_conf_print_tph_req_cap(const pcireg_ } static void -pci_conf_print_ltr_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_ltr_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; printf("\n Latency Tolerance Reporting\n"); - reg = regs[o2i(extcapoff + PCI_LTR_MAXSNOOPLAT)] & 0xffff; - printf(" Max Snoop Latency Register: 0x%04x\n", reg); - printf(" Max Snoop LatencyValue: %u\n", - (pcireg_t)__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_VAL)); - printf(" Max Snoop LatencyScale: %uns\n", - PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_SCALE))); - reg = regs[o2i(extcapoff + PCI_LTR_MAXNOSNOOPLAT)] >> 16; - printf(" Max No-Snoop Latency Register: 0x%04x\n", reg); - printf(" Max No-Snoop LatencyValue: %u\n", - (pcireg_t)__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_VAL)); - printf(" Max No-Snoop LatencyScale: %uns\n", - PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_SCALE))); + reg = regs[o2i(extcapoff + PCI_LTR_MAXSNOOPLAT)]; + printf(" Max Snoop Latency Register: 0x%04x\n", reg & 0xffff); + printf(" Max Snoop Latency: %juns\n", + (uintmax_t)(__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_VAL) + * PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_SCALE)))); + printf(" Max No-Snoop Latency Register: 0x%04x\n", reg >> 16); + printf(" Max No-Snoop Latency: %juns\n", + (uintmax_t)(__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_VAL) + * PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_SCALE)))); } static void -pci_conf_print_sec_pcie_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_sec_pcie_cap(const pcireg_t *regs, int extcapoff) { int pcie_capoff; pcireg_t reg; @@ -3505,7 +3802,7 @@ pci_conf_print_sec_pcie_cap(const pcireg printf(" Lane Error Status register: 0x%08x\n", reg); /* Get Max Link Width */ - if (pci_conf_find_cap(regs, capoff, PCI_CAP_PCIEXPRESS, &pcie_capoff)){ + if (pci_conf_find_cap(regs, PCI_CAP_PCIEXPRESS, &pcie_capoff)) { reg = regs[o2i(pcie_capoff + PCIE_LCAP)]; maxlinkwidth = __SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH); } else { @@ -3536,7 +3833,7 @@ pci_conf_print_sec_pcie_cap(const pcireg /* XXX pci_conf_print_pmux_cap */ static void -pci_conf_print_pasid_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_pasid_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl; unsigned int num; @@ -3559,7 +3856,7 @@ pci_conf_print_pasid_cap(const pcireg_t } static void -pci_conf_print_lnr_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_lnr_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl; unsigned int num; @@ -3597,7 +3894,7 @@ pci_conf_print_dpc_pio(pcireg_t r) } static void -pci_conf_print_dpc_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_dpc_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg, cap, ctl, stat, errsrc; const char *trigstr; @@ -3717,7 +4014,7 @@ pci_conf_print_dpc_cap(const pcireg_t *r extcapoff + PCI_DPC_RPPIO_HLOG); printf(" RP PIO ImpSpec Log Register: start from 0x%03x\n", extcapoff + PCI_DPC_RPPIO_IMPSLOG); - printf(" RP PIO TPL Prefix Log Register: start from 0x%03x\n", + printf(" RP PIO TLP Prefix Log Register: start from 0x%03x\n", extcapoff + PCI_DPC_RPPIO_TLPPLOG); } @@ -3740,10 +4037,11 @@ pci_conf_l1pm_cap_tposcale(unsigned char } static void -pci_conf_print_l1pm_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_l1pm_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; int scale, val; + int pcie_capoff; printf("\n L1 PM Substates\n"); @@ -3754,6 +4052,14 @@ pci_conf_print_l1pm_cap(const pcireg_t * onoff("ASPM L1.2 Supported", reg, PCI_L1PM_CAP_ASPM12); onoff("ASPM L1.1 Supported", reg, PCI_L1PM_CAP_ASPM11); onoff("L1 PM Substates Supported", reg, PCI_L1PM_CAP_L1PM); + /* The Link Activation Supported bit is only for Downstream Port */ + if (pci_conf_find_cap(regs, PCI_CAP_PCIEXPRESS, &pcie_capoff)) { + uint32_t t = regs[o2i(pcie_capoff)]; + + if ((t == PCIE_XCAP_TYPE_ROOT) || (t == PCIE_XCAP_TYPE_DOWN)) + onoff("Link Activation Supported", reg, + PCI_L1PM_CAP_LA); + } printf(" Port Common Mode Restore Time: %uus\n", (unsigned int)__SHIFTOUT(reg, PCI_L1PM_CAP_PCMRT)); scale = pci_conf_l1pm_cap_tposcale( @@ -3771,6 +4077,8 @@ pci_conf_print_l1pm_cap(const pcireg_t * onoff("PCI-PM L1.1 Enable", reg, PCI_L1PM_CTL1_PCIPM11_EN); onoff("ASPM L1.2 Enable", reg, PCI_L1PM_CTL1_ASPM12_EN); onoff("ASPM L1.1 Enable", reg, PCI_L1PM_CTL1_ASPM11_EN); + onoff("Link Activation Interrupt Enable", reg, PCI_L1PM_CTL1_LAIE); + onoff("Link Activation Control", reg, PCI_L1PM_CTL1_LA); printf(" Common Mode Restore Time: %uus\n", (unsigned int)__SHIFTOUT(reg, PCI_L1PM_CTL1_CMRT)); scale = PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_L1PM_CTL1_LTRTHSCALE)); @@ -3787,10 +4095,16 @@ pci_conf_print_l1pm_cap(const pcireg_t * printf("unknown\n"); else printf("%dus\n", val * scale); + + if (PCI_EXTCAPLIST_VERSION(regs[o2i(extcapoff)]) >= 2) { + reg = regs[o2i(extcapoff + PCI_L1PM_CTL2)]; + printf(" L1 PM Substates Status register: 0x%08x\n", reg); + onoff("Link Activation Status", reg, PCI_L1PM_STAT_LA); + } } static void -pci_conf_print_ptm_cap(const pcireg_t *regs, int capoff, int extcapoff) +pci_conf_print_ptm_cap(const pcireg_t *regs, int extcapoff) { pcireg_t reg; uint32_t val; @@ -3841,6 +4155,7 @@ pci_conf_print_ptm_cap(const pcireg_t *r /* XXX pci_conf_print_desigvndsp_cap */ /* XXX pci_conf_print_vf_resizbar_cap */ /* XXX pci_conf_print_hierarchyid_cap */ +/* XXX pci_conf_print_npem_cap */ #undef MS #undef SM @@ -3849,7 +4164,7 @@ pci_conf_print_ptm_cap(const pcireg_t *r static struct { pcireg_t cap; const char *name; - void (*printfunc)(const pcireg_t *, int, int); + void (*printfunc)(const pcireg_t *, int); } pci_extcaptab[] = { { 0, "reserved", NULL }, @@ -3907,7 +4222,7 @@ static struct { NULL }, { PCI_EXTCAP_PASID, "Process Address Space ID", pci_conf_print_pasid_cap }, - { PCI_EXTCAP_LN_REQ, "LN Requester", + { PCI_EXTCAP_LNR, "LN Requester", pci_conf_print_lnr_cap }, { PCI_EXTCAP_DPC, "Downstream Port Containment", pci_conf_print_dpc_cap }, @@ -3925,13 +4240,17 @@ static struct { NULL }, { PCI_EXTCAP_VF_RESIZBAR, "VF Resizable BARs", NULL }, + { 0x25, "unknown", NULL }, + { 0x26, "unknown", NULL }, + { 0x27, "unknown", NULL }, { PCI_EXTCAP_HIERARCHYID, "Hierarchy ID", NULL }, + { PCI_EXTCAP_NPEM, "Native PCIe Enclosure Management", + NULL }, }; static int -pci_conf_find_extcap(const pcireg_t *regs, int capoff, unsigned int capid, - int *offsetp) +pci_conf_find_extcap(const pcireg_t *regs, unsigned int capid, int *offsetp) { int off; pcireg_t rval; @@ -3954,7 +4273,7 @@ pci_conf_print_extcaplist( #ifdef _KERNEL pci_chipset_tag_t pc, pcitag_t tag, #endif - const pcireg_t *regs, int capoff) + const pcireg_t *regs) { int off; pcireg_t foundcap; @@ -4009,14 +4328,14 @@ pci_conf_print_extcaplist( * print all capabilities that the capabiliy type is * the same. */ - if (pci_conf_find_extcap(regs, capoff, i, &off) == 0) + if (pci_conf_find_extcap(regs, i, &off) == 0) continue; rval = regs[o2i(off)]; if ((PCI_EXTCAPLIST_VERSION(rval) <= 0) || (pci_extcaptab[i].printfunc == NULL)) continue; - pci_extcaptab[i].printfunc(regs, capoff, off); + pci_extcaptab[i].printfunc(regs, off); } } @@ -4067,6 +4386,7 @@ pci_conf_print_type0( { int off, width; pcireg_t rval; + const char *str; for (off = PCI_MAPREG_START; off < PCI_MAPREG_END; off += width) { #ifdef _KERNEL @@ -4083,9 +4403,43 @@ pci_conf_print_type0( printf(" Subsystem vendor ID: 0x%04x\n", PCI_VENDOR(rval)); printf(" Subsystem ID: 0x%04x\n", PCI_PRODUCT(rval)); - /* XXX */ - printf(" Expansion ROM Base Address: 0x%08x\n", - regs[o2i(PCI_MAPREG_ROM)]); + rval = regs[o2i(PCI_MAPREG_ROM)]; + printf(" Expansion ROM Base Address Register: 0x%08x\n", rval); + printf(" base: 0x%08x\n", (uint32_t)PCI_MAPREG_ROM_ADDR(rval)); + onoff("Expansion ROM Enable", rval, PCI_MAPREG_ROM_ENABLE); + printf(" Validation Status: "); + switch (__SHIFTOUT(rval, PCI_MAPREG_ROM_VALID_STAT)) { + case PCI_MAPREG_ROM_VSTAT_NOTSUPP: + str = "Validation not supported"; + break; + case PCI_MAPREG_ROM_VSTAT_INPROG: + str = "Validation in Progress"; + break; + case PCI_MAPREG_ROM_VSTAT_VPASS: + str = "Validation Pass. " + "Valid contents, trust test was not performed"; + break; + case PCI_MAPREG_ROM_VSTAT_VPASSTRUST: + str = "Validation Pass. Valid and trusted contents"; + break; + case PCI_MAPREG_ROM_VSTAT_VFAIL: + str = "Validation Fail. Invalid contents"; + break; + case PCI_MAPREG_ROM_VSTAT_VFAILUNTRUST: + str = "Validation Fail. Valid but untrusted contents"; + break; + case PCI_MAPREG_ROM_VSTAT_WPASS: + str = "Warning Pass. Validation passed with warning. " + "Valid contents, trust test was not performed"; + break; + case PCI_MAPREG_ROM_VSTAT_WPASSTRUST: + str = "Warning Pass. Validation passed with warning. " + "Valid and trusted contents"; + break; + } + printf("%s\n", str); + printf(" Validation Details: 0x%x\n", + (uint32_t)__SHIFTOUT(rval, PCI_MAPREG_ROM_VALID_DETAIL)); if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT) printf(" Capability list pointer: 0x%02x\n", @@ -4131,7 +4485,7 @@ pci_conf_print_type1( const pcireg_t *regs) { int off, width; - pcireg_t rval; + pcireg_t rval, csreg; uint32_t base, limit; uint32_t base_h, limit_h; uint64_t pbase, plimit; @@ -4190,9 +4544,9 @@ pci_conf_print_type1( } if (base < limit) { if (use_upper == 1) - printf(" range: 0x%08x-0x%08x\n", base, limit); + printf(" range: 0x%08x-0x%08x\n", base, limit); else - printf(" range: 0x%04x-0x%04x\n", base, limit); + printf(" range: 0x%04x-0x%04x\n", base, limit); } else printf(" range: not set\n"); @@ -4208,9 +4562,9 @@ pci_conf_print_type1( limit = (((rval >> PCI_BRIDGE_MEMORY_LIMIT_SHIFT) & PCI_BRIDGE_MEMORY_LIMIT_MASK) << 20) | 0x000fffff; if (base < limit) - printf(" range: 0x%08x-0x%08x\n", base, limit); + printf(" range: 0x%08x-0x%08x\n", base, limit); else - printf(" range: not set\n"); + printf(" range: not set\n"); /* Prefetchable memory region */ rval = regs[o2i(PCI_BRIDGE_PREFETCHMEM_REG)]; @@ -4240,15 +4594,16 @@ pci_conf_print_type1( } if (pbase < plimit) { if (use_upper == 1) - printf(" range: 0x%016" PRIx64 "-0x%016" PRIx64 + printf(" range: 0x%016" PRIx64 "-0x%016" PRIx64 "\n", pbase, plimit); else - printf(" range: 0x%08x-0x%08x\n", + printf(" range: 0x%08x-0x%08x\n", (uint32_t)pbase, (uint32_t)plimit); } else - printf(" range: not set\n"); + printf(" range: not set\n"); - if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT) + csreg = regs[o2i(PCI_COMMAND_STATUS_REG)]; + if (csreg & PCI_STATUS_CAPLIST_SUPPORT) printf(" Capability list pointer: 0x%02x\n", PCI_CAPLIST_PTR(regs[o2i(PCI_CAPLISTPTR_REG)])); else @@ -4290,6 +4645,13 @@ pci_conf_print_type1( onoff("Secondary SERR forwarding", rval, PCI_BRIDGE_CONTROL_SERR); onoff("ISA enable", rval, PCI_BRIDGE_CONTROL_ISA); onoff("VGA enable", rval, PCI_BRIDGE_CONTROL_VGA); + /* + * VGA 16bit decode bit has meaning if the VGA enable bit or the + * VGA Palette Snoop Enable bit is set. + */ + if (((rval & PCI_BRIDGE_CONTROL_VGA) != 0) + || ((csreg & PCI_COMMAND_PALETTE_ENABLE) != 0)) + onoff("VGA 16bit enable", rval, PCI_BRIDGE_CONTROL_VGA16); onoff("Master abort reporting", rval, PCI_BRIDGE_CONTROL_MABRT); onoff("Secondary bus reset", rval, PCI_BRIDGE_CONTROL_SECBR); onoff("Fast back-to-back capable", rval,PCI_BRIDGE_CONTROL_SECFASTB2B); @@ -4510,23 +4872,23 @@ pci_conf_print( /* device-dependent header */ printf(" Device-dependent header:\n"); pci_conf_print_regs(regs, endoff, PCI_CONF_SIZE); - printf("\n"); #ifdef _KERNEL + printf("\n"); if (printfn) (*printfn)(pc, tag, regs); else printf(" Don't know how to pretty-print device-dependent header.\n"); - printf("\n"); #endif /* _KERNEL */ if (regs[o2i(PCI_EXTCAPLIST_BASE)] == 0xffffffff || regs[o2i(PCI_EXTCAPLIST_BASE)] == 0) return; + printf("\n"); #ifdef _KERNEL - pci_conf_print_extcaplist(pc, tag, regs, capoff); + pci_conf_print_extcaplist(pc, tag, regs); #else - pci_conf_print_extcaplist(regs, capoff); + pci_conf_print_extcaplist(regs); #endif printf("\n");