1*084b4880SRobin Zhang /* SPDX-License-Identifier: BSD-3-Clause
2*084b4880SRobin Zhang * Copyright(c) 2022 Intel Corporation
3*084b4880SRobin Zhang * Implements SFF-8079 optics diagnostics.
4*084b4880SRobin Zhang */
5*084b4880SRobin Zhang
6*084b4880SRobin Zhang #include <stdio.h>
7*084b4880SRobin Zhang
8*084b4880SRobin Zhang #include "sff_common.h"
9*084b4880SRobin Zhang
sff_8079_show_identifier(const uint8_t * data,struct rte_tel_data * d)10*084b4880SRobin Zhang static void sff_8079_show_identifier(const uint8_t *data, struct rte_tel_data *d)
11*084b4880SRobin Zhang {
12*084b4880SRobin Zhang sff_8024_show_identifier(data, 0, d);
13*084b4880SRobin Zhang }
14*084b4880SRobin Zhang
sff_8079_show_ext_identifier(const uint8_t * data,struct rte_tel_data * d)15*084b4880SRobin Zhang static void sff_8079_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d)
16*084b4880SRobin Zhang {
17*084b4880SRobin Zhang char val_string[SFF_ITEM_VAL_COMPOSE_SIZE];
18*084b4880SRobin Zhang
19*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "0x%02x", data[1]);
20*084b4880SRobin Zhang if (data[1] == 0x00)
21*084b4880SRobin Zhang strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)",
22*084b4880SRobin Zhang sizeof(val_string));
23*084b4880SRobin Zhang else if (data[1] == 0x04)
24*084b4880SRobin Zhang strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)",
25*084b4880SRobin Zhang sizeof(val_string));
26*084b4880SRobin Zhang else if (data[1] <= 0x07) {
27*084b4880SRobin Zhang char tmp[SFF_ITEM_VAL_COMPOSE_SIZE];
28*084b4880SRobin Zhang snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]);
29*084b4880SRobin Zhang strlcat(val_string, tmp, sizeof(val_string));
30*084b4880SRobin Zhang } else
31*084b4880SRobin Zhang strlcat(val_string, " (unknown)", sizeof(val_string));
32*084b4880SRobin Zhang ssf_add_dict_string(d, "Extended identifier", val_string);
33*084b4880SRobin Zhang }
34*084b4880SRobin Zhang
sff_8079_show_connector(const uint8_t * data,struct rte_tel_data * d)35*084b4880SRobin Zhang static void sff_8079_show_connector(const uint8_t *data, struct rte_tel_data *d)
36*084b4880SRobin Zhang {
37*084b4880SRobin Zhang sff_8024_show_connector(data, 2, d);
38*084b4880SRobin Zhang }
39*084b4880SRobin Zhang
sff_8079_show_transceiver(const uint8_t * data,struct rte_tel_data * d)40*084b4880SRobin Zhang static void sff_8079_show_transceiver(const uint8_t *data, struct rte_tel_data *d)
41*084b4880SRobin Zhang {
42*084b4880SRobin Zhang static const char *name = "Transceiver type";
43*084b4880SRobin Zhang char val_string[SFF_ITEM_VAL_COMPOSE_SIZE];
44*084b4880SRobin Zhang
45*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string),
46*084b4880SRobin Zhang "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
47*084b4880SRobin Zhang data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]);
48*084b4880SRobin Zhang ssf_add_dict_string(d, "Transceiver codes", val_string);
49*084b4880SRobin Zhang
50*084b4880SRobin Zhang /* 10G Ethernet Compliance Codes */
51*084b4880SRobin Zhang if (data[3] & (1 << 7))
52*084b4880SRobin Zhang ssf_add_dict_string(d, "10G Ethernet transceiver type",
53*084b4880SRobin Zhang "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]");
54*084b4880SRobin Zhang if (data[3] & (1 << 6))
55*084b4880SRobin Zhang ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM");
56*084b4880SRobin Zhang if (data[3] & (1 << 5))
57*084b4880SRobin Zhang ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR");
58*084b4880SRobin Zhang if (data[3] & (1 << 4))
59*084b4880SRobin Zhang ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR");
60*084b4880SRobin Zhang
61*084b4880SRobin Zhang /* Infiniband Compliance Codes */
62*084b4880SRobin Zhang if (data[3] & (1 << 3))
63*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Infiniband: 1X SX");
64*084b4880SRobin Zhang if (data[3] & (1 << 2))
65*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Infiniband: 1X LX");
66*084b4880SRobin Zhang if (data[3] & (1 << 1))
67*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Infiniband: 1X Copper Active");
68*084b4880SRobin Zhang if (data[3] & (1 << 0))
69*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Infiniband: 1X Copper Passive");
70*084b4880SRobin Zhang
71*084b4880SRobin Zhang /* ESCON Compliance Codes */
72*084b4880SRobin Zhang if (data[4] & (1 << 7))
73*084b4880SRobin Zhang ssf_add_dict_string(d, name, "ESCON: ESCON MMF, 1310nm LED");
74*084b4880SRobin Zhang if (data[4] & (1 << 6))
75*084b4880SRobin Zhang ssf_add_dict_string(d, name, "ESCON: ESCON SMF, 1310nm Laser");
76*084b4880SRobin Zhang
77*084b4880SRobin Zhang /* SONET Compliance Codes */
78*084b4880SRobin Zhang if (data[4] & (1 << 5))
79*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-192, short reach");
80*084b4880SRobin Zhang if (data[4] & (1 << 4))
81*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 1");
82*084b4880SRobin Zhang if (data[4] & (1 << 3))
83*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 2");
84*084b4880SRobin Zhang if (data[4] & (1 << 2))
85*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-48, long reach");
86*084b4880SRobin Zhang if (data[4] & (1 << 1))
87*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach");
88*084b4880SRobin Zhang if (data[4] & (1 << 0))
89*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-48, short reach");
90*084b4880SRobin Zhang if (data[5] & (1 << 6))
91*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-12, single mode, long reach");
92*084b4880SRobin Zhang if (data[5] & (1 << 5))
93*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-12, single mode, inter. reach");
94*084b4880SRobin Zhang if (data[5] & (1 << 4))
95*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-12, short reach");
96*084b4880SRobin Zhang if (data[5] & (1 << 2))
97*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-3, single mode, long reach");
98*084b4880SRobin Zhang if (data[5] & (1 << 1))
99*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-3, single mode, inter. reach");
100*084b4880SRobin Zhang if (data[5] & (1 << 0))
101*084b4880SRobin Zhang ssf_add_dict_string(d, name, "SONET: OC-3, short reach");
102*084b4880SRobin Zhang
103*084b4880SRobin Zhang /* Ethernet Compliance Codes */
104*084b4880SRobin Zhang if (data[6] & (1 << 7))
105*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: BASE-PX");
106*084b4880SRobin Zhang if (data[6] & (1 << 6))
107*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: BASE-BX10");
108*084b4880SRobin Zhang if (data[6] & (1 << 5))
109*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: 100BASE-FX");
110*084b4880SRobin Zhang if (data[6] & (1 << 4))
111*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: 100BASE-LX/LX10");
112*084b4880SRobin Zhang if (data[6] & (1 << 3))
113*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T");
114*084b4880SRobin Zhang if (data[6] & (1 << 2))
115*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX");
116*084b4880SRobin Zhang if (data[6] & (1 << 1))
117*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX");
118*084b4880SRobin Zhang if (data[6] & (1 << 0))
119*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX");
120*084b4880SRobin Zhang
121*084b4880SRobin Zhang /* Fibre Channel link length */
122*084b4880SRobin Zhang if (data[7] & (1 << 7))
123*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: very long distance (V)");
124*084b4880SRobin Zhang if (data[7] & (1 << 6))
125*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: short distance (S)");
126*084b4880SRobin Zhang if (data[7] & (1 << 5))
127*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: intermediate distance (I)");
128*084b4880SRobin Zhang if (data[7] & (1 << 4))
129*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: long distance (L)");
130*084b4880SRobin Zhang if (data[7] & (1 << 3))
131*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: medium distance (M)");
132*084b4880SRobin Zhang
133*084b4880SRobin Zhang /* Fibre Channel transmitter technology */
134*084b4880SRobin Zhang if (data[7] & (1 << 2))
135*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Shortwave laser, linear Rx (SA)");
136*084b4880SRobin Zhang if (data[7] & (1 << 1))
137*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Longwave laser (LC)");
138*084b4880SRobin Zhang if (data[7] & (1 << 0))
139*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)");
140*084b4880SRobin Zhang if (data[8] & (1 << 7))
141*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)");
142*084b4880SRobin Zhang if (data[8] & (1 << 6))
143*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)");
144*084b4880SRobin Zhang if (data[8] & (1 << 5))
145*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)");
146*084b4880SRobin Zhang if (data[8] & (1 << 4))
147*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Longwave laser (LL)");
148*084b4880SRobin Zhang if (data[8] & (1 << 3))
149*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Active Cable");
150*084b4880SRobin Zhang if (data[8] & (1 << 2))
151*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Passive Cable");
152*084b4880SRobin Zhang if (data[8] & (1 << 1))
153*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Copper FC-BaseT");
154*084b4880SRobin Zhang
155*084b4880SRobin Zhang /* Fibre Channel transmission media */
156*084b4880SRobin Zhang if (data[9] & (1 << 7))
157*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)");
158*084b4880SRobin Zhang if (data[9] & (1 << 6))
159*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)");
160*084b4880SRobin Zhang if (data[9] & (1 << 5))
161*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)");
162*084b4880SRobin Zhang if (data[9] & (1 << 4))
163*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Video Coax (TV)");
164*084b4880SRobin Zhang if (data[9] & (1 << 3))
165*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Multimode, 62.5um (M6)");
166*084b4880SRobin Zhang if (data[9] & (1 << 2))
167*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Multimode, 50um (M5)");
168*084b4880SRobin Zhang if (data[9] & (1 << 0))
169*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: Single Mode (SM)");
170*084b4880SRobin Zhang
171*084b4880SRobin Zhang /* Fibre Channel speed */
172*084b4880SRobin Zhang if (data[10] & (1 << 7))
173*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec");
174*084b4880SRobin Zhang if (data[10] & (1 << 6))
175*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: 800 MBytes/sec");
176*084b4880SRobin Zhang if (data[10] & (1 << 4))
177*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: 400 MBytes/sec");
178*084b4880SRobin Zhang if (data[10] & (1 << 2))
179*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: 200 MBytes/sec");
180*084b4880SRobin Zhang if (data[10] & (1 << 0))
181*084b4880SRobin Zhang ssf_add_dict_string(d, name, "FC: 100 MBytes/sec");
182*084b4880SRobin Zhang
183*084b4880SRobin Zhang /* Extended Specification Compliance Codes from SFF-8024 */
184*084b4880SRobin Zhang switch (data[36]) {
185*084b4880SRobin Zhang case 0x1:
186*084b4880SRobin Zhang ssf_add_dict_string(d, name,
187*084b4880SRobin Zhang "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)");
188*084b4880SRobin Zhang break;
189*084b4880SRobin Zhang case 0x2:
190*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 100G Base-SR4 or 25GBase-SR");
191*084b4880SRobin Zhang break;
192*084b4880SRobin Zhang case 0x3:
193*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 100G Base-LR4 or 25GBase-LR");
194*084b4880SRobin Zhang break;
195*084b4880SRobin Zhang case 0x4:
196*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 100G Base-ER4 or 25GBase-ER");
197*084b4880SRobin Zhang break;
198*084b4880SRobin Zhang case 0x8:
199*084b4880SRobin Zhang ssf_add_dict_string(d, name,
200*084b4880SRobin Zhang "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)");
201*084b4880SRobin Zhang break;
202*084b4880SRobin Zhang case 0xb:
203*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L");
204*084b4880SRobin Zhang break;
205*084b4880SRobin Zhang case 0xc:
206*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-S");
207*084b4880SRobin Zhang break;
208*084b4880SRobin Zhang case 0xd:
209*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-N");
210*084b4880SRobin Zhang break;
211*084b4880SRobin Zhang case 0x16:
212*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 10Gbase-T with SFI electrical interface");
213*084b4880SRobin Zhang break;
214*084b4880SRobin Zhang case 0x18:
215*084b4880SRobin Zhang ssf_add_dict_string(d, name,
216*084b4880SRobin Zhang "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)");
217*084b4880SRobin Zhang break;
218*084b4880SRobin Zhang case 0x19:
219*084b4880SRobin Zhang ssf_add_dict_string(d, name,
220*084b4880SRobin Zhang "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)");
221*084b4880SRobin Zhang break;
222*084b4880SRobin Zhang case 0x1c:
223*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Extended: 10Gbase-T Short Reach");
224*084b4880SRobin Zhang break;
225*084b4880SRobin Zhang default:
226*084b4880SRobin Zhang break;
227*084b4880SRobin Zhang }
228*084b4880SRobin Zhang }
229*084b4880SRobin Zhang
sff_8079_show_encoding(const uint8_t * data,struct rte_tel_data * d)230*084b4880SRobin Zhang static void sff_8079_show_encoding(const uint8_t *data, struct rte_tel_data *d)
231*084b4880SRobin Zhang {
232*084b4880SRobin Zhang sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, d);
233*084b4880SRobin Zhang }
234*084b4880SRobin Zhang
sff_8079_show_rate_identifier(const uint8_t * data,struct rte_tel_data * d)235*084b4880SRobin Zhang static void sff_8079_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d)
236*084b4880SRobin Zhang {
237*084b4880SRobin Zhang char val_string[SFF_ITEM_VAL_COMPOSE_SIZE];
238*084b4880SRobin Zhang
239*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "0x%02x", data[13]);
240*084b4880SRobin Zhang
241*084b4880SRobin Zhang switch (data[13]) {
242*084b4880SRobin Zhang case 0x00:
243*084b4880SRobin Zhang strlcat(val_string, " (unspecified)", sizeof(val_string));
244*084b4880SRobin Zhang break;
245*084b4880SRobin Zhang case 0x01:
246*084b4880SRobin Zhang strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string));
247*084b4880SRobin Zhang break;
248*084b4880SRobin Zhang case 0x02:
249*084b4880SRobin Zhang strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string));
250*084b4880SRobin Zhang break;
251*084b4880SRobin Zhang case 0x03:
252*084b4880SRobin Zhang strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)",
253*084b4880SRobin Zhang sizeof(val_string));
254*084b4880SRobin Zhang break;
255*084b4880SRobin Zhang case 0x04:
256*084b4880SRobin Zhang strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string));
257*084b4880SRobin Zhang break;
258*084b4880SRobin Zhang default:
259*084b4880SRobin Zhang strlcat(val_string, " (reserved or unknown)", sizeof(val_string));
260*084b4880SRobin Zhang break;
261*084b4880SRobin Zhang }
262*084b4880SRobin Zhang ssf_add_dict_string(d, "Rate identifier", val_string);
263*084b4880SRobin Zhang }
264*084b4880SRobin Zhang
sff_8079_show_oui(const uint8_t * data,struct rte_tel_data * d)265*084b4880SRobin Zhang static void sff_8079_show_oui(const uint8_t *data, struct rte_tel_data *d)
266*084b4880SRobin Zhang {
267*084b4880SRobin Zhang sff_8024_show_oui(data, 37, d);
268*084b4880SRobin Zhang }
269*084b4880SRobin Zhang
270*084b4880SRobin Zhang static void
sff_8079_show_wavelength_or_copper_compliance(const uint8_t * data,struct rte_tel_data * d)271*084b4880SRobin Zhang sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data,
272*084b4880SRobin Zhang struct rte_tel_data *d)
273*084b4880SRobin Zhang {
274*084b4880SRobin Zhang char val_string[SFF_ITEM_VAL_COMPOSE_SIZE];
275*084b4880SRobin Zhang
276*084b4880SRobin Zhang if (data[8] & (1 << 2)) {
277*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "0x%02x", data[60]);
278*084b4880SRobin Zhang switch (data[60]) {
279*084b4880SRobin Zhang case 0x00:
280*084b4880SRobin Zhang strlcat(val_string, " (unspecified)", sizeof(val_string));
281*084b4880SRobin Zhang break;
282*084b4880SRobin Zhang case 0x01:
283*084b4880SRobin Zhang strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string));
284*084b4880SRobin Zhang break;
285*084b4880SRobin Zhang default:
286*084b4880SRobin Zhang strlcat(val_string, " (unknown)", sizeof(val_string));
287*084b4880SRobin Zhang break;
288*084b4880SRobin Zhang }
289*084b4880SRobin Zhang strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string));
290*084b4880SRobin Zhang ssf_add_dict_string(d, "Passive Cu cmplnce.", val_string);
291*084b4880SRobin Zhang } else if (data[8] & (1 << 3)) {
292*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "0x%02x", data[60]);
293*084b4880SRobin Zhang switch (data[60]) {
294*084b4880SRobin Zhang case 0x00:
295*084b4880SRobin Zhang strlcat(val_string, " (unspecified)", sizeof(val_string));
296*084b4880SRobin Zhang break;
297*084b4880SRobin Zhang case 0x01:
298*084b4880SRobin Zhang strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string));
299*084b4880SRobin Zhang break;
300*084b4880SRobin Zhang case 0x04:
301*084b4880SRobin Zhang strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string));
302*084b4880SRobin Zhang break;
303*084b4880SRobin Zhang default:
304*084b4880SRobin Zhang strlcat(val_string, " (unknown)", sizeof(val_string));
305*084b4880SRobin Zhang break;
306*084b4880SRobin Zhang }
307*084b4880SRobin Zhang strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string));
308*084b4880SRobin Zhang ssf_add_dict_string(d, "Active Cu cmplnce.", val_string);
309*084b4880SRobin Zhang } else {
310*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]);
311*084b4880SRobin Zhang ssf_add_dict_string(d, "Laser wavelength", val_string);
312*084b4880SRobin Zhang }
313*084b4880SRobin Zhang }
314*084b4880SRobin Zhang
sff_8079_show_options(const uint8_t * data,struct rte_tel_data * d)315*084b4880SRobin Zhang static void sff_8079_show_options(const uint8_t *data, struct rte_tel_data *d)
316*084b4880SRobin Zhang {
317*084b4880SRobin Zhang static const char *name = "Option";
318*084b4880SRobin Zhang char val_string[SFF_ITEM_VAL_COMPOSE_SIZE];
319*084b4880SRobin Zhang
320*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]);
321*084b4880SRobin Zhang ssf_add_dict_string(d, "Option values", val_string);
322*084b4880SRobin Zhang
323*084b4880SRobin Zhang if (data[65] & (1 << 1))
324*084b4880SRobin Zhang ssf_add_dict_string(d, name, "RX_LOS implemented");
325*084b4880SRobin Zhang if (data[65] & (1 << 2))
326*084b4880SRobin Zhang ssf_add_dict_string(d, name, "RX_LOS implemented, inverted");
327*084b4880SRobin Zhang if (data[65] & (1 << 3))
328*084b4880SRobin Zhang ssf_add_dict_string(d, name, "TX_FAULT implemented");
329*084b4880SRobin Zhang if (data[65] & (1 << 4))
330*084b4880SRobin Zhang ssf_add_dict_string(d, name, "TX_DISABLE implemented");
331*084b4880SRobin Zhang if (data[65] & (1 << 5))
332*084b4880SRobin Zhang ssf_add_dict_string(d, name, "RATE_SELECT implemented");
333*084b4880SRobin Zhang if (data[65] & (1 << 6))
334*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Tunable transmitter technology");
335*084b4880SRobin Zhang if (data[65] & (1 << 7))
336*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Receiver decision threshold implemented");
337*084b4880SRobin Zhang if (data[64] & (1 << 0))
338*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Linear receiver output implemented");
339*084b4880SRobin Zhang if (data[64] & (1 << 1))
340*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Power level 2 requirement");
341*084b4880SRobin Zhang if (data[64] & (1 << 2))
342*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Cooled transceiver implemented");
343*084b4880SRobin Zhang if (data[64] & (1 << 3))
344*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Retimer or CDR implemented");
345*084b4880SRobin Zhang if (data[64] & (1 << 4))
346*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Paging implemented");
347*084b4880SRobin Zhang if (data[64] & (1 << 5))
348*084b4880SRobin Zhang ssf_add_dict_string(d, name, "Power level 3 requirement");
349*084b4880SRobin Zhang }
350*084b4880SRobin Zhang
sff_8079_show_all(const uint8_t * data,struct rte_tel_data * d)351*084b4880SRobin Zhang void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d)
352*084b4880SRobin Zhang {
353*084b4880SRobin Zhang sff_8079_show_identifier(data, d);
354*084b4880SRobin Zhang if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) {
355*084b4880SRobin Zhang unsigned int br_nom, br_min, br_max;
356*084b4880SRobin Zhang char val_string[SFF_ITEM_VAL_COMPOSE_SIZE];
357*084b4880SRobin Zhang
358*084b4880SRobin Zhang if (data[12] == 0) {
359*084b4880SRobin Zhang br_nom = br_min = br_max = 0;
360*084b4880SRobin Zhang } else if (data[12] == 255) {
361*084b4880SRobin Zhang br_nom = data[66] * 250;
362*084b4880SRobin Zhang br_max = data[67];
363*084b4880SRobin Zhang br_min = data[67];
364*084b4880SRobin Zhang } else {
365*084b4880SRobin Zhang br_nom = data[12] * 100;
366*084b4880SRobin Zhang br_max = data[66];
367*084b4880SRobin Zhang br_min = data[67];
368*084b4880SRobin Zhang }
369*084b4880SRobin Zhang sff_8079_show_ext_identifier(data, d);
370*084b4880SRobin Zhang sff_8079_show_connector(data, d);
371*084b4880SRobin Zhang sff_8079_show_transceiver(data, d);
372*084b4880SRobin Zhang sff_8079_show_encoding(data, d);
373*084b4880SRobin Zhang
374*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "%uMBd", br_nom);
375*084b4880SRobin Zhang ssf_add_dict_string(d, "BR, Nominal", val_string);
376*084b4880SRobin Zhang
377*084b4880SRobin Zhang sff_8079_show_rate_identifier(data, d);
378*084b4880SRobin Zhang sff_show_value_with_unit(data, 14,
379*084b4880SRobin Zhang "Length (SMF,km)", 1, "km", d);
380*084b4880SRobin Zhang sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", d);
381*084b4880SRobin Zhang sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", d);
382*084b4880SRobin Zhang sff_show_value_with_unit(data, 17,
383*084b4880SRobin Zhang "Length (62.5um)", 10, "m", d);
384*084b4880SRobin Zhang sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", d);
385*084b4880SRobin Zhang sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", d);
386*084b4880SRobin Zhang sff_8079_show_wavelength_or_copper_compliance(data, d);
387*084b4880SRobin Zhang sff_show_ascii(data, 20, 35, "Vendor name", d);
388*084b4880SRobin Zhang sff_8079_show_oui(data, d);
389*084b4880SRobin Zhang sff_show_ascii(data, 40, 55, "Vendor PN", d);
390*084b4880SRobin Zhang sff_show_ascii(data, 56, 59, "Vendor rev", d);
391*084b4880SRobin Zhang sff_8079_show_options(data, d);
392*084b4880SRobin Zhang
393*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "%u%%", br_max);
394*084b4880SRobin Zhang ssf_add_dict_string(d, "BR margin, max", val_string);
395*084b4880SRobin Zhang snprintf(val_string, sizeof(val_string), "%u%%", br_min);
396*084b4880SRobin Zhang ssf_add_dict_string(d, "BR margin, min", val_string);
397*084b4880SRobin Zhang
398*084b4880SRobin Zhang sff_show_ascii(data, 68, 83, "Vendor SN", d);
399*084b4880SRobin Zhang sff_show_ascii(data, 84, 91, "Date code", d);
400*084b4880SRobin Zhang }
401*084b4880SRobin Zhang }
402