145d3dd98SRobert Mustacchi /*
245d3dd98SRobert Mustacchi  * This file and its contents are supplied under the terms of the
345d3dd98SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
445d3dd98SRobert Mustacchi  * You may only use this file in accordance with the terms of version
545d3dd98SRobert Mustacchi  * 1.0 of the CDDL.
645d3dd98SRobert Mustacchi  *
745d3dd98SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
845d3dd98SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
945d3dd98SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
1045d3dd98SRobert Mustacchi  */
1145d3dd98SRobert Mustacchi 
1245d3dd98SRobert Mustacchi /*
1345d3dd98SRobert Mustacchi  * Copyright (c) 2017, Joyent, Inc.
1445d3dd98SRobert Mustacchi  */
1545d3dd98SRobert Mustacchi 
1645d3dd98SRobert Mustacchi /*
1745d3dd98SRobert Mustacchi  * Print and tests SFF Wavelength values. Note that in both SFF 8472 and SFF
1845d3dd98SRobert Mustacchi  * 8636 the wavelength values also double for various copper complaince values.
1945d3dd98SRobert Mustacchi  * We check both forms here. Note that the copper compliance in SFF 8472 is
2045d3dd98SRobert Mustacchi  * currently tested in libsff_compliance.c. SFF 8636's Copper Attenuation values
2145d3dd98SRobert Mustacchi  * are tested here.
2245d3dd98SRobert Mustacchi  */
2345d3dd98SRobert Mustacchi 
2445d3dd98SRobert Mustacchi #include <stdio.h>
2545d3dd98SRobert Mustacchi #include <errno.h>
2645d3dd98SRobert Mustacchi #include <strings.h>
2745d3dd98SRobert Mustacchi #include <err.h>
2845d3dd98SRobert Mustacchi #include <libsff.h>
2945d3dd98SRobert Mustacchi 
3045d3dd98SRobert Mustacchi /*
3145d3dd98SRobert Mustacchi  * Pick up private sff header file with offsets from lib/libsff.
3245d3dd98SRobert Mustacchi  */
3345d3dd98SRobert Mustacchi #include "sff.h"
3445d3dd98SRobert Mustacchi 
3545d3dd98SRobert Mustacchi int
main(void)3645d3dd98SRobert Mustacchi main(void)
3745d3dd98SRobert Mustacchi {
3845d3dd98SRobert Mustacchi 	int ret, i;
3945d3dd98SRobert Mustacchi 	uint8_t buf[256];
4045d3dd98SRobert Mustacchi 	nvlist_t *nvl;
4145d3dd98SRobert Mustacchi 	char *val;
4245d3dd98SRobert Mustacchi 	char *attenuate[] = { LIBSFF_KEY_ATTENUATE_2G, LIBSFF_KEY_ATTENUATE_5G,
4345d3dd98SRobert Mustacchi 	    LIBSFF_KEY_ATTENUATE_7G, LIBSFF_KEY_ATTENUATE_12G, NULL };
4445d3dd98SRobert Mustacchi 	char *wave[] = { LIBSFF_KEY_WAVELENGTH, LIBSFF_KEY_WAVE_TOLERANCE,
4545d3dd98SRobert Mustacchi 	    NULL };
4645d3dd98SRobert Mustacchi 
4745d3dd98SRobert Mustacchi 	bzero(buf, sizeof (buf));
4845d3dd98SRobert Mustacchi 	buf[SFF_8472_WAVELENGTH_HI] = 0x12;
4945d3dd98SRobert Mustacchi 	buf[SFF_8472_WAVELENGTH_LOW] = 0x34;
5045d3dd98SRobert Mustacchi 
5145d3dd98SRobert Mustacchi 	if ((ret = libsff_parse(buf, sizeof (buf), 0xa0, &nvl)) != 0) {
52*8d195583SRobert Mustacchi 		errc(1, ret, "TEST FAILED: failed to parse SFP wavelength "
53*8d195583SRobert Mustacchi 		    "values");
5445d3dd98SRobert Mustacchi 	}
5545d3dd98SRobert Mustacchi 
5645d3dd98SRobert Mustacchi 	if ((ret = nvlist_lookup_string(nvl, LIBSFF_KEY_WAVELENGTH, &val)) !=
5745d3dd98SRobert Mustacchi 	    0) {
58*8d195583SRobert Mustacchi 		errc(1, ret, "TEST FAILED: failed to find %s",
59*8d195583SRobert Mustacchi 		    LIBSFF_KEY_WAVELENGTH);
6045d3dd98SRobert Mustacchi 	}
6145d3dd98SRobert Mustacchi 	(void) printf("%s: %s\n", LIBSFF_KEY_WAVELENGTH, val);
6245d3dd98SRobert Mustacchi 	nvlist_free(nvl);
6345d3dd98SRobert Mustacchi 
6445d3dd98SRobert Mustacchi 	/*
6545d3dd98SRobert Mustacchi 	 * Make sure wavelength is missing if we specify a copper compliance.
6645d3dd98SRobert Mustacchi 	 */
6745d3dd98SRobert Mustacchi 	bzero(buf, sizeof (buf));
6845d3dd98SRobert Mustacchi 	buf[SFF_8472_COMPLIANCE_SFP] = 0x08;
6945d3dd98SRobert Mustacchi 	buf[SFF_8472_WAVELENGTH_HI] = 0x12;
7045d3dd98SRobert Mustacchi 	buf[SFF_8472_WAVELENGTH_LOW] = 0x34;
7145d3dd98SRobert Mustacchi 
7245d3dd98SRobert Mustacchi 	if ((ret = libsff_parse(buf, sizeof (buf), 0xa0, &nvl)) != 0) {
73*8d195583SRobert Mustacchi 		errc(1, ret, "TEST FAILED: failed to parse SFP wavelength "
74*8d195583SRobert Mustacchi 		    "values");
7545d3dd98SRobert Mustacchi 	}
7645d3dd98SRobert Mustacchi 
7745d3dd98SRobert Mustacchi 	if ((ret = nvlist_lookup_string(nvl, LIBSFF_KEY_WAVELENGTH, &val)) !=
7845d3dd98SRobert Mustacchi 	    ENOENT) {
7945d3dd98SRobert Mustacchi 		errx(1, "TEST FALIED: found unexpected return value for key "
80*8d195583SRobert Mustacchi 		    "%s: %d", LIBSFF_KEY_WAVELENGTH, ret);
8145d3dd98SRobert Mustacchi 	}
8245d3dd98SRobert Mustacchi 
8345d3dd98SRobert Mustacchi 	nvlist_free(nvl);
8445d3dd98SRobert Mustacchi 
8545d3dd98SRobert Mustacchi 	bzero(buf, sizeof (buf));
8645d3dd98SRobert Mustacchi 	buf[SFF_8472_COMPLIANCE_SFP] = 0x04;
8745d3dd98SRobert Mustacchi 	buf[SFF_8472_WAVELENGTH_HI] = 0x12;
8845d3dd98SRobert Mustacchi 	buf[SFF_8472_WAVELENGTH_LOW] = 0x34;
8945d3dd98SRobert Mustacchi 
9045d3dd98SRobert Mustacchi 	if ((ret = libsff_parse(buf, sizeof (buf), 0xa0, &nvl)) != 0) {
91*8d195583SRobert Mustacchi 		errc(1, ret, "TEST FAILED: failed to parse SFP wavelength "
92*8d195583SRobert Mustacchi 		    "values");
9345d3dd98SRobert Mustacchi 	}
9445d3dd98SRobert Mustacchi 
9545d3dd98SRobert Mustacchi 	if ((ret = nvlist_lookup_string(nvl, LIBSFF_KEY_WAVELENGTH, &val)) !=
9645d3dd98SRobert Mustacchi 	    ENOENT) {
9745d3dd98SRobert Mustacchi 		errx(1, "TEST FALIED: found unexpected return value for key "
98*8d195583SRobert Mustacchi 		    "%s: %d", LIBSFF_KEY_WAVELENGTH, ret);
9945d3dd98SRobert Mustacchi 	}
10045d3dd98SRobert Mustacchi 
10145d3dd98SRobert Mustacchi 	nvlist_free(nvl);
10245d3dd98SRobert Mustacchi 
10345d3dd98SRobert Mustacchi 	/*
10445d3dd98SRobert Mustacchi 	 * Now for QSFP+
10545d3dd98SRobert Mustacchi 	 */
10645d3dd98SRobert Mustacchi 	(void) puts("\n\nQSFP\n");
10745d3dd98SRobert Mustacchi 
10845d3dd98SRobert Mustacchi 	/* First copper */
10945d3dd98SRobert Mustacchi 	bzero(buf, sizeof (buf));
11045d3dd98SRobert Mustacchi 	buf[SFF_8472_IDENTIFIER] = SFF_8024_ID_QSFP;
11145d3dd98SRobert Mustacchi 	buf[SFF_8636_DEVICE_TECH] = 0xa0;
11245d3dd98SRobert Mustacchi 
11345d3dd98SRobert Mustacchi 	buf[SFF_8636_ATTENUATE_2G] = 0x42;
11445d3dd98SRobert Mustacchi 	buf[SFF_8636_ATTENUATE_5G] = 0x43;
11545d3dd98SRobert Mustacchi 	buf[SFF_8636_ATTENUATE_7G] = 0x44;
11645d3dd98SRobert Mustacchi 	buf[SFF_8636_ATTENUATE_12G] = 0x45;
11745d3dd98SRobert Mustacchi 
11845d3dd98SRobert Mustacchi 	if ((ret = libsff_parse(buf, sizeof (buf), 0xa0, &nvl)) != 0) {
119*8d195583SRobert Mustacchi 		errc(1, ret, "TEST FAILED: failed to parse QSFP BR "
120*8d195583SRobert Mustacchi 		    "values");
12145d3dd98SRobert Mustacchi 	}
12245d3dd98SRobert Mustacchi 
12345d3dd98SRobert Mustacchi 	for (i = 0; attenuate[i] != NULL; i++) {
12445d3dd98SRobert Mustacchi 		if ((ret = nvlist_lookup_string(nvl, attenuate[i], &val)) !=
12545d3dd98SRobert Mustacchi 		    0) {
126*8d195583SRobert Mustacchi 			errc(1, ret, "TEST FAILED: failed to find %s",
127*8d195583SRobert Mustacchi 			    attenuate[i]);
12845d3dd98SRobert Mustacchi 		}
12945d3dd98SRobert Mustacchi 		(void) printf("%s: %s\n", attenuate[i], val);
13045d3dd98SRobert Mustacchi 	}
13145d3dd98SRobert Mustacchi 
13245d3dd98SRobert Mustacchi 	for (i = 0; wave[i] != NULL; i++) {
13345d3dd98SRobert Mustacchi 		if ((ret = nvlist_lookup_string(nvl, wave[i], &val)) !=
13445d3dd98SRobert Mustacchi 		    ENOENT) {
135*8d195583SRobert Mustacchi 			errx(1, "TEST FAILED: found unexpected return value "
136*8d195583SRobert Mustacchi 			    "for key %s: %d", attenuate[i], ret);
13745d3dd98SRobert Mustacchi 		}
13845d3dd98SRobert Mustacchi 
13945d3dd98SRobert Mustacchi 	}
14045d3dd98SRobert Mustacchi 	nvlist_free(nvl);
14145d3dd98SRobert Mustacchi 
14245d3dd98SRobert Mustacchi 	/* Now normal wavelengths */
14345d3dd98SRobert Mustacchi 	bzero(buf, sizeof (buf));
14445d3dd98SRobert Mustacchi 	buf[SFF_8472_IDENTIFIER] = SFF_8024_ID_QSFP;
14545d3dd98SRobert Mustacchi 
14645d3dd98SRobert Mustacchi 	buf[SFF_8636_WAVELENGTH_NOMINAL_HI] = 0x12;
14745d3dd98SRobert Mustacchi 	buf[SFF_8636_WAVELENGTH_NOMINAL_LOW] = 0x34;
14845d3dd98SRobert Mustacchi 	buf[SFF_8636_WAVELENGTH_TOLERANCE_HI] = 0x56;
14945d3dd98SRobert Mustacchi 	buf[SFF_8636_WAVELENGTH_TOLERANCE_LOW] = 0x78;
15045d3dd98SRobert Mustacchi 
15145d3dd98SRobert Mustacchi 	if ((ret = libsff_parse(buf, sizeof (buf), 0xa0, &nvl)) != 0) {
152*8d195583SRobert Mustacchi 		errc(1, ret, "TEST FAILED: failed to parse QSFP Wavelength "
153*8d195583SRobert Mustacchi 		    "values");
15445d3dd98SRobert Mustacchi 	}
15545d3dd98SRobert Mustacchi 
15645d3dd98SRobert Mustacchi 	for (i = 0; wave[i] != NULL; i++) {
15745d3dd98SRobert Mustacchi 		if ((ret = nvlist_lookup_string(nvl, wave[i], &val)) != 0) {
158*8d195583SRobert Mustacchi 			errc(1, ret, "TEST FAILED: failed to find %s", wave[i]);
15945d3dd98SRobert Mustacchi 		}
16045d3dd98SRobert Mustacchi 		(void) printf("%s: %s\n", wave[i], val);
16145d3dd98SRobert Mustacchi 	}
16245d3dd98SRobert Mustacchi 
16345d3dd98SRobert Mustacchi 	for (i = 0; attenuate[i] != NULL; i++) {
16445d3dd98SRobert Mustacchi 		if ((ret = nvlist_lookup_string(nvl, attenuate[i], &val)) !=
16545d3dd98SRobert Mustacchi 		    ENOENT) {
16645d3dd98SRobert Mustacchi 			errx(1, "TEST FALIED: found unexpected return value "
167*8d195583SRobert Mustacchi 			    "for key %s: %d", attenuate[i], ret);
16845d3dd98SRobert Mustacchi 		}
16945d3dd98SRobert Mustacchi 
17045d3dd98SRobert Mustacchi 	}
17145d3dd98SRobert Mustacchi 	nvlist_free(nvl);
17245d3dd98SRobert Mustacchi 
17345d3dd98SRobert Mustacchi 	return (0);
17445d3dd98SRobert Mustacchi }
175