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