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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to