1 /*
2 * sff-common.c: Implements SFF-8024 Rev 4.0 i.e. Specifcation
3 * of pluggable I/O configuration
4 *
5 * Common utilities across SFF-8436/8636 and SFF-8472/8079
6 * are defined in this file
7 *
8 * Copyright 2010 Solarflare Communications Inc.
9 * Aurelien Guillaume <[email protected]> (C) 2012
10 * Copyright (C) 2014 Cumulus networks Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Freeoftware Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * Vidya Sagar Ravipati <[email protected]>
18 * This implementation is loosely based on current SFP parser
19 * and SFF-8024 Rev 4.0 spec (ftp://ftp.seagate.com/pub/sff/SFF-8024.PDF)
20 * by SFF Committee.
21 */
22
23 #include <stdio.h>
24 #include <math.h>
25 #include "sff-common.h"
26
convert_mw_to_dbm(double mw)27 double convert_mw_to_dbm(double mw)
28 {
29 return (10. * log10(mw / 1000.)) + 30.;
30 }
31
sff_show_value_with_unit(const __u8 * id,unsigned int reg,const char * name,unsigned int mult,const char * unit)32 void sff_show_value_with_unit(const __u8 *id, unsigned int reg,
33 const char *name, unsigned int mult,
34 const char *unit)
35 {
36 unsigned int val = id[reg];
37
38 printf("\t%-41s : %u%s\n", name, val * mult, unit);
39 }
40
sff_show_ascii(const __u8 * id,unsigned int first_reg,unsigned int last_reg,const char * name)41 void sff_show_ascii(const __u8 *id, unsigned int first_reg,
42 unsigned int last_reg, const char *name)
43 {
44 unsigned int reg, val;
45
46 printf("\t%-41s : ", name);
47 while (first_reg <= last_reg && id[last_reg] == ' ')
48 last_reg--;
49 for (reg = first_reg; reg <= last_reg; reg++) {
50 val = id[reg];
51 putchar(((val >= 32) && (val <= 126)) ? val : '_');
52 }
53 printf("\n");
54 }
55
sff_show_lane_status(const char * name,unsigned int lane_cnt,const char * yes,const char * no,unsigned int value)56 void sff_show_lane_status(const char *name, unsigned int lane_cnt,
57 const char *yes, const char *no, unsigned int value)
58 {
59 printf("\t%-41s : ", name);
60 if (!value) {
61 printf("None\n");
62 return;
63 }
64
65 printf("[");
66 while (lane_cnt--) {
67 printf(" %s%c", value & 1 ? yes : no, lane_cnt ? ',': ' ');
68 value >>= 1;
69 }
70 printf("]\n");
71 }
72
sff8024_show_oui(const __u8 * id,int id_offset)73 void sff8024_show_oui(const __u8 *id, int id_offset)
74 {
75 printf("\t%-41s : %02x:%02x:%02x\n", "Vendor OUI",
76 id[id_offset], id[(id_offset) + 1],
77 id[(id_offset) + 2]);
78 }
79
sff8024_show_identifier(const __u8 * id,int id_offset)80 void sff8024_show_identifier(const __u8 *id, int id_offset)
81 {
82 printf("\t%-41s : 0x%02x", "Identifier", id[id_offset]);
83 switch (id[id_offset]) {
84 case SFF8024_ID_UNKNOWN:
85 printf(" (no module present, unknown, or unspecified)\n");
86 break;
87 case SFF8024_ID_GBIC:
88 printf(" (GBIC)\n");
89 break;
90 case SFF8024_ID_SOLDERED_MODULE:
91 printf(" (module soldered to motherboard)\n");
92 break;
93 case SFF8024_ID_SFP:
94 printf(" (SFP)\n");
95 break;
96 case SFF8024_ID_300_PIN_XBI:
97 printf(" (300 pin XBI)\n");
98 break;
99 case SFF8024_ID_XENPAK:
100 printf(" (XENPAK)\n");
101 break;
102 case SFF8024_ID_XFP:
103 printf(" (XFP)\n");
104 break;
105 case SFF8024_ID_XFF:
106 printf(" (XFF)\n");
107 break;
108 case SFF8024_ID_XFP_E:
109 printf(" (XFP-E)\n");
110 break;
111 case SFF8024_ID_XPAK:
112 printf(" (XPAK)\n");
113 break;
114 case SFF8024_ID_X2:
115 printf(" (X2)\n");
116 break;
117 case SFF8024_ID_DWDM_SFP:
118 printf(" (DWDM-SFP)\n");
119 break;
120 case SFF8024_ID_QSFP:
121 printf(" (QSFP)\n");
122 break;
123 case SFF8024_ID_QSFP_PLUS:
124 printf(" (QSFP+)\n");
125 break;
126 case SFF8024_ID_CXP:
127 printf(" (CXP)\n");
128 break;
129 case SFF8024_ID_HD4X:
130 printf(" (Shielded Mini Multilane HD 4X)\n");
131 break;
132 case SFF8024_ID_HD8X:
133 printf(" (Shielded Mini Multilane HD 8X)\n");
134 break;
135 case SFF8024_ID_QSFP28:
136 printf(" (QSFP28)\n");
137 break;
138 case SFF8024_ID_CXP2:
139 printf(" (CXP2/CXP28)\n");
140 break;
141 case SFF8024_ID_CDFP:
142 printf(" (CDFP Style 1/Style 2)\n");
143 break;
144 case SFF8024_ID_HD4X_FANOUT:
145 printf(" (Shielded Mini Multilane HD 4X Fanout Cable)\n");
146 break;
147 case SFF8024_ID_HD8X_FANOUT:
148 printf(" (Shielded Mini Multilane HD 8X Fanout Cable)\n");
149 break;
150 case SFF8024_ID_CDFP_S3:
151 printf(" (CDFP Style 3)\n");
152 break;
153 case SFF8024_ID_MICRO_QSFP:
154 printf(" (microQSFP)\n");
155 break;
156 case SFF8024_ID_QSFP_DD:
157 printf(" (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))\n");
158 break;
159 case SFF8024_ID_OSFP:
160 printf(" (OSFP 8X Pluggable Transceiver)\n");
161 break;
162 case SFF8024_ID_DSFP:
163 printf(" (DSFP Dual Small Form Factor Pluggable Transceiver)\n");
164 break;
165 default:
166 printf(" (reserved or unknown)\n");
167 break;
168 }
169 }
170
sff8024_show_connector(const __u8 * id,int ctor_offset)171 void sff8024_show_connector(const __u8 *id, int ctor_offset)
172 {
173 printf("\t%-41s : 0x%02x", "Connector", id[ctor_offset]);
174 switch (id[ctor_offset]) {
175 case SFF8024_CTOR_UNKNOWN:
176 printf(" (unknown or unspecified)\n");
177 break;
178 case SFF8024_CTOR_SC:
179 printf(" (SC)\n");
180 break;
181 case SFF8024_CTOR_FC_STYLE_1:
182 printf(" (Fibre Channel Style 1 copper)\n");
183 break;
184 case SFF8024_CTOR_FC_STYLE_2:
185 printf(" (Fibre Channel Style 2 copper)\n");
186 break;
187 case SFF8024_CTOR_BNC_TNC:
188 printf(" (BNC/TNC)\n");
189 break;
190 case SFF8024_CTOR_FC_COAX:
191 printf(" (Fibre Channel coaxial headers)\n");
192 break;
193 case SFF8024_CTOR_FIBER_JACK:
194 printf(" (FibreJack)\n");
195 break;
196 case SFF8024_CTOR_LC:
197 printf(" (LC)\n");
198 break;
199 case SFF8024_CTOR_MT_RJ:
200 printf(" (MT-RJ)\n");
201 break;
202 case SFF8024_CTOR_MU:
203 printf(" (MU)\n");
204 break;
205 case SFF8024_CTOR_SG:
206 printf(" (SG)\n");
207 break;
208 case SFF8024_CTOR_OPT_PT:
209 printf(" (Optical pigtail)\n");
210 break;
211 case SFF8024_CTOR_MPO:
212 printf(" (MPO Parallel Optic)\n");
213 break;
214 case SFF8024_CTOR_MPO_2:
215 printf(" (MPO Parallel Optic - 2x16)\n");
216 break;
217 case SFF8024_CTOR_HSDC_II:
218 printf(" (HSSDC II)\n");
219 break;
220 case SFF8024_CTOR_COPPER_PT:
221 printf(" (Copper pigtail)\n");
222 break;
223 case SFF8024_CTOR_RJ45:
224 printf(" (RJ45)\n");
225 break;
226 case SFF8024_CTOR_NO_SEPARABLE:
227 printf(" (No separable connector)\n");
228 break;
229 case SFF8024_CTOR_MXC_2x16:
230 printf(" (MXC 2x16)\n");
231 break;
232 case SFF8024_CTOR_CS_OPTICAL:
233 printf(" (CS optical connector)\n");
234 break;
235 case SFF8024_CTOR_CS_OPTICAL_MINI:
236 printf(" (Mini CS optical connector)\n");
237 break;
238 case SFF8024_CTOR_MPO_2X12:
239 printf(" (MPO 2x12)\n");
240 break;
241 case SFF8024_CTOR_MPO_1X16:
242 printf(" (MPO 1x16)\n");
243 break;
244 default:
245 printf(" (reserved or unknown)\n");
246 break;
247 }
248 }
249
sff8024_show_encoding(const __u8 * id,int encoding_offset,int sff_type)250 void sff8024_show_encoding(const __u8 *id, int encoding_offset, int sff_type)
251 {
252 printf("\t%-41s : 0x%02x", "Encoding", id[encoding_offset]);
253 switch (id[encoding_offset]) {
254 case SFF8024_ENCODING_UNSPEC:
255 printf(" (unspecified)\n");
256 break;
257 case SFF8024_ENCODING_8B10B:
258 printf(" (8B/10B)\n");
259 break;
260 case SFF8024_ENCODING_4B5B:
261 printf(" (4B/5B)\n");
262 break;
263 case SFF8024_ENCODING_NRZ:
264 printf(" (NRZ)\n");
265 break;
266 case SFF8024_ENCODING_4h:
267 if (sff_type == ETH_MODULE_SFF_8472)
268 printf(" (Manchester)\n");
269 else if (sff_type == ETH_MODULE_SFF_8636)
270 printf(" (SONET Scrambled)\n");
271 break;
272 case SFF8024_ENCODING_5h:
273 if (sff_type == ETH_MODULE_SFF_8472)
274 printf(" (SONET Scrambled)\n");
275 else if (sff_type == ETH_MODULE_SFF_8636)
276 printf(" (64B/66B)\n");
277 break;
278 case SFF8024_ENCODING_6h:
279 if (sff_type == ETH_MODULE_SFF_8472)
280 printf(" (64B/66B)\n");
281 else if (sff_type == ETH_MODULE_SFF_8636)
282 printf(" (Manchester)\n");
283 break;
284 case SFF8024_ENCODING_256B:
285 printf(" ((256B/257B (transcoded FEC-enabled data))\n");
286 break;
287 case SFF8024_ENCODING_PAM4:
288 printf(" (PAM4)\n");
289 break;
290 default:
291 printf(" (reserved or unknown)\n");
292 break;
293 }
294 }
295
sff_show_thresholds(struct sff_diags sd)296 void sff_show_thresholds(struct sff_diags sd)
297 {
298 PRINT_BIAS("Laser bias current high alarm threshold",
299 sd.bias_cur[HALRM]);
300 PRINT_BIAS("Laser bias current low alarm threshold",
301 sd.bias_cur[LALRM]);
302 PRINT_BIAS("Laser bias current high warning threshold",
303 sd.bias_cur[HWARN]);
304 PRINT_BIAS("Laser bias current low warning threshold",
305 sd.bias_cur[LWARN]);
306
307 PRINT_xX_PWR("Laser output power high alarm threshold",
308 sd.tx_power[HALRM]);
309 PRINT_xX_PWR("Laser output power low alarm threshold",
310 sd.tx_power[LALRM]);
311 PRINT_xX_PWR("Laser output power high warning threshold",
312 sd.tx_power[HWARN]);
313 PRINT_xX_PWR("Laser output power low warning threshold",
314 sd.tx_power[LWARN]);
315
316 PRINT_TEMP("Module temperature high alarm threshold",
317 sd.sfp_temp[HALRM]);
318 PRINT_TEMP("Module temperature low alarm threshold",
319 sd.sfp_temp[LALRM]);
320 PRINT_TEMP("Module temperature high warning threshold",
321 sd.sfp_temp[HWARN]);
322 PRINT_TEMP("Module temperature low warning threshold",
323 sd.sfp_temp[LWARN]);
324
325 PRINT_VCC("Module voltage high alarm threshold",
326 sd.sfp_voltage[HALRM]);
327 PRINT_VCC("Module voltage low alarm threshold",
328 sd.sfp_voltage[LALRM]);
329 PRINT_VCC("Module voltage high warning threshold",
330 sd.sfp_voltage[HWARN]);
331 PRINT_VCC("Module voltage low warning threshold",
332 sd.sfp_voltage[LWARN]);
333
334 PRINT_xX_PWR("Laser rx power high alarm threshold",
335 sd.rx_power[HALRM]);
336 PRINT_xX_PWR("Laser rx power low alarm threshold",
337 sd.rx_power[LALRM]);
338 PRINT_xX_PWR("Laser rx power high warning threshold",
339 sd.rx_power[HWARN]);
340 PRINT_xX_PWR("Laser rx power low warning threshold",
341 sd.rx_power[LWARN]);
342 }
343
sff_show_revision_compliance(const __u8 * id,int rev_offset)344 void sff_show_revision_compliance(const __u8 *id, int rev_offset)
345 {
346 static const char *pfx =
347 "\tRevision Compliance :";
348
349 switch (id[rev_offset]) {
350 case SFF8636_REV_UNSPECIFIED:
351 printf("%s Revision not specified\n", pfx);
352 break;
353 case SFF8636_REV_8436_48:
354 printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
355 break;
356 case SFF8636_REV_8436_8636:
357 printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
358 break;
359 case SFF8636_REV_8636_13:
360 printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx);
361 break;
362 case SFF8636_REV_8636_14:
363 printf("%s SFF-8636 Rev 1.4\n", pfx);
364 break;
365 case SFF8636_REV_8636_15:
366 printf("%s SFF-8636 Rev 1.5\n", pfx);
367 break;
368 case SFF8636_REV_8636_20:
369 printf("%s SFF-8636 Rev 2.0\n", pfx);
370 break;
371 case SFF8636_REV_8636_27:
372 printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx);
373 break;
374 default:
375 printf("%s Unallocated\n", pfx);
376 break;
377 }
378 }
379