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 
sff8024_show_oui(const __u8 * id,int id_offset)56 void sff8024_show_oui(const __u8 *id, int id_offset)
57 {
58 	printf("\t%-41s : %02x:%02x:%02x\n", "Vendor OUI",
59 		      id[id_offset], id[(id_offset) + 1],
60 		      id[(id_offset) + 2]);
61 }
62 
sff8024_show_identifier(const __u8 * id,int id_offset)63 void sff8024_show_identifier(const __u8 *id, int id_offset)
64 {
65 	printf("\t%-41s : 0x%02x", "Identifier", id[id_offset]);
66 	switch (id[id_offset]) {
67 	case SFF8024_ID_UNKNOWN:
68 		printf(" (no module present, unknown, or unspecified)\n");
69 		break;
70 	case SFF8024_ID_GBIC:
71 		printf(" (GBIC)\n");
72 		break;
73 	case SFF8024_ID_SOLDERED_MODULE:
74 		printf(" (module soldered to motherboard)\n");
75 		break;
76 	case SFF8024_ID_SFP:
77 		printf(" (SFP)\n");
78 		break;
79 	case SFF8024_ID_300_PIN_XBI:
80 		printf(" (300 pin XBI)\n");
81 		break;
82 	case SFF8024_ID_XENPAK:
83 		printf(" (XENPAK)\n");
84 		break;
85 	case SFF8024_ID_XFP:
86 		printf(" (XFP)\n");
87 		break;
88 	case SFF8024_ID_XFF:
89 		printf(" (XFF)\n");
90 		break;
91 	case SFF8024_ID_XFP_E:
92 		printf(" (XFP-E)\n");
93 		break;
94 	case SFF8024_ID_XPAK:
95 		printf(" (XPAK)\n");
96 		break;
97 	case SFF8024_ID_X2:
98 		printf(" (X2)\n");
99 		break;
100 	case SFF8024_ID_DWDM_SFP:
101 		printf(" (DWDM-SFP)\n");
102 		break;
103 	case SFF8024_ID_QSFP:
104 		printf(" (QSFP)\n");
105 		break;
106 	case SFF8024_ID_QSFP_PLUS:
107 		printf(" (QSFP+)\n");
108 		break;
109 	case SFF8024_ID_CXP:
110 		printf(" (CXP)\n");
111 		break;
112 	case SFF8024_ID_HD4X:
113 		printf(" (Shielded Mini Multilane HD 4X)\n");
114 		break;
115 	case SFF8024_ID_HD8X:
116 		printf(" (Shielded Mini Multilane HD 8X)\n");
117 		break;
118 	case SFF8024_ID_QSFP28:
119 		printf(" (QSFP28)\n");
120 		break;
121 	case SFF8024_ID_CXP2:
122 		printf(" (CXP2/CXP28)\n");
123 		break;
124 	case SFF8024_ID_CDFP:
125 		printf(" (CDFP Style 1/Style 2)\n");
126 		break;
127 	case SFF8024_ID_HD4X_FANOUT:
128 		printf(" (Shielded Mini Multilane HD 4X Fanout Cable)\n");
129 		break;
130 	case SFF8024_ID_HD8X_FANOUT:
131 		printf(" (Shielded Mini Multilane HD 8X Fanout Cable)\n");
132 		break;
133 	case SFF8024_ID_CDFP_S3:
134 		printf(" (CDFP Style 3)\n");
135 		break;
136 	case SFF8024_ID_MICRO_QSFP:
137 		printf(" (microQSFP)\n");
138 		break;
139 	default:
140 		printf(" (reserved or unknown)\n");
141 		break;
142 	}
143 }
144 
sff8024_show_connector(const __u8 * id,int ctor_offset)145 void sff8024_show_connector(const __u8 *id, int ctor_offset)
146 {
147 	printf("\t%-41s : 0x%02x", "Connector", id[ctor_offset]);
148 	switch (id[ctor_offset]) {
149 	case  SFF8024_CTOR_UNKNOWN:
150 		printf(" (unknown or unspecified)\n");
151 		break;
152 	case SFF8024_CTOR_SC:
153 		printf(" (SC)\n");
154 		break;
155 	case SFF8024_CTOR_FC_STYLE_1:
156 		printf(" (Fibre Channel Style 1 copper)\n");
157 		break;
158 	case SFF8024_CTOR_FC_STYLE_2:
159 		printf(" (Fibre Channel Style 2 copper)\n");
160 		break;
161 	case SFF8024_CTOR_BNC_TNC:
162 		printf(" (BNC/TNC)\n");
163 		break;
164 	case SFF8024_CTOR_FC_COAX:
165 		printf(" (Fibre Channel coaxial headers)\n");
166 		break;
167 	case SFF8024_CTOR_FIBER_JACK:
168 		printf(" (FibreJack)\n");
169 		break;
170 	case SFF8024_CTOR_LC:
171 		printf(" (LC)\n");
172 		break;
173 	case SFF8024_CTOR_MT_RJ:
174 		printf(" (MT-RJ)\n");
175 		break;
176 	case SFF8024_CTOR_MU:
177 		printf(" (MU)\n");
178 		break;
179 	case SFF8024_CTOR_SG:
180 		printf(" (SG)\n");
181 		break;
182 	case SFF8024_CTOR_OPT_PT:
183 		printf(" (Optical pigtail)\n");
184 		break;
185 	case SFF8024_CTOR_MPO:
186 		printf(" (MPO Parallel Optic)\n");
187 		break;
188 	case SFF8024_CTOR_MPO_2:
189 		printf(" (MPO Parallel Optic - 2x16)\n");
190 		break;
191 	case SFF8024_CTOR_HSDC_II:
192 		printf(" (HSSDC II)\n");
193 		break;
194 	case SFF8024_CTOR_COPPER_PT:
195 		printf(" (Copper pigtail)\n");
196 		break;
197 	case SFF8024_CTOR_RJ45:
198 		printf(" (RJ45)\n");
199 		break;
200 	case SFF8024_CTOR_NO_SEPARABLE:
201 		printf(" (No separable connector)\n");
202 		break;
203 	case SFF8024_CTOR_MXC_2x16:
204 		printf(" (MXC 2x16)\n");
205 		break;
206 	default:
207 		printf(" (reserved or unknown)\n");
208 		break;
209 	}
210 }
211 
sff8024_show_encoding(const __u8 * id,int encoding_offset,int sff_type)212 void sff8024_show_encoding(const __u8 *id, int encoding_offset, int sff_type)
213 {
214 	printf("\t%-41s : 0x%02x", "Encoding", id[encoding_offset]);
215 	switch (id[encoding_offset]) {
216 	case SFF8024_ENCODING_UNSPEC:
217 		printf(" (unspecified)\n");
218 		break;
219 	case SFF8024_ENCODING_8B10B:
220 		printf(" (8B/10B)\n");
221 		break;
222 	case SFF8024_ENCODING_4B5B:
223 		printf(" (4B/5B)\n");
224 		break;
225 	case SFF8024_ENCODING_NRZ:
226 		printf(" (NRZ)\n");
227 		break;
228 	case SFF8024_ENCODING_4h:
229 		if (sff_type == ETH_MODULE_SFF_8472)
230 			printf(" (Manchester)\n");
231 		else if (sff_type == ETH_MODULE_SFF_8636)
232 			printf(" (SONET Scrambled)\n");
233 		break;
234 	case SFF8024_ENCODING_5h:
235 		if (sff_type == ETH_MODULE_SFF_8472)
236 			printf(" (SONET Scrambled)\n");
237 		else if (sff_type == ETH_MODULE_SFF_8636)
238 			printf(" (64B/66B)\n");
239 		break;
240 	case SFF8024_ENCODING_6h:
241 		if (sff_type == ETH_MODULE_SFF_8472)
242 			printf(" (64B/66B)\n");
243 		else if (sff_type == ETH_MODULE_SFF_8636)
244 			printf(" (Manchester)\n");
245 		break;
246 	case SFF8024_ENCODING_256B:
247 		printf(" ((256B/257B (transcoded FEC-enabled data))\n");
248 		break;
249 	case SFF8024_ENCODING_PAM4:
250 		printf(" (PAM4)\n");
251 		break;
252 	default:
253 		printf(" (reserved or unknown)\n");
254 		break;
255 	}
256 }
257 
sff_show_thresholds(struct sff_diags sd)258 void sff_show_thresholds(struct sff_diags sd)
259 {
260 	PRINT_BIAS("Laser bias current high alarm threshold",
261 		   sd.bias_cur[HALRM]);
262 	PRINT_BIAS("Laser bias current low alarm threshold",
263 		   sd.bias_cur[LALRM]);
264 	PRINT_BIAS("Laser bias current high warning threshold",
265 		   sd.bias_cur[HWARN]);
266 	PRINT_BIAS("Laser bias current low warning threshold",
267 		   sd.bias_cur[LWARN]);
268 
269 	PRINT_xX_PWR("Laser output power high alarm threshold",
270 		     sd.tx_power[HALRM]);
271 	PRINT_xX_PWR("Laser output power low alarm threshold",
272 		     sd.tx_power[LALRM]);
273 	PRINT_xX_PWR("Laser output power high warning threshold",
274 		     sd.tx_power[HWARN]);
275 	PRINT_xX_PWR("Laser output power low warning threshold",
276 		     sd.tx_power[LWARN]);
277 
278 	PRINT_TEMP("Module temperature high alarm threshold",
279 		   sd.sfp_temp[HALRM]);
280 	PRINT_TEMP("Module temperature low alarm threshold",
281 		   sd.sfp_temp[LALRM]);
282 	PRINT_TEMP("Module temperature high warning threshold",
283 		   sd.sfp_temp[HWARN]);
284 	PRINT_TEMP("Module temperature low warning threshold",
285 		   sd.sfp_temp[LWARN]);
286 
287 	PRINT_VCC("Module voltage high alarm threshold",
288 		  sd.sfp_voltage[HALRM]);
289 	PRINT_VCC("Module voltage low alarm threshold",
290 		  sd.sfp_voltage[LALRM]);
291 	PRINT_VCC("Module voltage high warning threshold",
292 		  sd.sfp_voltage[HWARN]);
293 	PRINT_VCC("Module voltage low warning threshold",
294 		  sd.sfp_voltage[LWARN]);
295 
296 	PRINT_xX_PWR("Laser rx power high alarm threshold",
297 		     sd.rx_power[HALRM]);
298 	PRINT_xX_PWR("Laser rx power low alarm threshold",
299 		     sd.rx_power[LALRM]);
300 	PRINT_xX_PWR("Laser rx power high warning threshold",
301 		     sd.rx_power[HWARN]);
302 	PRINT_xX_PWR("Laser rx power low warning threshold",
303 		     sd.rx_power[LWARN]);
304 }
305