#define PCI_EXP_RTSTA_PME_REQID 0x0000ffff /* PME Requester ID */
#define PCI_EXP_RTSTA_PME_STATUS 0x00010000 /* PME Status */
#define PCI_EXP_RTSTA_PME_PENDING 0x00020000 /* PME is Pending */
+#define PCI_EXP_DEVCAP2 0x24 /* Device capabilities 2 */
+#define PCI_EXP_DEVCTL2 0x28 /* Device Control */
+#define PCI_EXP_DEV2_TIMEOUT_RANGE(x) ((x) & 0xf) /* Completion Timeout Ranges Supported */
+#define PCI_EXP_DEV2_TIMEOUT_VALUE(x) ((x) & 0xf) /* Completion Timeout Value */
+#define PCI_EXP_DEV2_TIMEOUT_DIS 0x0010 /* Completion Timeout Disable Supported */
+#define PCI_EXP_DEV2_ARI 0x0020 /* ARI Forwarding */
+#define PCI_EXP_DEVSTA2 0x2a /* Device Status */
+#define PCI_EXP_LNKCAP2 0x2c /* Link Capabilities */
+#define PCI_EXP_LNKCTL2 0x30 /* Link Control */
+#define PCI_EXP_LNKCTL2_SPEED(x) ((x) & 0xf) /* Target Link Speed */
+#define PCI_EXP_LNKCTL2_CMPLNC 0x0010 /* Enter Compliance */
+#define PCI_EXP_LNKCTL2_SPEED_DIS 0x0020 /* Hardware Autonomous Speed Disable */
+#define PCI_EXP_LNKCTL2_DEEMPHASIS(x) (((x) >> 6) & 1) /* Selectable De-emphasis */
+#define PCI_EXP_LNKCTL2_MARGIN(x) (((x) >> 7) & 7) /* Transmit Margin */
+#define PCI_EXP_LNKCTL2_MOD_CMPLNC 0x0400 /* Enter Modified Compliance */
+#define PCI_EXP_LNKCTL2_CMPLNC_SOS 0x0800 /* Compliance SOS */
+#define PCI_EXP_LNKCTL2_COM_DEEMPHASIS(x) (((x) >> 12) & 1) /* Compliance De-emphasis */
+#define PCI_EXP_LNKSTA2 0x32 /* Link Status */
+#define PCI_EXP_LINKSTA2_DEEMPHASIS(x) ((x) & 1) /* Current De-emphasis Level */
+#define PCI_EXP_SLTCAP2 0x34 /* Slot Capabilities */
+#define PCI_EXP_SLTCTL2 0x38 /* Slot Control */
+#define PCI_EXP_SLTSTA2 0x3a /* Slot Status */
/* MSI-X */
#define PCI_MSIX_ENABLE 0x8000
FLAG(w, PCI_EXP_DEVSTA_URD),
FLAG(w, PCI_EXP_DEVSTA_AUXPD),
FLAG(w, PCI_EXP_DEVSTA_TRPND));
-
- /* FIXME: Second set of control/status registers is not supported yet. */
}
static char *link_speed(int speed)
FLAG(w, PCI_EXP_RTSTA_PME_PENDING));
}
+static const char *cap_express_dev2_timeout_range(int type)
+{
+ /* Decode Completion Timeout Ranges. */
+ switch (type)
+ {
+ case 0:
+ return "Not Supported";
+ case 1:
+ return "Range A";
+ case 2:
+ return "Range B";
+ case 3:
+ return "Range AB";
+ case 6:
+ return "Range BC";
+ case 7:
+ return "Range ABC";
+ case 14:
+ return "Range BCD";
+ case 15:
+ return "Range ABCD";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *cap_express_dev2_timeout_value(int type)
+{
+ /* Decode Completion Timeout Value. */
+ switch (type)
+ {
+ case 0:
+ return "50us to 50ms";
+ case 1:
+ return "50us to 100us";
+ case 2:
+ return "1ms to 10ms";
+ case 5:
+ return "16ms to 55ms";
+ case 6:
+ return "65ms to 210ms";
+ case 9:
+ return "260ms to 900ms";
+ case 10:
+ return "1s to 3.5s";
+ case 13:
+ return "4s to 13s";
+ case 14:
+ return "17s to 64s";
+ default:
+ return "Unknown";
+ }
+}
+
+static void cap_express_dev2(struct device *d, int where, int type)
+{
+ u32 l;
+ u16 w;
+
+ l = get_conf_long(d, where + PCI_EXP_DEVCAP2);
+ printf("\t\tDevCap2: Completion Timeout: %s, TimeoutDis%c",
+ cap_express_dev2_timeout_range(PCI_EXP_DEV2_TIMEOUT_RANGE(l)),
+ FLAG(l, PCI_EXP_DEV2_TIMEOUT_DIS));
+ if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM)
+ printf(" ARIFwd%c\n", FLAG(l, PCI_EXP_DEV2_ARI));
+ else
+ printf("\n");
+
+ w = get_conf_word(d, where + PCI_EXP_DEVCTL2);
+ printf("\t\tDevCtl2: Completion Timeout: %s, TimeoutDis%c",
+ cap_express_dev2_timeout_value(PCI_EXP_DEV2_TIMEOUT_VALUE(w)),
+ FLAG(w, PCI_EXP_DEV2_TIMEOUT_DIS));
+ if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM)
+ printf(" ARIFwd%c\n", FLAG(w, PCI_EXP_DEV2_ARI));
+ else
+ printf("\n");
+}
+
+static const char *cap_express_link2_speed(int type)
+{
+ switch (type)
+ {
+ case 0: /* hardwire to 0 means only the 2.5GT/s is supported */
+ case 1:
+ return "2.5GT/s";
+ case 2:
+ return "5GT/s";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *cap_express_link2_deemphasis(int type)
+{
+ switch (type)
+ {
+ case 0:
+ return "-6dB";
+ case 1:
+ return "-3.5dB";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *cap_express_link2_transmargin(int type)
+{
+ switch (type)
+ {
+ case 0:
+ return "Normal Operating Range";
+ case 1:
+ return "800-1200mV(full-swing)/400-700mV(half-swing)";
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return "200-400mV(full-swing)/100-200mV(half-swing)";
+ default:
+ return "Unknown";
+ }
+}
+
+static void cap_express_link2(struct device *d, int where, int type UNUSED)
+{
+ u16 w;
+
+ w = get_conf_word(d, where + PCI_EXP_LNKCTL2);
+ printf("\t\tLnkCtl2: Target Link Speed: %s, EnterCompliance%c SpeedDis%c, Selectable De-emphasis: %s\n"
+ "\t\t\t Transmit Margin: %s, EnterModifiedCompliance%c ComplianceSOS%c\n"
+ "\t\t\t Compliance De-emphasis: %s\n",
+ cap_express_link2_speed(PCI_EXP_LNKCTL2_SPEED(w)),
+ FLAG(w, PCI_EXP_LNKCTL2_CMPLNC),
+ FLAG(w, PCI_EXP_LNKCTL2_SPEED_DIS),
+ cap_express_link2_deemphasis(PCI_EXP_LNKCTL2_DEEMPHASIS(w)),
+ cap_express_link2_transmargin(PCI_EXP_LNKCTL2_MARGIN(w)),
+ FLAG(w, PCI_EXP_LNKCTL2_MOD_CMPLNC),
+ FLAG(w, PCI_EXP_LNKCTL2_CMPLNC_SOS),
+ cap_express_link2_deemphasis(PCI_EXP_LNKCTL2_COM_DEEMPHASIS(w)));
+
+ w = get_conf_word(d, where + PCI_EXP_LNKSTA2);
+ printf("\t\tLnkSta2: Current De-emphasis Level: %s\n",
+ cap_express_link2_deemphasis(PCI_EXP_LINKSTA2_DEEMPHASIS(w)));
+}
+
+static void cap_express_slot2(struct device *d UNUSED, int where UNUSED)
+{
+ /* No capabilities that require this field in PCIe rev2.0 spec. */
+}
+
static void
cap_express(struct device *d, int where, int cap)
{
cap_express_slot(d, where);
if (type == PCI_EXP_TYPE_ROOT_PORT)
cap_express_root(d, where);
+
+ if ((cap & PCI_EXP_FLAGS_VERS) < 2)
+ return;
+
+ size = 16;
+ if (slot)
+ size = 24;
+ if (!config_fetch(d, where + PCI_EXP_DEVCAP2, size))
+ return;
+
+ cap_express_dev2(d, where, type);
+ cap_express_link2(d, where, type);
+ if (slot)
+ cap_express_slot2(d, where);
}
static void