version 1.148, 2016/06/20 10:02:43 |
version 1.148.2.1, 2016/11/04 14:49:10 |
Line 54 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 54 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/module.h> |
#include <sys/module.h> |
#else |
#else |
#include <pci.h> |
#include <pci.h> |
|
#include <stdarg.h> |
#include <stdbool.h> |
#include <stdbool.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
Line 567 static const struct pci_class pci_class[ |
|
Line 568 static const struct pci_class pci_class[ |
|
|
|
DEV_VERBOSE_DEFINE(pci); |
DEV_VERBOSE_DEFINE(pci); |
|
|
|
/* |
|
* Append a formatted string to dest without writing more than len |
|
* characters (including the trailing NUL character). dest and len |
|
* are updated for use in subsequent calls to snappendf(). |
|
* |
|
* Returns 0 on success, a negative value if vnsprintf() fails, or |
|
* a positive value if the dest buffer would have overflowed. |
|
*/ |
|
|
|
static int __printflike(3,4) |
|
snappendf(char **dest, size_t *len, const char * restrict fmt, ...) |
|
{ |
|
va_list ap; |
|
int count; |
|
|
|
va_start(ap, fmt); |
|
count = vsnprintf(*dest, *len, fmt, ap); |
|
va_end(ap); |
|
|
|
/* Let vsnprintf() errors bubble up to caller */ |
|
if (count < 0 || *len == 0) |
|
return count; |
|
|
|
/* Handle overflow */ |
|
if ((size_t)count >= *len) { |
|
*dest += *len - 1; |
|
*len = 1; |
|
return 1; |
|
} |
|
|
|
/* Update dest & len to point at trailing NUL */ |
|
*dest += count; |
|
*len -= count; |
|
|
|
return 0; |
|
} |
|
|
void |
void |
pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp, |
pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp, |
size_t l) |
size_t l) |
Line 577 pci_devinfo(pcireg_t id_reg, pcireg_t cl |
|
Line 615 pci_devinfo(pcireg_t id_reg, pcireg_t cl |
|
pci_revision_t revision; |
pci_revision_t revision; |
char vendor[PCI_VENDORSTR_LEN], product[PCI_PRODUCTSTR_LEN]; |
char vendor[PCI_VENDORSTR_LEN], product[PCI_PRODUCTSTR_LEN]; |
const struct pci_class *classp, *subclassp, *interfacep; |
const struct pci_class *classp, *subclassp, *interfacep; |
char *ep; |
|
|
|
ep = cp + l; |
|
|
|
pciclass = PCI_CLASS(class_reg); |
pciclass = PCI_CLASS(class_reg); |
subclass = PCI_SUBCLASS(class_reg); |
subclass = PCI_SUBCLASS(class_reg); |
Line 612 pci_devinfo(pcireg_t id_reg, pcireg_t cl |
|
Line 647 pci_devinfo(pcireg_t id_reg, pcireg_t cl |
|
interfacep++; |
interfacep++; |
} |
} |
|
|
cp += snprintf(cp, ep - cp, "%s %s", vendor, product); |
(void)snappendf(&cp, &l, "%s %s", vendor, product); |
if (showclass) { |
if (showclass) { |
cp += snprintf(cp, ep - cp, " ("); |
(void)snappendf(&cp, &l, " ("); |
if (classp->name == NULL) |
if (classp->name == NULL) |
cp += snprintf(cp, ep - cp, |
(void)snappendf(&cp, &l, |
"class 0x%02x, subclass 0x%02x", pciclass, subclass); |
"class 0x%02x, subclass 0x%02x", |
|
pciclass, subclass); |
else { |
else { |
if (subclassp == NULL || subclassp->name == NULL) |
if (subclassp == NULL || subclassp->name == NULL) |
cp += snprintf(cp, ep - cp, |
(void)snappendf(&cp, &l, |
"%s, subclass 0x%02x", |
"%s, subclass 0x%02x", |
classp->name, subclass); |
classp->name, subclass); |
else |
else |
cp += snprintf(cp, ep - cp, "%s %s", |
(void)snappendf(&cp, &l, "%s %s", |
subclassp->name, classp->name); |
subclassp->name, classp->name); |
} |
} |
if ((interfacep == NULL) || (interfacep->name == NULL)) { |
if ((interfacep == NULL) || (interfacep->name == NULL)) { |
if (interface != 0) |
if (interface != 0) |
cp += snprintf(cp, ep - cp, |
(void)snappendf(&cp, &l, ", interface 0x%02x", |
", interface 0x%02x", interface); |
interface); |
} else if (strncmp(interfacep->name, "", 1) != 0) |
} else if (strncmp(interfacep->name, "", 1) != 0) |
cp += snprintf(cp, ep - cp, ", %s", |
(void)snappendf(&cp, &l, ", %s", interfacep->name); |
interfacep->name); |
|
if (revision != 0) |
if (revision != 0) |
cp += snprintf(cp, ep - cp, ", revision 0x%02x", |
(void)snappendf(&cp, &l, ", revision 0x%02x", revision); |
revision); |
(void)snappendf(&cp, &l, ")"); |
cp += snprintf(cp, ep - cp, ")"); |
|
} |
} |
} |
} |
|
|
Line 1080 pci_conf_print_msi_cap(const pcireg_t *r |
|
Line 1114 pci_conf_print_msi_cap(const pcireg_t *r |
|
mme > 0 ? "on" : "off", 1 << mme, mme > 0 ? "s" : ""); |
mme > 0 ? "on" : "off", 1 << mme, mme > 0 ? "s" : ""); |
onoff("64 Bit Address Capable", ctl, PCI_MSI_CTL_64BIT_ADDR); |
onoff("64 Bit Address Capable", ctl, PCI_MSI_CTL_64BIT_ADDR); |
onoff("Per-Vector Masking Capable", ctl, PCI_MSI_CTL_PERVEC_MASK); |
onoff("Per-Vector Masking Capable", ctl, PCI_MSI_CTL_PERVEC_MASK); |
|
onoff("Extended Message Data Capable", ctl, PCI_MSI_CTL_EXTMDATA_CAP); |
|
onoff("Extended Message Data Enable", ctl, PCI_MSI_CTL_EXTMDATA_EN); |
printf(" Message Address %sregister: 0x%08x\n", |
printf(" Message Address %sregister: 0x%08x\n", |
ctl & PCI_MSI_CTL_64BIT_ADDR ? "(lower) " : "", *regs++); |
ctl & PCI_MSI_CTL_64BIT_ADDR ? "(lower) " : "", *regs++); |
if (ctl & PCI_MSI_CTL_64BIT_ADDR) { |
if (ctl & PCI_MSI_CTL_64BIT_ADDR) { |
Line 1594 pci_conf_print_pcie_cap(const pcireg_t * |
|
Line 1630 pci_conf_print_pcie_cap(const pcireg_t * |
|
onoff("Unsupported Request Detected", reg, PCIE_DCSR_URD); |
onoff("Unsupported Request Detected", reg, PCIE_DCSR_URD); |
onoff("Aux Power Detected", reg, PCIE_DCSR_AUX_PWR); |
onoff("Aux Power Detected", reg, PCIE_DCSR_AUX_PWR); |
onoff("Transaction Pending", reg, PCIE_DCSR_TRANSACTION_PND); |
onoff("Transaction Pending", reg, PCIE_DCSR_TRANSACTION_PND); |
|
onoff("Emergency Power Reduction Detected", reg, |
|
PCIE_DCSR_EMGPWRREDD); |
|
|
if (check_link) { |
if (check_link) { |
/* Link Capability Register */ |
/* Link Capability Register */ |
Line 1862 pci_conf_print_pcie_cap(const pcireg_t * |
|
Line 1900 pci_conf_print_pcie_cap(const pcireg_t * |
|
onoff("End-End TLP Prefix Supported", reg, PCIE_DCAP2_EETLP_PREF); |
onoff("End-End TLP Prefix Supported", reg, PCIE_DCAP2_EETLP_PREF); |
printf(" Max End-End TLP Prefixes: %u\n", |
printf(" Max End-End TLP Prefixes: %u\n", |
(unsigned int)(reg & PCIE_DCAP2_MAX_EETLP) >> 22); |
(unsigned int)(reg & PCIE_DCAP2_MAX_EETLP) >> 22); |
|
printf(" Emergency Power Reduction Supported: "); |
|
switch (__SHIFTOUT(reg, PCIE_DCAP2_EMGPWRRED)) { |
|
case 0x0: |
|
printf("Not supported\n"); |
|
break; |
|
case 0x1: |
|
printf("Device Specific mechanism\n"); |
|
break; |
|
case 0x2: |
|
printf("Form Factor spec or Device Specific mechanism\n"); |
|
break; |
|
case 0x3: |
|
printf("Reserved\n"); |
|
break; |
|
} |
|
onoff("Emergency Power Reduction Initialization Required", reg, |
|
PCIE_DCAP2_EMGPWRRED_INI); |
onoff("FRS Supported", reg, PCIE_DCAP2_FRS); |
onoff("FRS Supported", reg, PCIE_DCAP2_FRS); |
|
|
/* Device Control 2 */ |
/* Device Control 2 */ |
Line 1876 pci_conf_print_pcie_cap(const pcireg_t * |
|
Line 1931 pci_conf_print_pcie_cap(const pcireg_t * |
|
onoff("IDO Request Enabled", reg, PCIE_DCSR2_IDO_REQ); |
onoff("IDO Request Enabled", reg, PCIE_DCSR2_IDO_REQ); |
onoff("IDO Completion Enabled", reg, PCIE_DCSR2_IDO_COMP); |
onoff("IDO Completion Enabled", reg, PCIE_DCSR2_IDO_COMP); |
onoff("LTR Mechanism Enabled", reg, PCIE_DCSR2_LTR_MEC); |
onoff("LTR Mechanism Enabled", reg, PCIE_DCSR2_LTR_MEC); |
|
onoff("Emergency Power Reduction Request", reg, |
|
PCIE_DCSR2_EMGPWRRED_REQ); |
printf(" OBFF: "); |
printf(" OBFF: "); |
switch ((reg & PCIE_DCSR2_OBFF_EN) >> 13) { |
switch ((reg & PCIE_DCSR2_OBFF_EN) >> 13) { |
case 0x0: |
case 0x0: |
Line 2478 pci_conf_print_pwrbdgt_base_power(uint8_ |
|
Line 2535 pci_conf_print_pwrbdgt_base_power(uint8_ |
|
case 0xf2: |
case 0xf2: |
return "275W < x <= 300W"; |
return "275W < x <= 300W"; |
default: |
default: |
return "Unknown"; |
break; |
} |
} |
|
if (reg >= 0xf3) |
|
return "reserved for above 300W"; |
|
|
|
return "Unknown"; |
} |
} |
|
|
static const char * |
static const char * |
Line 2513 pci_conf_print_pwrbdgt_type(uint8_t reg) |
|
Line 2574 pci_conf_print_pwrbdgt_type(uint8_t reg) |
|
return "Idle"; |
return "Idle"; |
case 0x03: |
case 0x03: |
return "Sustained"; |
return "Sustained"; |
|
case 0x04: |
|
return "Sustained (Emergency Power Reduction)"; |
|
case 0x05: |
|
return "Maximum (Emergency Power Reduction)"; |
case 0x07: |
case 0x07: |
return "Maximun"; |
return "Maximun"; |
default: |
default: |
Line 2992 pci_conf_print_page_req_cap(const pcireg |
|
Line 3057 pci_conf_print_page_req_cap(const pcireg |
|
} |
} |
|
|
/* XXX pci_conf_print_amd_cap */ |
/* XXX pci_conf_print_amd_cap */ |
/* XXX pci_conf_print_resiz_bar_cap */ |
|
/* XXX pci_conf_print_dpa_cap */ |
#define MEM_PBUFSIZE sizeof("999GB") |
|
|
|
static void |
|
pci_conf_print_resizbar_cap(const pcireg_t *regs, int capoff, int extcapoff) |
|
{ |
|
pcireg_t cap, ctl; |
|
unsigned int bars, i, n; |
|
char pbuf[MEM_PBUFSIZE]; |
|
|
|
printf("\n Resizable BAR\n"); |
|
|
|
/* Get Number of Resizable BARs */ |
|
ctl = regs[o2i(extcapoff + PCI_RESIZBAR_CTL(0))]; |
|
bars = __SHIFTOUT(ctl, PCI_RESIZBAR_CTL_NUMBAR); |
|
printf(" Number of Resizable BARs: "); |
|
if (bars <= 6) |
|
printf("%u\n", bars); |
|
else { |
|
printf("incorrect (%u)\n", bars); |
|
return; |
|
} |
|
|
|
for (n = 0; n < 6; n++) { |
|
cap = regs[o2i(extcapoff + PCI_RESIZBAR_CAP(n))]; |
|
printf(" Capability register(%u): 0x%08x\n", n, cap); |
|
if ((cap & PCI_RESIZBAR_CAP_SIZEMASK) == 0) |
|
continue; /* Not Used */ |
|
printf(" Acceptable BAR sizes:"); |
|
for (i = 4; i <= 23; i++) { |
|
if ((cap & (1 << i)) != 0) { |
|
humanize_number(pbuf, MEM_PBUFSIZE, |
|
(int64_t)1024 * 1024 << (i - 4), "B", |
|
#ifdef _KERNEL |
|
1); |
|
#else |
|
HN_AUTOSCALE, HN_NOSPACE); |
|
#endif |
|
printf(" %s", pbuf); |
|
} |
|
} |
|
printf("\n"); |
|
|
|
ctl = regs[o2i(extcapoff + PCI_RESIZBAR_CTL(n))]; |
|
printf(" Control register(%u): 0x%08x\n", n, ctl); |
|
printf(" BAR Index: %u\n", |
|
(unsigned int)__SHIFTOUT(ctl, PCI_RESIZBAR_CTL_BARIDX)); |
|
humanize_number(pbuf, MEM_PBUFSIZE, |
|
(int64_t)1024 * 1024 |
|
<< __SHIFTOUT(ctl, PCI_RESIZBAR_CTL_BARSIZ), |
|
"B", |
|
#ifdef _KERNEL |
|
1); |
|
#else |
|
HN_AUTOSCALE, HN_NOSPACE); |
|
#endif |
|
printf(" BAR Size: %s\n", pbuf); |
|
} |
|
} |
|
|
|
static void |
|
pci_conf_print_dpa_cap(const pcireg_t *regs, int capoff, int extcapoff) |
|
{ |
|
pcireg_t reg; |
|
unsigned int substmax, i; |
|
|
|
printf("\n Dynamic Power Allocation\n"); |
|
|
|
reg = regs[o2i(extcapoff + PCI_DPA_CAP)]; |
|
printf(" Capability register: 0x%08x\n", reg); |
|
substmax = __SHIFTOUT(reg, PCI_DPA_CAP_SUBSTMAX); |
|
printf(" Substate Max: %u\n", substmax); |
|
printf(" Transition Latency Unit: "); |
|
switch (__SHIFTOUT(reg, PCI_DPA_CAP_TLUINT)) { |
|
case 0: |
|
printf("1ms\n"); |
|
break; |
|
case 1: |
|
printf("10ms\n"); |
|
break; |
|
case 2: |
|
printf("100ms\n"); |
|
break; |
|
default: |
|
printf("reserved\n"); |
|
break; |
|
} |
|
printf(" Power Allocation Scale: "); |
|
switch (__SHIFTOUT(reg, PCI_DPA_CAP_PAS)) { |
|
case 0: |
|
printf("10.0x\n"); |
|
break; |
|
case 1: |
|
printf("1.0x\n"); |
|
break; |
|
case 2: |
|
printf("0.1x\n"); |
|
break; |
|
case 3: |
|
printf("0.01x\n"); |
|
break; |
|
} |
|
printf(" Transition Latency Value 0: %u\n", |
|
(unsigned int)__SHIFTOUT(reg, PCI_DPA_CAP_XLCY0)); |
|
printf(" Transition Latency Value 1: %u\n", |
|
(unsigned int)__SHIFTOUT(reg, PCI_DPA_CAP_XLCY1)); |
|
|
|
reg = regs[o2i(extcapoff + PCI_DPA_LATIND)]; |
|
printf(" Latency Indicatior register: 0x%08x\n", reg); |
|
|
|
reg = regs[o2i(extcapoff + PCI_DPA_CS)]; |
|
printf(" Status register: 0x%04x\n", reg & 0xffff); |
|
printf(" Substate Status: %02x\n", |
|
(unsigned int)__SHIFTOUT(reg, PCI_DPA_CS_SUBSTSTAT)); |
|
onoff("Substate Control Enabled", reg, PCI_DPA_CS_SUBSTCTLEN); |
|
printf(" Control register: 0x%04x\n", reg >> 16); |
|
printf(" Substate Control: %02x\n", |
|
(unsigned int)__SHIFTOUT(reg, PCI_DPA_CS_SUBSTCTL)); |
|
|
|
for (i = 0; i <= substmax; i++) |
|
printf(" Substate Power Allocation register %d: 0x%02x\n", |
|
i, (regs[PCI_DPA_PWRALLOC + (i / 4)] >> (i % 4) & 0xff)); |
|
} |
|
|
static const char * |
static const char * |
pci_conf_print_tph_req_cap_sttabloc(unsigned char val) |
pci_conf_print_tph_req_cap_sttabloc(unsigned char val) |
Line 3283 pci_conf_print_ptm_cap(const pcireg_t *r |
|
Line 3469 pci_conf_print_ptm_cap(const pcireg_t *r |
|
/* XXX pci_conf_print_frsq_cap */ |
/* XXX pci_conf_print_frsq_cap */ |
/* XXX pci_conf_print_rtr_cap */ |
/* XXX pci_conf_print_rtr_cap */ |
/* XXX pci_conf_print_desigvndsp_cap */ |
/* XXX pci_conf_print_desigvndsp_cap */ |
|
/* XXX pci_conf_print_vf_resizbar_cap */ |
|
|
#undef MS |
#undef MS |
#undef SM |
#undef SM |
Line 3335 static struct { |
|
Line 3522 static struct { |
|
pci_conf_print_page_req_cap }, |
pci_conf_print_page_req_cap }, |
{ PCI_EXTCAP_AMD, "Reserved for AMD", |
{ PCI_EXTCAP_AMD, "Reserved for AMD", |
NULL }, |
NULL }, |
{ PCI_EXTCAP_RESIZ_BAR, "Resizable BAR", |
{ PCI_EXTCAP_RESIZBAR, "Resizable BAR", |
NULL }, |
pci_conf_print_resizbar_cap }, |
{ PCI_EXTCAP_DPA, "Dynamic Power Allocation", |
{ PCI_EXTCAP_DPA, "Dynamic Power Allocation", |
NULL }, |
NULL }, |
{ PCI_EXTCAP_TPH_REQ, "TPH Requester", |
{ PCI_EXTCAP_TPH_REQ, "TPH Requester", |
Line 3365 static struct { |
|
Line 3552 static struct { |
|
NULL }, |
NULL }, |
{ PCI_EXTCAP_DESIGVNDSP, "Designated Vendor-Specific", |
{ PCI_EXTCAP_DESIGVNDSP, "Designated Vendor-Specific", |
NULL }, |
NULL }, |
|
{ PCI_EXTCAP_VF_RESIZBAR, "VF Resizable BARs", |
|
NULL }, |
}; |
}; |
|
|
static int |
static int |