Add support for Enhanced Allocation in pciconf

* Modified pciconf to print EA capability structure
 * Added register description to pcireg.h

Obtained from:         Semihalf
Sponsored by:          Cavium
Approved by:           cognet (mentor)
Reviewed by:           jhb
Differential revision: https://reviews.freebsd.org/D5440
This commit is contained in:
Wojciech Macek 2016-02-26 08:35:04 +00:00
parent de867427d8
commit a2862b1169
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=296081
2 changed files with 185 additions and 0 deletions

View File

@ -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 */

View File

@ -534,6 +534,141 @@ cap_pciaf(int fd, struct pci_conf *p, uint8_t ptr)
cap & PCIM_PCIAFCAP_TP ? " TP" : "");
}
static const char *
ea_bei_to_name(uint8_t bei)
{
static const char *barstr[] = {
"BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5"
};
static const char *vfbarstr[] = {
"VFBAR0", "VFBAR1", "VFBAR2", "VFBAR3", "VFBAR4", "VFBAR5"
};
if ((bei >= PCIM_EA_BEI_BAR_0) && (bei <= PCIM_EA_BEI_BAR_5))
return (barstr[bei - PCIM_EA_BEI_BAR_0]);
if ((bei >= PCIM_EA_BEI_VF_BAR_0) && (bei <= PCIM_EA_BEI_VF_BAR_5))
return (vfbarstr[bei - PCIM_EA_BEI_VF_BAR_0]);
switch (bei) {
case PCIM_EA_BEI_BRIDGE:
return "BRIDGE";
case PCIM_EA_BEI_ENI:
return "ENI";
case PCIM_EA_BEI_ROM:
return "ROM";
case PCIM_EA_BEI_RESERVED:
default:
return "RSVD";
}
}
static const char *
ea_prop_to_name(uint8_t prop)
{
switch (prop) {
case PCIM_EA_P_MEM:
return "Non-Prefetchable Memory";
case PCIM_EA_P_MEM_PREFETCH:
return "Prefetchable Memory";
case PCIM_EA_P_IO:
return "I/O Space";
case PCIM_EA_P_VF_MEM_PREFETCH:
return "VF Prefetchable Memory";
case PCIM_EA_P_VF_MEM:
return "VF Non-Prefetchable Memory";
case PCIM_EA_P_BRIDGE_MEM:
return "Bridge Non-Prefetchable Memory";
case PCIM_EA_P_BRIDGE_MEM_PREFETCH:
return "Bridge Prefetchable Memory";
case PCIM_EA_P_BRIDGE_IO:
return "Bridge I/O Space";
case PCIM_EA_P_MEM_RESERVED:
return "Reserved Memory";
case PCIM_EA_P_IO_RESERVED:
return "Reserved I/O Space";
case PCIM_EA_P_UNAVAILABLE:
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 +740,9 @@ list_caps(int fd, struct pci_conf *p)
case PCIY_PCIAF:
cap_pciaf(fd, p, ptr);
break;
case PCIY_EA:
cap_ea(fd, p, ptr);
break;
default:
printf("unknown");
break;