1/*-
2 * Copyright (c) 2014, Alexander V. Chernikov
3 * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#pragma once
30
31#include <stdbool.h>
32#include <stdint.h>
33
34#include <libifconfig.h>
35#include <libifconfig_sfp_tables.h>
36
37/** SFP module information in raw numeric form
38 * These are static properties of the hardware.
39 */
40struct ifconfig_sfp_info;
41
42/** SFP module information formatted as strings
43 * These are static strings that do not need to be freed.
44 */
45struct ifconfig_sfp_info_strings;
46
47#define SFF_VENDOR_STRING_SIZE	16	/**< max chars in a vendor string */
48#define SFF_VENDOR_DATE_SIZE	6	/**< chars in a vendor date code */
49
50/** SFP module vendor info strings */
51struct ifconfig_sfp_vendor_info {
52	char name[SFF_VENDOR_STRING_SIZE + 1];	/**< vendor name */
53	char pn[SFF_VENDOR_STRING_SIZE + 1];	/**< vendor part number */
54	char sn[SFF_VENDOR_STRING_SIZE + 1];	/**< vendor serial number */
55	char date[SFF_VENDOR_DATE_SIZE + 5];	/**< formatted vendor date */
56};
57
58/** SFP module status
59 * These are dynamic properties of the hardware.
60 */
61struct ifconfig_sfp_status {
62	double temp;		/**< module temperature in degrees C,
63				     valid range -40.0 to 125.0 */
64	double voltage;		/**< module voltage in volts */
65	struct sfp_channel {
66		uint16_t rx;	/**< channel receive power, LSB 0.1uW */
67		uint16_t tx;	/**< channel transmit bias current, LSB 2uA */
68	} *channel;		/**< array of channel rx/tx status */
69	uint32_t bitrate;	/**< link bitrate,
70				     only present for QSFP modules,
71				     zero for SFP modules */
72};
73
74#define SFF_DUMP_SIZE	256	/**< size of the memory dump buffer */
75
76#define SFP_DUMP_START	0	/**< start address of an SFP module dump */
77#define SFP_DUMP_SIZE	128	/**< bytes in an SFP module dump */
78
79#define QSFP_DUMP0_START	0	/**< start address of the first region
80					     in a QSFP module dump */
81#define QSFP_DUMP0_SIZE		82	/**< bytes in the first region
82					     in a QSFP module dump */
83#define QSFP_DUMP1_START	128	/**< start address of the second region
84					     in a QSFP module dump */
85#define QSFP_DUMP1_SIZE		128	/**< bytes in the second region
86					     in a QSFP module dump */
87
88/** SFP module I2C memory dump
89 * SFP modules have one region, QSFP modules have two regions.
90 */
91struct ifconfig_sfp_dump {
92	uint8_t data[SFF_DUMP_SIZE];	/**< memory dump data */
93};
94
95/** Get information about the static properties of an SFP/QSFP module
96 * The information is returned in numeric form.
97 * @see ifconfig_sfp_get_sfp_info_strings to get corresponding strings.
98 * @param h	An open ifconfig state handle
99 * @param name	The name of an interface
100 * @param sfp	Pointer to an object to fill, will be zeroed by this function
101 * @return	0 if successful, -1 with error info set in the handle otherwise
102 */
103int ifconfig_sfp_get_sfp_info(ifconfig_handle_t *h, const char *name,
104    struct ifconfig_sfp_info *sfp);
105
106/** Get the number of channels present on the given module
107 * @param sfp	Pointer to a filled SFP module info object
108 * @return	The number of channels or 0 if unknown
109 */
110size_t ifconfig_sfp_channel_count(const struct ifconfig_sfp_info *sfp);
111
112/** Is the given module ID a QSFP
113 * NB: This convenience function is implemented in the header to keep the
114 * classification criteria visible to the user.
115 * @param id	The sfp_id field of a SFP module info object
116 * @return	A bool true if QSFP-type sfp_id otherwise false
117 */
118static inline bool
119ifconfig_sfp_id_is_qsfp(enum sfp_id id)
120{
121	switch (id) {
122	case SFP_ID_QSFP:
123	case SFP_ID_QSFPPLUS:
124	case SFP_ID_QSFP28:
125		return (true);
126	default:
127		return (false);
128	}
129}
130
131/** Get string descriptions of the given SFP/QSFP module info
132 * The strings are static and do not need to be freed.
133 * @see ifconfig_sfp_get_sfp_info to obtain the input info.
134 * @param sfp	Pointer to a filled SFP module info object
135 * @param strings	Pointer to an object to be filled with pointers to
136 *                      static strings describing the given info
137 */
138void ifconfig_sfp_get_sfp_info_strings(const struct ifconfig_sfp_info *sfp,
139    struct ifconfig_sfp_info_strings *strings);
140
141/** Get a string describing the given SFP/QSFP module's physical layer spec
142 * The correct field in ifconfig_sfp_info varies depending on the module.  This
143 * function chooses the appropriate string based on the provided module info.
144 * The string returned is static and does not need to be freed.
145 * @param sfp	Pointer to a filled SFP module info object
146 * @param strings	Pointer to a filled SFP module strings object
147 * @return	Pointer to a static string describing the module's spec
148 */
149const char *ifconfig_sfp_physical_spec(const struct ifconfig_sfp_info *sfp,
150    const struct ifconfig_sfp_info_strings *strings);
151
152/** Get the vendor info strings from an SFP/QSFP module
153 * @param h	An open ifconfig state handle
154 * @param name	The name of an interface
155 * @param vi	Pointer to an object to be filled with the vendor info strings,
156 *              will be zeroed by this function
157 * @return	0 if successful, -1 with error info set in the handle otherwise
158 */
159int ifconfig_sfp_get_sfp_vendor_info(ifconfig_handle_t *h, const char *name,
160    struct ifconfig_sfp_vendor_info *vi);
161
162/** Get the status of an SFP/QSFP module's dynamic properties
163 * @see ifconfig_sfp_free_sfp_status to free the allocations
164 * @param h	An open ifconfig state handle
165 * @param name	The name of an interface
166 * @param ss	Pointer to an object to be filled with the module's status
167 * @return	0 if successful, -1 with error info set in the handle otherwise
168 *              where the errcode `ENXIO` indicates an SFP module that is not
169 *              calibrated or does not provide diagnostic status measurements
170 */
171int ifconfig_sfp_get_sfp_status(ifconfig_handle_t *h, const char *name,
172    struct ifconfig_sfp_status *ss);
173
174/** Free the memory allocations in an ifconfig_sfp_status struct
175 * @param ss	Pointer to an object whose internal allocations are to be freed
176 * 		if not NULL
177 */
178void ifconfig_sfp_free_sfp_status(struct ifconfig_sfp_status *ss);
179
180/** Dump the I2C memory of an SFP/QSFP module
181 * SFP modules have one memory region dumped, QSFP modules have two.
182 * @param h	An open ifconfig state handle
183 * @param name	The name of an interface
184 * @param buf	Pointer to a dump data buffer object
185 * @return	0 if successful, -1 with error info set in the handle otherwise
186 */
187int ifconfig_sfp_get_sfp_dump(ifconfig_handle_t *h, const char *name,
188    struct ifconfig_sfp_dump *buf);
189
190/** Get the number of I2C memory dump regions present in the given dump
191 * @param dp	Pointer to a filled dump data buffer object
192 * @return	The number of regions or 0 if unknown
193 */
194size_t ifconfig_sfp_dump_region_count(const struct ifconfig_sfp_dump *dp);
195
196/** Convert channel power to milliwatts power
197 * This is provided as a convenience for displaying channel power levels.
198 * @see (struct ifconfig_sfp_status).channel
199 * @param power	Power in 0.1 mW units
200 * @return	Power in milliwatts (mW)
201 */
202double power_mW(uint16_t power);
203
204/** Convert channel power to decibel-milliwats power level
205 * This is provided as a convenience for displaying channel power levels.
206 * @see (struct ifconfig_sfp_status).channel
207 * @param power	Power in 0.1 mW units
208 * @return	Power level in decibel-milliwatts (dBm)
209 */
210
211double power_dBm(uint16_t power);
212
213/** Convert channel bias current to milliamps
214 * This is provided as a convenience for displaying channel bias currents.
215 * @see (struct ifconfig_sfp_status).channel
216 * @param bias	Bias current in 2 mA units
217 * @return	Bias current in milliamps (mA)
218 */
219double bias_mA(uint16_t bias);
220