1*1b481fc3SMaciej Żenczykowski /**
2*1b481fc3SMaciej Żenczykowski * Description:
3*1b481fc3SMaciej Żenczykowski *
4*1b481fc3SMaciej Żenczykowski * This module adds CMIS support to ethtool. The changes are similar to
5*1b481fc3SMaciej Żenczykowski * the ones already existing in qsfp.c, but customized to use the memory
6*1b481fc3SMaciej Żenczykowski * addresses and logic as defined in the specification's document.
7*1b481fc3SMaciej Żenczykowski *
8*1b481fc3SMaciej Żenczykowski */
9*1b481fc3SMaciej Żenczykowski
10*1b481fc3SMaciej Żenczykowski #include <stdio.h>
11*1b481fc3SMaciej Żenczykowski #include <math.h>
12*1b481fc3SMaciej Żenczykowski #include <errno.h>
13*1b481fc3SMaciej Żenczykowski #include "internal.h"
14*1b481fc3SMaciej Żenczykowski #include "sff-common.h"
15*1b481fc3SMaciej Żenczykowski #include "cmis.h"
16*1b481fc3SMaciej Żenczykowski #include "netlink/extapi.h"
17*1b481fc3SMaciej Żenczykowski
18*1b481fc3SMaciej Żenczykowski /* The maximum number of supported Banks. Relevant documents:
19*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page. 128, section 8.4.4, Table 8-40
20*1b481fc3SMaciej Żenczykowski */
21*1b481fc3SMaciej Żenczykowski #define CMIS_MAX_BANKS 4
22*1b481fc3SMaciej Żenczykowski #define CMIS_CHANNELS_PER_BANK 8
23*1b481fc3SMaciej Żenczykowski #define CMIS_MAX_CHANNEL_NUM (CMIS_MAX_BANKS * CMIS_CHANNELS_PER_BANK)
24*1b481fc3SMaciej Żenczykowski
25*1b481fc3SMaciej Żenczykowski /* We are not parsing further than Page 11h. */
26*1b481fc3SMaciej Żenczykowski #define CMIS_MAX_PAGES 18
27*1b481fc3SMaciej Żenczykowski
28*1b481fc3SMaciej Żenczykowski struct cmis_memory_map {
29*1b481fc3SMaciej Żenczykowski const __u8 *lower_memory;
30*1b481fc3SMaciej Żenczykowski const __u8 *upper_memory[CMIS_MAX_BANKS][CMIS_MAX_PAGES];
31*1b481fc3SMaciej Żenczykowski #define page_00h upper_memory[0x0][0x0]
32*1b481fc3SMaciej Żenczykowski #define page_01h upper_memory[0x0][0x1]
33*1b481fc3SMaciej Żenczykowski #define page_02h upper_memory[0x0][0x2]
34*1b481fc3SMaciej Żenczykowski };
35*1b481fc3SMaciej Żenczykowski
36*1b481fc3SMaciej Żenczykowski #define CMIS_PAGE_SIZE 0x80
37*1b481fc3SMaciej Żenczykowski #define CMIS_I2C_ADDRESS 0x50
38*1b481fc3SMaciej Żenczykowski
39*1b481fc3SMaciej Żenczykowski static struct {
40*1b481fc3SMaciej Żenczykowski const char *str;
41*1b481fc3SMaciej Żenczykowski int offset;
42*1b481fc3SMaciej Żenczykowski __u8 value; /* Alarm is on if (offset & value) != 0. */
43*1b481fc3SMaciej Żenczykowski } cmis_aw_mod_flags[] = {
44*1b481fc3SMaciej Żenczykowski { "Module temperature high alarm",
45*1b481fc3SMaciej Żenczykowski CMIS_TEMP_AW_OFFSET, CMIS_TEMP_HALARM_STATUS },
46*1b481fc3SMaciej Żenczykowski { "Module temperature low alarm",
47*1b481fc3SMaciej Żenczykowski CMIS_TEMP_AW_OFFSET, CMIS_TEMP_LALARM_STATUS },
48*1b481fc3SMaciej Żenczykowski { "Module temperature high warning",
49*1b481fc3SMaciej Żenczykowski CMIS_TEMP_AW_OFFSET, CMIS_TEMP_HWARN_STATUS },
50*1b481fc3SMaciej Żenczykowski { "Module temperature low warning",
51*1b481fc3SMaciej Żenczykowski CMIS_TEMP_AW_OFFSET, CMIS_TEMP_LWARN_STATUS },
52*1b481fc3SMaciej Żenczykowski
53*1b481fc3SMaciej Żenczykowski { "Module voltage high alarm",
54*1b481fc3SMaciej Żenczykowski CMIS_VCC_AW_OFFSET, CMIS_VCC_HALARM_STATUS },
55*1b481fc3SMaciej Żenczykowski { "Module voltage low alarm",
56*1b481fc3SMaciej Żenczykowski CMIS_VCC_AW_OFFSET, CMIS_VCC_LALARM_STATUS },
57*1b481fc3SMaciej Żenczykowski { "Module voltage high warning",
58*1b481fc3SMaciej Żenczykowski CMIS_VCC_AW_OFFSET, CMIS_VCC_HWARN_STATUS },
59*1b481fc3SMaciej Żenczykowski { "Module voltage low warning",
60*1b481fc3SMaciej Żenczykowski CMIS_VCC_AW_OFFSET, CMIS_VCC_LWARN_STATUS },
61*1b481fc3SMaciej Żenczykowski
62*1b481fc3SMaciej Żenczykowski { NULL, 0, 0 },
63*1b481fc3SMaciej Żenczykowski };
64*1b481fc3SMaciej Żenczykowski
65*1b481fc3SMaciej Żenczykowski static struct {
66*1b481fc3SMaciej Żenczykowski const char *fmt_str;
67*1b481fc3SMaciej Żenczykowski int offset;
68*1b481fc3SMaciej Żenczykowski int adver_offset; /* In Page 01h. */
69*1b481fc3SMaciej Żenczykowski __u8 adver_value; /* Supported if (offset & value) != 0. */
70*1b481fc3SMaciej Żenczykowski } cmis_aw_chan_flags[] = {
71*1b481fc3SMaciej Żenczykowski { "Laser bias current high alarm (Chan %d)",
72*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_AW_HALARM_OFFSET,
73*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
74*1b481fc3SMaciej Żenczykowski { "Laser bias current low alarm (Chan %d)",
75*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_AW_LALARM_OFFSET,
76*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
77*1b481fc3SMaciej Żenczykowski { "Laser bias current high warning (Chan %d)",
78*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_AW_HWARN_OFFSET,
79*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
80*1b481fc3SMaciej Żenczykowski { "Laser bias current low warning (Chan %d)",
81*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_AW_LWARN_OFFSET,
82*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
83*1b481fc3SMaciej Żenczykowski
84*1b481fc3SMaciej Żenczykowski { "Laser tx power high alarm (Channel %d)",
85*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_AW_HALARM_OFFSET,
86*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
87*1b481fc3SMaciej Żenczykowski { "Laser tx power low alarm (Channel %d)",
88*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_AW_LALARM_OFFSET,
89*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
90*1b481fc3SMaciej Żenczykowski { "Laser tx power high warning (Channel %d)",
91*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_AW_HWARN_OFFSET,
92*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
93*1b481fc3SMaciej Żenczykowski { "Laser tx power low warning (Channel %d)",
94*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_AW_LWARN_OFFSET,
95*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
96*1b481fc3SMaciej Żenczykowski
97*1b481fc3SMaciej Żenczykowski { "Laser rx power high alarm (Channel %d)",
98*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_AW_HALARM_OFFSET,
99*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
100*1b481fc3SMaciej Żenczykowski { "Laser rx power low alarm (Channel %d)",
101*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_AW_LALARM_OFFSET,
102*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
103*1b481fc3SMaciej Żenczykowski { "Laser rx power high warning (Channel %d)",
104*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_AW_HWARN_OFFSET,
105*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
106*1b481fc3SMaciej Żenczykowski { "Laser rx power low warning (Channel %d)",
107*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_AW_LWARN_OFFSET,
108*1b481fc3SMaciej Żenczykowski CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
109*1b481fc3SMaciej Żenczykowski
110*1b481fc3SMaciej Żenczykowski { NULL, 0, 0, 0 },
111*1b481fc3SMaciej Żenczykowski };
112*1b481fc3SMaciej Żenczykowski
cmis_show_identifier(const struct cmis_memory_map * map)113*1b481fc3SMaciej Żenczykowski static void cmis_show_identifier(const struct cmis_memory_map *map)
114*1b481fc3SMaciej Żenczykowski {
115*1b481fc3SMaciej Żenczykowski sff8024_show_identifier(map->lower_memory, CMIS_ID_OFFSET);
116*1b481fc3SMaciej Żenczykowski }
117*1b481fc3SMaciej Żenczykowski
cmis_show_connector(const struct cmis_memory_map * map)118*1b481fc3SMaciej Żenczykowski static void cmis_show_connector(const struct cmis_memory_map *map)
119*1b481fc3SMaciej Żenczykowski {
120*1b481fc3SMaciej Żenczykowski sff8024_show_connector(map->page_00h, CMIS_CTOR_OFFSET);
121*1b481fc3SMaciej Żenczykowski }
122*1b481fc3SMaciej Żenczykowski
cmis_show_oui(const struct cmis_memory_map * map)123*1b481fc3SMaciej Żenczykowski static void cmis_show_oui(const struct cmis_memory_map *map)
124*1b481fc3SMaciej Żenczykowski {
125*1b481fc3SMaciej Żenczykowski sff8024_show_oui(map->page_00h, CMIS_VENDOR_OUI_OFFSET);
126*1b481fc3SMaciej Żenczykowski }
127*1b481fc3SMaciej Żenczykowski
128*1b481fc3SMaciej Żenczykowski /**
129*1b481fc3SMaciej Żenczykowski * Print the revision compliance. Relevant documents:
130*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, pag. 45, section 1.7.2.1, Table 18
131*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, pag. 81, section 8.2.1, Table 8-2
132*1b481fc3SMaciej Żenczykowski */
cmis_show_rev_compliance(const struct cmis_memory_map * map)133*1b481fc3SMaciej Żenczykowski static void cmis_show_rev_compliance(const struct cmis_memory_map *map)
134*1b481fc3SMaciej Żenczykowski {
135*1b481fc3SMaciej Żenczykowski __u8 rev = map->lower_memory[CMIS_REV_COMPLIANCE_OFFSET];
136*1b481fc3SMaciej Żenczykowski int major = (rev >> 4) & 0x0F;
137*1b481fc3SMaciej Żenczykowski int minor = rev & 0x0F;
138*1b481fc3SMaciej Żenczykowski
139*1b481fc3SMaciej Żenczykowski printf("\t%-41s : Rev. %d.%d\n", "Revision compliance", major, minor);
140*1b481fc3SMaciej Żenczykowski }
141*1b481fc3SMaciej Żenczykowski
142*1b481fc3SMaciej Żenczykowski static void
cmis_show_signals_one(const struct cmis_memory_map * map,const char * name,int off,int ioff,unsigned int imask)143*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(const struct cmis_memory_map *map, const char *name,
144*1b481fc3SMaciej Żenczykowski int off, int ioff, unsigned int imask)
145*1b481fc3SMaciej Żenczykowski {
146*1b481fc3SMaciej Żenczykowski unsigned int v;
147*1b481fc3SMaciej Żenczykowski int i;
148*1b481fc3SMaciej Żenczykowski
149*1b481fc3SMaciej Żenczykowski if (!map->page_01h)
150*1b481fc3SMaciej Żenczykowski return;
151*1b481fc3SMaciej Żenczykowski
152*1b481fc3SMaciej Żenczykowski v = 0;
153*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_MAX_BANKS && map->upper_memory[i][0x11]; i++)
154*1b481fc3SMaciej Żenczykowski v |= map->upper_memory[i][0x11][off] << (i * 8);
155*1b481fc3SMaciej Żenczykowski
156*1b481fc3SMaciej Żenczykowski if (map->page_01h[ioff] & imask)
157*1b481fc3SMaciej Żenczykowski sff_show_lane_status(name, i * 8, "Yes", "No", v);
158*1b481fc3SMaciej Żenczykowski }
159*1b481fc3SMaciej Żenczykowski
cmis_show_signals(const struct cmis_memory_map * map)160*1b481fc3SMaciej Żenczykowski static void cmis_show_signals(const struct cmis_memory_map *map)
161*1b481fc3SMaciej Żenczykowski {
162*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(map, "Rx loss of signal", CMIS_RX_LOS_OFFSET,
163*1b481fc3SMaciej Żenczykowski CMIS_DIAG_FLAGS_RX_OFFSET, CMIS_DIAG_FL_RX_LOS);
164*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(map, "Tx loss of signal", CMIS_TX_LOS_OFFSET,
165*1b481fc3SMaciej Żenczykowski CMIS_DIAG_FLAGS_TX_OFFSET, CMIS_DIAG_FL_TX_LOS);
166*1b481fc3SMaciej Żenczykowski
167*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(map, "Rx loss of lock", CMIS_RX_LOL_OFFSET,
168*1b481fc3SMaciej Żenczykowski CMIS_DIAG_FLAGS_RX_OFFSET, CMIS_DIAG_FL_RX_LOL);
169*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(map, "Tx loss of lock", CMIS_TX_LOL_OFFSET,
170*1b481fc3SMaciej Żenczykowski CMIS_DIAG_FLAGS_TX_OFFSET, CMIS_DIAG_FL_TX_LOL);
171*1b481fc3SMaciej Żenczykowski
172*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(map, "Tx fault", CMIS_TX_FAIL_OFFSET,
173*1b481fc3SMaciej Żenczykowski CMIS_DIAG_FLAGS_TX_OFFSET, CMIS_DIAG_FL_TX_FAIL);
174*1b481fc3SMaciej Żenczykowski
175*1b481fc3SMaciej Żenczykowski cmis_show_signals_one(map, "Tx adaptive eq fault",
176*1b481fc3SMaciej Żenczykowski CMIS_TX_EQ_FAIL_OFFSET, CMIS_DIAG_FLAGS_TX_OFFSET,
177*1b481fc3SMaciej Żenczykowski CMIS_DIAG_FL_TX_ADAPTIVE_EQ_FAIL);
178*1b481fc3SMaciej Żenczykowski }
179*1b481fc3SMaciej Żenczykowski
180*1b481fc3SMaciej Żenczykowski /**
181*1b481fc3SMaciej Żenczykowski * Print information about the device's power consumption.
182*1b481fc3SMaciej Żenczykowski * Relevant documents:
183*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, pag. 59, section 1.7.3.9, Table 30
184*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, pag. 94, section 8.3.9, Table 8-18
185*1b481fc3SMaciej Żenczykowski * [3] QSFP-DD Hardware Rev 5.0, pag. 22, section 4.2.1
186*1b481fc3SMaciej Żenczykowski */
cmis_show_power_info(const struct cmis_memory_map * map)187*1b481fc3SMaciej Żenczykowski static void cmis_show_power_info(const struct cmis_memory_map *map)
188*1b481fc3SMaciej Żenczykowski {
189*1b481fc3SMaciej Żenczykowski float max_power = 0.0f;
190*1b481fc3SMaciej Żenczykowski __u8 base_power = 0;
191*1b481fc3SMaciej Żenczykowski __u8 power_class;
192*1b481fc3SMaciej Żenczykowski
193*1b481fc3SMaciej Żenczykowski /* Get the power class (first 3 most significat bytes) */
194*1b481fc3SMaciej Żenczykowski power_class = (map->page_00h[CMIS_PWR_CLASS_OFFSET] >> 5) & 0x07;
195*1b481fc3SMaciej Żenczykowski
196*1b481fc3SMaciej Żenczykowski /* Get the base power in multiples of 0.25W */
197*1b481fc3SMaciej Żenczykowski base_power = map->page_00h[CMIS_PWR_MAX_POWER_OFFSET];
198*1b481fc3SMaciej Żenczykowski max_power = base_power * 0.25f;
199*1b481fc3SMaciej Żenczykowski
200*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %d\n", "Power class", power_class + 1);
201*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %.02fW\n", "Max power", max_power);
202*1b481fc3SMaciej Żenczykowski }
203*1b481fc3SMaciej Żenczykowski
204*1b481fc3SMaciej Żenczykowski /**
205*1b481fc3SMaciej Żenczykowski * Print the cable assembly length, for both passive copper and active
206*1b481fc3SMaciej Żenczykowski * optical or electrical cables. The base length (bits 5-0) must be
207*1b481fc3SMaciej Żenczykowski * multiplied with the SMF length multiplier (bits 7-6) to obtain the
208*1b481fc3SMaciej Żenczykowski * correct value. Relevant documents:
209*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, pag. 59, section 1.7.3.10, Table 31
210*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, pag. 94, section 8.3.10, Table 8-19
211*1b481fc3SMaciej Żenczykowski */
cmis_show_cbl_asm_len(const struct cmis_memory_map * map)212*1b481fc3SMaciej Żenczykowski static void cmis_show_cbl_asm_len(const struct cmis_memory_map *map)
213*1b481fc3SMaciej Żenczykowski {
214*1b481fc3SMaciej Żenczykowski static const char *fn = "Cable assembly length";
215*1b481fc3SMaciej Żenczykowski float mul = 1.0f;
216*1b481fc3SMaciej Żenczykowski float val = 0.0f;
217*1b481fc3SMaciej Żenczykowski
218*1b481fc3SMaciej Żenczykowski /* Check if max length */
219*1b481fc3SMaciej Żenczykowski if (map->page_00h[CMIS_CBL_ASM_LEN_OFFSET] == CMIS_6300M_MAX_LEN) {
220*1b481fc3SMaciej Żenczykowski printf("\t%-41s : > 6.3km\n", fn);
221*1b481fc3SMaciej Żenczykowski return;
222*1b481fc3SMaciej Żenczykowski }
223*1b481fc3SMaciej Żenczykowski
224*1b481fc3SMaciej Żenczykowski /* Get the multiplier from the first two bits */
225*1b481fc3SMaciej Żenczykowski switch (map->page_00h[CMIS_CBL_ASM_LEN_OFFSET] & CMIS_LEN_MUL_MASK) {
226*1b481fc3SMaciej Żenczykowski case CMIS_MULTIPLIER_00:
227*1b481fc3SMaciej Żenczykowski mul = 0.1f;
228*1b481fc3SMaciej Żenczykowski break;
229*1b481fc3SMaciej Żenczykowski case CMIS_MULTIPLIER_01:
230*1b481fc3SMaciej Żenczykowski mul = 1.0f;
231*1b481fc3SMaciej Żenczykowski break;
232*1b481fc3SMaciej Żenczykowski case CMIS_MULTIPLIER_10:
233*1b481fc3SMaciej Żenczykowski mul = 10.0f;
234*1b481fc3SMaciej Żenczykowski break;
235*1b481fc3SMaciej Żenczykowski case CMIS_MULTIPLIER_11:
236*1b481fc3SMaciej Żenczykowski mul = 100.0f;
237*1b481fc3SMaciej Żenczykowski break;
238*1b481fc3SMaciej Żenczykowski default:
239*1b481fc3SMaciej Żenczykowski break;
240*1b481fc3SMaciej Żenczykowski }
241*1b481fc3SMaciej Żenczykowski
242*1b481fc3SMaciej Żenczykowski /* Get base value from first 6 bits and multiply by mul */
243*1b481fc3SMaciej Żenczykowski val = (map->page_00h[CMIS_CBL_ASM_LEN_OFFSET] & CMIS_LEN_VAL_MASK);
244*1b481fc3SMaciej Żenczykowski val = (float)val * mul;
245*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %0.2fm\n", fn, val);
246*1b481fc3SMaciej Żenczykowski }
247*1b481fc3SMaciej Żenczykowski
248*1b481fc3SMaciej Żenczykowski /**
249*1b481fc3SMaciej Żenczykowski * Print the length for SMF fiber. The base length (bits 5-0) must be
250*1b481fc3SMaciej Żenczykowski * multiplied with the SMF length multiplier (bits 7-6) to obtain the
251*1b481fc3SMaciej Żenczykowski * correct value. Relevant documents:
252*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, pag. 63, section 1.7.4.2, Table 39
253*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, pag. 99, section 8.4.2, Table 8-27
254*1b481fc3SMaciej Żenczykowski */
cmis_print_smf_cbl_len(const struct cmis_memory_map * map)255*1b481fc3SMaciej Żenczykowski static void cmis_print_smf_cbl_len(const struct cmis_memory_map *map)
256*1b481fc3SMaciej Żenczykowski {
257*1b481fc3SMaciej Żenczykowski static const char *fn = "Length (SMF)";
258*1b481fc3SMaciej Żenczykowski float mul = 1.0f;
259*1b481fc3SMaciej Żenczykowski float val = 0.0f;
260*1b481fc3SMaciej Żenczykowski
261*1b481fc3SMaciej Żenczykowski if (!map->page_01h)
262*1b481fc3SMaciej Żenczykowski return;
263*1b481fc3SMaciej Żenczykowski
264*1b481fc3SMaciej Żenczykowski /* Get the multiplier from the first two bits */
265*1b481fc3SMaciej Żenczykowski switch (map->page_01h[CMIS_SMF_LEN_OFFSET] & CMIS_LEN_MUL_MASK) {
266*1b481fc3SMaciej Żenczykowski case CMIS_MULTIPLIER_00:
267*1b481fc3SMaciej Żenczykowski mul = 0.1f;
268*1b481fc3SMaciej Żenczykowski break;
269*1b481fc3SMaciej Żenczykowski case CMIS_MULTIPLIER_01:
270*1b481fc3SMaciej Żenczykowski mul = 1.0f;
271*1b481fc3SMaciej Żenczykowski break;
272*1b481fc3SMaciej Żenczykowski default:
273*1b481fc3SMaciej Żenczykowski break;
274*1b481fc3SMaciej Żenczykowski }
275*1b481fc3SMaciej Żenczykowski
276*1b481fc3SMaciej Żenczykowski /* Get base value from first 6 bits and multiply by mul */
277*1b481fc3SMaciej Żenczykowski val = (map->page_01h[CMIS_SMF_LEN_OFFSET] & CMIS_LEN_VAL_MASK);
278*1b481fc3SMaciej Żenczykowski val = (float)val * mul;
279*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %0.2fkm\n", fn, val);
280*1b481fc3SMaciej Żenczykowski }
281*1b481fc3SMaciej Żenczykowski
282*1b481fc3SMaciej Żenczykowski /**
283*1b481fc3SMaciej Żenczykowski * Print relevant signal integrity control properties. Relevant documents:
284*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, pag. 71, section 1.7.4.10, Table 46
285*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, pag. 105, section 8.4.10, Table 8-34
286*1b481fc3SMaciej Żenczykowski */
cmis_show_sig_integrity(const struct cmis_memory_map * map)287*1b481fc3SMaciej Żenczykowski static void cmis_show_sig_integrity(const struct cmis_memory_map *map)
288*1b481fc3SMaciej Żenczykowski {
289*1b481fc3SMaciej Żenczykowski if (!map->page_01h)
290*1b481fc3SMaciej Żenczykowski return;
291*1b481fc3SMaciej Żenczykowski
292*1b481fc3SMaciej Żenczykowski /* CDR Bypass control: 2nd bit from each byte */
293*1b481fc3SMaciej Żenczykowski printf("\t%-41s : ", "Tx CDR bypass control");
294*1b481fc3SMaciej Żenczykowski printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_TX_OFFSET] & 0x02));
295*1b481fc3SMaciej Żenczykowski
296*1b481fc3SMaciej Żenczykowski printf("\t%-41s : ", "Rx CDR bypass control");
297*1b481fc3SMaciej Żenczykowski printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_RX_OFFSET] & 0x02));
298*1b481fc3SMaciej Żenczykowski
299*1b481fc3SMaciej Żenczykowski /* CDR Implementation: 1st bit from each byte */
300*1b481fc3SMaciej Żenczykowski printf("\t%-41s : ", "Tx CDR");
301*1b481fc3SMaciej Żenczykowski printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_TX_OFFSET] & 0x01));
302*1b481fc3SMaciej Żenczykowski
303*1b481fc3SMaciej Żenczykowski printf("\t%-41s : ", "Rx CDR");
304*1b481fc3SMaciej Żenczykowski printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_RX_OFFSET] & 0x01));
305*1b481fc3SMaciej Żenczykowski }
306*1b481fc3SMaciej Żenczykowski
307*1b481fc3SMaciej Żenczykowski /**
308*1b481fc3SMaciej Żenczykowski * Print relevant media interface technology info. Relevant documents:
309*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3
310*1b481fc3SMaciej Żenczykowski * --> pag. 61, section 1.7.3.14, Table 36
311*1b481fc3SMaciej Żenczykowski * --> pag. 64, section 1.7.4.3, 1.7.4.4
312*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4
313*1b481fc3SMaciej Żenczykowski * --> pag. 97, section 8.3.14, Table 8-24
314*1b481fc3SMaciej Żenczykowski * --> pag. 98, section 8.4, Table 8-25
315*1b481fc3SMaciej Żenczykowski * --> page 100, section 8.4.3, 8.4.4
316*1b481fc3SMaciej Żenczykowski */
cmis_show_mit_compliance(const struct cmis_memory_map * map)317*1b481fc3SMaciej Żenczykowski static void cmis_show_mit_compliance(const struct cmis_memory_map *map)
318*1b481fc3SMaciej Żenczykowski {
319*1b481fc3SMaciej Żenczykowski static const char *cc = " (Copper cable,";
320*1b481fc3SMaciej Żenczykowski
321*1b481fc3SMaciej Żenczykowski printf("\t%-41s : 0x%02x", "Transmitter technology",
322*1b481fc3SMaciej Żenczykowski map->page_00h[CMIS_MEDIA_INTF_TECH_OFFSET]);
323*1b481fc3SMaciej Żenczykowski
324*1b481fc3SMaciej Żenczykowski switch (map->page_00h[CMIS_MEDIA_INTF_TECH_OFFSET]) {
325*1b481fc3SMaciej Żenczykowski case CMIS_850_VCSEL:
326*1b481fc3SMaciej Żenczykowski printf(" (850 nm VCSEL)\n");
327*1b481fc3SMaciej Żenczykowski break;
328*1b481fc3SMaciej Żenczykowski case CMIS_1310_VCSEL:
329*1b481fc3SMaciej Żenczykowski printf(" (1310 nm VCSEL)\n");
330*1b481fc3SMaciej Żenczykowski break;
331*1b481fc3SMaciej Żenczykowski case CMIS_1550_VCSEL:
332*1b481fc3SMaciej Żenczykowski printf(" (1550 nm VCSEL)\n");
333*1b481fc3SMaciej Żenczykowski break;
334*1b481fc3SMaciej Żenczykowski case CMIS_1310_FP:
335*1b481fc3SMaciej Żenczykowski printf(" (1310 nm FP)\n");
336*1b481fc3SMaciej Żenczykowski break;
337*1b481fc3SMaciej Żenczykowski case CMIS_1310_DFB:
338*1b481fc3SMaciej Żenczykowski printf(" (1310 nm DFB)\n");
339*1b481fc3SMaciej Żenczykowski break;
340*1b481fc3SMaciej Żenczykowski case CMIS_1550_DFB:
341*1b481fc3SMaciej Żenczykowski printf(" (1550 nm DFB)\n");
342*1b481fc3SMaciej Żenczykowski break;
343*1b481fc3SMaciej Żenczykowski case CMIS_1310_EML:
344*1b481fc3SMaciej Żenczykowski printf(" (1310 nm EML)\n");
345*1b481fc3SMaciej Żenczykowski break;
346*1b481fc3SMaciej Żenczykowski case CMIS_1550_EML:
347*1b481fc3SMaciej Żenczykowski printf(" (1550 nm EML)\n");
348*1b481fc3SMaciej Żenczykowski break;
349*1b481fc3SMaciej Żenczykowski case CMIS_OTHERS:
350*1b481fc3SMaciej Żenczykowski printf(" (Others/Undefined)\n");
351*1b481fc3SMaciej Żenczykowski break;
352*1b481fc3SMaciej Żenczykowski case CMIS_1490_DFB:
353*1b481fc3SMaciej Żenczykowski printf(" (1490 nm DFB)\n");
354*1b481fc3SMaciej Żenczykowski break;
355*1b481fc3SMaciej Żenczykowski case CMIS_COPPER_UNEQUAL:
356*1b481fc3SMaciej Żenczykowski printf("%s unequalized)\n", cc);
357*1b481fc3SMaciej Żenczykowski break;
358*1b481fc3SMaciej Żenczykowski case CMIS_COPPER_PASS_EQUAL:
359*1b481fc3SMaciej Żenczykowski printf("%s passive equalized)\n", cc);
360*1b481fc3SMaciej Żenczykowski break;
361*1b481fc3SMaciej Żenczykowski case CMIS_COPPER_NF_EQUAL:
362*1b481fc3SMaciej Żenczykowski printf("%s near and far end limiting active equalizers)\n", cc);
363*1b481fc3SMaciej Żenczykowski break;
364*1b481fc3SMaciej Żenczykowski case CMIS_COPPER_F_EQUAL:
365*1b481fc3SMaciej Żenczykowski printf("%s far end limiting active equalizers)\n", cc);
366*1b481fc3SMaciej Żenczykowski break;
367*1b481fc3SMaciej Żenczykowski case CMIS_COPPER_N_EQUAL:
368*1b481fc3SMaciej Żenczykowski printf("%s near end limiting active equalizers)\n", cc);
369*1b481fc3SMaciej Żenczykowski break;
370*1b481fc3SMaciej Żenczykowski case CMIS_COPPER_LINEAR_EQUAL:
371*1b481fc3SMaciej Żenczykowski printf("%s linear active equalizers)\n", cc);
372*1b481fc3SMaciej Żenczykowski break;
373*1b481fc3SMaciej Żenczykowski }
374*1b481fc3SMaciej Żenczykowski
375*1b481fc3SMaciej Żenczykowski if (map->page_00h[CMIS_MEDIA_INTF_TECH_OFFSET] >= CMIS_COPPER_UNEQUAL) {
376*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %udb\n", "Attenuation at 5GHz",
377*1b481fc3SMaciej Żenczykowski map->page_00h[CMIS_COPPER_ATT_5GHZ]);
378*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %udb\n", "Attenuation at 7GHz",
379*1b481fc3SMaciej Żenczykowski map->page_00h[CMIS_COPPER_ATT_7GHZ]);
380*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %udb\n", "Attenuation at 12.9GHz",
381*1b481fc3SMaciej Żenczykowski map->page_00h[CMIS_COPPER_ATT_12P9GHZ]);
382*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %udb\n", "Attenuation at 25.8GHz",
383*1b481fc3SMaciej Żenczykowski map->page_00h[CMIS_COPPER_ATT_25P8GHZ]);
384*1b481fc3SMaciej Żenczykowski } else if (map->page_01h) {
385*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %.3lfnm\n", "Laser wavelength",
386*1b481fc3SMaciej Żenczykowski (((map->page_01h[CMIS_NOM_WAVELENGTH_MSB] << 8) |
387*1b481fc3SMaciej Żenczykowski map->page_01h[CMIS_NOM_WAVELENGTH_LSB]) * 0.05));
388*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %.3lfnm\n", "Laser wavelength tolerance",
389*1b481fc3SMaciej Żenczykowski (((map->page_01h[CMIS_WAVELENGTH_TOL_MSB] << 8) |
390*1b481fc3SMaciej Żenczykowski map->page_01h[CMIS_WAVELENGTH_TOL_LSB]) * 0.005));
391*1b481fc3SMaciej Żenczykowski }
392*1b481fc3SMaciej Żenczykowski }
393*1b481fc3SMaciej Żenczykowski
394*1b481fc3SMaciej Żenczykowski /**
395*1b481fc3SMaciej Żenczykowski * Print relevant info about the maximum supported fiber media length
396*1b481fc3SMaciej Żenczykowski * for each type of fiber media at the maximum module-supported bit rate.
397*1b481fc3SMaciej Żenczykowski * Relevant documents:
398*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, page 64, section 1.7.4.2, Table 39
399*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, page 99, section 8.4.2, Table 8-27
400*1b481fc3SMaciej Żenczykowski */
cmis_show_link_len(const struct cmis_memory_map * map)401*1b481fc3SMaciej Żenczykowski static void cmis_show_link_len(const struct cmis_memory_map *map)
402*1b481fc3SMaciej Żenczykowski {
403*1b481fc3SMaciej Żenczykowski cmis_print_smf_cbl_len(map);
404*1b481fc3SMaciej Żenczykowski if (!map->page_01h)
405*1b481fc3SMaciej Żenczykowski return;
406*1b481fc3SMaciej Żenczykowski sff_show_value_with_unit(map->page_01h, CMIS_OM5_LEN_OFFSET,
407*1b481fc3SMaciej Żenczykowski "Length (OM5)", 2, "m");
408*1b481fc3SMaciej Żenczykowski sff_show_value_with_unit(map->page_01h, CMIS_OM4_LEN_OFFSET,
409*1b481fc3SMaciej Żenczykowski "Length (OM4)", 2, "m");
410*1b481fc3SMaciej Żenczykowski sff_show_value_with_unit(map->page_01h, CMIS_OM3_LEN_OFFSET,
411*1b481fc3SMaciej Żenczykowski "Length (OM3 50/125um)", 2, "m");
412*1b481fc3SMaciej Żenczykowski sff_show_value_with_unit(map->page_01h, CMIS_OM2_LEN_OFFSET,
413*1b481fc3SMaciej Żenczykowski "Length (OM2 50/125um)", 1, "m");
414*1b481fc3SMaciej Żenczykowski }
415*1b481fc3SMaciej Żenczykowski
416*1b481fc3SMaciej Żenczykowski /**
417*1b481fc3SMaciej Żenczykowski * Show relevant information about the vendor. Relevant documents:
418*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 3, page 56, section 1.7.3, Table 27
419*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 4, page 91, section 8.2, Table 8-15
420*1b481fc3SMaciej Żenczykowski */
cmis_show_vendor_info(const struct cmis_memory_map * map)421*1b481fc3SMaciej Żenczykowski static void cmis_show_vendor_info(const struct cmis_memory_map *map)
422*1b481fc3SMaciej Żenczykowski {
423*1b481fc3SMaciej Żenczykowski const char *clei;
424*1b481fc3SMaciej Żenczykowski
425*1b481fc3SMaciej Żenczykowski sff_show_ascii(map->page_00h, CMIS_VENDOR_NAME_START_OFFSET,
426*1b481fc3SMaciej Żenczykowski CMIS_VENDOR_NAME_END_OFFSET, "Vendor name");
427*1b481fc3SMaciej Żenczykowski cmis_show_oui(map);
428*1b481fc3SMaciej Żenczykowski sff_show_ascii(map->page_00h, CMIS_VENDOR_PN_START_OFFSET,
429*1b481fc3SMaciej Żenczykowski CMIS_VENDOR_PN_END_OFFSET, "Vendor PN");
430*1b481fc3SMaciej Żenczykowski sff_show_ascii(map->page_00h, CMIS_VENDOR_REV_START_OFFSET,
431*1b481fc3SMaciej Żenczykowski CMIS_VENDOR_REV_END_OFFSET, "Vendor rev");
432*1b481fc3SMaciej Żenczykowski sff_show_ascii(map->page_00h, CMIS_VENDOR_SN_START_OFFSET,
433*1b481fc3SMaciej Żenczykowski CMIS_VENDOR_SN_END_OFFSET, "Vendor SN");
434*1b481fc3SMaciej Żenczykowski sff_show_ascii(map->page_00h, CMIS_DATE_YEAR_OFFSET,
435*1b481fc3SMaciej Żenczykowski CMIS_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
436*1b481fc3SMaciej Żenczykowski
437*1b481fc3SMaciej Żenczykowski clei = (const char *)(map->page_00h + CMIS_CLEI_START_OFFSET);
438*1b481fc3SMaciej Żenczykowski if (*clei && strncmp(clei, CMIS_CLEI_BLANK, CMIS_CLEI_LEN))
439*1b481fc3SMaciej Żenczykowski sff_show_ascii(map->page_00h, CMIS_CLEI_START_OFFSET,
440*1b481fc3SMaciej Żenczykowski CMIS_CLEI_END_OFFSET, "CLEI code");
441*1b481fc3SMaciej Żenczykowski }
442*1b481fc3SMaciej Żenczykowski
443*1b481fc3SMaciej Żenczykowski /* Print the current Module State. Relevant documents:
444*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, pag. 57, section 6.3.2.2, Figure 6-3
445*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 5, pag. 60, section 6.3.2.3, Figure 6-4
446*1b481fc3SMaciej Żenczykowski * [3] CMIS Rev. 5, pag. 107, section 8.2.2, Table 8-6
447*1b481fc3SMaciej Żenczykowski */
cmis_show_mod_state(const struct cmis_memory_map * map)448*1b481fc3SMaciej Żenczykowski static void cmis_show_mod_state(const struct cmis_memory_map *map)
449*1b481fc3SMaciej Żenczykowski {
450*1b481fc3SMaciej Żenczykowski __u8 mod_state;
451*1b481fc3SMaciej Żenczykowski
452*1b481fc3SMaciej Żenczykowski mod_state = (map->lower_memory[CMIS_MODULE_STATE_OFFSET] &
453*1b481fc3SMaciej Żenczykowski CMIS_MODULE_STATE_MASK) >> 1;
454*1b481fc3SMaciej Żenczykowski printf("\t%-41s : 0x%02x", "Module State", mod_state);
455*1b481fc3SMaciej Żenczykowski switch (mod_state) {
456*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_STATE_MODULE_LOW_PWR:
457*1b481fc3SMaciej Żenczykowski printf(" (ModuleLowPwr)\n");
458*1b481fc3SMaciej Żenczykowski break;
459*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_STATE_MODULE_PWR_UP:
460*1b481fc3SMaciej Żenczykowski printf(" (ModulePwrUp)\n");
461*1b481fc3SMaciej Żenczykowski break;
462*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_STATE_MODULE_READY:
463*1b481fc3SMaciej Żenczykowski printf(" (ModuleReady)\n");
464*1b481fc3SMaciej Żenczykowski break;
465*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_STATE_MODULE_PWR_DN:
466*1b481fc3SMaciej Żenczykowski printf(" (ModulePwrDn)\n");
467*1b481fc3SMaciej Żenczykowski break;
468*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_STATE_MODULE_FAULT:
469*1b481fc3SMaciej Żenczykowski printf(" (ModuleFault)\n");
470*1b481fc3SMaciej Żenczykowski break;
471*1b481fc3SMaciej Żenczykowski default:
472*1b481fc3SMaciej Żenczykowski printf(" (reserved or unknown)\n");
473*1b481fc3SMaciej Żenczykowski break;
474*1b481fc3SMaciej Żenczykowski }
475*1b481fc3SMaciej Żenczykowski }
476*1b481fc3SMaciej Żenczykowski
477*1b481fc3SMaciej Żenczykowski /* Print the Module Fault Information. Relevant documents:
478*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, pag. 64, section 6.3.2.12
479*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 5, pag. 115, section 8.2.10, Table 8-15
480*1b481fc3SMaciej Żenczykowski */
cmis_show_mod_fault_cause(const struct cmis_memory_map * map)481*1b481fc3SMaciej Żenczykowski static void cmis_show_mod_fault_cause(const struct cmis_memory_map *map)
482*1b481fc3SMaciej Żenczykowski {
483*1b481fc3SMaciej Żenczykowski __u8 mod_state, fault_cause;
484*1b481fc3SMaciej Żenczykowski
485*1b481fc3SMaciej Żenczykowski mod_state = (map->lower_memory[CMIS_MODULE_STATE_OFFSET] &
486*1b481fc3SMaciej Żenczykowski CMIS_MODULE_STATE_MASK) >> 1;
487*1b481fc3SMaciej Żenczykowski if (mod_state != CMIS_MODULE_STATE_MODULE_FAULT)
488*1b481fc3SMaciej Żenczykowski return;
489*1b481fc3SMaciej Żenczykowski
490*1b481fc3SMaciej Żenczykowski fault_cause = map->lower_memory[CMIS_MODULE_FAULT_OFFSET];
491*1b481fc3SMaciej Żenczykowski printf("\t%-41s : 0x%02x", "Module Fault Cause", fault_cause);
492*1b481fc3SMaciej Żenczykowski switch (fault_cause) {
493*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_FAULT_NO_FAULT:
494*1b481fc3SMaciej Żenczykowski printf(" (No fault detected / not supported)\n");
495*1b481fc3SMaciej Żenczykowski break;
496*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_FAULT_TEC_RUNAWAY:
497*1b481fc3SMaciej Żenczykowski printf(" (TEC runaway)\n");
498*1b481fc3SMaciej Żenczykowski break;
499*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_FAULT_DATA_MEM_CORRUPTED:
500*1b481fc3SMaciej Żenczykowski printf(" (Data memory corrupted)\n");
501*1b481fc3SMaciej Żenczykowski break;
502*1b481fc3SMaciej Żenczykowski case CMIS_MODULE_FAULT_PROG_MEM_CORRUPTED:
503*1b481fc3SMaciej Żenczykowski printf(" (Program memory corrupted)\n");
504*1b481fc3SMaciej Żenczykowski break;
505*1b481fc3SMaciej Żenczykowski default:
506*1b481fc3SMaciej Żenczykowski printf(" (reserved or unknown)\n");
507*1b481fc3SMaciej Żenczykowski break;
508*1b481fc3SMaciej Żenczykowski }
509*1b481fc3SMaciej Żenczykowski }
510*1b481fc3SMaciej Żenczykowski
511*1b481fc3SMaciej Żenczykowski /* Print the current Module-Level Controls. Relevant documents:
512*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, pag. 58, section 6.3.2.2, Table 6-12
513*1b481fc3SMaciej Żenczykowski * [2] CMIS Rev. 5, pag. 111, section 8.2.6, Table 8-10
514*1b481fc3SMaciej Żenczykowski */
cmis_show_mod_lvl_controls(const struct cmis_memory_map * map)515*1b481fc3SMaciej Żenczykowski static void cmis_show_mod_lvl_controls(const struct cmis_memory_map *map)
516*1b481fc3SMaciej Żenczykowski {
517*1b481fc3SMaciej Żenczykowski printf("\t%-41s : ", "LowPwrAllowRequestHW");
518*1b481fc3SMaciej Żenczykowski printf("%s\n", ONOFF(map->lower_memory[CMIS_MODULE_CONTROL_OFFSET] &
519*1b481fc3SMaciej Żenczykowski CMIS_LOW_PWR_ALLOW_REQUEST_HW_MASK));
520*1b481fc3SMaciej Żenczykowski printf("\t%-41s : ", "LowPwrRequestSW");
521*1b481fc3SMaciej Żenczykowski printf("%s\n", ONOFF(map->lower_memory[CMIS_MODULE_CONTROL_OFFSET] &
522*1b481fc3SMaciej Żenczykowski CMIS_LOW_PWR_REQUEST_SW_MASK));
523*1b481fc3SMaciej Żenczykowski }
524*1b481fc3SMaciej Żenczykowski
cmis_parse_dom_power_type(const struct cmis_memory_map * map,struct sff_diags * sd)525*1b481fc3SMaciej Żenczykowski static void cmis_parse_dom_power_type(const struct cmis_memory_map *map,
526*1b481fc3SMaciej Żenczykowski struct sff_diags *sd)
527*1b481fc3SMaciej Żenczykowski {
528*1b481fc3SMaciej Żenczykowski sd->rx_power_type = map->page_01h[CMIS_DIAG_TYPE_OFFSET] &
529*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_TYPE_MASK;
530*1b481fc3SMaciej Żenczykowski sd->tx_power_type = map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] &
531*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_MON_MASK;
532*1b481fc3SMaciej Żenczykowski }
533*1b481fc3SMaciej Żenczykowski
cmis_parse_dom_mod_lvl_monitors(const struct cmis_memory_map * map,struct sff_diags * sd)534*1b481fc3SMaciej Żenczykowski static void cmis_parse_dom_mod_lvl_monitors(const struct cmis_memory_map *map,
535*1b481fc3SMaciej Żenczykowski struct sff_diags *sd)
536*1b481fc3SMaciej Żenczykowski {
537*1b481fc3SMaciej Żenczykowski sd->sfp_voltage[MCURR] = OFFSET_TO_U16_PTR(map->lower_memory,
538*1b481fc3SMaciej Żenczykowski CMIS_CURR_VCC_OFFSET);
539*1b481fc3SMaciej Żenczykowski sd->sfp_temp[MCURR] = (__s16)OFFSET_TO_U16_PTR(map->lower_memory,
540*1b481fc3SMaciej Żenczykowski CMIS_CURR_TEMP_OFFSET);
541*1b481fc3SMaciej Żenczykowski }
542*1b481fc3SMaciej Żenczykowski
cmis_parse_dom_mod_lvl_thresh(const struct cmis_memory_map * map,struct sff_diags * sd)543*1b481fc3SMaciej Żenczykowski static void cmis_parse_dom_mod_lvl_thresh(const struct cmis_memory_map *map,
544*1b481fc3SMaciej Żenczykowski struct sff_diags *sd)
545*1b481fc3SMaciej Żenczykowski {
546*1b481fc3SMaciej Żenczykowski /* Page is not present in IOCTL path. */
547*1b481fc3SMaciej Żenczykowski if (!map->page_02h)
548*1b481fc3SMaciej Żenczykowski return;
549*1b481fc3SMaciej Żenczykowski sd->supports_alarms = 1;
550*1b481fc3SMaciej Żenczykowski
551*1b481fc3SMaciej Żenczykowski sd->sfp_voltage[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
552*1b481fc3SMaciej Żenczykowski CMIS_VCC_HALRM_OFFSET);
553*1b481fc3SMaciej Żenczykowski sd->sfp_voltage[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
554*1b481fc3SMaciej Żenczykowski CMIS_VCC_LALRM_OFFSET);
555*1b481fc3SMaciej Żenczykowski sd->sfp_voltage[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
556*1b481fc3SMaciej Żenczykowski CMIS_VCC_HWARN_OFFSET);
557*1b481fc3SMaciej Żenczykowski sd->sfp_voltage[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
558*1b481fc3SMaciej Żenczykowski CMIS_VCC_LWARN_OFFSET);
559*1b481fc3SMaciej Żenczykowski
560*1b481fc3SMaciej Żenczykowski sd->sfp_temp[HALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
561*1b481fc3SMaciej Żenczykowski CMIS_TEMP_HALRM_OFFSET);
562*1b481fc3SMaciej Żenczykowski sd->sfp_temp[LALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
563*1b481fc3SMaciej Żenczykowski CMIS_TEMP_LALRM_OFFSET);
564*1b481fc3SMaciej Żenczykowski sd->sfp_temp[HWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
565*1b481fc3SMaciej Żenczykowski CMIS_TEMP_HWARN_OFFSET);
566*1b481fc3SMaciej Żenczykowski sd->sfp_temp[LWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
567*1b481fc3SMaciej Żenczykowski CMIS_TEMP_LWARN_OFFSET);
568*1b481fc3SMaciej Żenczykowski }
569*1b481fc3SMaciej Żenczykowski
cmis_tx_bias_mul(const struct cmis_memory_map * map)570*1b481fc3SMaciej Żenczykowski static __u8 cmis_tx_bias_mul(const struct cmis_memory_map *map)
571*1b481fc3SMaciej Żenczykowski {
572*1b481fc3SMaciej Żenczykowski switch (map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] &
573*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_MUL_MASK) {
574*1b481fc3SMaciej Żenczykowski case CMIS_TX_BIAS_MUL_1:
575*1b481fc3SMaciej Żenczykowski return 0;
576*1b481fc3SMaciej Żenczykowski case CMIS_TX_BIAS_MUL_2:
577*1b481fc3SMaciej Żenczykowski return 1;
578*1b481fc3SMaciej Żenczykowski case CMIS_TX_BIAS_MUL_4:
579*1b481fc3SMaciej Żenczykowski return 2;
580*1b481fc3SMaciej Żenczykowski }
581*1b481fc3SMaciej Żenczykowski
582*1b481fc3SMaciej Żenczykowski return 0;
583*1b481fc3SMaciej Żenczykowski }
584*1b481fc3SMaciej Żenczykowski
585*1b481fc3SMaciej Żenczykowski static void
cmis_parse_dom_chan_lvl_monitors_bank(const struct cmis_memory_map * map,struct sff_diags * sd,int bank)586*1b481fc3SMaciej Żenczykowski cmis_parse_dom_chan_lvl_monitors_bank(const struct cmis_memory_map *map,
587*1b481fc3SMaciej Żenczykowski struct sff_diags *sd, int bank)
588*1b481fc3SMaciej Żenczykowski {
589*1b481fc3SMaciej Żenczykowski const __u8 *page_11h = map->upper_memory[bank][0x11];
590*1b481fc3SMaciej Żenczykowski int i;
591*1b481fc3SMaciej Żenczykowski
592*1b481fc3SMaciej Żenczykowski if (!page_11h)
593*1b481fc3SMaciej Żenczykowski return;
594*1b481fc3SMaciej Żenczykowski
595*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
596*1b481fc3SMaciej Żenczykowski __u8 tx_bias_offset, rx_power_offset, tx_power_offset;
597*1b481fc3SMaciej Żenczykowski int chan = bank * CMIS_CHANNELS_PER_BANK + i;
598*1b481fc3SMaciej Żenczykowski __u8 bias_mul = cmis_tx_bias_mul(map);
599*1b481fc3SMaciej Żenczykowski
600*1b481fc3SMaciej Żenczykowski tx_bias_offset = CMIS_TX_BIAS_OFFSET + i * sizeof(__u16);
601*1b481fc3SMaciej Żenczykowski rx_power_offset = CMIS_RX_PWR_OFFSET + i * sizeof(__u16);
602*1b481fc3SMaciej Żenczykowski tx_power_offset = CMIS_TX_PWR_OFFSET + i * sizeof(__u16);
603*1b481fc3SMaciej Żenczykowski
604*1b481fc3SMaciej Żenczykowski sd->scd[chan].bias_cur = OFFSET_TO_U16_PTR(page_11h,
605*1b481fc3SMaciej Żenczykowski tx_bias_offset);
606*1b481fc3SMaciej Żenczykowski sd->scd[chan].bias_cur >>= bias_mul;
607*1b481fc3SMaciej Żenczykowski sd->scd[chan].rx_power = OFFSET_TO_U16_PTR(page_11h,
608*1b481fc3SMaciej Żenczykowski rx_power_offset);
609*1b481fc3SMaciej Żenczykowski sd->scd[chan].tx_power = OFFSET_TO_U16_PTR(page_11h,
610*1b481fc3SMaciej Żenczykowski tx_power_offset);
611*1b481fc3SMaciej Żenczykowski }
612*1b481fc3SMaciej Żenczykowski }
613*1b481fc3SMaciej Żenczykowski
cmis_parse_dom_chan_lvl_monitors(const struct cmis_memory_map * map,struct sff_diags * sd)614*1b481fc3SMaciej Żenczykowski static void cmis_parse_dom_chan_lvl_monitors(const struct cmis_memory_map *map,
615*1b481fc3SMaciej Żenczykowski struct sff_diags *sd)
616*1b481fc3SMaciej Żenczykowski {
617*1b481fc3SMaciej Żenczykowski int i;
618*1b481fc3SMaciej Żenczykowski
619*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_MAX_BANKS; i++)
620*1b481fc3SMaciej Żenczykowski cmis_parse_dom_chan_lvl_monitors_bank(map, sd, i);
621*1b481fc3SMaciej Żenczykowski }
622*1b481fc3SMaciej Żenczykowski
cmis_parse_dom_chan_lvl_thresh(const struct cmis_memory_map * map,struct sff_diags * sd)623*1b481fc3SMaciej Żenczykowski static void cmis_parse_dom_chan_lvl_thresh(const struct cmis_memory_map *map,
624*1b481fc3SMaciej Żenczykowski struct sff_diags *sd)
625*1b481fc3SMaciej Żenczykowski {
626*1b481fc3SMaciej Żenczykowski __u8 bias_mul = cmis_tx_bias_mul(map);
627*1b481fc3SMaciej Żenczykowski
628*1b481fc3SMaciej Żenczykowski if (!map->page_02h)
629*1b481fc3SMaciej Żenczykowski return;
630*1b481fc3SMaciej Żenczykowski
631*1b481fc3SMaciej Żenczykowski sd->bias_cur[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
632*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_HALRM_OFFSET);
633*1b481fc3SMaciej Żenczykowski sd->bias_cur[HALRM] >>= bias_mul;
634*1b481fc3SMaciej Żenczykowski sd->bias_cur[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
635*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_LALRM_OFFSET);
636*1b481fc3SMaciej Żenczykowski sd->bias_cur[LALRM] >>= bias_mul;
637*1b481fc3SMaciej Żenczykowski sd->bias_cur[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
638*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_HWARN_OFFSET);
639*1b481fc3SMaciej Żenczykowski sd->bias_cur[HWARN] >>= bias_mul;
640*1b481fc3SMaciej Żenczykowski sd->bias_cur[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
641*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_LWARN_OFFSET);
642*1b481fc3SMaciej Żenczykowski sd->bias_cur[LWARN] >>= bias_mul;
643*1b481fc3SMaciej Żenczykowski
644*1b481fc3SMaciej Żenczykowski sd->tx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
645*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_HALRM_OFFSET);
646*1b481fc3SMaciej Żenczykowski sd->tx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
647*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_LALRM_OFFSET);
648*1b481fc3SMaciej Żenczykowski sd->tx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
649*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_HWARN_OFFSET);
650*1b481fc3SMaciej Żenczykowski sd->tx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
651*1b481fc3SMaciej Żenczykowski CMIS_TX_PWR_LWARN_OFFSET);
652*1b481fc3SMaciej Żenczykowski
653*1b481fc3SMaciej Żenczykowski sd->rx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
654*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_HALRM_OFFSET);
655*1b481fc3SMaciej Żenczykowski sd->rx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
656*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_LALRM_OFFSET);
657*1b481fc3SMaciej Żenczykowski sd->rx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
658*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_HWARN_OFFSET);
659*1b481fc3SMaciej Żenczykowski sd->rx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
660*1b481fc3SMaciej Żenczykowski CMIS_RX_PWR_LWARN_OFFSET);
661*1b481fc3SMaciej Żenczykowski }
662*1b481fc3SMaciej Żenczykowski
cmis_parse_dom(const struct cmis_memory_map * map,struct sff_diags * sd)663*1b481fc3SMaciej Żenczykowski static void cmis_parse_dom(const struct cmis_memory_map *map,
664*1b481fc3SMaciej Żenczykowski struct sff_diags *sd)
665*1b481fc3SMaciej Żenczykowski {
666*1b481fc3SMaciej Żenczykowski cmis_parse_dom_power_type(map, sd);
667*1b481fc3SMaciej Żenczykowski cmis_parse_dom_mod_lvl_monitors(map, sd);
668*1b481fc3SMaciej Żenczykowski cmis_parse_dom_mod_lvl_thresh(map, sd);
669*1b481fc3SMaciej Żenczykowski cmis_parse_dom_chan_lvl_monitors(map, sd);
670*1b481fc3SMaciej Żenczykowski cmis_parse_dom_chan_lvl_thresh(map, sd);
671*1b481fc3SMaciej Żenczykowski }
672*1b481fc3SMaciej Żenczykowski
673*1b481fc3SMaciej Żenczykowski /* Print module-level monitoring values. Relevant documents:
674*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 110, section 8.2.5, Table 8-9
675*1b481fc3SMaciej Żenczykowski */
cmis_show_dom_mod_lvl_monitors(const struct sff_diags * sd)676*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_mod_lvl_monitors(const struct sff_diags *sd)
677*1b481fc3SMaciej Żenczykowski {
678*1b481fc3SMaciej Żenczykowski PRINT_TEMP("Module temperature", sd->sfp_temp[MCURR]);
679*1b481fc3SMaciej Żenczykowski PRINT_VCC("Module voltage", sd->sfp_voltage[MCURR]);
680*1b481fc3SMaciej Żenczykowski }
681*1b481fc3SMaciej Żenczykowski
682*1b481fc3SMaciej Żenczykowski /* Print channel Tx laser bias current. Relevant documents:
683*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 165, section 8.9.4, Table 8-79
684*1b481fc3SMaciej Żenczykowski */
685*1b481fc3SMaciej Żenczykowski static void
cmis_show_dom_chan_lvl_tx_bias_bank(const struct cmis_memory_map * map,const struct sff_diags * sd,int bank)686*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_tx_bias_bank(const struct cmis_memory_map *map,
687*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd, int bank)
688*1b481fc3SMaciej Żenczykowski {
689*1b481fc3SMaciej Żenczykowski const __u8 *page_11h = map->upper_memory[bank][0x11];
690*1b481fc3SMaciej Żenczykowski int i;
691*1b481fc3SMaciej Żenczykowski
692*1b481fc3SMaciej Żenczykowski if (!page_11h)
693*1b481fc3SMaciej Żenczykowski return;
694*1b481fc3SMaciej Żenczykowski
695*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
696*1b481fc3SMaciej Żenczykowski int chan = bank * CMIS_CHANNELS_PER_BANK + i;
697*1b481fc3SMaciej Żenczykowski char fmt_str[80];
698*1b481fc3SMaciej Żenczykowski
699*1b481fc3SMaciej Żenczykowski snprintf(fmt_str, 80, "%s (Channel %d)",
700*1b481fc3SMaciej Żenczykowski "Laser tx bias current", chan + 1);
701*1b481fc3SMaciej Żenczykowski PRINT_BIAS(fmt_str, sd->scd[chan].bias_cur);
702*1b481fc3SMaciej Żenczykowski }
703*1b481fc3SMaciej Żenczykowski }
704*1b481fc3SMaciej Żenczykowski
cmis_show_dom_chan_lvl_tx_bias(const struct cmis_memory_map * map,const struct sff_diags * sd)705*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_chan_lvl_tx_bias(const struct cmis_memory_map *map,
706*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd)
707*1b481fc3SMaciej Żenczykowski {
708*1b481fc3SMaciej Żenczykowski int i;
709*1b481fc3SMaciej Żenczykowski
710*1b481fc3SMaciej Żenczykowski if(!(map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] &
711*1b481fc3SMaciej Żenczykowski CMIS_TX_BIAS_MON_MASK))
712*1b481fc3SMaciej Żenczykowski return;
713*1b481fc3SMaciej Żenczykowski
714*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_MAX_BANKS; i++)
715*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_tx_bias_bank(map, sd, i);
716*1b481fc3SMaciej Żenczykowski }
717*1b481fc3SMaciej Żenczykowski
718*1b481fc3SMaciej Żenczykowski /* Print channel Tx average optical power. Relevant documents:
719*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 165, section 8.9.4, Table 8-79
720*1b481fc3SMaciej Żenczykowski */
721*1b481fc3SMaciej Żenczykowski static void
cmis_show_dom_chan_lvl_tx_power_bank(const struct cmis_memory_map * map,const struct sff_diags * sd,int bank)722*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_tx_power_bank(const struct cmis_memory_map *map,
723*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd, int bank)
724*1b481fc3SMaciej Żenczykowski {
725*1b481fc3SMaciej Żenczykowski const __u8 *page_11h = map->upper_memory[bank][0x11];
726*1b481fc3SMaciej Żenczykowski int i;
727*1b481fc3SMaciej Żenczykowski
728*1b481fc3SMaciej Żenczykowski if (!page_11h)
729*1b481fc3SMaciej Żenczykowski return;
730*1b481fc3SMaciej Żenczykowski
731*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
732*1b481fc3SMaciej Żenczykowski int chan = bank * CMIS_CHANNELS_PER_BANK + i;
733*1b481fc3SMaciej Żenczykowski char fmt_str[80];
734*1b481fc3SMaciej Żenczykowski
735*1b481fc3SMaciej Żenczykowski snprintf(fmt_str, 80, "%s (Channel %d)",
736*1b481fc3SMaciej Żenczykowski "Transmit avg optical power", chan + 1);
737*1b481fc3SMaciej Żenczykowski PRINT_xX_PWR(fmt_str, sd->scd[chan].tx_power);
738*1b481fc3SMaciej Żenczykowski }
739*1b481fc3SMaciej Żenczykowski }
740*1b481fc3SMaciej Żenczykowski
cmis_show_dom_chan_lvl_tx_power(const struct cmis_memory_map * map,const struct sff_diags * sd)741*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_chan_lvl_tx_power(const struct cmis_memory_map *map,
742*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd)
743*1b481fc3SMaciej Żenczykowski {
744*1b481fc3SMaciej Żenczykowski int i;
745*1b481fc3SMaciej Żenczykowski
746*1b481fc3SMaciej Żenczykowski if (!sd->tx_power_type)
747*1b481fc3SMaciej Żenczykowski return;
748*1b481fc3SMaciej Żenczykowski
749*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_MAX_BANKS; i++)
750*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_tx_power_bank(map, sd, i);
751*1b481fc3SMaciej Żenczykowski }
752*1b481fc3SMaciej Żenczykowski
753*1b481fc3SMaciej Żenczykowski /* Print channel Rx input optical power. Relevant documents:
754*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 165, section 8.9.4, Table 8-79
755*1b481fc3SMaciej Żenczykowski */
756*1b481fc3SMaciej Żenczykowski static void
cmis_show_dom_chan_lvl_rx_power_bank(const struct cmis_memory_map * map,const struct sff_diags * sd,int bank)757*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_rx_power_bank(const struct cmis_memory_map *map,
758*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd, int bank)
759*1b481fc3SMaciej Żenczykowski {
760*1b481fc3SMaciej Żenczykowski const __u8 *page_11h = map->upper_memory[bank][0x11];
761*1b481fc3SMaciej Żenczykowski int i;
762*1b481fc3SMaciej Żenczykowski
763*1b481fc3SMaciej Żenczykowski if (!page_11h)
764*1b481fc3SMaciej Żenczykowski return;
765*1b481fc3SMaciej Żenczykowski
766*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
767*1b481fc3SMaciej Żenczykowski int chan = bank * CMIS_CHANNELS_PER_BANK + i;
768*1b481fc3SMaciej Żenczykowski char *rx_power_str;
769*1b481fc3SMaciej Żenczykowski char fmt_str[80];
770*1b481fc3SMaciej Żenczykowski
771*1b481fc3SMaciej Żenczykowski if (!sd->rx_power_type)
772*1b481fc3SMaciej Żenczykowski rx_power_str = "Receiver signal OMA";
773*1b481fc3SMaciej Żenczykowski else
774*1b481fc3SMaciej Żenczykowski rx_power_str = "Rcvr signal avg optical power";
775*1b481fc3SMaciej Żenczykowski
776*1b481fc3SMaciej Żenczykowski snprintf(fmt_str, 80, "%s (Channel %d)", rx_power_str,
777*1b481fc3SMaciej Żenczykowski chan + 1);
778*1b481fc3SMaciej Żenczykowski PRINT_xX_PWR(fmt_str, sd->scd[chan].rx_power);
779*1b481fc3SMaciej Żenczykowski }
780*1b481fc3SMaciej Żenczykowski }
781*1b481fc3SMaciej Żenczykowski
cmis_show_dom_chan_lvl_rx_power(const struct cmis_memory_map * map,const struct sff_diags * sd)782*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_chan_lvl_rx_power(const struct cmis_memory_map *map,
783*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd)
784*1b481fc3SMaciej Żenczykowski {
785*1b481fc3SMaciej Żenczykowski int i;
786*1b481fc3SMaciej Żenczykowski
787*1b481fc3SMaciej Żenczykowski if(!(map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] & CMIS_RX_PWR_MON_MASK))
788*1b481fc3SMaciej Żenczykowski return;
789*1b481fc3SMaciej Żenczykowski
790*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_MAX_BANKS; i++)
791*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_rx_power_bank(map, sd, i);
792*1b481fc3SMaciej Żenczykowski }
793*1b481fc3SMaciej Żenczykowski
cmis_show_dom_chan_lvl_monitors(const struct cmis_memory_map * map,const struct sff_diags * sd)794*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_chan_lvl_monitors(const struct cmis_memory_map *map,
795*1b481fc3SMaciej Żenczykowski const struct sff_diags *sd)
796*1b481fc3SMaciej Żenczykowski {
797*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_tx_bias(map, sd);
798*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_tx_power(map, sd);
799*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_rx_power(map, sd);
800*1b481fc3SMaciej Żenczykowski }
801*1b481fc3SMaciej Żenczykowski
802*1b481fc3SMaciej Żenczykowski /* Print module-level flags. Relevant documents:
803*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 109, section 8.2.4, Table 8-8
804*1b481fc3SMaciej Żenczykowski */
cmis_show_dom_mod_lvl_flags(const struct cmis_memory_map * map)805*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_mod_lvl_flags(const struct cmis_memory_map *map)
806*1b481fc3SMaciej Żenczykowski {
807*1b481fc3SMaciej Żenczykowski int i;
808*1b481fc3SMaciej Żenczykowski
809*1b481fc3SMaciej Żenczykowski for (i = 0; cmis_aw_mod_flags[i].str; i++) {
810*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %s\n", cmis_aw_mod_flags[i].str,
811*1b481fc3SMaciej Żenczykowski map->lower_memory[cmis_aw_mod_flags[i].offset] &
812*1b481fc3SMaciej Żenczykowski cmis_aw_mod_flags[i].value ? "On" : "Off");
813*1b481fc3SMaciej Żenczykowski }
814*1b481fc3SMaciej Żenczykowski }
815*1b481fc3SMaciej Żenczykowski
816*1b481fc3SMaciej Żenczykowski /* Print channel-level flags. Relevant documents:
817*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 162, section 8.9.3, Table 8-77
818*1b481fc3SMaciej Żenczykowski * [1] CMIS Rev. 5, page 164, section 8.9.3, Table 8-78
819*1b481fc3SMaciej Żenczykowski */
cmis_show_dom_chan_lvl_flags_chan(const struct cmis_memory_map * map,int bank,int chan)820*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_chan_lvl_flags_chan(const struct cmis_memory_map *map,
821*1b481fc3SMaciej Żenczykowski int bank, int chan)
822*1b481fc3SMaciej Żenczykowski {
823*1b481fc3SMaciej Żenczykowski const __u8 *page_11h = map->upper_memory[bank][0x11];
824*1b481fc3SMaciej Żenczykowski int i;
825*1b481fc3SMaciej Żenczykowski
826*1b481fc3SMaciej Żenczykowski for (i = 0; cmis_aw_chan_flags[i].fmt_str; i++) {
827*1b481fc3SMaciej Żenczykowski char str[80];
828*1b481fc3SMaciej Żenczykowski
829*1b481fc3SMaciej Żenczykowski if (!(map->page_01h[cmis_aw_chan_flags[i].adver_offset] &
830*1b481fc3SMaciej Żenczykowski cmis_aw_chan_flags[i].adver_value))
831*1b481fc3SMaciej Żenczykowski continue;
832*1b481fc3SMaciej Żenczykowski
833*1b481fc3SMaciej Żenczykowski snprintf(str, 80, cmis_aw_chan_flags[i].fmt_str, chan + 1);
834*1b481fc3SMaciej Żenczykowski printf("\t%-41s : %s\n", str,
835*1b481fc3SMaciej Żenczykowski page_11h[cmis_aw_chan_flags[i].offset] & chan ?
836*1b481fc3SMaciej Żenczykowski "On" : "Off");
837*1b481fc3SMaciej Żenczykowski }
838*1b481fc3SMaciej Żenczykowski }
839*1b481fc3SMaciej Żenczykowski
840*1b481fc3SMaciej Żenczykowski static void
cmis_show_dom_chan_lvl_flags_bank(const struct cmis_memory_map * map,int bank)841*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_flags_bank(const struct cmis_memory_map *map,
842*1b481fc3SMaciej Żenczykowski int bank)
843*1b481fc3SMaciej Żenczykowski {
844*1b481fc3SMaciej Żenczykowski const __u8 *page_11h = map->upper_memory[bank][0x11];
845*1b481fc3SMaciej Żenczykowski int i;
846*1b481fc3SMaciej Żenczykowski
847*1b481fc3SMaciej Żenczykowski if (!page_11h)
848*1b481fc3SMaciej Żenczykowski return;
849*1b481fc3SMaciej Żenczykowski
850*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
851*1b481fc3SMaciej Żenczykowski int chan = bank * CMIS_CHANNELS_PER_BANK + i;
852*1b481fc3SMaciej Żenczykowski
853*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_flags_chan(map, bank, chan);
854*1b481fc3SMaciej Żenczykowski }
855*1b481fc3SMaciej Żenczykowski }
856*1b481fc3SMaciej Żenczykowski
cmis_show_dom_chan_lvl_flags(const struct cmis_memory_map * map)857*1b481fc3SMaciej Żenczykowski static void cmis_show_dom_chan_lvl_flags(const struct cmis_memory_map *map)
858*1b481fc3SMaciej Żenczykowski {
859*1b481fc3SMaciej Żenczykowski int i;
860*1b481fc3SMaciej Żenczykowski
861*1b481fc3SMaciej Żenczykowski for (i = 0; i < CMIS_MAX_BANKS; i++)
862*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_flags_bank(map, i);
863*1b481fc3SMaciej Żenczykowski }
864*1b481fc3SMaciej Żenczykowski
865*1b481fc3SMaciej Żenczykowski
cmis_show_dom(const struct cmis_memory_map * map)866*1b481fc3SMaciej Żenczykowski static void cmis_show_dom(const struct cmis_memory_map *map)
867*1b481fc3SMaciej Żenczykowski {
868*1b481fc3SMaciej Żenczykowski struct sff_diags sd = {};
869*1b481fc3SMaciej Żenczykowski
870*1b481fc3SMaciej Żenczykowski /* Diagnostic information is only relevant when the module memory
871*1b481fc3SMaciej Żenczykowski * model is paged and not flat.
872*1b481fc3SMaciej Żenczykowski */
873*1b481fc3SMaciej Żenczykowski if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
874*1b481fc3SMaciej Żenczykowski CMIS_MEMORY_MODEL_MASK)
875*1b481fc3SMaciej Żenczykowski return;
876*1b481fc3SMaciej Żenczykowski
877*1b481fc3SMaciej Żenczykowski cmis_parse_dom(map, &sd);
878*1b481fc3SMaciej Żenczykowski
879*1b481fc3SMaciej Żenczykowski cmis_show_dom_mod_lvl_monitors(&sd);
880*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_monitors(map, &sd);
881*1b481fc3SMaciej Żenczykowski cmis_show_dom_mod_lvl_flags(map);
882*1b481fc3SMaciej Żenczykowski cmis_show_dom_chan_lvl_flags(map);
883*1b481fc3SMaciej Żenczykowski if (sd.supports_alarms)
884*1b481fc3SMaciej Żenczykowski sff_show_thresholds(sd);
885*1b481fc3SMaciej Żenczykowski }
886*1b481fc3SMaciej Żenczykowski
cmis_show_all_common(const struct cmis_memory_map * map)887*1b481fc3SMaciej Żenczykowski static void cmis_show_all_common(const struct cmis_memory_map *map)
888*1b481fc3SMaciej Żenczykowski {
889*1b481fc3SMaciej Żenczykowski cmis_show_identifier(map);
890*1b481fc3SMaciej Żenczykowski cmis_show_power_info(map);
891*1b481fc3SMaciej Żenczykowski cmis_show_connector(map);
892*1b481fc3SMaciej Żenczykowski cmis_show_cbl_asm_len(map);
893*1b481fc3SMaciej Żenczykowski cmis_show_sig_integrity(map);
894*1b481fc3SMaciej Żenczykowski cmis_show_mit_compliance(map);
895*1b481fc3SMaciej Żenczykowski cmis_show_link_len(map);
896*1b481fc3SMaciej Żenczykowski cmis_show_vendor_info(map);
897*1b481fc3SMaciej Żenczykowski cmis_show_rev_compliance(map);
898*1b481fc3SMaciej Żenczykowski cmis_show_signals(map);
899*1b481fc3SMaciej Żenczykowski cmis_show_mod_state(map);
900*1b481fc3SMaciej Żenczykowski cmis_show_mod_fault_cause(map);
901*1b481fc3SMaciej Żenczykowski cmis_show_mod_lvl_controls(map);
902*1b481fc3SMaciej Żenczykowski cmis_show_dom(map);
903*1b481fc3SMaciej Żenczykowski }
904*1b481fc3SMaciej Żenczykowski
cmis_memory_map_init_buf(struct cmis_memory_map * map,const __u8 * id)905*1b481fc3SMaciej Żenczykowski static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
906*1b481fc3SMaciej Żenczykowski const __u8 *id)
907*1b481fc3SMaciej Żenczykowski {
908*1b481fc3SMaciej Żenczykowski /* Lower Memory and Page 00h are always present.
909*1b481fc3SMaciej Żenczykowski *
910*1b481fc3SMaciej Żenczykowski * Offset into Upper Memory is between page size and twice the page
911*1b481fc3SMaciej Żenczykowski * size. Therefore, set the base address of each page to base address
912*1b481fc3SMaciej Żenczykowski * plus page size multiplied by the page number.
913*1b481fc3SMaciej Żenczykowski */
914*1b481fc3SMaciej Żenczykowski map->lower_memory = id;
915*1b481fc3SMaciej Żenczykowski map->page_00h = id;
916*1b481fc3SMaciej Żenczykowski
917*1b481fc3SMaciej Żenczykowski /* Page 01h is only present when the module memory model is paged and
918*1b481fc3SMaciej Żenczykowski * not flat.
919*1b481fc3SMaciej Żenczykowski */
920*1b481fc3SMaciej Żenczykowski if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
921*1b481fc3SMaciej Żenczykowski CMIS_MEMORY_MODEL_MASK)
922*1b481fc3SMaciej Żenczykowski return;
923*1b481fc3SMaciej Żenczykowski
924*1b481fc3SMaciej Żenczykowski map->page_01h = id + CMIS_PAGE_SIZE;
925*1b481fc3SMaciej Żenczykowski }
926*1b481fc3SMaciej Żenczykowski
cmis_show_all_ioctl(const __u8 * id)927*1b481fc3SMaciej Żenczykowski void cmis_show_all_ioctl(const __u8 *id)
928*1b481fc3SMaciej Żenczykowski {
929*1b481fc3SMaciej Żenczykowski struct cmis_memory_map map = {};
930*1b481fc3SMaciej Żenczykowski
931*1b481fc3SMaciej Żenczykowski cmis_memory_map_init_buf(&map, id);
932*1b481fc3SMaciej Żenczykowski cmis_show_all_common(&map);
933*1b481fc3SMaciej Żenczykowski }
934*1b481fc3SMaciej Żenczykowski
cmis_request_init(struct ethtool_module_eeprom * request,u8 bank,u8 page,u32 offset)935*1b481fc3SMaciej Żenczykowski static void cmis_request_init(struct ethtool_module_eeprom *request, u8 bank,
936*1b481fc3SMaciej Żenczykowski u8 page, u32 offset)
937*1b481fc3SMaciej Żenczykowski {
938*1b481fc3SMaciej Żenczykowski request->offset = offset;
939*1b481fc3SMaciej Żenczykowski request->length = CMIS_PAGE_SIZE;
940*1b481fc3SMaciej Żenczykowski request->page = page;
941*1b481fc3SMaciej Żenczykowski request->bank = bank;
942*1b481fc3SMaciej Żenczykowski request->i2c_address = CMIS_I2C_ADDRESS;
943*1b481fc3SMaciej Żenczykowski request->data = NULL;
944*1b481fc3SMaciej Żenczykowski }
945*1b481fc3SMaciej Żenczykowski
cmis_num_banks_get(const struct cmis_memory_map * map,int * p_num_banks)946*1b481fc3SMaciej Żenczykowski static int cmis_num_banks_get(const struct cmis_memory_map *map,
947*1b481fc3SMaciej Żenczykowski int *p_num_banks)
948*1b481fc3SMaciej Żenczykowski {
949*1b481fc3SMaciej Żenczykowski switch (map->page_01h[CMIS_PAGES_ADVER_OFFSET] &
950*1b481fc3SMaciej Żenczykowski CMIS_BANKS_SUPPORTED_MASK) {
951*1b481fc3SMaciej Żenczykowski case CMIS_BANK_0_SUPPORTED:
952*1b481fc3SMaciej Żenczykowski *p_num_banks = 1;
953*1b481fc3SMaciej Żenczykowski break;
954*1b481fc3SMaciej Żenczykowski case CMIS_BANK_0_1_SUPPORTED:
955*1b481fc3SMaciej Żenczykowski *p_num_banks = 2;
956*1b481fc3SMaciej Żenczykowski break;
957*1b481fc3SMaciej Żenczykowski case CMIS_BANK_0_3_SUPPORTED:
958*1b481fc3SMaciej Żenczykowski *p_num_banks = 4;
959*1b481fc3SMaciej Żenczykowski break;
960*1b481fc3SMaciej Żenczykowski default:
961*1b481fc3SMaciej Żenczykowski return -EINVAL;
962*1b481fc3SMaciej Żenczykowski }
963*1b481fc3SMaciej Żenczykowski
964*1b481fc3SMaciej Żenczykowski return 0;
965*1b481fc3SMaciej Żenczykowski }
966*1b481fc3SMaciej Żenczykowski
967*1b481fc3SMaciej Żenczykowski static int
cmis_memory_map_init_pages(struct cmd_context * ctx,struct cmis_memory_map * map)968*1b481fc3SMaciej Żenczykowski cmis_memory_map_init_pages(struct cmd_context *ctx,
969*1b481fc3SMaciej Żenczykowski struct cmis_memory_map *map)
970*1b481fc3SMaciej Żenczykowski {
971*1b481fc3SMaciej Żenczykowski struct ethtool_module_eeprom request;
972*1b481fc3SMaciej Żenczykowski int num_banks, i, ret;
973*1b481fc3SMaciej Żenczykowski
974*1b481fc3SMaciej Żenczykowski /* Lower Memory and Page 00h are always present.
975*1b481fc3SMaciej Żenczykowski *
976*1b481fc3SMaciej Żenczykowski * Offset into Upper Memory is between page size and twice the page
977*1b481fc3SMaciej Żenczykowski * size. Therefore, set the base address of each page to its base
978*1b481fc3SMaciej Żenczykowski * address minus page size.
979*1b481fc3SMaciej Żenczykowski */
980*1b481fc3SMaciej Żenczykowski cmis_request_init(&request, 0, 0x0, 0);
981*1b481fc3SMaciej Żenczykowski ret = nl_get_eeprom_page(ctx, &request);
982*1b481fc3SMaciej Żenczykowski if (ret < 0)
983*1b481fc3SMaciej Żenczykowski return ret;
984*1b481fc3SMaciej Żenczykowski map->lower_memory = request.data;
985*1b481fc3SMaciej Żenczykowski
986*1b481fc3SMaciej Żenczykowski cmis_request_init(&request, 0, 0x0, CMIS_PAGE_SIZE);
987*1b481fc3SMaciej Żenczykowski ret = nl_get_eeprom_page(ctx, &request);
988*1b481fc3SMaciej Żenczykowski if (ret < 0)
989*1b481fc3SMaciej Żenczykowski return ret;
990*1b481fc3SMaciej Żenczykowski map->page_00h = request.data - CMIS_PAGE_SIZE;
991*1b481fc3SMaciej Żenczykowski
992*1b481fc3SMaciej Żenczykowski /* Pages 01h and 02h are only present when the module memory model is
993*1b481fc3SMaciej Żenczykowski * paged and not flat.
994*1b481fc3SMaciej Żenczykowski */
995*1b481fc3SMaciej Żenczykowski if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
996*1b481fc3SMaciej Żenczykowski CMIS_MEMORY_MODEL_MASK)
997*1b481fc3SMaciej Żenczykowski return 0;
998*1b481fc3SMaciej Żenczykowski
999*1b481fc3SMaciej Żenczykowski cmis_request_init(&request, 0, 0x1, CMIS_PAGE_SIZE);
1000*1b481fc3SMaciej Żenczykowski ret = nl_get_eeprom_page(ctx, &request);
1001*1b481fc3SMaciej Żenczykowski if (ret < 0)
1002*1b481fc3SMaciej Żenczykowski return ret;
1003*1b481fc3SMaciej Żenczykowski map->page_01h = request.data - CMIS_PAGE_SIZE;
1004*1b481fc3SMaciej Żenczykowski
1005*1b481fc3SMaciej Żenczykowski cmis_request_init(&request, 0, 0x2, CMIS_PAGE_SIZE);
1006*1b481fc3SMaciej Żenczykowski ret = nl_get_eeprom_page(ctx, &request);
1007*1b481fc3SMaciej Żenczykowski if (ret < 0)
1008*1b481fc3SMaciej Żenczykowski return ret;
1009*1b481fc3SMaciej Żenczykowski map->page_02h = request.data - CMIS_PAGE_SIZE;
1010*1b481fc3SMaciej Żenczykowski
1011*1b481fc3SMaciej Żenczykowski /* Bank 0 of Page 11h provides lane-specific registers for the first 8
1012*1b481fc3SMaciej Żenczykowski * lanes, and each additional Banks provides support for an additional
1013*1b481fc3SMaciej Żenczykowski * 8 lanes. Only initialize supported Banks.
1014*1b481fc3SMaciej Żenczykowski */
1015*1b481fc3SMaciej Żenczykowski ret = cmis_num_banks_get(map, &num_banks);
1016*1b481fc3SMaciej Żenczykowski if (ret < 0)
1017*1b481fc3SMaciej Żenczykowski return ret;
1018*1b481fc3SMaciej Żenczykowski
1019*1b481fc3SMaciej Żenczykowski for (i = 0; i < num_banks; i++) {
1020*1b481fc3SMaciej Żenczykowski cmis_request_init(&request, i, 0x11, CMIS_PAGE_SIZE);
1021*1b481fc3SMaciej Żenczykowski ret = nl_get_eeprom_page(ctx, &request);
1022*1b481fc3SMaciej Żenczykowski if (ret < 0)
1023*1b481fc3SMaciej Żenczykowski return ret;
1024*1b481fc3SMaciej Żenczykowski map->upper_memory[i][0x11] = request.data - CMIS_PAGE_SIZE;
1025*1b481fc3SMaciej Żenczykowski }
1026*1b481fc3SMaciej Żenczykowski
1027*1b481fc3SMaciej Żenczykowski return 0;
1028*1b481fc3SMaciej Żenczykowski }
1029*1b481fc3SMaciej Żenczykowski
cmis_show_all_nl(struct cmd_context * ctx)1030*1b481fc3SMaciej Żenczykowski int cmis_show_all_nl(struct cmd_context *ctx)
1031*1b481fc3SMaciej Żenczykowski {
1032*1b481fc3SMaciej Żenczykowski struct cmis_memory_map map = {};
1033*1b481fc3SMaciej Żenczykowski int ret;
1034*1b481fc3SMaciej Żenczykowski
1035*1b481fc3SMaciej Żenczykowski ret = cmis_memory_map_init_pages(ctx, &map);
1036*1b481fc3SMaciej Żenczykowski if (ret < 0)
1037*1b481fc3SMaciej Żenczykowski return ret;
1038*1b481fc3SMaciej Żenczykowski cmis_show_all_common(&map);
1039*1b481fc3SMaciej Żenczykowski
1040*1b481fc3SMaciej Żenczykowski return 0;
1041*1b481fc3SMaciej Żenczykowski }
1042