svn commit: r296081 - in head: sys/dev/pci usr.sbin/pciconf

Wojciech Macek wma at FreeBSD.org
Fri Feb 26 08:35:06 UTC 2016


Author: wma
Date: Fri Feb 26 08:35:04 2016
New Revision: 296081
URL: https://svnweb.freebsd.org/changeset/base/296081

Log:
  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

Modified:
  head/sys/dev/pci/pcireg.h
  head/usr.sbin/pciconf/cap.c

Modified: head/sys/dev/pci/pcireg.h
==============================================================================
--- head/sys/dev/pci/pcireg.h	Fri Feb 26 08:16:44 2016	(r296080)
+++ head/sys/dev/pci/pcireg.h	Fri Feb 26 08:35:04 2016	(r296081)
@@ -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 */

Modified: head/usr.sbin/pciconf/cap.c
==============================================================================
--- head/usr.sbin/pciconf/cap.c	Fri Feb 26 08:16:44 2016	(r296080)
+++ head/usr.sbin/pciconf/cap.c	Fri Feb 26 08:35:04 2016	(r296081)
@@ -534,6 +534,141 @@ cap_pciaf(int fd, struct pci_conf *p, ui
 	    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;


More information about the svn-src-head mailing list