@@ -17,7 +17,7 @@ ethtool_SOURCES += \
smsc911x.c at76c50x-usb.c sfc.c stmmac.c \
sff-common.c sff-common.h sfpid.c sfpdiag.c \
ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c lan78xx.c \
- igc.c
+ igc.c qsfp-dd.c qsfp-dd.h
endif
if ENABLE_BASH_COMPLETION
new file mode 100644
@@ -0,0 +1,333 @@
+/**
+ * Description:
+ *
+ * This module adds QSFP-DD support to ethtool. The changes are similar to
+ * the ones already existing in qsfp.c, but customized to use the memory
+ * addresses and logic as defined in the specification's document.
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "internal.h"
+#include "sff-common.h"
+#include "qsfp-dd.h"
+
+static void qsfp_dd_show_identifier(const __u8 *id)
+{
+ sff8024_show_identifier(id, QSFP_DD_ID_OFFSET);
+}
+
+static void qsfp_dd_show_connector(const __u8 *id)
+{
+ sff8024_show_connector(id, QSFP_DD_CTOR_OFFSET);
+}
+
+static void qsfp_dd_show_oui(const __u8 *id)
+{
+ sff8024_show_oui(id, QSFP_DD_VENDOR_OUI_OFFSET);
+}
+
+/**
+ * Print the revision compliance. Relevant documents:
+ * [1] CMIS Rev. 3, pag. 45, section 1.7.2.1, Table 18
+ * [2] CMIS Rev. 4, pag. 81, section 8.2.1, Table 8-2
+ */
+static void qsfp_dd_show_rev_compliance(const __u8 *id)
+{
+ __u8 rev = id[QSFP_DD_REV_COMPLIANCE_OFFSET];
+ int major = (rev >> 4) & 0x0F;
+ int minor = rev & 0x0F;
+
+ printf("\t%-41s : Rev. %d.%d\n", "Revision compliance", major, minor);
+}
+
+/**
+ * Print information about the device's power consumption.
+ * Relevant documents:
+ * [1] CMIS Rev. 3, pag. 59, section 1.7.3.9, Table 30
+ * [2] CMIS Rev. 4, pag. 94, section 8.3.9, Table 8-18
+ * [3] QSFP-DD Hardware Rev 5.0, pag. 22, section 4.2.1
+ */
+static void qsfp_dd_show_power_info(const __u8 *id)
+{
+ float max_power = 0.0f;
+ __u8 base_power = 0;
+ __u8 power_class;
+
+ /* Get the power class (first 3 most significat bytes) */
+ power_class = (id[QSFP_DD_PWR_CLASS_OFFSET] >> 5) & 0x07;
+
+ /* Get the base power in multiples of 0.25W */
+ base_power = id[QSFP_DD_PWR_MAX_POWER_OFFSET];
+ max_power = base_power * 0.25f;
+
+ printf("\t%-41s : %d\n", "Power class", power_class + 1);
+ printf("\t%-41s : %.02fW\n", "Max power", max_power);
+}
+
+/**
+ * Print the cable assembly length, for both passive copper and active
+ * optical or electrical cables. The base length (bits 5-0) must be
+ * multiplied with the SMF length multiplier (bits 7-6) to obtain the
+ * correct value. Relevant documents:
+ * [1] CMIS Rev. 3, pag. 59, section 1.7.3.10, Table 31
+ * [2] CMIS Rev. 4, pag. 94, section 8.3.10, Table 8-19
+ */
+static void qsfp_dd_show_cbl_asm_len(const __u8 *id)
+{
+ static const char *fn = "Cable assembly length";
+ float mul = 1.0f;
+ float val = 0.0f;
+
+ /* Check if max length */
+ if (id[QSFP_DD_CBL_ASM_LEN_OFFSET] == QSFP_DD_6300M_MAX_LEN) {
+ printf("\t%-41s : > 6.3km\n", fn);
+ return;
+ }
+
+ /* Get the multiplier from the first two bits */
+ switch (id[QSFP_DD_CBL_ASM_LEN_OFFSET] & QSFP_DD_LEN_MUL_MASK) {
+ case QSFP_DD_MULTIPLIER_00:
+ mul = 0.1f;
+ break;
+ case QSFP_DD_MULTIPLIER_01:
+ mul = 1.0f;
+ break;
+ case QSFP_DD_MULTIPLIER_10:
+ mul = 10.0f;
+ break;
+ case QSFP_DD_MULTIPLIER_11:
+ mul = 100.0f;
+ break;
+ default:
+ break;
+ }
+
+ /* Get base value from first 6 bits and multiply by mul */
+ val = (id[QSFP_DD_CBL_ASM_LEN_OFFSET] & QSFP_DD_LEN_VAL_MASK);
+ val = (float)val * mul;
+ printf("\t%-41s : %0.2fm\n", fn, val);
+}
+
+/**
+ * Print the length for SMF fiber. The base length (bits 5-0) must be
+ * multiplied with the SMF length multiplier (bits 7-6) to obtain the
+ * correct value. Relevant documents:
+ * [1] CMIS Rev. 3, pag. 63, section 1.7.4.2, Table 39
+ * [2] CMIS Rev. 4, pag. 99, section 8.4.2, Table 8-27
+ */
+static void qsfp_dd_print_smf_cbl_len(const __u8 *id)
+{
+ static const char *fn = "Length (SMF)";
+ float mul = 1.0f;
+ float val = 0.0f;
+
+ /* Get the multiplier from the first two bits */
+ switch (id[QSFP_DD_SMF_LEN_OFFSET] & QSFP_DD_LEN_MUL_MASK) {
+ case QSFP_DD_MULTIPLIER_00:
+ mul = 0.1f;
+ break;
+ case QSFP_DD_MULTIPLIER_01:
+ mul = 1.0f;
+ break;
+ default:
+ break;
+ }
+
+ /* Get base value from first 6 bits and multiply by mul */
+ val = (id[QSFP_DD_SMF_LEN_OFFSET] & QSFP_DD_LEN_VAL_MASK);
+ val = (float)val * mul;
+ printf("\t%-41s : %0.2fkm\n", fn, val);
+}
+
+/**
+ * Print relevant signal integrity control properties. Relevant documents:
+ * [1] CMIS Rev. 3, pag. 71, section 1.7.4.10, Table 46
+ * [2] CMIS Rev. 4, pag. 105, section 8.4.10, Table 8-34
+ */
+static void qsfp_dd_show_sig_integrity(const __u8 *id)
+{
+ /* CDR Bypass control: 2nd bit from each byte */
+ printf("\t%-41s : ", "Tx CDR bypass control");
+ printf("%s\n", YESNO(id[QSFP_DD_SIG_INTEG_TX_OFFSET] & 0x02));
+
+ printf("\t%-41s : ", "Rx CDR bypass control");
+ printf("%s\n", YESNO(id[QSFP_DD_SIG_INTEG_RX_OFFSET] & 0x02));
+
+ /* CDR Implementation: 1st bit from each byte */
+ printf("\t%-41s : ", "Tx CDR");
+ printf("%s\n", YESNO(id[QSFP_DD_SIG_INTEG_TX_OFFSET] & 0x01));
+
+ printf("\t%-41s : ", "Rx CDR");
+ printf("%s\n", YESNO(id[QSFP_DD_SIG_INTEG_RX_OFFSET] & 0x01));
+}
+
+/**
+ * Print relevant media interface technology info. Relevant documents:
+ * [1] CMIS Rev. 3
+ * --> pag. 61, section 1.7.3.14, Table 36
+ * --> pag. 64, section 1.7.4.3, 1.7.4.4
+ * [2] CMIS Rev. 4
+ * --> pag. 97, section 8.3.14, Table 8-24
+ * --> pag. 98, section 8.4, Table 8-25
+ * --> page 100, section 8.4.3, 8.4.4
+ */
+static void qsfp_dd_show_mit_compliance(const __u8 *id)
+{
+ static const char *cc = " (Copper cable,";
+
+ printf("\t%-41s : 0x%02x", "Transmitter technology",
+ id[QSFP_DD_MEDIA_INTF_TECH_OFFSET]);
+
+ switch (id[QSFP_DD_MEDIA_INTF_TECH_OFFSET]) {
+ case QSFP_DD_850_VCSEL:
+ printf(" (850 nm VCSEL)\n");
+ break;
+ case QSFP_DD_1310_VCSEL:
+ printf(" (1310 nm VCSEL)\n");
+ break;
+ case QSFP_DD_1550_VCSEL:
+ printf(" (1550 nm VCSEL)\n");
+ break;
+ case QSFP_DD_1310_FP:
+ printf(" (1310 nm FP)\n");
+ break;
+ case QSFP_DD_1310_DFB:
+ printf(" (1310 nm DFB)\n");
+ break;
+ case QSFP_DD_1550_DFB:
+ printf(" (1550 nm DFB)\n");
+ break;
+ case QSFP_DD_1310_EML:
+ printf(" (1310 nm EML)\n");
+ break;
+ case QSFP_DD_1550_EML:
+ printf(" (1550 nm EML)\n");
+ break;
+ case QSFP_DD_OTHERS:
+ printf(" (Others/Undefined)\n");
+ break;
+ case QSFP_DD_1490_DFB:
+ printf(" (1490 nm DFB)\n");
+ break;
+ case QSFP_DD_COPPER_UNEQUAL:
+ printf("%s unequalized)\n", cc);
+ break;
+ case QSFP_DD_COPPER_PASS_EQUAL:
+ printf("%s passive equalized)\n", cc);
+ break;
+ case QSFP_DD_COPPER_NF_EQUAL:
+ printf("%s near and far end limiting active equalizers)\n", cc);
+ break;
+ case QSFP_DD_COPPER_F_EQUAL:
+ printf("%s far end limiting active equalizers)\n", cc);
+ break;
+ case QSFP_DD_COPPER_N_EQUAL:
+ printf("%s near end limiting active equalizers)\n", cc);
+ break;
+ case QSFP_DD_COPPER_LINEAR_EQUAL:
+ printf("%s linear active equalizers)\n", cc);
+ break;
+ }
+
+ if (id[QSFP_DD_MEDIA_INTF_TECH_OFFSET] >= QSFP_DD_COPPER_UNEQUAL) {
+ printf("\t%-41s : %udb\n", "Attenuation at 5GHz",
+ id[QSFP_DD_COPPER_ATT_5GHZ]);
+ printf("\t%-41s : %udb\n", "Attenuation at 7GHz",
+ id[QSFP_DD_COPPER_ATT_7GHZ]);
+ printf("\t%-41s : %udb\n", "Attenuation at 12.9GHz",
+ id[QSFP_DD_COPPER_ATT_12P9GHZ]);
+ printf("\t%-41s : %udb\n", "Attenuation at 25.8GHz",
+ id[QSFP_DD_COPPER_ATT_25P8GHZ]);
+ } else {
+ printf("\t%-41s : %.3lfnm\n", "Laser wavelength",
+ (((id[QSFP_DD_NOM_WAVELENGTH_MSB] << 8) |
+ id[QSFP_DD_NOM_WAVELENGTH_LSB]) * 0.05));
+ printf("\t%-41s : %.3lfnm\n", "Laser wavelength tolerance",
+ (((id[QSFP_DD_WAVELENGTH_TOL_MSB] << 8) |
+ id[QSFP_DD_WAVELENGTH_TOL_LSB]) * 0.005));
+ }
+}
+
+/*
+ * 2-byte internal temperature conversions:
+ * First byte is a signed 8-bit integer, which is the temp decimal part
+ * Second byte is a multiple of 1/256th of a degree, which is added to
+ * the dec part.
+ */
+#define OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
+
+/**
+ * Print relevant module level monitoring values. Relevant documents:
+ * [1] CMIS Rev. 3:
+ * --> pag. 50, section 1.7.2.4, Table 22
+ *
+ * [2] CMIS Rev. 4:
+ * --> pag. 84, section 8.2.4, Table 8-6
+ */
+static void qsfp_dd_show_mod_lvl_monitors(const __u8 *id)
+{
+ PRINT_TEMP("Module temperature",
+ OFFSET_TO_TEMP(QSFP_DD_CURR_TEMP_OFFSET));
+ PRINT_VCC("Module voltage",
+ OFFSET_TO_U16(QSFP_DD_CURR_CURR_OFFSET));
+}
+
+/**
+ * Print relevant info about the maximum supported fiber media length
+ * for each type of fiber media at the maximum module-supported bit rate.
+ * Relevant documents:
+ * [1] CMIS Rev. 3, page 64, section 1.7.4.2, Table 39
+ * [2] CMIS Rev. 4, page 99, section 8.4.2, Table 8-27
+ */
+static void qsfp_dd_show_link_len(const __u8 *id)
+{
+ qsfp_dd_print_smf_cbl_len(id);
+ sff_show_value_with_unit(id, QSFP_DD_OM5_LEN_OFFSET,
+ "Length (OM5)", 2, "m");
+ sff_show_value_with_unit(id, QSFP_DD_OM4_LEN_OFFSET,
+ "Length (OM4)", 2, "m");
+ sff_show_value_with_unit(id, QSFP_DD_OM3_LEN_OFFSET,
+ "Length (OM3 50/125um)", 2, "m");
+ sff_show_value_with_unit(id, QSFP_DD_OM2_LEN_OFFSET,
+ "Length (OM2 50/125um)", 1, "m");
+}
+
+/**
+ * Show relevant information about the vendor. Relevant documents:
+ * [1] CMIS Rev. 3, page 56, section 1.7.3, Table 27
+ * [2] CMIS Rev. 4, page 91, section 8.2, Table 8-15
+ */
+static void qsfp_dd_show_vendor_info(const __u8 *id)
+{
+ sff_show_ascii(id, QSFP_DD_VENDOR_NAME_START_OFFSET,
+ QSFP_DD_VENDOR_NAME_END_OFFSET, "Vendor name");
+ qsfp_dd_show_oui(id);
+ sff_show_ascii(id, QSFP_DD_VENDOR_PN_START_OFFSET,
+ QSFP_DD_VENDOR_PN_END_OFFSET, "Vendor PN");
+ sff_show_ascii(id, QSFP_DD_VENDOR_REV_START_OFFSET,
+ QSFP_DD_VENDOR_REV_END_OFFSET, "Vendor rev");
+ sff_show_ascii(id, QSFP_DD_VENDOR_SN_START_OFFSET,
+ QSFP_DD_VENDOR_SN_END_OFFSET, "Vendor SN");
+ sff_show_ascii(id, QSFP_DD_DATE_YEAR_OFFSET,
+ QSFP_DD_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
+
+ if (id[QSFP_DD_CLEI_PRESENT_BYTE] & QSFP_DD_CLEI_PRESENT_MASK)
+ sff_show_ascii(id, QSFP_DD_CLEI_START_OFFSET,
+ QSFP_DD_CLEI_END_OFFSET, "CLEI code");
+}
+
+void qsfp_dd_show_all(const __u8 *id)
+{
+ qsfp_dd_show_identifier(id);
+ qsfp_dd_show_power_info(id);
+ qsfp_dd_show_connector(id);
+ qsfp_dd_show_cbl_asm_len(id);
+ qsfp_dd_show_sig_integrity(id);
+ qsfp_dd_show_mit_compliance(id);
+ qsfp_dd_show_mod_lvl_monitors(id);
+ qsfp_dd_show_link_len(id);
+ qsfp_dd_show_vendor_info(id);
+ qsfp_dd_show_rev_compliance(id);
+}
new file mode 100644
@@ -0,0 +1,125 @@
+#ifndef QSFP_DD_H__
+#define QSFP_DD_H__
+
+/* Identifier and revision compliance (Page 0) */
+#define QSFP_DD_ID_OFFSET 0x00
+#define QSFP_DD_REV_COMPLIANCE_OFFSET 0x01
+
+#define QSFP_DD_MODULE_TYPE_OFFSET 0x55
+#define QSFP_DD_MT_MMF 0x01
+#define QSFP_DD_MT_SMF 0x02
+
+/* Module-Level Monitors (Page 0) */
+#define QSFP_DD_CURR_TEMP_OFFSET 0x0E
+#define QSFP_DD_CURR_CURR_OFFSET 0x10
+
+#define QSFP_DD_CTOR_OFFSET 0xCB
+
+/* Vendor related information (Page 0) */
+#define QSFP_DD_VENDOR_NAME_START_OFFSET 0x81
+#define QSFP_DD_VENDOR_NAME_END_OFFSET 0x90
+
+#define QSFP_DD_VENDOR_OUI_OFFSET 0x91
+
+#define QSFP_DD_VENDOR_PN_START_OFFSET 0x94
+#define QSFP_DD_VENDOR_PN_END_OFFSET 0xA3
+
+#define QSFP_DD_VENDOR_REV_START_OFFSET 0xA4
+#define QSFP_DD_VENDOR_REV_END_OFFSET 0xA5
+
+#define QSFP_DD_VENDOR_SN_START_OFFSET 0xA6
+#define QSFP_DD_VENDOR_SN_END_OFFSET 0xB5
+
+#define QSFP_DD_DATE_YEAR_OFFSET 0xB6
+#define QSFP_DD_DATE_VENDOR_LOT_OFFSET 0xBC
+
+/* CLEI Code (Page 0) */
+#define QSFP_DD_CLEI_PRESENT_BYTE 0x02
+#define QSFP_DD_CLEI_PRESENT_MASK 0x20
+#define QSFP_DD_CLEI_START_OFFSET 0xBE
+#define QSFP_DD_CLEI_END_OFFSET 0xC7
+
+/* Cable assembly length */
+#define QSFP_DD_CBL_ASM_LEN_OFFSET 0xCA
+#define QSFP_DD_6300M_MAX_LEN 0xFF
+
+/* Cable length with multiplier */
+#define QSFP_DD_MULTIPLIER_00 0x00
+#define QSFP_DD_MULTIPLIER_01 0x40
+#define QSFP_DD_MULTIPLIER_10 0x80
+#define QSFP_DD_MULTIPLIER_11 0xC0
+#define QSFP_DD_LEN_MUL_MASK 0xC0
+#define QSFP_DD_LEN_VAL_MASK 0x3F
+
+/* Module power characteristics */
+#define QSFP_DD_PWR_CLASS_OFFSET 0xC8
+#define QSFP_DD_PWR_MAX_POWER_OFFSET 0xC9
+#define QSFP_DD_PWR_CLASS_MASK 0xE0
+#define QSFP_DD_PWR_CLASS_1 0x00
+#define QSFP_DD_PWR_CLASS_2 0x01
+#define QSFP_DD_PWR_CLASS_3 0x02
+#define QSFP_DD_PWR_CLASS_4 0x03
+#define QSFP_DD_PWR_CLASS_5 0x04
+#define QSFP_DD_PWR_CLASS_6 0x05
+#define QSFP_DD_PWR_CLASS_7 0x06
+#define QSFP_DD_PWR_CLASS_8 0x07
+
+/* Copper cable attenuation */
+#define QSFP_DD_COPPER_ATT_5GHZ 0xCC
+#define QSFP_DD_COPPER_ATT_7GHZ 0xCD
+#define QSFP_DD_COPPER_ATT_12P9GHZ 0xCE
+#define QSFP_DD_COPPER_ATT_25P8GHZ 0xCF
+
+/* Cable assembly lane */
+#define QSFP_DD_CABLE_ASM_NEAR_END_OFFSET 0xD2
+#define QSFP_DD_CABLE_ASM_FAR_END_OFFSET 0xD3
+
+/* Media interface technology */
+#define QSFP_DD_MEDIA_INTF_TECH_OFFSET 0xD4
+#define QSFP_DD_850_VCSEL 0x00
+#define QSFP_DD_1310_VCSEL 0x01
+#define QSFP_DD_1550_VCSEL 0x02
+#define QSFP_DD_1310_FP 0x03
+#define QSFP_DD_1310_DFB 0x04
+#define QSFP_DD_1550_DFB 0x05
+#define QSFP_DD_1310_EML 0x06
+#define QSFP_DD_1550_EML 0x07
+#define QSFP_DD_OTHERS 0x08
+#define QSFP_DD_1490_DFB 0x09
+#define QSFP_DD_COPPER_UNEQUAL 0x0A
+#define QSFP_DD_COPPER_PASS_EQUAL 0x0B
+#define QSFP_DD_COPPER_NF_EQUAL 0x0C
+#define QSFP_DD_COPPER_F_EQUAL 0x0D
+#define QSFP_DD_COPPER_N_EQUAL 0x0E
+#define QSFP_DD_COPPER_LINEAR_EQUAL 0x0F
+
+/*-----------------------------------------------------------------------
+ * Upper Memory Page 0x01: contains advertising fields that define properties
+ * that are unique to active modules and cable assemblies.
+ * RealOffset = 1 * 0x80 + LocalOffset
+ */
+#define PAG01H_UPPER_OFFSET (0x01 * 0x80)
+
+/* Supported Link Length (Page 1) */
+#define QSFP_DD_SMF_LEN_OFFSET (PAG01H_UPPER_OFFSET + 0x84)
+#define QSFP_DD_OM5_LEN_OFFSET (PAG01H_UPPER_OFFSET + 0x85)
+#define QSFP_DD_OM4_LEN_OFFSET (PAG01H_UPPER_OFFSET + 0x86)
+#define QSFP_DD_OM3_LEN_OFFSET (PAG01H_UPPER_OFFSET + 0x87)
+#define QSFP_DD_OM2_LEN_OFFSET (PAG01H_UPPER_OFFSET + 0x88)
+
+/* Wavelength (Page 1) */
+#define QSFP_DD_NOM_WAVELENGTH_MSB (PAG01H_UPPER_OFFSET + 0x8A)
+#define QSFP_DD_NOM_WAVELENGTH_LSB (PAG01H_UPPER_OFFSET + 0x8B)
+#define QSFP_DD_WAVELENGTH_TOL_MSB (PAG01H_UPPER_OFFSET + 0x8C)
+#define QSFP_DD_WAVELENGTH_TOL_LSB (PAG01H_UPPER_OFFSET + 0x8D)
+
+/* Signal integrity controls */
+#define QSFP_DD_SIG_INTEG_TX_OFFSET (PAG01H_UPPER_OFFSET + 0xA1)
+#define QSFP_DD_SIG_INTEG_RX_OFFSET (PAG01H_UPPER_OFFSET + 0xA2)
+
+#define YESNO(x) (((x) != 0) ? "Yes" : "No")
+#define ONOFF(x) (((x) != 0) ? "On" : "Off")
+
+void qsfp_dd_show_all(const __u8 *id);
+
+#endif /* QSFP_DD_H__ */
@@ -58,6 +58,7 @@
#include "internal.h"
#include "sff-common.h"
#include "qsfp.h"
+#include "qsfp-dd.h"
#define MAX_DESC_SIZE 42
@@ -579,9 +580,9 @@ static void sff8636_show_rate_identifier(const __u8 *id)
id[SFF8636_EXT_RS_OFFSET]);
}
-static void sff8636_show_oui(const __u8 *id)
+static void sff8636_show_oui(const __u8 *id, int id_offset)
{
- sff8024_show_oui(id, SFF8636_VENDOR_OUI_OFFSET);
+ sff8024_show_oui(id, id_offset);
}
static void sff8636_show_wavelength_or_copper_compliance(const __u8 *id)
@@ -662,38 +663,7 @@ static void sff8636_show_wavelength_or_copper_compliance(const __u8 *id)
static void sff8636_show_revision_compliance(const __u8 *id)
{
- static const char *pfx =
- "\tRevision Compliance :";
-
- switch (id[SFF8636_REV_COMPLIANCE_OFFSET]) {
- case SFF8636_REV_UNSPECIFIED:
- printf("%s Revision not specified\n", pfx);
- break;
- case SFF8636_REV_8436_48:
- printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
- break;
- case SFF8636_REV_8436_8636:
- printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
- break;
- case SFF8636_REV_8636_13:
- printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx);
- break;
- case SFF8636_REV_8636_14:
- printf("%s SFF-8636 Rev 1.4\n", pfx);
- break;
- case SFF8636_REV_8636_15:
- printf("%s SFF-8636 Rev 1.5\n", pfx);
- break;
- case SFF8636_REV_8636_20:
- printf("%s SFF-8636 Rev 2.0\n", pfx);
- break;
- case SFF8636_REV_8636_27:
- printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx);
- break;
- default:
- printf("%s Unallocated\n", pfx);
- break;
- }
+ sff_show_revision_compliance(id, SFF8636_REV_COMPLIANCE_OFFSET);
}
/*
@@ -846,10 +816,15 @@ static void sff8636_show_dom(const __u8 *id, __u32 eeprom_len)
sff_show_thresholds(sd);
}
-
}
+
void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
{
+ if (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_DD) {
+ qsfp_dd_show_all(id);
+ return;
+ }
+
sff8636_show_identifier(id);
if ((id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP) ||
(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_PLUS) ||
@@ -874,7 +849,7 @@ void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
sff8636_show_wavelength_or_copper_compliance(id);
sff_show_ascii(id, SFF8636_VENDOR_NAME_START_OFFSET,
SFF8636_VENDOR_NAME_END_OFFSET, "Vendor name");
- sff8636_show_oui(id);
+ sff8636_show_oui(id, SFF8636_VENDOR_OUI_OFFSET);
sff_show_ascii(id, SFF8636_VENDOR_PN_START_OFFSET,
SFF8636_VENDOR_PN_END_OFFSET, "Vendor PN");
sff_show_ascii(id, SFF8636_VENDOR_REV_START_OFFSET,
@@ -31,14 +31,6 @@
#define SFF8636_ID_OFFSET 0x00
#define SFF8636_REV_COMPLIANCE_OFFSET 0x01
-#define SFF8636_REV_UNSPECIFIED 0x00
-#define SFF8636_REV_8436_48 0x01
-#define SFF8636_REV_8436_8636 0x02
-#define SFF8636_REV_8636_13 0x03
-#define SFF8636_REV_8636_14 0x04
-#define SFF8636_REV_8636_15 0x05
-#define SFF8636_REV_8636_20 0x06
-#define SFF8636_REV_8636_27 0x07
#define SFF8636_STATUS_2_OFFSET 0x02
/* Flat Memory:0- Paging, 1- Page 0 only */
@@ -136,6 +136,9 @@ void sff8024_show_identifier(const __u8 *id, int id_offset)
case SFF8024_ID_MICRO_QSFP:
printf(" (microQSFP)\n");
break;
+ case SFF8024_ID_QSFP_DD:
+ printf(" (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))\n");
+ break;
default:
printf(" (reserved or unknown)\n");
break;
@@ -203,6 +206,18 @@ void sff8024_show_connector(const __u8 *id, int ctor_offset)
case SFF8024_CTOR_MXC_2x16:
printf(" (MXC 2x16)\n");
break;
+ case SFF8024_CTOR_CS_OPTICAL:
+ printf(" (CS optical connector)\n");
+ break;
+ case SFF8024_CTOR_CS_OPTICAL_MINI:
+ printf(" (Mini CS optical connector)\n");
+ break;
+ case SFF8024_CTOR_MPO_2X12:
+ printf(" (MPO 2x12)\n");
+ break;
+ case SFF8024_CTOR_MPO_1X16:
+ printf(" (MPO 1x16)\n");
+ break;
default:
printf(" (reserved or unknown)\n");
break;
@@ -302,3 +317,39 @@ void sff_show_thresholds(struct sff_diags sd)
PRINT_xX_PWR("Laser rx power low warning threshold",
sd.rx_power[LWARN]);
}
+
+void sff_show_revision_compliance(const __u8 *id, int rev_offset)
+{
+ static const char *pfx =
+ "\tRevision Compliance :";
+
+ switch (id[rev_offset]) {
+ case SFF8636_REV_UNSPECIFIED:
+ printf("%s Revision not specified\n", pfx);
+ break;
+ case SFF8636_REV_8436_48:
+ printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
+ break;
+ case SFF8636_REV_8436_8636:
+ printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
+ break;
+ case SFF8636_REV_8636_13:
+ printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx);
+ break;
+ case SFF8636_REV_8636_14:
+ printf("%s SFF-8636 Rev 1.4\n", pfx);
+ break;
+ case SFF8636_REV_8636_15:
+ printf("%s SFF-8636 Rev 1.5\n", pfx);
+ break;
+ case SFF8636_REV_8636_20:
+ printf("%s SFF-8636 Rev 2.0\n", pfx);
+ break;
+ case SFF8636_REV_8636_27:
+ printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx);
+ break;
+ default:
+ printf("%s Unallocated\n", pfx);
+ break;
+ }
+}
@@ -26,7 +26,17 @@
#include <stdio.h>
#include "internal.h"
-#define SFF8024_ID_OFFSET 0x00
+/* Revision compliance */
+#define SFF8636_REV_UNSPECIFIED 0x00
+#define SFF8636_REV_8436_48 0x01
+#define SFF8636_REV_8436_8636 0x02
+#define SFF8636_REV_8636_13 0x03
+#define SFF8636_REV_8636_14 0x04
+#define SFF8636_REV_8636_15 0x05
+#define SFF8636_REV_8636_20 0x06
+#define SFF8636_REV_8636_27 0x07
+
+#define SFF8024_ID_OFFSET 0x00
#define SFF8024_ID_UNKNOWN 0x00
#define SFF8024_ID_GBIC 0x01
#define SFF8024_ID_SOLDERED_MODULE 0x02
@@ -51,7 +61,8 @@
#define SFF8024_ID_HD8X_FANOUT 0x15
#define SFF8024_ID_CDFP_S3 0x16
#define SFF8024_ID_MICRO_QSFP 0x17
-#define SFF8024_ID_LAST SFF8024_ID_MICRO_QSFP
+#define SFF8024_ID_QSFP_DD 0x18
+#define SFF8024_ID_LAST SFF8024_ID_QSFP_DD
#define SFF8024_ID_UNALLOCATED_LAST 0x7F
#define SFF8024_ID_VENDOR_START 0x80
#define SFF8024_ID_VENDOR_LAST 0xFF
@@ -76,8 +87,14 @@
#define SFF8024_CTOR_RJ45 0x22
#define SFF8024_CTOR_NO_SEPARABLE 0x23
#define SFF8024_CTOR_MXC_2x16 0x24
-#define SFF8024_CTOR_LAST SFF8024_CTOR_MXC_2x16
-#define SFF8024_CTOR_UNALLOCATED_LAST 0x7F
+#define SFF8024_CTOR_CS_OPTICAL 0x25
+#define SFF8024_CTOR_CS_OPTICAL_MINI 0x26
+#define SFF8024_CTOR_MPO_2X12 0x27
+#define SFF8024_CTOR_MPO_1X16 0x28
+#define SFF8024_CTOR_LAST SFF8024_CTOR_MPO_1X16
+
+#define SFF8024_CTOR_NO_SEP_QSFP_DD 0x6F
+#define SFF8024_CTOR_UNALLOCATED_LAST 0x7F
#define SFF8024_CTOR_VENDOR_START 0x80
#define SFF8024_CTOR_VENDOR_LAST 0xFF
@@ -185,5 +202,6 @@ void sff8024_show_oui(const __u8 *id, int id_offset);
void sff8024_show_identifier(const __u8 *id, int id_offset);
void sff8024_show_connector(const __u8 *id, int ctor_offset);
void sff8024_show_encoding(const __u8 *id, int encoding_offset, int sff_type);
+void sff_show_revision_compliance(const __u8 *id, int rev_offset);
#endif /* SFF_COMMON_H__ */