xref: /illumos-gate/usr/src/lib/libi2c/common/libi2c_impl.h (revision 04a1c1a11476a9a84da46c1937024cde61ddb850)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2025 Oxide Computer Company
14  */
15 
16 #ifndef _LIBI2C_IMPL_H
17 #define	_LIBI2C_IMPL_H
18 
19 /*
20  * Implementation details of libi2c.
21  */
22 
23 #include <locale.h>
24 #include <libnvpair.h>
25 #include <libi2c.h>
26 #include <sys/i2c/ioctl.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /*
33  * Maximum size of an internal error message.
34  */
35 #define	I2C_ERR_LEN	1024
36 
37 /*
38  * Name of the driver that we expect to be driving an instance of the i2c nexus.
39  */
40 #define	I2C_NEX_DRV	"i2cnex"
41 
42 typedef struct i2c_err_data {
43 	i2c_err_t ie_err;
44 	int32_t ie_syserr;
45 	i2c_ctrl_error_t ie_ctrl_err;
46 	char ie_errmsg[I2C_ERR_LEN];
47 	size_t ie_errlen;
48 } i2c_err_data_t;
49 
50 struct i2c_hdl {
51 	i2c_err_data_t ih_err;
52 	locale_t ih_c_loc;
53 	int ih_devfd;
54 };
55 
56 struct i2c_ctrl_disc {
57 	di_node_t icd_devi;
58 	di_minor_t icd_minor;
59 };
60 
61 struct i2c_ctrl_iter {
62 	i2c_hdl_t *ci_hdl;
63 	di_node_t ci_root;
64 	bool ci_done;
65 	di_node_t ci_cur;
66 	i2c_ctrl_disc_t ci_disc;
67 };
68 
69 struct i2c_ctrl {
70 	i2c_hdl_t *ctrl_hdl;
71 	int32_t ctrl_inst;
72 	char *ctrl_name;
73 	char *ctrl_path;
74 	char *ctrl_minor;
75 	uint16_t ctrl_nstd;
76 	uint16_t ctrl_npriv;
77 	int ctrl_fd;
78 };
79 
80 struct i2c_port_disc {
81 	di_node_t pd_devi;
82 	char pd_path[PATH_MAX];
83 };
84 
85 struct i2c_port_iter {
86 	i2c_hdl_t *pi_hdl;
87 	bool pi_done;
88 	di_node_t pi_root;
89 	uint32_t pi_nalloc;
90 	uint32_t pi_nports;
91 	uint32_t pi_curport;
92 	di_node_t *pi_ports;
93 	i2c_port_disc_t pi_disc;
94 };
95 
96 struct i2c_port {
97 	i2c_hdl_t *port_hdl;
98 	int32_t port_inst;
99 	int port_fd;
100 	char *port_name;
101 	char *port_minor;
102 	char port_path[PATH_MAX];
103 	ui2c_port_info_t port_info;
104 	i2c_port_type_t port_type;
105 };
106 
107 struct i2c_port_map {
108 	i2c_hdl_t *pm_hdl;
109 	ui2c_port_info_t pm_info;
110 };
111 
112 struct i2c_io_req {
113 	i2c_port_t *io_port;
114 	bool io_addr_valid;
115 	i2c_addr_t io_addr;
116 	size_t io_tx_len;
117 	size_t io_rx_len;
118 	const void *io_tx_buf;
119 	void *io_rx_buf;
120 };
121 
122 struct smbus_io_req {
123 	i2c_port_t *sir_port;
124 	bool sir_addr_valid;
125 	i2c_addr_t sir_addr;
126 	bool sir_op_valid;
127 	smbus_op_t sir_op;
128 	i2c_req_flags_t sir_flags;
129 	uint8_t sir_cmd;
130 	uint64_t sir_write;
131 	const void *sir_writep;
132 	size_t sir_wlen;
133 	void *sir_readp;
134 	size_t sir_rlen;
135 };
136 
137 typedef enum {
138 	I2C_DEV_ADD_REQ_FIELD_NAME	= 1 << 0,
139 	I2C_DEV_ADD_REQ_FIELD_ADDR	= 1 << 1
140 } i2c_dev_add_req_field_t;
141 
142 struct i2c_dev_add_req {
143 	i2c_port_t *add_port;
144 	nvlist_t *add_nvl;
145 	uint32_t add_need;
146 };
147 
148 typedef struct {
149 	di_minor_t dmi_minor;
150 	di_node_t dmi_node;
151 } dev_map_info_t;
152 
153 typedef struct {
154 	di_node_t dpi_port;
155 	bool dpi_scanned;
156 	bool dpi_7bit_done;
157 	bool dpi_10bit_done;
158 	uint16_t dpi_curidx;
159 	dev_map_info_t dpi_7b[1 << 7];
160 	dev_map_info_t dpi_10b[1 << 10];
161 } dev_port_info_t;
162 
163 struct i2c_dev_disc {
164 	const dev_map_info_t *idd_map;
165 	const dev_port_info_t *idd_port;
166 	char idd_path[PATH_MAX];
167 };
168 
169 struct i2c_dev_iter {
170 	i2c_hdl_t *di_hdl;
171 	bool di_done;
172 	i2c_port_iter_t *di_iter;
173 	const i2c_port_disc_t *di_curport;
174 	dev_port_info_t di_info;
175 	i2c_dev_disc_t di_disc;
176 };
177 
178 struct i2c_dev_info {
179 	char *dinfo_name;
180 	char dinfo_path[PATH_MAX];
181 	char *dinfo_driver;
182 	char *dinfo_minor;
183 	int dinfo_inst;
184 	uint32_t dinfo_naddrs;
185 	i2c_addr_t *dinfo_addrs;
186 	ui2c_dev_info_t dinfo_info;
187 };
188 
189 struct i2c_prop_info {
190 	i2c_hdl_t *pinfo_hdl;
191 	ui2c_prop_info_t pinfo_info;
192 	bool pinfo_sup;
193 };
194 
195 struct i2c_mux_disc {
196 	di_node_t md_devi;
197 	di_minor_t md_minor;
198 	char md_path[PATH_MAX];
199 	ui2c_mux_info_t md_info;
200 };
201 
202 struct i2c_mux_iter {
203 	i2c_hdl_t *mi_hdl;
204 	di_node_t mi_root;
205 	di_node_t mi_cur;
206 	bool mi_done;
207 	i2c_mux_disc_t mi_disc;
208 };
209 
210 /*
211  * Common success and failure interfaces.
212  */
213 extern bool i2c_error(i2c_hdl_t *, i2c_err_t, int32_t, const char *, ...)
214     __PRINTFLIKE(4);
215 extern bool i2c_success(i2c_hdl_t *);
216 extern bool i2c_ioctl_syserror(i2c_hdl_t *, int, const char *);
217 extern bool i2c_ioctl_error(i2c_hdl_t *, const i2c_error_t *, const char *);
218 extern bool i2c_nvlist_error(i2c_hdl_t *, int, const char *);
219 
220 /*
221  * Common validation routines
222  */
223 extern bool i2c_addr_validate(i2c_hdl_t *, const i2c_addr_t *);
224 extern bool i2c_name_validate(i2c_hdl_t *, const char *, const char *);
225 
226 /*
227  * Misc. routines.
228  */
229 typedef enum {
230 	I2C_NODE_T_CTRL,
231 	I2C_NODE_T_PORT,
232 	I2C_NODE_T_DEV,
233 	I2C_NODE_T_MUX,
234 	I2C_NODE_T_OTHER
235 } i2c_node_type_t;
236 
237 extern i2c_node_type_t i2c_node_type(di_node_t);
238 extern di_minor_t i2c_node_minor(di_node_t);
239 extern bool i2c_node_is_type(di_node_t, i2c_node_type_t);
240 extern bool i2c_node_to_path(i2c_hdl_t *, di_node_t, char *, size_t);
241 extern bool i2c_kernel_address_parse(i2c_hdl_t *, const char *, i2c_addr_t *);
242 extern bool i2c_reg_to_addr(i2c_hdl_t *, di_node_t, i2c_addr_t *, uint32_t);
243 extern bool i2c_addr_equal(const i2c_addr_t *, const i2c_addr_t *);
244 
245 /*
246  * Various path lookup routines.
247  */
248 extern di_node_t i2c_path_find_ctrl(di_node_t, const char *);
249 extern di_node_t i2c_path_find_mux(di_node_t);
250 extern di_node_t i2c_path_find_port(di_node_t, const char *);
251 extern di_node_t i2c_path_find_device(i2c_hdl_t *, di_node_t, const char *);
252 extern bool i2c_path_parse(i2c_hdl_t *, const char *, di_node_t, di_node_t *,
253     i2c_node_type_t *, i2c_err_t);
254 
255 #ifdef __cplusplus
256 }
257 #endif
258 
259 #endif /* _LIBI2C_IMPL_H */
260