1 /****************************************************************************
2  * Support for Solarflare Solarstorm network controllers and boards
3  * Copyright 2010 Solarflare Communications Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published
7  * by the Free Software Foundation, incorporated herein by reference.
8  */
9 
10 #include <stdio.h>
11 #include "internal.h"
12 #include "sff-common.h"
13 
sff8079_show_identifier(const __u8 * id)14 static void sff8079_show_identifier(const __u8 *id)
15 {
16 	sff8024_show_identifier(id, 0);
17 }
18 
sff8079_show_ext_identifier(const __u8 * id)19 static void sff8079_show_ext_identifier(const __u8 *id)
20 {
21 	printf("\t%-41s : 0x%02x", "Extended identifier", id[1]);
22 	if (id[1] == 0x00)
23 		printf(" (GBIC not specified / not MOD_DEF compliant)\n");
24 	else if (id[1] == 0x04)
25 		printf(" (GBIC/SFP defined by 2-wire interface ID)\n");
26 	else if (id[1] <= 0x07)
27 		printf(" (GBIC compliant with MOD_DEF %u)\n", id[1]);
28 	else
29 		printf(" (unknown)\n");
30 }
31 
sff8079_show_connector(const __u8 * id)32 static void sff8079_show_connector(const __u8 *id)
33 {
34 	sff8024_show_connector(id, 2);
35 }
36 
sff8079_show_transceiver(const __u8 * id)37 static void sff8079_show_transceiver(const __u8 *id)
38 {
39 	static const char *pfx =
40 		"\tTransceiver type                          :";
41 
42 	printf("\t%-41s : 0x%02x 0x%02x 0x%02x " \
43 	       "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
44 		   "Transceiver codes",
45 	       id[3], id[4], id[5], id[6],
46 	       id[7], id[8], id[9], id[10], id[36]);
47 	/* 10G Ethernet Compliance Codes */
48 	if (id[3] & (1 << 7))
49 		printf("%s 10G Ethernet: 10G Base-ER" \
50 		       " [SFF-8472 rev10.4 only]\n", pfx);
51 	if (id[3] & (1 << 6))
52 		printf("%s 10G Ethernet: 10G Base-LRM\n", pfx);
53 	if (id[3] & (1 << 5))
54 		printf("%s 10G Ethernet: 10G Base-LR\n", pfx);
55 	if (id[3] & (1 << 4))
56 		printf("%s 10G Ethernet: 10G Base-SR\n", pfx);
57 	/* Infiniband Compliance Codes */
58 	if (id[3] & (1 << 3))
59 		printf("%s Infiniband: 1X SX\n", pfx);
60 	if (id[3] & (1 << 2))
61 		printf("%s Infiniband: 1X LX\n", pfx);
62 	if (id[3] & (1 << 1))
63 		printf("%s Infiniband: 1X Copper Active\n", pfx);
64 	if (id[3] & (1 << 0))
65 		printf("%s Infiniband: 1X Copper Passive\n", pfx);
66 	/* ESCON Compliance Codes */
67 	if (id[4] & (1 << 7))
68 		printf("%s ESCON: ESCON MMF, 1310nm LED\n", pfx);
69 	if (id[4] & (1 << 6))
70 		printf("%s ESCON: ESCON SMF, 1310nm Laser\n", pfx);
71 	/* SONET Compliance Codes */
72 	if (id[4] & (1 << 5))
73 		printf("%s SONET: OC-192, short reach\n", pfx);
74 	if (id[4] & (1 << 4))
75 		printf("%s SONET: SONET reach specifier bit 1\n", pfx);
76 	if (id[4] & (1 << 3))
77 		printf("%s SONET: SONET reach specifier bit 2\n", pfx);
78 	if (id[4] & (1 << 2))
79 		printf("%s SONET: OC-48, long reach\n", pfx);
80 	if (id[4] & (1 << 1))
81 		printf("%s SONET: OC-48, intermediate reach\n", pfx);
82 	if (id[4] & (1 << 0))
83 		printf("%s SONET: OC-48, short reach\n", pfx);
84 	if (id[5] & (1 << 6))
85 		printf("%s SONET: OC-12, single mode, long reach\n", pfx);
86 	if (id[5] & (1 << 5))
87 		printf("%s SONET: OC-12, single mode, inter. reach\n", pfx);
88 	if (id[5] & (1 << 4))
89 		printf("%s SONET: OC-12, short reach\n", pfx);
90 	if (id[5] & (1 << 2))
91 		printf("%s SONET: OC-3, single mode, long reach\n", pfx);
92 	if (id[5] & (1 << 1))
93 		printf("%s SONET: OC-3, single mode, inter. reach\n", pfx);
94 	if (id[5] & (1 << 0))
95 		printf("%s SONET: OC-3, short reach\n", pfx);
96 	/* Ethernet Compliance Codes */
97 	if (id[6] & (1 << 7))
98 		printf("%s Ethernet: BASE-PX\n", pfx);
99 	if (id[6] & (1 << 6))
100 		printf("%s Ethernet: BASE-BX10\n", pfx);
101 	if (id[6] & (1 << 5))
102 		printf("%s Ethernet: 100BASE-FX\n", pfx);
103 	if (id[6] & (1 << 4))
104 		printf("%s Ethernet: 100BASE-LX/LX10\n", pfx);
105 	if (id[6] & (1 << 3))
106 		printf("%s Ethernet: 1000BASE-T\n", pfx);
107 	if (id[6] & (1 << 2))
108 		printf("%s Ethernet: 1000BASE-CX\n", pfx);
109 	if (id[6] & (1 << 1))
110 		printf("%s Ethernet: 1000BASE-LX\n", pfx);
111 	if (id[6] & (1 << 0))
112 		printf("%s Ethernet: 1000BASE-SX\n", pfx);
113 	/* Fibre Channel link length */
114 	if (id[7] & (1 << 7))
115 		printf("%s FC: very long distance (V)\n", pfx);
116 	if (id[7] & (1 << 6))
117 		printf("%s FC: short distance (S)\n", pfx);
118 	if (id[7] & (1 << 5))
119 		printf("%s FC: intermediate distance (I)\n", pfx);
120 	if (id[7] & (1 << 4))
121 		printf("%s FC: long distance (L)\n", pfx);
122 	if (id[7] & (1 << 3))
123 		printf("%s FC: medium distance (M)\n", pfx);
124 	/* Fibre Channel transmitter technology */
125 	if (id[7] & (1 << 2))
126 		printf("%s FC: Shortwave laser, linear Rx (SA)\n", pfx);
127 	if (id[7] & (1 << 1))
128 		printf("%s FC: Longwave laser (LC)\n", pfx);
129 	if (id[7] & (1 << 0))
130 		printf("%s FC: Electrical inter-enclosure (EL)\n", pfx);
131 	if (id[8] & (1 << 7))
132 		printf("%s FC: Electrical intra-enclosure (EL)\n", pfx);
133 	if (id[8] & (1 << 6))
134 		printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx);
135 	if (id[8] & (1 << 5))
136 		printf("%s FC: Shortwave laser with OFC (SL)\n", pfx);
137 	if (id[8] & (1 << 4))
138 		printf("%s FC: Longwave laser (LL)\n", pfx);
139 	if (id[8] & (1 << 3))
140 		printf("%s Active Cable\n", pfx);
141 	if (id[8] & (1 << 2))
142 		printf("%s Passive Cable\n", pfx);
143 	if (id[8] & (1 << 1))
144 		printf("%s FC: Copper FC-BaseT\n", pfx);
145 	/* Fibre Channel transmission media */
146 	if (id[9] & (1 << 7))
147 		printf("%s FC: Twin Axial Pair (TW)\n", pfx);
148 	if (id[9] & (1 << 6))
149 		printf("%s FC: Twisted Pair (TP)\n", pfx);
150 	if (id[9] & (1 << 5))
151 		printf("%s FC: Miniature Coax (MI)\n", pfx);
152 	if (id[9] & (1 << 4))
153 		printf("%s FC: Video Coax (TV)\n", pfx);
154 	if (id[9] & (1 << 3))
155 		printf("%s FC: Multimode, 62.5um (M6)\n", pfx);
156 	if (id[9] & (1 << 2))
157 		printf("%s FC: Multimode, 50um (M5)\n", pfx);
158 	if (id[9] & (1 << 0))
159 		printf("%s FC: Single Mode (SM)\n", pfx);
160 	/* Fibre Channel speed */
161 	if (id[10] & (1 << 7))
162 		printf("%s FC: 1200 MBytes/sec\n", pfx);
163 	if (id[10] & (1 << 6))
164 		printf("%s FC: 800 MBytes/sec\n", pfx);
165 	if (id[10] & (1 << 4))
166 		printf("%s FC: 400 MBytes/sec\n", pfx);
167 	if (id[10] & (1 << 2))
168 		printf("%s FC: 200 MBytes/sec\n", pfx);
169 	if (id[10] & (1 << 0))
170 		printf("%s FC: 100 MBytes/sec\n", pfx);
171 	/* Extended Specification Compliance Codes from SFF-8024 */
172 	if (id[36] == 0x1)
173 		printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", pfx);
174 	if (id[36] == 0x2)
175 		printf("%s Extended: 100G Base-SR4 or 25GBase-SR\n", pfx);
176 	if (id[36] == 0x3)
177 		printf("%s Extended: 100G Base-LR4 or 25GBase-LR\n", pfx);
178 	if (id[36] == 0x4)
179 		printf("%s Extended: 100G Base-ER4 or 25GBase-ER\n", pfx);
180 	if (id[36] == 0x8)
181 		printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", pfx);
182 	if (id[36] == 0xb)
183 		printf("%s Extended: 100G Base-CR4 or 25G Base-CR CA-L\n", pfx);
184 	if (id[36] == 0xc)
185 		printf("%s Extended: 25G Base-CR CA-S\n", pfx);
186 	if (id[36] == 0xd)
187 		printf("%s Extended: 25G Base-CR CA-N\n", pfx);
188 	if (id[36] == 0x18)
189 		printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", pfx);
190 	if (id[36] == 0x19)
191 		printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", pfx);
192 }
193 
sff8079_show_encoding(const __u8 * id)194 static void sff8079_show_encoding(const __u8 *id)
195 {
196 	sff8024_show_encoding(id, 11, ETH_MODULE_SFF_8472);
197 }
198 
sff8079_show_rate_identifier(const __u8 * id)199 static void sff8079_show_rate_identifier(const __u8 *id)
200 {
201 	printf("\t%-41s : 0x%02x", "Rate identifier", id[13]);
202 	switch (id[13]) {
203 	case 0x00:
204 		printf(" (unspecified)\n");
205 		break;
206 	case 0x01:
207 		printf(" (4/2/1G Rate_Select & AS0/AS1)\n");
208 		break;
209 	case 0x02:
210 		printf(" (8/4/2G Rx Rate_Select only)\n");
211 		break;
212 	case 0x03:
213 		printf(" (8/4/2G Independent Rx & Tx Rate_Select)\n");
214 		break;
215 	case 0x04:
216 		printf(" (8/4/2G Tx Rate_Select only)\n");
217 		break;
218 	default:
219 		printf(" (reserved or unknown)\n");
220 		break;
221 	}
222 }
223 
sff8079_show_oui(const __u8 * id)224 static void sff8079_show_oui(const __u8 *id)
225 {
226 	printf("\t%-41s : %02x:%02x:%02x\n", "Vendor OUI",
227 	       id[37], id[38], id[39]);
228 }
229 
sff8079_show_wavelength_or_copper_compliance(const __u8 * id)230 static void sff8079_show_wavelength_or_copper_compliance(const __u8 *id)
231 {
232 	if (id[8] & (1 << 2)) {
233 		printf("\t%-41s : 0x%02x", "Passive Cu cmplnce.", id[60]);
234 		switch (id[60]) {
235 		case 0x00:
236 			printf(" (unspecified)");
237 			break;
238 		case 0x01:
239 			printf(" (SFF-8431 appendix E)");
240 			break;
241 		default:
242 			printf(" (unknown)");
243 			break;
244 		}
245 		printf(" [SFF-8472 rev10.4 only]\n");
246 	} else if (id[8] & (1 << 3)) {
247 		printf("\t%-41s : 0x%02x", "Active Cu cmplnce.", id[60]);
248 		switch (id[60]) {
249 		case 0x00:
250 			printf(" (unspecified)");
251 			break;
252 		case 0x01:
253 			printf(" (SFF-8431 appendix E)");
254 			break;
255 		case 0x04:
256 			printf(" (SFF-8431 limiting)");
257 			break;
258 		default:
259 			printf(" (unknown)");
260 			break;
261 		}
262 		printf(" [SFF-8472 rev10.4 only]\n");
263 	} else {
264 		printf("\t%-41s : %unm\n", "Laser wavelength",
265 		       (id[60] << 8) | id[61]);
266 	}
267 }
268 
sff8079_show_value_with_unit(const __u8 * id,unsigned int reg,const char * name,unsigned int mult,const char * unit)269 static void sff8079_show_value_with_unit(const __u8 *id, unsigned int reg,
270 					 const char *name, unsigned int mult,
271 					 const char *unit)
272 {
273 	unsigned int val = id[reg];
274 
275 	printf("\t%-41s : %u%s\n", name, val * mult, unit);
276 }
277 
sff8079_show_ascii(const __u8 * id,unsigned int first_reg,unsigned int last_reg,const char * name)278 static void sff8079_show_ascii(const __u8 *id, unsigned int first_reg,
279 			       unsigned int last_reg, const char *name)
280 {
281 	unsigned int reg, val;
282 
283 	printf("\t%-41s : ", name);
284 	while (first_reg <= last_reg && id[last_reg] == ' ')
285 		last_reg--;
286 	for (reg = first_reg; reg <= last_reg; reg++) {
287 		val = id[reg];
288 		putchar(((val >= 32) && (val <= 126)) ? val : '_');
289 	}
290 	printf("\n");
291 }
292 
sff8079_show_options(const __u8 * id)293 static void sff8079_show_options(const __u8 *id)
294 {
295 	static const char *pfx =
296 		"\tOption                                    :";
297 
298 	printf("\t%-41s : 0x%02x 0x%02x\n", "Option values", id[64], id[65]);
299 	if (id[65] & (1 << 1))
300 		printf("%s RX_LOS implemented\n", pfx);
301 	if (id[65] & (1 << 2))
302 		printf("%s RX_LOS implemented, inverted\n", pfx);
303 	if (id[65] & (1 << 3))
304 		printf("%s TX_FAULT implemented\n", pfx);
305 	if (id[65] & (1 << 4))
306 		printf("%s TX_DISABLE implemented\n", pfx);
307 	if (id[65] & (1 << 5))
308 		printf("%s RATE_SELECT implemented\n", pfx);
309 	if (id[65] & (1 << 6))
310 		printf("%s Tunable transmitter technology\n", pfx);
311 	if (id[65] & (1 << 7))
312 		printf("%s Receiver decision threshold implemented\n", pfx);
313 	if (id[64] & (1 << 0))
314 		printf("%s Linear receiver output implemented\n", pfx);
315 	if (id[64] & (1 << 1))
316 		printf("%s Power level 2 requirement\n", pfx);
317 	if (id[64] & (1 << 2))
318 		printf("%s Cooled transceiver implemented\n", pfx);
319 	if (id[64] & (1 << 3))
320 		printf("%s Retimer or CDR implemented\n", pfx);
321 	if (id[64] & (1 << 4))
322 		printf("%s Paging implemented\n", pfx);
323 	if (id[64] & (1 << 5))
324 		printf("%s Power level 3 requirement\n", pfx);
325 }
326 
sff8079_show_all(const __u8 * id)327 void sff8079_show_all(const __u8 *id)
328 {
329 	sff8079_show_identifier(id);
330 	if (((id[0] == 0x02) || (id[0] == 0x03)) && (id[1] == 0x04)) {
331 		sff8079_show_ext_identifier(id);
332 		sff8079_show_connector(id);
333 		sff8079_show_transceiver(id);
334 		sff8079_show_encoding(id);
335 		sff8079_show_value_with_unit(id, 12, "BR, Nominal", 100, "MBd");
336 		sff8079_show_rate_identifier(id);
337 		sff8079_show_value_with_unit(id, 14,
338 					     "Length (SMF,km)", 1, "km");
339 		sff8079_show_value_with_unit(id, 15, "Length (SMF)", 100, "m");
340 		sff8079_show_value_with_unit(id, 16, "Length (50um)", 10, "m");
341 		sff8079_show_value_with_unit(id, 17,
342 					     "Length (62.5um)", 10, "m");
343 		sff8079_show_value_with_unit(id, 18, "Length (Copper)", 1, "m");
344 		sff8079_show_value_with_unit(id, 19, "Length (OM3)", 10, "m");
345 		sff8079_show_wavelength_or_copper_compliance(id);
346 		sff8079_show_ascii(id, 20, 35, "Vendor name");
347 		sff8079_show_oui(id);
348 		sff8079_show_ascii(id, 40, 55, "Vendor PN");
349 		sff8079_show_ascii(id, 56, 59, "Vendor rev");
350 		sff8079_show_options(id);
351 		sff8079_show_value_with_unit(id, 66, "BR margin, max", 1, "%");
352 		sff8079_show_value_with_unit(id, 67, "BR margin, min", 1, "%");
353 		sff8079_show_ascii(id, 68, 83, "Vendor SN");
354 		sff8079_show_ascii(id, 84, 91, "Date code");
355 	}
356 }
357