Index: sys/dev/pci/pcireg.h =================================================================== --- sys/dev/pci/pcireg.h +++ sys/dev/pci/pcireg.h @@ -146,6 +146,7 @@ #define PCIY_MSIX 0x11 /* MSI-X */ #define PCIY_SATA 0x12 /* SATA */ #define PCIY_PCIAF 0x13 /* PCI Advanced Features */ +#define PCIY_EA 0x14 /* PCI Extended Allocation */ /* Extended Capability Register Fields */ @@ -586,6 +587,52 @@ #define PCIR_MSI_MASK 0x10 #define PCIR_MSI_PENDING 0x14 +/* PCI Enhanced Allocation registers */ +#define PCIR_EA_NUM_ENT 2 /* Number of Capability Entries */ +#define PCIM_EA_NUM_ENT_MASK 0x3f /* Num Entries Mask */ +#define PCIR_EA_FIRST_ENT 4 /* First EA Entry in List */ +#define PCIR_EA_FIRST_ENT_BRIDGE 8 /* First EA Entry for Bridges */ +#define PCIM_EA_ES 0x00000007 /* Entry Size */ +#define PCIM_EA_BEI 0x000000f0 /* BAR Equivalent Indicator */ +#define PCIM_EA_BEI_OFFSET 4 +/* 0-5 map to BARs 0-5 respectively */ +#define PCIM_EA_BEI_BAR_0 0 +#define PCIM_EA_BEI_BAR_5 5 +#define PCIM_EA_BEI_BAR(x) (((x) >> PCIM_EA_BEI_OFFSET) & 0xf) +#define PCIM_EA_BEI_BRIDGE 0x6 /* Resource behind bridge */ +#define PCIM_EA_BEI_ENI 0x7 /* Equivalent Not Indicated */ +#define PCIM_EA_BEI_ROM 0x8 /* Expansion ROM */ +/* 9-14 map to VF BARs 0-5 respectively */ +#define PCIM_EA_BEI_VF_BAR_0 9 +#define PCIM_EA_BEI_VF_BAR_5 14 +#define PCIM_EA_BEI_RESERVED 0xf /* Reserved - Treat like ENI */ +#define PCIM_EA_PP 0x0000ff00 /* Primary Properties */ +#define PCIM_EA_PP_OFFSET 8 +#define PCIM_EA_SP_OFFSET 16 +#define PCIM_EA_SP 0x00ff0000 /* Secondary Properties */ +#define PCIM_EA_P_MEM 0x00 /* Non-Prefetch Memory */ +#define PCIM_EA_P_MEM_PREFETCH 0x01 /* Prefetchable Memory */ +#define PCIM_EA_P_IO 0x02 /* I/O Space */ +#define PCIM_EA_P_VF_MEM_PREFETCH 0x03 /* VF Prefetchable Memory */ +#define PCIM_EA_P_VF_MEM 0x04 /* VF Non-Prefetch Memory */ +#define PCIM_EA_P_BRIDGE_MEM 0x05 /* Bridge Non-Prefetch Memory */ +#define PCIM_EA_P_BRIDGE_MEM_PREFETCH 0x06 /* Bridge Prefetchable Memory */ +#define PCIM_EA_P_BRIDGE_IO 0x07 /* Bridge I/O Space */ +/* 0x08-0xfc reserved */ +#define PCIM_EA_P_MEM_RESERVED 0xfd /* Reserved Memory */ +#define PCIM_EA_P_IO_RESERVED 0xfe /* Reserved I/O Space */ +#define PCIM_EA_P_UNAVAILABLE 0xff /* Entry Unavailable */ +#define PCIM_EA_WRITABLE 0x40000000 /* Writable: 1 = RW, 0 = HwInit */ +#define PCIM_EA_ENABLE 0x80000000 /* Enable for this entry */ +#define PCIM_EA_BASE 4 /* Base Address Offset */ +#define PCIM_EA_MAX_OFFSET 8 /* MaxOffset (resource length) */ +/* bit 0 is reserved */ +#define PCIM_EA_IS_64 0x00000002 /* 64-bit field flag */ +#define PCIM_EA_FIELD_MASK 0xfffffffc /* For Base & Max Offset */ +/* Bridge config register */ +#define PCIM_EA_SEC_NR(reg) ((reg) & 0xff) +#define PCIM_EA_SUB_NR(reg) (((reg) >> 8) & 0xff) + /* PCI-X definitions */ /* For header type 0 devices */ Index: usr.sbin/pciconf/cap.c =================================================================== --- usr.sbin/pciconf/cap.c +++ usr.sbin/pciconf/cap.c @@ -534,6 +534,150 @@ cap & PCIM_PCIAFCAP_TP ? " TP" : ""); } +static const char * +ea_bei_to_name(uint8_t bei) +{ + + switch (bei) { + case 0: + return "BAR0"; + case 1: + return "BAR1"; + case 2: + return "BAR2"; + case 3: + return "BAR3"; + case 4: + return "BAR4"; + case 5: + return "BAR5"; + case 6: + return "BRIDGE"; + case 7: + return "ENI"; + case 8: + return "ROM"; + case 9: + return "VFBAR0"; + case 10: + return "VFBAR1"; + case 11: + return "VFBAR2"; + case 12: + return "VFBAR3"; + case 13: + return "VFBAR4"; + case 14: + return "VFBAR5"; + case 15: + default: + return "RSVD"; + } +} + +static const char * +ea_prop_to_name(uint8_t prop) +{ + + switch (prop) { + case 0: + return "Non-Prefetchable Memory"; + case 1: + return "Prefetchable Memory"; + case 2: + return "I/O Space"; + case 3: + return "VF Prefetchable Memory"; + case 4: + return "VF Non-Prefetchable Memory"; + case 5: + return "Bridge Non-Prefetchable Memory"; + case 6: + return "Bridge Prefetchable Memory"; + case 7: + return "Bridge I/O Space"; + case 0xff: + return "Unavailable"; + default: + return "Reserved"; + } +} + +static void +cap_ea(int fd, struct pci_conf *p, uint8_t ptr) +{ + int num_ent; + int a, b; + uint32_t bei; + uint32_t val; + int ent_size; + uint32_t dw[4]; + uint32_t flags, flags_pp, flags_sp; + uint64_t base, max_offset; + uint8_t fixed_sub_bus_nr, fixed_sec_bus_nr; + + /* Determine the number of entries */ + num_ent = read_config(fd, &p->pc_sel, ptr + PCIR_EA_NUM_ENT, 2); + num_ent &= PCIM_EA_NUM_ENT_MASK; + + printf("PCI Enhanced Allocation (%d entries)", num_ent); + + /* Find the first entry to care of */ + ptr += PCIR_EA_FIRST_ENT; + + /* Print BUS numbers for bridges */ + if ((p->pc_hdr & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) { + val = read_config(fd, &p->pc_sel, ptr, 4); + + fixed_sec_bus_nr = PCIM_EA_SEC_NR(val); + fixed_sub_bus_nr = PCIM_EA_SUB_NR(val); + + printf("\n\t\t BRIDGE, sec bus [%d], sub bus [%d]", + fixed_sec_bus_nr, fixed_sub_bus_nr); + ptr += 4; + } + + for (a = 0; a < num_ent; a++) { + /* Read a number of dwords in the entry */ + val = read_config(fd, &p->pc_sel, ptr, 4); + ptr += 4; + ent_size = (val & PCIM_EA_ES); + + for (b = 0; b < ent_size; b++) { + dw[b] = read_config(fd, &p->pc_sel, ptr, 4); + ptr += 4; + } + + flags = val; + flags_pp = (flags & PCIM_EA_PP) >> PCIM_EA_PP_OFFSET; + flags_sp = (flags & PCIM_EA_SP) >> PCIM_EA_SP_OFFSET; + bei = (PCIM_EA_BEI & val) >> PCIM_EA_BEI_OFFSET; + + base = dw[0] & PCIM_EA_FIELD_MASK; + max_offset = dw[1] | ~PCIM_EA_FIELD_MASK; + b = 2; + if (((dw[0] & PCIM_EA_IS_64) != 0) && (b < ent_size)) { + base |= (uint64_t)dw[b] << 32UL; + b++; + } + if (((dw[1] & PCIM_EA_IS_64) != 0) + && (b < ent_size)) { + max_offset |= (uint64_t)dw[b] << 32UL; + b++; + } + + printf("\n\t\t [%d] %s, %s, %s, base [0x%lx], size [0x%lx]" + "\n\t\t\tPrimary properties [0x%x] (%s)" + "\n\t\t\tSecondary properties [0x%x] (%s)", + bei, ea_bei_to_name(bei), + (flags & PCIM_EA_ENABLE ? "Enabled" : "Disabled"), + (flags & PCIM_EA_WRITABLE ? "Writable" : "Read-only"), + base, max_offset + 1, + flags_pp, ea_prop_to_name(flags_pp), + flags_sp, ea_prop_to_name(flags_sp)); + } +} + void list_caps(int fd, struct pci_conf *p) { @@ -605,6 +749,9 @@ case PCIY_PCIAF: cap_pciaf(fd, p, ptr); break; + case PCIY_EA: + cap_ea(fd, p, ptr); + break; default: printf("unknown"); break;