xref: /aosp_15_r20/external/ethtool/qsfp.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
1*1b481fc3SMaciej Żenczykowski /*
2*1b481fc3SMaciej Żenczykowski  * qsfp.c: Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map.
3*1b481fc3SMaciej Żenczykowski  *
4*1b481fc3SMaciej Żenczykowski  * Copyright 2010 Solarflare Communications Inc.
5*1b481fc3SMaciej Żenczykowski  * Aurelien Guillaume <[email protected]> (C) 2012
6*1b481fc3SMaciej Żenczykowski  * Copyright (C) 2014 Cumulus networks Inc.
7*1b481fc3SMaciej Żenczykowski  *
8*1b481fc3SMaciej Żenczykowski  * This program is free software; you can redistribute it and/or modify
9*1b481fc3SMaciej Żenczykowski  * it under the terms of the GNU General Public License as published by
10*1b481fc3SMaciej Żenczykowski  * the Freeoftware Foundation; either version 2 of the License, or
11*1b481fc3SMaciej Żenczykowski  * (at your option) any later version.
12*1b481fc3SMaciej Żenczykowski  *
13*1b481fc3SMaciej Żenczykowski  *  Vidya Ravipati <[email protected]>
14*1b481fc3SMaciej Żenczykowski  *   This implementation is loosely based on current SFP parser
15*1b481fc3SMaciej Żenczykowski  *   and SFF-8636 spec Rev 2.7 (ftp://ftp.seagate.com/pub/sff/SFF-8636.PDF)
16*1b481fc3SMaciej Żenczykowski  *   by SFF Committee.
17*1b481fc3SMaciej Żenczykowski  */
18*1b481fc3SMaciej Żenczykowski 
19*1b481fc3SMaciej Żenczykowski /*
20*1b481fc3SMaciej Żenczykowski  *	Description:
21*1b481fc3SMaciej Żenczykowski  *	a) The register/memory layout is up to 5 128 byte pages defined by
22*1b481fc3SMaciej Żenczykowski  *		a "pages valid" register and switched via a "page select"
23*1b481fc3SMaciej Żenczykowski  *		register. Memory of 256 bytes can be memory mapped at a time
24*1b481fc3SMaciej Żenczykowski  *		according to SFF 8636.
25*1b481fc3SMaciej Żenczykowski  *	b) SFF 8636 based 640 bytes memory layout is presented for parser
26*1b481fc3SMaciej Żenczykowski  *
27*1b481fc3SMaciej Żenczykowski  *           SFF 8636 based QSFP Memory Map
28*1b481fc3SMaciej Żenczykowski  *
29*1b481fc3SMaciej Żenczykowski  *           2-Wire Serial Address: 1010000x
30*1b481fc3SMaciej Żenczykowski  *
31*1b481fc3SMaciej Żenczykowski  *           Lower Page 00h (128 bytes)
32*1b481fc3SMaciej Żenczykowski  *           ======================
33*1b481fc3SMaciej Żenczykowski  *           |                     |
34*1b481fc3SMaciej Żenczykowski  *           |Page Select Byte(127)|
35*1b481fc3SMaciej Żenczykowski  *           ======================
36*1b481fc3SMaciej Żenczykowski  *                    |
37*1b481fc3SMaciej Żenczykowski  *                    V
38*1b481fc3SMaciej Żenczykowski  *	     ----------------------------------------
39*1b481fc3SMaciej Żenczykowski  *	    |             |            |             |
40*1b481fc3SMaciej Żenczykowski  *	    V             V            V             V
41*1b481fc3SMaciej Żenczykowski  *	 ----------   ----------   ---------    ------------
42*1b481fc3SMaciej Żenczykowski  *	| Upper    | | Upper    | | Upper    | | Upper      |
43*1b481fc3SMaciej Żenczykowski  *	| Page 00h | | Page 01h | | Page 02h | | Page 03h   |
44*1b481fc3SMaciej Żenczykowski  *	|          | |(Optional)| |(Optional)| | (Optional) |
45*1b481fc3SMaciej Żenczykowski  *	|          | |          | |          | |            |
46*1b481fc3SMaciej Żenczykowski  *	|          | |          | |          | |            |
47*1b481fc3SMaciej Żenczykowski  *	|    ID    | |   AST    | |  User    | |  For       |
48*1b481fc3SMaciej Żenczykowski  *	|  Fields  | |  Table   | | EEPROM   | |  Cable     |
49*1b481fc3SMaciej Żenczykowski  *	|          | |          | | Data     | | Assemblies |
50*1b481fc3SMaciej Żenczykowski  *	|          | |          | |          | |            |
51*1b481fc3SMaciej Żenczykowski  *	|          | |          | |          | |            |
52*1b481fc3SMaciej Żenczykowski  *	-----------  -----------   ----------  --------------
53*1b481fc3SMaciej Żenczykowski  *
54*1b481fc3SMaciej Żenczykowski  *
55*1b481fc3SMaciej Żenczykowski  **/
56*1b481fc3SMaciej Żenczykowski #include <stdio.h>
57*1b481fc3SMaciej Żenczykowski #include <math.h>
58*1b481fc3SMaciej Żenczykowski #include <errno.h>
59*1b481fc3SMaciej Żenczykowski #include "internal.h"
60*1b481fc3SMaciej Żenczykowski #include "sff-common.h"
61*1b481fc3SMaciej Żenczykowski #include "qsfp.h"
62*1b481fc3SMaciej Żenczykowski #include "cmis.h"
63*1b481fc3SMaciej Żenczykowski #include "netlink/extapi.h"
64*1b481fc3SMaciej Żenczykowski 
65*1b481fc3SMaciej Żenczykowski struct sff8636_memory_map {
66*1b481fc3SMaciej Żenczykowski 	const __u8 *lower_memory;
67*1b481fc3SMaciej Żenczykowski 	const __u8 *upper_memory[4];
68*1b481fc3SMaciej Żenczykowski #define page_00h upper_memory[0x0]
69*1b481fc3SMaciej Żenczykowski #define page_03h upper_memory[0x3]
70*1b481fc3SMaciej Żenczykowski };
71*1b481fc3SMaciej Żenczykowski 
72*1b481fc3SMaciej Żenczykowski #define SFF8636_PAGE_SIZE	0x80
73*1b481fc3SMaciej Żenczykowski #define SFF8636_I2C_ADDRESS	0x50
74*1b481fc3SMaciej Żenczykowski #define SFF8636_MAX_CHANNEL_NUM	4
75*1b481fc3SMaciej Żenczykowski 
76*1b481fc3SMaciej Żenczykowski #define MAX_DESC_SIZE	42
77*1b481fc3SMaciej Żenczykowski 
78*1b481fc3SMaciej Żenczykowski static struct sff8636_aw_flags {
79*1b481fc3SMaciej Żenczykowski 	const char *str;        /* Human-readable string, null at the end */
80*1b481fc3SMaciej Żenczykowski 	int offset;
81*1b481fc3SMaciej Żenczykowski 	__u8 value;             /* Alarm is on if (offset & value) != 0. */
82*1b481fc3SMaciej Żenczykowski } sff8636_aw_flags[] = {
83*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high alarm   (Chan 1)",
84*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_HALARM) },
85*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low alarm    (Chan 1)",
86*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_LALARM) },
87*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high warning (Chan 1)",
88*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_HWARN) },
89*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low warning  (Chan 1)",
90*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_LWARN) },
91*1b481fc3SMaciej Żenczykowski 
92*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high alarm   (Chan 2)",
93*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_HALARM) },
94*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low alarm    (Chan 2)",
95*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_LALARM) },
96*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high warning (Chan 2)",
97*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_HWARN) },
98*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low warning  (Chan 2)",
99*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_LWARN) },
100*1b481fc3SMaciej Żenczykowski 
101*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high alarm   (Chan 3)",
102*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_HALARM) },
103*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low alarm    (Chan 3)",
104*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_LALARM) },
105*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high warning (Chan 3)",
106*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_HWARN) },
107*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low warning  (Chan 3)",
108*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_LWARN) },
109*1b481fc3SMaciej Żenczykowski 
110*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high alarm   (Chan 4)",
111*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_HALARM) },
112*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low alarm    (Chan 4)",
113*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_LALARM) },
114*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current high warning (Chan 4)",
115*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_HWARN) },
116*1b481fc3SMaciej Żenczykowski 	{ "Laser bias current low warning  (Chan 4)",
117*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_LWARN) },
118*1b481fc3SMaciej Żenczykowski 
119*1b481fc3SMaciej Żenczykowski 	{ "Module temperature high alarm",
120*1b481fc3SMaciej Żenczykowski 		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_HALARM_STATUS) },
121*1b481fc3SMaciej Żenczykowski 	{ "Module temperature low alarm",
122*1b481fc3SMaciej Żenczykowski 		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_LALARM_STATUS) },
123*1b481fc3SMaciej Żenczykowski 	{ "Module temperature high warning",
124*1b481fc3SMaciej Żenczykowski 		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_HWARN_STATUS) },
125*1b481fc3SMaciej Żenczykowski 	{ "Module temperature low warning",
126*1b481fc3SMaciej Żenczykowski 		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_LWARN_STATUS) },
127*1b481fc3SMaciej Żenczykowski 
128*1b481fc3SMaciej Żenczykowski 	{ "Module voltage high alarm",
129*1b481fc3SMaciej Żenczykowski 		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_HALARM_STATUS) },
130*1b481fc3SMaciej Żenczykowski 	{ "Module voltage low alarm",
131*1b481fc3SMaciej Żenczykowski 		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_LALARM_STATUS) },
132*1b481fc3SMaciej Żenczykowski 	{ "Module voltage high warning",
133*1b481fc3SMaciej Żenczykowski 		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_HWARN_STATUS) },
134*1b481fc3SMaciej Żenczykowski 	{ "Module voltage low warning",
135*1b481fc3SMaciej Żenczykowski 		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_LWARN_STATUS) },
136*1b481fc3SMaciej Żenczykowski 
137*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high alarm   (Channel 1)",
138*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_HALARM) },
139*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low alarm    (Channel 1)",
140*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_LALARM) },
141*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high warning (Channel 1)",
142*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_HWARN) },
143*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low warning  (Channel 1)",
144*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_LWARN) },
145*1b481fc3SMaciej Żenczykowski 
146*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high alarm   (Channel 2)",
147*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_HALARM) },
148*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low alarm    (Channel 2)",
149*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_LALARM) },
150*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high warning (Channel 2)",
151*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_HWARN) },
152*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low warning  (Channel 2)",
153*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_LWARN) },
154*1b481fc3SMaciej Żenczykowski 
155*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high alarm   (Channel 3)",
156*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_HALARM) },
157*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low alarm    (Channel 3)",
158*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_LALARM) },
159*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high warning (Channel 3)",
160*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_HWARN) },
161*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low warning  (Channel 3)",
162*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_LWARN) },
163*1b481fc3SMaciej Żenczykowski 
164*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high alarm   (Channel 4)",
165*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_HALARM) },
166*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low alarm    (Channel 4)",
167*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_LALARM) },
168*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power high warning (Channel 4)",
169*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_HWARN) },
170*1b481fc3SMaciej Żenczykowski 	{ "Laser tx power low warning  (Channel 4)",
171*1b481fc3SMaciej Żenczykowski 		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_LWARN) },
172*1b481fc3SMaciej Żenczykowski 
173*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high alarm   (Channel 1)",
174*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_HALARM) },
175*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low alarm    (Channel 1)",
176*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_LALARM) },
177*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high warning (Channel 1)",
178*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_HWARN) },
179*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low warning  (Channel 1)",
180*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_LWARN) },
181*1b481fc3SMaciej Żenczykowski 
182*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high alarm   (Channel 2)",
183*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_HALARM) },
184*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low alarm    (Channel 2)",
185*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_LALARM) },
186*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high warning (Channel 2)",
187*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_HWARN) },
188*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low warning  (Channel 2)",
189*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_LWARN) },
190*1b481fc3SMaciej Żenczykowski 
191*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high alarm   (Channel 3)",
192*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_HALARM) },
193*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low alarm    (Channel 3)",
194*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_LALARM) },
195*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high warning (Channel 3)",
196*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_HWARN) },
197*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low warning  (Channel 3)",
198*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_LWARN) },
199*1b481fc3SMaciej Żenczykowski 
200*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high alarm   (Channel 4)",
201*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_HALARM) },
202*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low alarm    (Channel 4)",
203*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_LALARM) },
204*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power high warning (Channel 4)",
205*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_HWARN) },
206*1b481fc3SMaciej Żenczykowski 	{ "Laser rx power low warning  (Channel 4)",
207*1b481fc3SMaciej Żenczykowski 		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_LWARN) },
208*1b481fc3SMaciej Żenczykowski 
209*1b481fc3SMaciej Żenczykowski 	{ NULL, 0, 0 },
210*1b481fc3SMaciej Żenczykowski };
211*1b481fc3SMaciej Żenczykowski 
sff8636_show_identifier(const struct sff8636_memory_map * map)212*1b481fc3SMaciej Żenczykowski static void sff8636_show_identifier(const struct sff8636_memory_map *map)
213*1b481fc3SMaciej Żenczykowski {
214*1b481fc3SMaciej Żenczykowski 	sff8024_show_identifier(map->lower_memory, SFF8636_ID_OFFSET);
215*1b481fc3SMaciej Żenczykowski }
216*1b481fc3SMaciej Żenczykowski 
sff8636_show_ext_identifier(const struct sff8636_memory_map * map)217*1b481fc3SMaciej Żenczykowski static void sff8636_show_ext_identifier(const struct sff8636_memory_map *map)
218*1b481fc3SMaciej Żenczykowski {
219*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : 0x%02x\n", "Extended identifier",
220*1b481fc3SMaciej Żenczykowski 	       map->page_00h[SFF8636_EXT_ID_OFFSET]);
221*1b481fc3SMaciej Żenczykowski 
222*1b481fc3SMaciej Żenczykowski 	static const char *pfx =
223*1b481fc3SMaciej Żenczykowski 		"\tExtended identifier description           :";
224*1b481fc3SMaciej Żenczykowski 
225*1b481fc3SMaciej Żenczykowski 	switch (map->page_00h[SFF8636_EXT_ID_OFFSET] &
226*1b481fc3SMaciej Żenczykowski 		SFF8636_EXT_ID_PWR_CLASS_MASK) {
227*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_1:
228*1b481fc3SMaciej Żenczykowski 		printf("%s 1.5W max. Power consumption\n", pfx);
229*1b481fc3SMaciej Żenczykowski 		break;
230*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_2:
231*1b481fc3SMaciej Żenczykowski 		printf("%s 2.0W max. Power consumption\n", pfx);
232*1b481fc3SMaciej Żenczykowski 		break;
233*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_3:
234*1b481fc3SMaciej Żenczykowski 		printf("%s 2.5W max. Power consumption\n", pfx);
235*1b481fc3SMaciej Żenczykowski 		break;
236*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_4:
237*1b481fc3SMaciej Żenczykowski 		printf("%s 3.5W max. Power consumption\n", pfx);
238*1b481fc3SMaciej Żenczykowski 		break;
239*1b481fc3SMaciej Żenczykowski 	}
240*1b481fc3SMaciej Żenczykowski 
241*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_TX_MASK)
242*1b481fc3SMaciej Żenczykowski 		printf("%s CDR present in TX,", pfx);
243*1b481fc3SMaciej Żenczykowski 	else
244*1b481fc3SMaciej Żenczykowski 		printf("%s No CDR in TX,", pfx);
245*1b481fc3SMaciej Żenczykowski 
246*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_RX_MASK)
247*1b481fc3SMaciej Żenczykowski 		printf(" CDR present in RX\n");
248*1b481fc3SMaciej Żenczykowski 	else
249*1b481fc3SMaciej Żenczykowski 		printf(" No CDR in RX\n");
250*1b481fc3SMaciej Żenczykowski 
251*1b481fc3SMaciej Żenczykowski 	switch (map->page_00h[SFF8636_EXT_ID_OFFSET] &
252*1b481fc3SMaciej Żenczykowski 		SFF8636_EXT_ID_EPWR_CLASS_MASK) {
253*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_LEGACY:
254*1b481fc3SMaciej Żenczykowski 		printf("%s", pfx);
255*1b481fc3SMaciej Żenczykowski 		break;
256*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_5:
257*1b481fc3SMaciej Żenczykowski 		printf("%s 4.0W max. Power consumption,", pfx);
258*1b481fc3SMaciej Żenczykowski 		break;
259*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_6:
260*1b481fc3SMaciej Żenczykowski 		printf("%s 4.5W max. Power consumption, ", pfx);
261*1b481fc3SMaciej Żenczykowski 		break;
262*1b481fc3SMaciej Żenczykowski 	case SFF8636_EXT_ID_PWR_CLASS_7:
263*1b481fc3SMaciej Żenczykowski 		printf("%s 5.0W max. Power consumption, ", pfx);
264*1b481fc3SMaciej Żenczykowski 		break;
265*1b481fc3SMaciej Żenczykowski 	}
266*1b481fc3SMaciej Żenczykowski 	if (map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
267*1b481fc3SMaciej Żenczykowski 	    SFF8636_HIGH_PWR_ENABLE)
268*1b481fc3SMaciej Żenczykowski 		printf(" High Power Class (> 3.5 W) enabled\n");
269*1b481fc3SMaciej Żenczykowski 	else
270*1b481fc3SMaciej Żenczykowski 		printf(" High Power Class (> 3.5 W) not enabled\n");
271*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : ", "Power set");
272*1b481fc3SMaciej Żenczykowski 	printf("%s\n", ONOFF(map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
273*1b481fc3SMaciej Żenczykowski 			     SFF8636_LOW_PWR_SET));
274*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : ", "Power override");
275*1b481fc3SMaciej Żenczykowski 	printf("%s\n", ONOFF(map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
276*1b481fc3SMaciej Żenczykowski 			     SFF8636_PWR_OVERRIDE));
277*1b481fc3SMaciej Żenczykowski }
278*1b481fc3SMaciej Żenczykowski 
sff8636_show_connector(const struct sff8636_memory_map * map)279*1b481fc3SMaciej Żenczykowski static void sff8636_show_connector(const struct sff8636_memory_map *map)
280*1b481fc3SMaciej Żenczykowski {
281*1b481fc3SMaciej Żenczykowski 	sff8024_show_connector(map->page_00h, SFF8636_CTOR_OFFSET);
282*1b481fc3SMaciej Żenczykowski }
283*1b481fc3SMaciej Żenczykowski 
sff8636_show_transceiver(const struct sff8636_memory_map * map)284*1b481fc3SMaciej Żenczykowski static void sff8636_show_transceiver(const struct sff8636_memory_map *map)
285*1b481fc3SMaciej Żenczykowski {
286*1b481fc3SMaciej Żenczykowski 	static const char *pfx =
287*1b481fc3SMaciej Żenczykowski 		"\tTransceiver type                          :";
288*1b481fc3SMaciej Żenczykowski 
289*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : 0x%02x 0x%02x 0x%02x " \
290*1b481fc3SMaciej Żenczykowski 			"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
291*1b481fc3SMaciej Żenczykowski 			"Transceiver codes",
292*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_ETHERNET_COMP_OFFSET],
293*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_SONET_COMP_OFFSET],
294*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_SAS_COMP_OFFSET],
295*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_GIGE_COMP_OFFSET],
296*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_FC_LEN_OFFSET],
297*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_FC_TECH_OFFSET],
298*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET],
299*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_FC_SPEED_OFFSET]);
300*1b481fc3SMaciej Żenczykowski 
301*1b481fc3SMaciej Żenczykowski 	/* 10G/40G Ethernet Compliance Codes */
302*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
303*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_10G_LRM)
304*1b481fc3SMaciej Żenczykowski 		printf("%s 10G Ethernet: 10G Base-LRM\n", pfx);
305*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
306*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_10G_LR)
307*1b481fc3SMaciej Żenczykowski 		printf("%s 10G Ethernet: 10G Base-LR\n", pfx);
308*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
309*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_10G_SR)
310*1b481fc3SMaciej Żenczykowski 		printf("%s 10G Ethernet: 10G Base-SR\n", pfx);
311*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
312*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_40G_CR4)
313*1b481fc3SMaciej Żenczykowski 		printf("%s 40G Ethernet: 40G Base-CR4\n", pfx);
314*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
315*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_40G_SR4)
316*1b481fc3SMaciej Żenczykowski 		printf("%s 40G Ethernet: 40G Base-SR4\n", pfx);
317*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
318*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_40G_LR4)
319*1b481fc3SMaciej Żenczykowski 		printf("%s 40G Ethernet: 40G Base-LR4\n", pfx);
320*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
321*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_40G_ACTIVE)
322*1b481fc3SMaciej Żenczykowski 		printf("%s 40G Ethernet: 40G Active Cable (XLPPI)\n", pfx);
323*1b481fc3SMaciej Żenczykowski 	/* Extended Specification Compliance Codes from SFF-8024 */
324*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
325*1b481fc3SMaciej Żenczykowski 	    SFF8636_ETHERNET_RSRVD) {
326*1b481fc3SMaciej Żenczykowski 		switch (map->page_00h[SFF8636_OPTION_1_OFFSET]) {
327*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_UNSPECIFIED:
328*1b481fc3SMaciej Żenczykowski 			printf("%s (reserved or unknown)\n", pfx);
329*1b481fc3SMaciej Żenczykowski 			break;
330*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_AOC:
331*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n",
332*1b481fc3SMaciej Żenczykowski 					pfx);
333*1b481fc3SMaciej Żenczykowski 			break;
334*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_SR4:
335*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G Base-SR4 or 25GBase-SR\n",
336*1b481fc3SMaciej Żenczykowski 					pfx);
337*1b481fc3SMaciej Żenczykowski 			break;
338*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_LR4:
339*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G Base-LR4\n", pfx);
340*1b481fc3SMaciej Żenczykowski 			break;
341*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_ER4:
342*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G Base-ER4\n", pfx);
343*1b481fc3SMaciej Żenczykowski 			break;
344*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_SR10:
345*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G Base-SR10\n", pfx);
346*1b481fc3SMaciej Żenczykowski 			break;
347*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_CWDM4_FEC:
348*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G CWDM4 MSA with FEC\n", pfx);
349*1b481fc3SMaciej Żenczykowski 			break;
350*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_PSM4:
351*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G PSM4 Parallel SMF\n", pfx);
352*1b481fc3SMaciej Żenczykowski 			break;
353*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_ACC:
354*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n",
355*1b481fc3SMaciej Żenczykowski 				pfx);
356*1b481fc3SMaciej Żenczykowski 			break;
357*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_CWDM4_NO_FEC:
358*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G CWDM4 MSA without FEC\n", pfx);
359*1b481fc3SMaciej Żenczykowski 			break;
360*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_RSVD1:
361*1b481fc3SMaciej Żenczykowski 			printf("%s (reserved or unknown)\n", pfx);
362*1b481fc3SMaciej Żenczykowski 			break;
363*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_CR4:
364*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L\n",
365*1b481fc3SMaciej Żenczykowski 				pfx);
366*1b481fc3SMaciej Żenczykowski 			break;
367*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_25G_CR_CA_S:
368*1b481fc3SMaciej Żenczykowski 			printf("%s 25G Ethernet: 25G Base-CR CA-S\n", pfx);
369*1b481fc3SMaciej Żenczykowski 			break;
370*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_25G_CR_CA_N:
371*1b481fc3SMaciej Żenczykowski 			printf("%s 25G Ethernet: 25G Base-CR CA-N\n", pfx);
372*1b481fc3SMaciej Żenczykowski 			break;
373*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_40G_ER4:
374*1b481fc3SMaciej Żenczykowski 			printf("%s 40G Ethernet: 40G Base-ER4\n", pfx);
375*1b481fc3SMaciej Żenczykowski 			break;
376*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_4X10_SR:
377*1b481fc3SMaciej Żenczykowski 			printf("%s 4x10G Ethernet: 10G Base-SR\n", pfx);
378*1b481fc3SMaciej Żenczykowski 			break;
379*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_40G_PSM4:
380*1b481fc3SMaciej Żenczykowski 			printf("%s 40G Ethernet: 40G PSM4 Parallel SMF\n", pfx);
381*1b481fc3SMaciej Żenczykowski 			break;
382*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_G959_P1I1_2D1:
383*1b481fc3SMaciej Żenczykowski 			printf("%s Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)\n",
384*1b481fc3SMaciej Żenczykowski 					pfx);
385*1b481fc3SMaciej Żenczykowski 			break;
386*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_G959_P1S1_2D2:
387*1b481fc3SMaciej Żenczykowski 			printf("%s Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)\n",
388*1b481fc3SMaciej Żenczykowski 					pfx);
389*1b481fc3SMaciej Żenczykowski 			break;
390*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_G959_P1L1_2D2:
391*1b481fc3SMaciej Żenczykowski 			printf("%s Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)\n",
392*1b481fc3SMaciej Żenczykowski 					pfx);
393*1b481fc3SMaciej Żenczykowski 			break;
394*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_10GT_SFI:
395*1b481fc3SMaciej Żenczykowski 			printf("%s 10G Ethernet: 10G Base-T with SFI electrical interface\n",
396*1b481fc3SMaciej Żenczykowski 					pfx);
397*1b481fc3SMaciej Żenczykowski 			break;
398*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_CLR4:
399*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G CLR4\n", pfx);
400*1b481fc3SMaciej Żenczykowski 			break;
401*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_AOC2:
402*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n",
403*1b481fc3SMaciej Żenczykowski 					pfx);
404*1b481fc3SMaciej Żenczykowski 			break;
405*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_ACC2:
406*1b481fc3SMaciej Żenczykowski 			printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n",
407*1b481fc3SMaciej Żenczykowski 					pfx);
408*1b481fc3SMaciej Żenczykowski 			break;
409*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100GE_DWDM2:
410*1b481fc3SMaciej Żenczykowski 			printf("%s 100GE-DWDM2 (DWDM transceiver using 2 wavelengths on a 1550 nm DWDM grid with a reach up to 80 km)\n",
411*1b481fc3SMaciej Żenczykowski 					pfx);
412*1b481fc3SMaciej Żenczykowski 			break;
413*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_1550NM_WDM:
414*1b481fc3SMaciej Żenczykowski 			printf("%s 100G 1550nm WDM (4 wavelengths)\n", pfx);
415*1b481fc3SMaciej Żenczykowski 			break;
416*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_10G_BASET_SR:
417*1b481fc3SMaciej Żenczykowski 			printf("%s 10GBASE-T Short Reach (30 meters)\n", pfx);
418*1b481fc3SMaciej Żenczykowski 			break;
419*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_5G_BASET:
420*1b481fc3SMaciej Żenczykowski 			printf("%s 5GBASE-T\n", pfx);
421*1b481fc3SMaciej Żenczykowski 			break;
422*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_2HALFG_BASET:
423*1b481fc3SMaciej Żenczykowski 			printf("%s 2.5GBASE-T\n", pfx);
424*1b481fc3SMaciej Żenczykowski 			break;
425*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_40G_SWDM4:
426*1b481fc3SMaciej Żenczykowski 			printf("%s 40G SWDM4\n", pfx);
427*1b481fc3SMaciej Żenczykowski 			break;
428*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_SWDM4:
429*1b481fc3SMaciej Żenczykowski 			printf("%s 100G SWDM4\n", pfx);
430*1b481fc3SMaciej Żenczykowski 			break;
431*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_PAM4_BIDI:
432*1b481fc3SMaciej Żenczykowski 			printf("%s 100G PAM4 BiDi\n", pfx);
433*1b481fc3SMaciej Żenczykowski 			break;
434*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_4WDM10_MSA:
435*1b481fc3SMaciej Żenczykowski 			printf("%s 4WDM-10 MSA (10km version of 100G CWDM4 with same RS(528,514) FEC in host system)\n",
436*1b481fc3SMaciej Żenczykowski 					pfx);
437*1b481fc3SMaciej Żenczykowski 			break;
438*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_4WDM20_MSA:
439*1b481fc3SMaciej Żenczykowski 			printf("%s 4WDM-20 MSA (20km version of 100GBASE-LR4 with RS(528,514) FEC in host system)\n",
440*1b481fc3SMaciej Żenczykowski 					pfx);
441*1b481fc3SMaciej Żenczykowski 			break;
442*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_4WDM40_MSA:
443*1b481fc3SMaciej Żenczykowski 			printf("%s 4WDM-40 MSA (40km reach with APD receiver and RS(528,514) FEC in host system)\n",
444*1b481fc3SMaciej Żenczykowski 					pfx);
445*1b481fc3SMaciej Żenczykowski 			break;
446*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_DR:
447*1b481fc3SMaciej Żenczykowski 			printf("%s 100GBASE-DR (clause 140), CAUI-4 (no FEC)\n", pfx);
448*1b481fc3SMaciej Żenczykowski 			break;
449*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_FR_NOFEC:
450*1b481fc3SMaciej Żenczykowski 			 printf("%s 100G-FR or 100GBASE-FR1 (clause 140), CAUI-4 (no FEC)\n", pfx);
451*1b481fc3SMaciej Żenczykowski 			break;
452*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_100G_LR_NOFEC:
453*1b481fc3SMaciej Żenczykowski 			printf("%s 100G-LR or 100GBASE-LR1 (clause 140), CAUI-4 (no FEC)\n", pfx);
454*1b481fc3SMaciej Żenczykowski 			break;
455*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_ACC1:
456*1b481fc3SMaciej Żenczykowski 			printf("%s Active Copper Cable with 50GAUI, 100GAUI-2 or 200GAUI-4 C2M. Providing a worst BER of 10-6 or below\n",
457*1b481fc3SMaciej Żenczykowski 					pfx);
458*1b481fc3SMaciej Żenczykowski 			break;
459*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_AOC1:
460*1b481fc3SMaciej Żenczykowski 			printf("%s Active Optical Cable with 50GAUI, 100GAUI-2 or 200GAUI-4 C2M. Providing a worst BER of 10-6 or below\n",
461*1b481fc3SMaciej Żenczykowski 					pfx);
462*1b481fc3SMaciej Żenczykowski 			break;
463*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_ACC2:
464*1b481fc3SMaciej Żenczykowski 			printf("%s Active Copper Cable with 50GAUI, 100GAUI-2 or 200GAUI-4 C2M. Providing a worst BER of 2.6x10-4 for ACC, 10-5 for AUI, or below\n",
465*1b481fc3SMaciej Żenczykowski 					pfx);
466*1b481fc3SMaciej Żenczykowski 			break;
467*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_A0C2:
468*1b481fc3SMaciej Żenczykowski 			printf("%s Active Optical Cable with 50GAUI, 100GAUI-2 or 200GAUI-4 C2M. Providing a worst BER of 2.6x10-4 for ACC, 10-5 for AUI, or below\n",
469*1b481fc3SMaciej Żenczykowski 					pfx);
470*1b481fc3SMaciej Żenczykowski 			break;
471*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_CR4:
472*1b481fc3SMaciej Żenczykowski 			printf("%s 50GBASE-CR, 100GBASE-CR2, or 200GBASE-CR4\n", pfx);
473*1b481fc3SMaciej Żenczykowski 			break;
474*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_SR4:
475*1b481fc3SMaciej Żenczykowski 			printf("%s 50GBASE-SR, 100GBASE-SR2, or 200GBASE-SR4\n", pfx);
476*1b481fc3SMaciej Żenczykowski 			break;
477*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_DR4:
478*1b481fc3SMaciej Żenczykowski 			printf("%s 50GBASE-FR or 200GBASE-DR4\n", pfx);
479*1b481fc3SMaciej Żenczykowski 			break;
480*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_FR4:
481*1b481fc3SMaciej Żenczykowski 			printf("%s 200GBASE-FR4\n", pfx);
482*1b481fc3SMaciej Żenczykowski 			break;
483*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_PSM4:
484*1b481fc3SMaciej Żenczykowski 			 printf("%s 200G 1550 nm PSM4\n", pfx);
485*1b481fc3SMaciej Żenczykowski 			break;
486*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_50G_LR:
487*1b481fc3SMaciej Żenczykowski 			printf("%s 50GBASE-LR\n", pfx);
488*1b481fc3SMaciej Żenczykowski 			break;
489*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_200G_LR4:
490*1b481fc3SMaciej Żenczykowski 			printf("%s 200GBASE-LR4\n", pfx);
491*1b481fc3SMaciej Żenczykowski 			break;
492*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_64G_EA:
493*1b481fc3SMaciej Żenczykowski 			printf("%s 64GFC EA\n", pfx);
494*1b481fc3SMaciej Żenczykowski 			break;
495*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_64G_SW:
496*1b481fc3SMaciej Żenczykowski 			printf("%s 64GFC SW\n", pfx);
497*1b481fc3SMaciej Żenczykowski 			break;
498*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_64G_LW:
499*1b481fc3SMaciej Żenczykowski 			printf("%s 64GFC LW\n", pfx);
500*1b481fc3SMaciej Żenczykowski 			break;
501*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_128FC_EA:
502*1b481fc3SMaciej Żenczykowski 			printf("%s 128GFC EA\n", pfx);
503*1b481fc3SMaciej Żenczykowski 			break;
504*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_128FC_SW:
505*1b481fc3SMaciej Żenczykowski 			printf("%s 128GFC SW\n", pfx);
506*1b481fc3SMaciej Żenczykowski 			break;
507*1b481fc3SMaciej Żenczykowski 		case SFF8636_ETHERNET_128FC_LW:
508*1b481fc3SMaciej Żenczykowski 			printf("%s 128GFC LW\n", pfx);
509*1b481fc3SMaciej Żenczykowski 			break;
510*1b481fc3SMaciej Żenczykowski 		default:
511*1b481fc3SMaciej Żenczykowski 			printf("%s (reserved or unknown)\n", pfx);
512*1b481fc3SMaciej Żenczykowski 			break;
513*1b481fc3SMaciej Żenczykowski 		}
514*1b481fc3SMaciej Żenczykowski 	}
515*1b481fc3SMaciej Żenczykowski 
516*1b481fc3SMaciej Żenczykowski 	/* SONET Compliance Codes */
517*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_SONET_COMP_OFFSET] &
518*1b481fc3SMaciej Żenczykowski 	    (SFF8636_SONET_40G_OTN))
519*1b481fc3SMaciej Żenczykowski 		printf("%s 40G OTN (OTU3B/OTU3C)\n", pfx);
520*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_LR))
521*1b481fc3SMaciej Żenczykowski 		printf("%s SONET: OC-48, long reach\n", pfx);
522*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_IR))
523*1b481fc3SMaciej Żenczykowski 		printf("%s SONET: OC-48, intermediate reach\n", pfx);
524*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_SR))
525*1b481fc3SMaciej Żenczykowski 		printf("%s SONET: OC-48, short reach\n", pfx);
526*1b481fc3SMaciej Żenczykowski 
527*1b481fc3SMaciej Żenczykowski 	/* SAS/SATA Compliance Codes */
528*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_6G))
529*1b481fc3SMaciej Żenczykowski 		printf("%s SAS 6.0G\n", pfx);
530*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_3G))
531*1b481fc3SMaciej Żenczykowski 		printf("%s SAS 3.0G\n", pfx);
532*1b481fc3SMaciej Żenczykowski 
533*1b481fc3SMaciej Żenczykowski 	/* Ethernet Compliance Codes */
534*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_T)
535*1b481fc3SMaciej Żenczykowski 		printf("%s Ethernet: 1000BASE-T\n", pfx);
536*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_CX)
537*1b481fc3SMaciej Żenczykowski 		printf("%s Ethernet: 1000BASE-CX\n", pfx);
538*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_LX)
539*1b481fc3SMaciej Żenczykowski 		printf("%s Ethernet: 1000BASE-LX\n", pfx);
540*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_SX)
541*1b481fc3SMaciej Żenczykowski 		printf("%s Ethernet: 1000BASE-SX\n", pfx);
542*1b481fc3SMaciej Żenczykowski 
543*1b481fc3SMaciej Żenczykowski 	/* Fibre Channel link length */
544*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_VERY_LONG)
545*1b481fc3SMaciej Żenczykowski 		printf("%s FC: very long distance (V)\n", pfx);
546*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_SHORT)
547*1b481fc3SMaciej Żenczykowski 		printf("%s FC: short distance (S)\n", pfx);
548*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_INT)
549*1b481fc3SMaciej Żenczykowski 		printf("%s FC: intermediate distance (I)\n", pfx);
550*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_LONG)
551*1b481fc3SMaciej Żenczykowski 		printf("%s FC: long distance (L)\n", pfx);
552*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_MED)
553*1b481fc3SMaciej Żenczykowski 		printf("%s FC: medium distance (M)\n", pfx);
554*1b481fc3SMaciej Żenczykowski 
555*1b481fc3SMaciej Żenczykowski 	/* Fibre Channel transmitter technology */
556*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_LONG_LC)
557*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Longwave laser (LC)\n", pfx);
558*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_ELEC_INTER)
559*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Electrical inter-enclosure (EL)\n", pfx);
560*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_ELEC_INTRA)
561*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Electrical intra-enclosure (EL)\n", pfx);
562*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TECH_OFFSET] &
563*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TECH_SHORT_WO_OFC)
564*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx);
565*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_SHORT_W_OFC)
566*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Shortwave laser with OFC (SL)\n", pfx);
567*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_LONG_LL)
568*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Longwave laser (LL)\n", pfx);
569*1b481fc3SMaciej Żenczykowski 
570*1b481fc3SMaciej Żenczykowski 	/* Fibre Channel transmission media */
571*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
572*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_TW)
573*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Twin Axial Pair (TW)\n", pfx);
574*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
575*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_TP)
576*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Twisted Pair (TP)\n", pfx);
577*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
578*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_MI)
579*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Miniature Coax (MI)\n", pfx);
580*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
581*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_TV)
582*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Video Coax (TV)\n", pfx);
583*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
584*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_M6)
585*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Multimode, 62.5m (M6)\n", pfx);
586*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
587*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_M5)
588*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Multimode, 50m (M5)\n", pfx);
589*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
590*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_OM3)
591*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Multimode, 50um (OM3)\n", pfx);
592*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
593*1b481fc3SMaciej Żenczykowski 	    SFF8636_FC_TRANS_MEDIA_SM)
594*1b481fc3SMaciej Żenczykowski 		printf("%s FC: Single Mode (SM)\n", pfx);
595*1b481fc3SMaciej Żenczykowski 
596*1b481fc3SMaciej Żenczykowski 	/* Fibre Channel speed */
597*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1200_MBPS)
598*1b481fc3SMaciej Żenczykowski 		printf("%s FC: 1200 MBytes/sec\n", pfx);
599*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_800_MBPS)
600*1b481fc3SMaciej Żenczykowski 		printf("%s FC: 800 MBytes/sec\n", pfx);
601*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1600_MBPS)
602*1b481fc3SMaciej Żenczykowski 		printf("%s FC: 1600 MBytes/sec\n", pfx);
603*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_400_MBPS)
604*1b481fc3SMaciej Żenczykowski 		printf("%s FC: 400 MBytes/sec\n", pfx);
605*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_200_MBPS)
606*1b481fc3SMaciej Żenczykowski 		printf("%s FC: 200 MBytes/sec\n", pfx);
607*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_100_MBPS)
608*1b481fc3SMaciej Żenczykowski 		printf("%s FC: 100 MBytes/sec\n", pfx);
609*1b481fc3SMaciej Żenczykowski }
610*1b481fc3SMaciej Żenczykowski 
sff8636_show_encoding(const struct sff8636_memory_map * map)611*1b481fc3SMaciej Żenczykowski static void sff8636_show_encoding(const struct sff8636_memory_map *map)
612*1b481fc3SMaciej Żenczykowski {
613*1b481fc3SMaciej Żenczykowski 	sff8024_show_encoding(map->page_00h, SFF8636_ENCODING_OFFSET,
614*1b481fc3SMaciej Żenczykowski 			      ETH_MODULE_SFF_8636);
615*1b481fc3SMaciej Żenczykowski }
616*1b481fc3SMaciej Żenczykowski 
sff8636_show_rate_identifier(const struct sff8636_memory_map * map)617*1b481fc3SMaciej Żenczykowski static void sff8636_show_rate_identifier(const struct sff8636_memory_map *map)
618*1b481fc3SMaciej Żenczykowski {
619*1b481fc3SMaciej Żenczykowski 	/* TODO: Need to fix rate select logic */
620*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : 0x%02x\n", "Rate identifier",
621*1b481fc3SMaciej Żenczykowski 	       map->page_00h[SFF8636_EXT_RS_OFFSET]);
622*1b481fc3SMaciej Żenczykowski }
623*1b481fc3SMaciej Żenczykowski 
624*1b481fc3SMaciej Żenczykowski static void
sff8636_show_wavelength_or_copper_compliance(const struct sff8636_memory_map * map)625*1b481fc3SMaciej Żenczykowski sff8636_show_wavelength_or_copper_compliance(const struct sff8636_memory_map *map)
626*1b481fc3SMaciej Żenczykowski {
627*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : 0x%02x", "Transmitter technology",
628*1b481fc3SMaciej Żenczykowski 	       map->page_00h[SFF8636_DEVICE_TECH_OFFSET] &
629*1b481fc3SMaciej Żenczykowski 	       SFF8636_TRANS_TECH_MASK);
630*1b481fc3SMaciej Żenczykowski 
631*1b481fc3SMaciej Żenczykowski 	switch (map->page_00h[SFF8636_DEVICE_TECH_OFFSET] &
632*1b481fc3SMaciej Żenczykowski 		SFF8636_TRANS_TECH_MASK) {
633*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_850_VCSEL:
634*1b481fc3SMaciej Żenczykowski 		printf(" (850 nm VCSEL)\n");
635*1b481fc3SMaciej Żenczykowski 		break;
636*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1310_VCSEL:
637*1b481fc3SMaciej Żenczykowski 		printf(" (1310 nm VCSEL)\n");
638*1b481fc3SMaciej Żenczykowski 		break;
639*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1550_VCSEL:
640*1b481fc3SMaciej Żenczykowski 		printf(" (1550 nm VCSEL)\n");
641*1b481fc3SMaciej Żenczykowski 		break;
642*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1310_FP:
643*1b481fc3SMaciej Żenczykowski 		printf(" (1310 nm FP)\n");
644*1b481fc3SMaciej Żenczykowski 		break;
645*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1310_DFB:
646*1b481fc3SMaciej Żenczykowski 		printf(" (1310 nm DFB)\n");
647*1b481fc3SMaciej Żenczykowski 		break;
648*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1550_DFB:
649*1b481fc3SMaciej Żenczykowski 		printf(" (1550 nm DFB)\n");
650*1b481fc3SMaciej Żenczykowski 		break;
651*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1310_EML:
652*1b481fc3SMaciej Żenczykowski 		printf(" (1310 nm EML)\n");
653*1b481fc3SMaciej Żenczykowski 		break;
654*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1550_EML:
655*1b481fc3SMaciej Żenczykowski 		printf(" (1550 nm EML)\n");
656*1b481fc3SMaciej Żenczykowski 		break;
657*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_OTHERS:
658*1b481fc3SMaciej Żenczykowski 		printf(" (Others/Undefined)\n");
659*1b481fc3SMaciej Żenczykowski 		break;
660*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_1490_DFB:
661*1b481fc3SMaciej Żenczykowski 		printf(" (1490 nm DFB)\n");
662*1b481fc3SMaciej Żenczykowski 		break;
663*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_COPPER_PAS_UNEQUAL:
664*1b481fc3SMaciej Żenczykowski 		printf(" (Copper cable unequalized)\n");
665*1b481fc3SMaciej Żenczykowski 		break;
666*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_COPPER_PAS_EQUAL:
667*1b481fc3SMaciej Żenczykowski 		printf(" (Copper cable passive equalized)\n");
668*1b481fc3SMaciej Żenczykowski 		break;
669*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_COPPER_LNR_FAR_EQUAL:
670*1b481fc3SMaciej Żenczykowski 		printf(" (Copper cable, near and far end limiting active equalizers)\n");
671*1b481fc3SMaciej Żenczykowski 		break;
672*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_COPPER_FAR_EQUAL:
673*1b481fc3SMaciej Żenczykowski 		printf(" (Copper cable, far end limiting active equalizers)\n");
674*1b481fc3SMaciej Żenczykowski 		break;
675*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_COPPER_NEAR_EQUAL:
676*1b481fc3SMaciej Żenczykowski 		printf(" (Copper cable, near end limiting active equalizers)\n");
677*1b481fc3SMaciej Żenczykowski 		break;
678*1b481fc3SMaciej Żenczykowski 	case SFF8636_TRANS_COPPER_LNR_EQUAL:
679*1b481fc3SMaciej Żenczykowski 		printf(" (Copper cable, linear active equalizers)\n");
680*1b481fc3SMaciej Żenczykowski 		break;
681*1b481fc3SMaciej Żenczykowski 	}
682*1b481fc3SMaciej Żenczykowski 
683*1b481fc3SMaciej Żenczykowski 	if ((map->page_00h[SFF8636_DEVICE_TECH_OFFSET] &
684*1b481fc3SMaciej Żenczykowski 	     SFF8636_TRANS_TECH_MASK) >= SFF8636_TRANS_COPPER_PAS_UNEQUAL) {
685*1b481fc3SMaciej Żenczykowski 		printf("\t%-41s : %udb\n", "Attenuation at 2.5GHz",
686*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_WAVELEN_HIGH_BYTE_OFFSET]);
687*1b481fc3SMaciej Żenczykowski 		printf("\t%-41s : %udb\n", "Attenuation at 5.0GHz",
688*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_WAVELEN_LOW_BYTE_OFFSET]);
689*1b481fc3SMaciej Żenczykowski 		printf("\t%-41s : %udb\n", "Attenuation at 7.0GHz",
690*1b481fc3SMaciej Żenczykowski 			map->page_00h[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET]);
691*1b481fc3SMaciej Żenczykowski 		printf("\t%-41s : %udb\n", "Attenuation at 12.9GHz",
692*1b481fc3SMaciej Żenczykowski 		       map->page_00h[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET]);
693*1b481fc3SMaciej Żenczykowski 	} else {
694*1b481fc3SMaciej Żenczykowski 		printf("\t%-41s : %.3lfnm\n", "Laser wavelength",
695*1b481fc3SMaciej Żenczykowski 		       (((map->page_00h[SFF8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) |
696*1b481fc3SMaciej Żenczykowski 			 map->page_00h[SFF8636_WAVELEN_LOW_BYTE_OFFSET]) * 0.05));
697*1b481fc3SMaciej Żenczykowski 		printf("\t%-41s : %.3lfnm\n", "Laser wavelength tolerance",
698*1b481fc3SMaciej Żenczykowski 		       (((map->page_00h[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) |
699*1b481fc3SMaciej Żenczykowski 			 map->page_00h[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET]) * 0.005));
700*1b481fc3SMaciej Żenczykowski 	}
701*1b481fc3SMaciej Żenczykowski }
702*1b481fc3SMaciej Żenczykowski 
703*1b481fc3SMaciej Żenczykowski /*
704*1b481fc3SMaciej Żenczykowski  * 2-byte internal temperature conversions:
705*1b481fc3SMaciej Żenczykowski  * First byte is a signed 8-bit integer, which is the temp decimal part
706*1b481fc3SMaciej Żenczykowski  * Second byte are 1/256th of degree, which are added to the dec part.
707*1b481fc3SMaciej Żenczykowski  */
708*1b481fc3SMaciej Żenczykowski #define SFF8636_OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
709*1b481fc3SMaciej Żenczykowski 
sff8636_dom_parse(const struct sff8636_memory_map * map,struct sff_diags * sd)710*1b481fc3SMaciej Żenczykowski static void sff8636_dom_parse(const struct sff8636_memory_map *map,
711*1b481fc3SMaciej Żenczykowski 			      struct sff_diags *sd)
712*1b481fc3SMaciej Żenczykowski {
713*1b481fc3SMaciej Żenczykowski 	const __u8 *id = map->lower_memory;
714*1b481fc3SMaciej Żenczykowski 	int i = 0;
715*1b481fc3SMaciej Żenczykowski 
716*1b481fc3SMaciej Żenczykowski 	/* Monitoring Thresholds for Alarms and Warnings */
717*1b481fc3SMaciej Żenczykowski 	sd->sfp_voltage[MCURR] = OFFSET_TO_U16_PTR(id, SFF8636_VCC_CURR);
718*1b481fc3SMaciej Żenczykowski 	sd->sfp_temp[MCURR] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_CURR);
719*1b481fc3SMaciej Żenczykowski 
720*1b481fc3SMaciej Żenczykowski 	if (!map->page_03h)
721*1b481fc3SMaciej Żenczykowski 		goto out;
722*1b481fc3SMaciej Żenczykowski 
723*1b481fc3SMaciej Żenczykowski 	sd->sfp_voltage[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
724*1b481fc3SMaciej Żenczykowski 						   SFF8636_VCC_HALRM);
725*1b481fc3SMaciej Żenczykowski 	sd->sfp_voltage[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
726*1b481fc3SMaciej Żenczykowski 						   SFF8636_VCC_LALRM);
727*1b481fc3SMaciej Żenczykowski 	sd->sfp_voltage[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
728*1b481fc3SMaciej Żenczykowski 						   SFF8636_VCC_HWARN);
729*1b481fc3SMaciej Żenczykowski 	sd->sfp_voltage[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
730*1b481fc3SMaciej Żenczykowski 						   SFF8636_VCC_LWARN);
731*1b481fc3SMaciej Żenczykowski 
732*1b481fc3SMaciej Żenczykowski 	sd->sfp_temp[HALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
733*1b481fc3SMaciej Żenczykowski 						       SFF8636_TEMP_HALRM);
734*1b481fc3SMaciej Żenczykowski 	sd->sfp_temp[LALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
735*1b481fc3SMaciej Żenczykowski 						       SFF8636_TEMP_LALRM);
736*1b481fc3SMaciej Żenczykowski 	sd->sfp_temp[HWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
737*1b481fc3SMaciej Żenczykowski 						       SFF8636_TEMP_HWARN);
738*1b481fc3SMaciej Żenczykowski 	sd->sfp_temp[LWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
739*1b481fc3SMaciej Żenczykowski 						       SFF8636_TEMP_LWARN);
740*1b481fc3SMaciej Żenczykowski 
741*1b481fc3SMaciej Żenczykowski 	sd->bias_cur[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
742*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_BIAS_HALRM);
743*1b481fc3SMaciej Żenczykowski 	sd->bias_cur[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
744*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_BIAS_LALRM);
745*1b481fc3SMaciej Żenczykowski 	sd->bias_cur[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
746*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_BIAS_HWARN);
747*1b481fc3SMaciej Żenczykowski 	sd->bias_cur[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
748*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_BIAS_LWARN);
749*1b481fc3SMaciej Żenczykowski 
750*1b481fc3SMaciej Żenczykowski 	sd->tx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
751*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_PWR_HALRM);
752*1b481fc3SMaciej Żenczykowski 	sd->tx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
753*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_PWR_LALRM);
754*1b481fc3SMaciej Żenczykowski 	sd->tx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
755*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_PWR_HWARN);
756*1b481fc3SMaciej Żenczykowski 	sd->tx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
757*1b481fc3SMaciej Żenczykowski 						SFF8636_TX_PWR_LWARN);
758*1b481fc3SMaciej Żenczykowski 
759*1b481fc3SMaciej Żenczykowski 	sd->rx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
760*1b481fc3SMaciej Żenczykowski 						SFF8636_RX_PWR_HALRM);
761*1b481fc3SMaciej Żenczykowski 	sd->rx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
762*1b481fc3SMaciej Żenczykowski 						SFF8636_RX_PWR_LALRM);
763*1b481fc3SMaciej Żenczykowski 	sd->rx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
764*1b481fc3SMaciej Żenczykowski 						SFF8636_RX_PWR_HWARN);
765*1b481fc3SMaciej Żenczykowski 	sd->rx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
766*1b481fc3SMaciej Żenczykowski 						SFF8636_RX_PWR_LWARN);
767*1b481fc3SMaciej Żenczykowski 
768*1b481fc3SMaciej Żenczykowski out:
769*1b481fc3SMaciej Żenczykowski 	/* Channel Specific Data */
770*1b481fc3SMaciej Żenczykowski 	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
771*1b481fc3SMaciej Żenczykowski 		u8 rx_power_offset, tx_bias_offset;
772*1b481fc3SMaciej Żenczykowski 		u8 tx_power_offset;
773*1b481fc3SMaciej Żenczykowski 
774*1b481fc3SMaciej Żenczykowski 		switch (i) {
775*1b481fc3SMaciej Żenczykowski 		case 0:
776*1b481fc3SMaciej Żenczykowski 			rx_power_offset = SFF8636_RX_PWR_1_OFFSET;
777*1b481fc3SMaciej Żenczykowski 			tx_power_offset = SFF8636_TX_PWR_1_OFFSET;
778*1b481fc3SMaciej Żenczykowski 			tx_bias_offset = SFF8636_TX_BIAS_1_OFFSET;
779*1b481fc3SMaciej Żenczykowski 			break;
780*1b481fc3SMaciej Żenczykowski 		case 1:
781*1b481fc3SMaciej Żenczykowski 			rx_power_offset = SFF8636_RX_PWR_2_OFFSET;
782*1b481fc3SMaciej Żenczykowski 			tx_power_offset = SFF8636_TX_PWR_2_OFFSET;
783*1b481fc3SMaciej Żenczykowski 			tx_bias_offset = SFF8636_TX_BIAS_2_OFFSET;
784*1b481fc3SMaciej Żenczykowski 			break;
785*1b481fc3SMaciej Żenczykowski 		case 2:
786*1b481fc3SMaciej Żenczykowski 			rx_power_offset = SFF8636_RX_PWR_3_OFFSET;
787*1b481fc3SMaciej Żenczykowski 			tx_power_offset = SFF8636_TX_PWR_3_OFFSET;
788*1b481fc3SMaciej Żenczykowski 			tx_bias_offset = SFF8636_TX_BIAS_3_OFFSET;
789*1b481fc3SMaciej Żenczykowski 			break;
790*1b481fc3SMaciej Żenczykowski 		case 3:
791*1b481fc3SMaciej Żenczykowski 			rx_power_offset = SFF8636_RX_PWR_4_OFFSET;
792*1b481fc3SMaciej Żenczykowski 			tx_power_offset = SFF8636_TX_PWR_4_OFFSET;
793*1b481fc3SMaciej Żenczykowski 			tx_bias_offset = SFF8636_TX_BIAS_4_OFFSET;
794*1b481fc3SMaciej Żenczykowski 			break;
795*1b481fc3SMaciej Żenczykowski 		}
796*1b481fc3SMaciej Żenczykowski 		sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset);
797*1b481fc3SMaciej Żenczykowski 		sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset);
798*1b481fc3SMaciej Żenczykowski 		sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset);
799*1b481fc3SMaciej Żenczykowski 	}
800*1b481fc3SMaciej Żenczykowski }
801*1b481fc3SMaciej Żenczykowski 
sff8636_show_dom(const struct sff8636_memory_map * map)802*1b481fc3SMaciej Żenczykowski static void sff8636_show_dom(const struct sff8636_memory_map *map)
803*1b481fc3SMaciej Żenczykowski {
804*1b481fc3SMaciej Żenczykowski 	struct sff_diags sd = {0};
805*1b481fc3SMaciej Żenczykowski 	char *rx_power_string = NULL;
806*1b481fc3SMaciej Żenczykowski 	char power_string[MAX_DESC_SIZE];
807*1b481fc3SMaciej Żenczykowski 	int i;
808*1b481fc3SMaciej Żenczykowski 
809*1b481fc3SMaciej Żenczykowski 	/*
810*1b481fc3SMaciej Żenczykowski 	 * There is no clear identifier to signify the existence of
811*1b481fc3SMaciej Żenczykowski 	 * optical diagnostics similar to SFF-8472. So checking existence
812*1b481fc3SMaciej Żenczykowski 	 * of page 3, will provide the gurantee for existence of alarms
813*1b481fc3SMaciej Żenczykowski 	 * and thresholds
814*1b481fc3SMaciej Żenczykowski 	 * If pagging support exists, then supports_alarms is marked as 1
815*1b481fc3SMaciej Żenczykowski 	 */
816*1b481fc3SMaciej Żenczykowski 	if (map->page_03h)
817*1b481fc3SMaciej Żenczykowski 		sd.supports_alarms = 1;
818*1b481fc3SMaciej Żenczykowski 
819*1b481fc3SMaciej Żenczykowski 	sd.rx_power_type = map->page_00h[SFF8636_DIAG_TYPE_OFFSET] &
820*1b481fc3SMaciej Żenczykowski 			   SFF8636_RX_PWR_TYPE_MASK;
821*1b481fc3SMaciej Żenczykowski 	sd.tx_power_type = map->page_00h[SFF8636_DIAG_TYPE_OFFSET] &
822*1b481fc3SMaciej Żenczykowski 			   SFF8636_RX_PWR_TYPE_MASK;
823*1b481fc3SMaciej Żenczykowski 
824*1b481fc3SMaciej Żenczykowski 	sff8636_dom_parse(map, &sd);
825*1b481fc3SMaciej Żenczykowski 
826*1b481fc3SMaciej Żenczykowski 	PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]);
827*1b481fc3SMaciej Żenczykowski 	PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]);
828*1b481fc3SMaciej Żenczykowski 
829*1b481fc3SMaciej Żenczykowski 	/*
830*1b481fc3SMaciej Żenczykowski 	 * SFF-8636/8436 spec is not clear whether RX power/ TX bias
831*1b481fc3SMaciej Żenczykowski 	 * current fields are supported or not. A valid temperature
832*1b481fc3SMaciej Żenczykowski 	 * reading is used as existence for TX/RX power.
833*1b481fc3SMaciej Żenczykowski 	 */
834*1b481fc3SMaciej Żenczykowski 	if ((sd.sfp_temp[MCURR] == 0x0) ||
835*1b481fc3SMaciej Żenczykowski 	    (sd.sfp_temp[MCURR] == (__s16)0xFFFF))
836*1b481fc3SMaciej Żenczykowski 		return;
837*1b481fc3SMaciej Żenczykowski 
838*1b481fc3SMaciej Żenczykowski 	printf("\t%-41s : %s\n", "Alarm/warning flags implemented",
839*1b481fc3SMaciej Żenczykowski 		(sd.supports_alarms ? "Yes" : "No"));
840*1b481fc3SMaciej Żenczykowski 
841*1b481fc3SMaciej Żenczykowski 	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
842*1b481fc3SMaciej Żenczykowski 		snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
843*1b481fc3SMaciej Żenczykowski 					"Laser tx bias current", i+1);
844*1b481fc3SMaciej Żenczykowski 		PRINT_BIAS(power_string, sd.scd[i].bias_cur);
845*1b481fc3SMaciej Żenczykowski 	}
846*1b481fc3SMaciej Żenczykowski 
847*1b481fc3SMaciej Żenczykowski 	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
848*1b481fc3SMaciej Żenczykowski 		snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
849*1b481fc3SMaciej Żenczykowski 					"Transmit avg optical power", i+1);
850*1b481fc3SMaciej Żenczykowski 		PRINT_xX_PWR(power_string, sd.scd[i].tx_power);
851*1b481fc3SMaciej Żenczykowski 	}
852*1b481fc3SMaciej Żenczykowski 
853*1b481fc3SMaciej Żenczykowski 	if (!sd.rx_power_type)
854*1b481fc3SMaciej Żenczykowski 		rx_power_string = "Receiver signal OMA";
855*1b481fc3SMaciej Żenczykowski 	else
856*1b481fc3SMaciej Żenczykowski 		rx_power_string = "Rcvr signal avg optical power";
857*1b481fc3SMaciej Żenczykowski 
858*1b481fc3SMaciej Żenczykowski 	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
859*1b481fc3SMaciej Żenczykowski 		snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)",
860*1b481fc3SMaciej Żenczykowski 					rx_power_string, i+1);
861*1b481fc3SMaciej Żenczykowski 		PRINT_xX_PWR(power_string, sd.scd[i].rx_power);
862*1b481fc3SMaciej Żenczykowski 	}
863*1b481fc3SMaciej Żenczykowski 
864*1b481fc3SMaciej Żenczykowski 	if (sd.supports_alarms) {
865*1b481fc3SMaciej Żenczykowski 		for (i = 0; sff8636_aw_flags[i].str; ++i) {
866*1b481fc3SMaciej Żenczykowski 			printf("\t%-41s : %s\n", sff8636_aw_flags[i].str,
867*1b481fc3SMaciej Żenczykowski 			       map->lower_memory[sff8636_aw_flags[i].offset]
868*1b481fc3SMaciej Żenczykowski 			       & sff8636_aw_flags[i].value ? "On" : "Off");
869*1b481fc3SMaciej Żenczykowski 		}
870*1b481fc3SMaciej Żenczykowski 
871*1b481fc3SMaciej Żenczykowski 		sff_show_thresholds(sd);
872*1b481fc3SMaciej Żenczykowski 	}
873*1b481fc3SMaciej Żenczykowski }
874*1b481fc3SMaciej Żenczykowski 
sff8636_show_signals(const struct sff8636_memory_map * map)875*1b481fc3SMaciej Żenczykowski static void sff8636_show_signals(const struct sff8636_memory_map *map)
876*1b481fc3SMaciej Żenczykowski {
877*1b481fc3SMaciej Żenczykowski 	unsigned int v;
878*1b481fc3SMaciej Żenczykowski 
879*1b481fc3SMaciej Żenczykowski 	/* There appears to be no Rx LOS support bit, use Tx for both */
880*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_OPTION_4_OFFSET] & SFF8636_O4_TX_LOS) {
881*1b481fc3SMaciej Żenczykowski 		v = map->lower_memory[SFF8636_LOS_AW_OFFSET] & 0xf;
882*1b481fc3SMaciej Żenczykowski 		sff_show_lane_status("Rx loss of signal", 4, "Yes", "No", v);
883*1b481fc3SMaciej Żenczykowski 		v = map->lower_memory[SFF8636_LOS_AW_OFFSET] >> 4;
884*1b481fc3SMaciej Żenczykowski 		sff_show_lane_status("Tx loss of signal", 4, "Yes", "No", v);
885*1b481fc3SMaciej Żenczykowski 	}
886*1b481fc3SMaciej Żenczykowski 
887*1b481fc3SMaciej Żenczykowski 	v = map->lower_memory[SFF8636_LOL_AW_OFFSET] & 0xf;
888*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_OPTION_3_OFFSET] & SFF8636_O3_RX_LOL)
889*1b481fc3SMaciej Żenczykowski 		sff_show_lane_status("Rx loss of lock", 4, "Yes", "No", v);
890*1b481fc3SMaciej Żenczykowski 
891*1b481fc3SMaciej Żenczykowski 	v = map->lower_memory[SFF8636_LOL_AW_OFFSET] >> 4;
892*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_OPTION_3_OFFSET] & SFF8636_O3_TX_LOL)
893*1b481fc3SMaciej Żenczykowski 		sff_show_lane_status("Tx loss of lock", 4, "Yes", "No", v);
894*1b481fc3SMaciej Żenczykowski 
895*1b481fc3SMaciej Żenczykowski 	v = map->lower_memory[SFF8636_FAULT_AW_OFFSET] & 0xf;
896*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_OPTION_4_OFFSET] & SFF8636_O4_TX_FAULT)
897*1b481fc3SMaciej Żenczykowski 		sff_show_lane_status("Tx fault", 4, "Yes", "No", v);
898*1b481fc3SMaciej Żenczykowski 
899*1b481fc3SMaciej Żenczykowski 	v = map->lower_memory[SFF8636_FAULT_AW_OFFSET] >> 4;
900*1b481fc3SMaciej Żenczykowski 	if (map->page_00h[SFF8636_OPTION_2_OFFSET] & SFF8636_O2_TX_EQ_AUTO)
901*1b481fc3SMaciej Żenczykowski 		sff_show_lane_status("Tx adaptive eq fault", 4, "Yes", "No", v);
902*1b481fc3SMaciej Żenczykowski }
903*1b481fc3SMaciej Żenczykowski 
sff8636_show_page_zero(const struct sff8636_memory_map * map)904*1b481fc3SMaciej Żenczykowski static void sff8636_show_page_zero(const struct sff8636_memory_map *map)
905*1b481fc3SMaciej Żenczykowski {
906*1b481fc3SMaciej Żenczykowski 	sff8636_show_ext_identifier(map);
907*1b481fc3SMaciej Żenczykowski 	sff8636_show_connector(map);
908*1b481fc3SMaciej Żenczykowski 	sff8636_show_transceiver(map);
909*1b481fc3SMaciej Żenczykowski 	sff8636_show_encoding(map);
910*1b481fc3SMaciej Żenczykowski 	sff_show_value_with_unit(map->page_00h, SFF8636_BR_NOMINAL_OFFSET,
911*1b481fc3SMaciej Żenczykowski 				 "BR, Nominal", 100, "Mbps");
912*1b481fc3SMaciej Żenczykowski 	sff8636_show_rate_identifier(map);
913*1b481fc3SMaciej Żenczykowski 	sff_show_value_with_unit(map->page_00h, SFF8636_SM_LEN_OFFSET,
914*1b481fc3SMaciej Żenczykowski 				 "Length (SMF,km)", 1, "km");
915*1b481fc3SMaciej Żenczykowski 	sff_show_value_with_unit(map->page_00h, SFF8636_OM3_LEN_OFFSET,
916*1b481fc3SMaciej Żenczykowski 				 "Length (OM3 50um)", 2, "m");
917*1b481fc3SMaciej Żenczykowski 	sff_show_value_with_unit(map->page_00h, SFF8636_OM2_LEN_OFFSET,
918*1b481fc3SMaciej Żenczykowski 				 "Length (OM2 50um)", 1, "m");
919*1b481fc3SMaciej Żenczykowski 	sff_show_value_with_unit(map->page_00h, SFF8636_OM1_LEN_OFFSET,
920*1b481fc3SMaciej Żenczykowski 				 "Length (OM1 62.5um)", 1, "m");
921*1b481fc3SMaciej Żenczykowski 	sff_show_value_with_unit(map->page_00h, SFF8636_CBL_LEN_OFFSET,
922*1b481fc3SMaciej Żenczykowski 				 "Length (Copper or Active cable)", 1, "m");
923*1b481fc3SMaciej Żenczykowski 	sff8636_show_wavelength_or_copper_compliance(map);
924*1b481fc3SMaciej Żenczykowski 	sff_show_ascii(map->page_00h, SFF8636_VENDOR_NAME_START_OFFSET,
925*1b481fc3SMaciej Żenczykowski 		       SFF8636_VENDOR_NAME_END_OFFSET, "Vendor name");
926*1b481fc3SMaciej Żenczykowski 	sff8024_show_oui(map->page_00h, SFF8636_VENDOR_OUI_OFFSET);
927*1b481fc3SMaciej Żenczykowski 	sff_show_ascii(map->page_00h, SFF8636_VENDOR_PN_START_OFFSET,
928*1b481fc3SMaciej Żenczykowski 		       SFF8636_VENDOR_PN_END_OFFSET, "Vendor PN");
929*1b481fc3SMaciej Żenczykowski 	sff_show_ascii(map->page_00h, SFF8636_VENDOR_REV_START_OFFSET,
930*1b481fc3SMaciej Żenczykowski 		       SFF8636_VENDOR_REV_END_OFFSET, "Vendor rev");
931*1b481fc3SMaciej Żenczykowski 	sff_show_ascii(map->page_00h, SFF8636_VENDOR_SN_START_OFFSET,
932*1b481fc3SMaciej Żenczykowski 		       SFF8636_VENDOR_SN_END_OFFSET, "Vendor SN");
933*1b481fc3SMaciej Żenczykowski 	sff_show_ascii(map->page_00h, SFF8636_DATE_YEAR_OFFSET,
934*1b481fc3SMaciej Żenczykowski 		       SFF8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
935*1b481fc3SMaciej Żenczykowski 	sff_show_revision_compliance(map->lower_memory,
936*1b481fc3SMaciej Żenczykowski 				     SFF8636_REV_COMPLIANCE_OFFSET);
937*1b481fc3SMaciej Żenczykowski 	sff8636_show_signals(map);
938*1b481fc3SMaciej Żenczykowski }
939*1b481fc3SMaciej Żenczykowski 
sff8636_show_all_common(const struct sff8636_memory_map * map)940*1b481fc3SMaciej Żenczykowski static void sff8636_show_all_common(const struct sff8636_memory_map *map)
941*1b481fc3SMaciej Żenczykowski {
942*1b481fc3SMaciej Żenczykowski 	sff8636_show_identifier(map);
943*1b481fc3SMaciej Żenczykowski 	switch (map->lower_memory[SFF8636_ID_OFFSET]) {
944*1b481fc3SMaciej Żenczykowski 	case SFF8024_ID_QSFP:
945*1b481fc3SMaciej Żenczykowski 	case SFF8024_ID_QSFP_PLUS:
946*1b481fc3SMaciej Żenczykowski 	case SFF8024_ID_QSFP28:
947*1b481fc3SMaciej Żenczykowski 		sff8636_show_page_zero(map);
948*1b481fc3SMaciej Żenczykowski 		sff8636_show_dom(map);
949*1b481fc3SMaciej Żenczykowski 		break;
950*1b481fc3SMaciej Żenczykowski 	}
951*1b481fc3SMaciej Żenczykowski }
952*1b481fc3SMaciej Żenczykowski 
sff8636_memory_map_init_buf(struct sff8636_memory_map * map,const __u8 * id,__u32 eeprom_len)953*1b481fc3SMaciej Żenczykowski static void sff8636_memory_map_init_buf(struct sff8636_memory_map *map,
954*1b481fc3SMaciej Żenczykowski 					const __u8 *id, __u32 eeprom_len)
955*1b481fc3SMaciej Żenczykowski {
956*1b481fc3SMaciej Żenczykowski 	/* Lower Memory and Page 00h are always present.
957*1b481fc3SMaciej Żenczykowski 	 *
958*1b481fc3SMaciej Żenczykowski 	 * Offset into Upper Memory is between page size and twice the page
959*1b481fc3SMaciej Żenczykowski 	 * size. Therefore, set the base address of each page to base address
960*1b481fc3SMaciej Żenczykowski 	 * plus page size multiplied by the page number.
961*1b481fc3SMaciej Żenczykowski 	 */
962*1b481fc3SMaciej Żenczykowski 	map->lower_memory = id;
963*1b481fc3SMaciej Żenczykowski 	map->page_00h = id;
964*1b481fc3SMaciej Żenczykowski 
965*1b481fc3SMaciej Żenczykowski 	/* Page 03h is only present when the module memory model is paged and
966*1b481fc3SMaciej Żenczykowski 	 * not flat and when we got a big enough buffer from the kernel.
967*1b481fc3SMaciej Żenczykowski 	 */
968*1b481fc3SMaciej Żenczykowski 	if (map->lower_memory[SFF8636_STATUS_2_OFFSET] &
969*1b481fc3SMaciej Żenczykowski 	    SFF8636_STATUS_PAGE_3_PRESENT ||
970*1b481fc3SMaciej Żenczykowski 	    eeprom_len != ETH_MODULE_SFF_8636_MAX_LEN)
971*1b481fc3SMaciej Żenczykowski 		return;
972*1b481fc3SMaciej Żenczykowski 
973*1b481fc3SMaciej Żenczykowski 	map->page_03h = id + 3 * SFF8636_PAGE_SIZE;
974*1b481fc3SMaciej Żenczykowski }
975*1b481fc3SMaciej Żenczykowski 
sff8636_show_all_ioctl(const __u8 * id,__u32 eeprom_len)976*1b481fc3SMaciej Żenczykowski void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
977*1b481fc3SMaciej Żenczykowski {
978*1b481fc3SMaciej Żenczykowski 	struct sff8636_memory_map map = {};
979*1b481fc3SMaciej Żenczykowski 
980*1b481fc3SMaciej Żenczykowski 	if (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_DD ||
981*1b481fc3SMaciej Żenczykowski 	    id[SFF8636_ID_OFFSET] == SFF8024_ID_OSFP ||
982*1b481fc3SMaciej Żenczykowski 	    id[SFF8636_ID_OFFSET] == SFF8024_ID_DSFP) {
983*1b481fc3SMaciej Żenczykowski 		cmis_show_all_ioctl(id);
984*1b481fc3SMaciej Żenczykowski 		return;
985*1b481fc3SMaciej Żenczykowski 	}
986*1b481fc3SMaciej Żenczykowski 
987*1b481fc3SMaciej Żenczykowski 	sff8636_memory_map_init_buf(&map, id, eeprom_len);
988*1b481fc3SMaciej Żenczykowski 	sff8636_show_all_common(&map);
989*1b481fc3SMaciej Żenczykowski }
990*1b481fc3SMaciej Żenczykowski 
sff8636_request_init(struct ethtool_module_eeprom * request,u8 page,u32 offset)991*1b481fc3SMaciej Żenczykowski static void sff8636_request_init(struct ethtool_module_eeprom *request, u8 page,
992*1b481fc3SMaciej Żenczykowski 				 u32 offset)
993*1b481fc3SMaciej Żenczykowski {
994*1b481fc3SMaciej Żenczykowski 	request->offset = offset;
995*1b481fc3SMaciej Żenczykowski 	request->length = SFF8636_PAGE_SIZE;
996*1b481fc3SMaciej Żenczykowski 	request->page = page;
997*1b481fc3SMaciej Żenczykowski 	request->bank = 0;
998*1b481fc3SMaciej Żenczykowski 	request->i2c_address = SFF8636_I2C_ADDRESS;
999*1b481fc3SMaciej Żenczykowski 	request->data = NULL;
1000*1b481fc3SMaciej Żenczykowski }
1001*1b481fc3SMaciej Żenczykowski 
1002*1b481fc3SMaciej Żenczykowski static int
sff8636_memory_map_init_pages(struct cmd_context * ctx,struct sff8636_memory_map * map)1003*1b481fc3SMaciej Żenczykowski sff8636_memory_map_init_pages(struct cmd_context *ctx,
1004*1b481fc3SMaciej Żenczykowski 			      struct sff8636_memory_map *map)
1005*1b481fc3SMaciej Żenczykowski {
1006*1b481fc3SMaciej Żenczykowski 	struct ethtool_module_eeprom request;
1007*1b481fc3SMaciej Żenczykowski 	int ret;
1008*1b481fc3SMaciej Żenczykowski 
1009*1b481fc3SMaciej Żenczykowski 	/* Lower Memory and Page 00h are always present.
1010*1b481fc3SMaciej Żenczykowski 	 *
1011*1b481fc3SMaciej Żenczykowski 	 * Offset into Upper Memory is between page size and twice the page
1012*1b481fc3SMaciej Żenczykowski 	 * size. Therefore, set the base address of each page to its base
1013*1b481fc3SMaciej Żenczykowski 	 * address minus page size.
1014*1b481fc3SMaciej Żenczykowski 	 */
1015*1b481fc3SMaciej Żenczykowski 	sff8636_request_init(&request, 0x0, 0);
1016*1b481fc3SMaciej Żenczykowski 	ret = nl_get_eeprom_page(ctx, &request);
1017*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
1018*1b481fc3SMaciej Żenczykowski 		return ret;
1019*1b481fc3SMaciej Żenczykowski 	map->lower_memory = request.data;
1020*1b481fc3SMaciej Żenczykowski 
1021*1b481fc3SMaciej Żenczykowski 	sff8636_request_init(&request, 0x0, SFF8636_PAGE_SIZE);
1022*1b481fc3SMaciej Żenczykowski 	ret = nl_get_eeprom_page(ctx, &request);
1023*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
1024*1b481fc3SMaciej Żenczykowski 		return ret;
1025*1b481fc3SMaciej Żenczykowski 	map->page_00h = request.data - SFF8636_PAGE_SIZE;
1026*1b481fc3SMaciej Żenczykowski 
1027*1b481fc3SMaciej Żenczykowski 	/* Page 03h is only present when the module memory model is paged and
1028*1b481fc3SMaciej Żenczykowski 	 * not flat.
1029*1b481fc3SMaciej Żenczykowski 	 */
1030*1b481fc3SMaciej Żenczykowski 	if (map->lower_memory[SFF8636_STATUS_2_OFFSET] &
1031*1b481fc3SMaciej Żenczykowski 	    SFF8636_STATUS_PAGE_3_PRESENT)
1032*1b481fc3SMaciej Żenczykowski 		return 0;
1033*1b481fc3SMaciej Żenczykowski 
1034*1b481fc3SMaciej Żenczykowski 	sff8636_request_init(&request, 0x3, SFF8636_PAGE_SIZE);
1035*1b481fc3SMaciej Żenczykowski 	ret = nl_get_eeprom_page(ctx, &request);
1036*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
1037*1b481fc3SMaciej Żenczykowski 		return ret;
1038*1b481fc3SMaciej Żenczykowski 	map->page_03h = request.data - SFF8636_PAGE_SIZE;
1039*1b481fc3SMaciej Żenczykowski 
1040*1b481fc3SMaciej Żenczykowski 	return 0;
1041*1b481fc3SMaciej Żenczykowski }
1042*1b481fc3SMaciej Żenczykowski 
sff8636_show_all_nl(struct cmd_context * ctx)1043*1b481fc3SMaciej Żenczykowski int sff8636_show_all_nl(struct cmd_context *ctx)
1044*1b481fc3SMaciej Żenczykowski {
1045*1b481fc3SMaciej Żenczykowski 	struct sff8636_memory_map map = {};
1046*1b481fc3SMaciej Żenczykowski 	int ret;
1047*1b481fc3SMaciej Żenczykowski 
1048*1b481fc3SMaciej Żenczykowski 	ret = sff8636_memory_map_init_pages(ctx, &map);
1049*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
1050*1b481fc3SMaciej Żenczykowski 		return ret;
1051*1b481fc3SMaciej Żenczykowski 	sff8636_show_all_common(&map);
1052*1b481fc3SMaciej Żenczykowski 
1053*1b481fc3SMaciej Żenczykowski 	return 0;
1054*1b481fc3SMaciej Żenczykowski }
1055