• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <aurelien@iwi.me> (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 <vidya@cumulusnetworks.com>
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 	case SFF8024_ID_QSFP_PLUS_CMIS:
166 		printf(" (QSFP+ or later with Common Management Interface Specification (CMIS))\n");
167 		break;
168 	case SFF8024_ID_SFP_DD_CMIS:
169 		printf(" (SFP-DD Double Density 2X Pluggable Transceiver with Common Management Interface Specification (CMIS))\n");
170 		break;
171 	case SFF8024_ID_SFP_PLUS_CMIS:
172 		printf(" (SFP+ and later with Common Management Interface Specification (CMIS))\n");
173 		break;
174 	default:
175 		printf(" (reserved or unknown)\n");
176 		break;
177 	}
178 }
179 
sff8024_show_connector(const __u8 * id,int ctor_offset)180 void sff8024_show_connector(const __u8 *id, int ctor_offset)
181 {
182 	printf("\t%-41s : 0x%02x", "Connector", id[ctor_offset]);
183 	switch (id[ctor_offset]) {
184 	case  SFF8024_CTOR_UNKNOWN:
185 		printf(" (unknown or unspecified)\n");
186 		break;
187 	case SFF8024_CTOR_SC:
188 		printf(" (SC)\n");
189 		break;
190 	case SFF8024_CTOR_FC_STYLE_1:
191 		printf(" (Fibre Channel Style 1 copper)\n");
192 		break;
193 	case SFF8024_CTOR_FC_STYLE_2:
194 		printf(" (Fibre Channel Style 2 copper)\n");
195 		break;
196 	case SFF8024_CTOR_BNC_TNC:
197 		printf(" (BNC/TNC)\n");
198 		break;
199 	case SFF8024_CTOR_FC_COAX:
200 		printf(" (Fibre Channel coaxial headers)\n");
201 		break;
202 	case SFF8024_CTOR_FIBER_JACK:
203 		printf(" (FibreJack)\n");
204 		break;
205 	case SFF8024_CTOR_LC:
206 		printf(" (LC)\n");
207 		break;
208 	case SFF8024_CTOR_MT_RJ:
209 		printf(" (MT-RJ)\n");
210 		break;
211 	case SFF8024_CTOR_MU:
212 		printf(" (MU)\n");
213 		break;
214 	case SFF8024_CTOR_SG:
215 		printf(" (SG)\n");
216 		break;
217 	case SFF8024_CTOR_OPT_PT:
218 		printf(" (Optical pigtail)\n");
219 		break;
220 	case SFF8024_CTOR_MPO:
221 		printf(" (MPO Parallel Optic)\n");
222 		break;
223 	case SFF8024_CTOR_MPO_2:
224 		printf(" (MPO Parallel Optic - 2x16)\n");
225 		break;
226 	case SFF8024_CTOR_HSDC_II:
227 		printf(" (HSSDC II)\n");
228 		break;
229 	case SFF8024_CTOR_COPPER_PT:
230 		printf(" (Copper pigtail)\n");
231 		break;
232 	case SFF8024_CTOR_RJ45:
233 		printf(" (RJ45)\n");
234 		break;
235 	case SFF8024_CTOR_NO_SEPARABLE:
236 		printf(" (No separable connector)\n");
237 		break;
238 	case SFF8024_CTOR_MXC_2x16:
239 		printf(" (MXC 2x16)\n");
240 		break;
241 	case SFF8024_CTOR_CS_OPTICAL:
242 		printf(" (CS optical connector)\n");
243 		break;
244 	case SFF8024_CTOR_CS_OPTICAL_MINI:
245 		printf(" (Mini CS optical connector)\n");
246 		break;
247 	case SFF8024_CTOR_MPO_2X12:
248 		printf(" (MPO 2x12)\n");
249 		break;
250 	case SFF8024_CTOR_MPO_1X16:
251 		printf(" (MPO 1x16)\n");
252 		break;
253 	default:
254 		printf(" (reserved or unknown)\n");
255 		break;
256 	}
257 }
258 
sff8024_show_encoding(const __u8 * id,int encoding_offset,int sff_type)259 void sff8024_show_encoding(const __u8 *id, int encoding_offset, int sff_type)
260 {
261 	printf("\t%-41s : 0x%02x", "Encoding", id[encoding_offset]);
262 	switch (id[encoding_offset]) {
263 	case SFF8024_ENCODING_UNSPEC:
264 		printf(" (unspecified)\n");
265 		break;
266 	case SFF8024_ENCODING_8B10B:
267 		printf(" (8B/10B)\n");
268 		break;
269 	case SFF8024_ENCODING_4B5B:
270 		printf(" (4B/5B)\n");
271 		break;
272 	case SFF8024_ENCODING_NRZ:
273 		printf(" (NRZ)\n");
274 		break;
275 	case SFF8024_ENCODING_4h:
276 		if (sff_type == ETH_MODULE_SFF_8472)
277 			printf(" (Manchester)\n");
278 		else if (sff_type == ETH_MODULE_SFF_8636)
279 			printf(" (SONET Scrambled)\n");
280 		break;
281 	case SFF8024_ENCODING_5h:
282 		if (sff_type == ETH_MODULE_SFF_8472)
283 			printf(" (SONET Scrambled)\n");
284 		else if (sff_type == ETH_MODULE_SFF_8636)
285 			printf(" (64B/66B)\n");
286 		break;
287 	case SFF8024_ENCODING_6h:
288 		if (sff_type == ETH_MODULE_SFF_8472)
289 			printf(" (64B/66B)\n");
290 		else if (sff_type == ETH_MODULE_SFF_8636)
291 			printf(" (Manchester)\n");
292 		break;
293 	case SFF8024_ENCODING_256B:
294 		printf(" ((256B/257B (transcoded FEC-enabled data))\n");
295 		break;
296 	case SFF8024_ENCODING_PAM4:
297 		printf(" (PAM4)\n");
298 		break;
299 	default:
300 		printf(" (reserved or unknown)\n");
301 		break;
302 	}
303 }
304 
sff_show_thresholds(struct sff_diags sd)305 void sff_show_thresholds(struct sff_diags sd)
306 {
307 	PRINT_BIAS("Laser bias current high alarm threshold",
308 		   sd.bias_cur[HALRM]);
309 	PRINT_BIAS("Laser bias current low alarm threshold",
310 		   sd.bias_cur[LALRM]);
311 	PRINT_BIAS("Laser bias current high warning threshold",
312 		   sd.bias_cur[HWARN]);
313 	PRINT_BIAS("Laser bias current low warning threshold",
314 		   sd.bias_cur[LWARN]);
315 
316 	PRINT_xX_PWR("Laser output power high alarm threshold",
317 		     sd.tx_power[HALRM]);
318 	PRINT_xX_PWR("Laser output power low alarm threshold",
319 		     sd.tx_power[LALRM]);
320 	PRINT_xX_PWR("Laser output power high warning threshold",
321 		     sd.tx_power[HWARN]);
322 	PRINT_xX_PWR("Laser output power low warning threshold",
323 		     sd.tx_power[LWARN]);
324 
325 	PRINT_TEMP("Module temperature high alarm threshold",
326 		   sd.sfp_temp[HALRM]);
327 	PRINT_TEMP("Module temperature low alarm threshold",
328 		   sd.sfp_temp[LALRM]);
329 	PRINT_TEMP("Module temperature high warning threshold",
330 		   sd.sfp_temp[HWARN]);
331 	PRINT_TEMP("Module temperature low warning threshold",
332 		   sd.sfp_temp[LWARN]);
333 
334 	PRINT_VCC("Module voltage high alarm threshold",
335 		  sd.sfp_voltage[HALRM]);
336 	PRINT_VCC("Module voltage low alarm threshold",
337 		  sd.sfp_voltage[LALRM]);
338 	PRINT_VCC("Module voltage high warning threshold",
339 		  sd.sfp_voltage[HWARN]);
340 	PRINT_VCC("Module voltage low warning threshold",
341 		  sd.sfp_voltage[LWARN]);
342 
343 	PRINT_xX_PWR("Laser rx power high alarm threshold",
344 		     sd.rx_power[HALRM]);
345 	PRINT_xX_PWR("Laser rx power low alarm threshold",
346 		     sd.rx_power[LALRM]);
347 	PRINT_xX_PWR("Laser rx power high warning threshold",
348 		     sd.rx_power[HWARN]);
349 	PRINT_xX_PWR("Laser rx power low warning threshold",
350 		     sd.rx_power[LWARN]);
351 }
352 
sff_show_revision_compliance(const __u8 * id,int rev_offset)353 void sff_show_revision_compliance(const __u8 *id, int rev_offset)
354 {
355 	static const char *pfx =
356 		"\tRevision Compliance                       :";
357 
358 	switch (id[rev_offset]) {
359 	case SFF8636_REV_UNSPECIFIED:
360 		printf("%s Revision not specified\n", pfx);
361 		break;
362 	case SFF8636_REV_8436_48:
363 		printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
364 		break;
365 	case SFF8636_REV_8436_8636:
366 		printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
367 		break;
368 	case SFF8636_REV_8636_13:
369 		printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx);
370 		break;
371 	case SFF8636_REV_8636_14:
372 		printf("%s SFF-8636 Rev 1.4\n", pfx);
373 		break;
374 	case SFF8636_REV_8636_15:
375 		printf("%s SFF-8636 Rev 1.5\n", pfx);
376 		break;
377 	case SFF8636_REV_8636_20:
378 		printf("%s SFF-8636 Rev 2.0\n", pfx);
379 		break;
380 	case SFF8636_REV_8636_27:
381 		printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx);
382 		break;
383 	default:
384 		printf("%s Unallocated\n", pfx);
385 		break;
386 	}
387 }
388