xref: /illumos-gate/usr/src/lib/libi2c/common/libi2c_error.c (revision 32002227574cf0a435dc03de622191ca53724f0a)
1*32002227SRobert Mustacchi /*
2*32002227SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*32002227SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*32002227SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*32002227SRobert Mustacchi  * 1.0 of the CDDL.
6*32002227SRobert Mustacchi  *
7*32002227SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*32002227SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*32002227SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*32002227SRobert Mustacchi  */
11*32002227SRobert Mustacchi 
12*32002227SRobert Mustacchi /*
13*32002227SRobert Mustacchi  * Copyright 2025 Oxide Computer Company
14*32002227SRobert Mustacchi  */
15*32002227SRobert Mustacchi 
16*32002227SRobert Mustacchi /*
17*32002227SRobert Mustacchi  * libi2c error manipulation and translation.
18*32002227SRobert Mustacchi  */
19*32002227SRobert Mustacchi 
20*32002227SRobert Mustacchi #include <stdarg.h>
21*32002227SRobert Mustacchi #include <stdio.h>
22*32002227SRobert Mustacchi #include <string.h>
23*32002227SRobert Mustacchi #include <upanic.h>
24*32002227SRobert Mustacchi #include <sys/debug.h>
25*32002227SRobert Mustacchi #include <sys/sysmacros.h>
26*32002227SRobert Mustacchi 
27*32002227SRobert Mustacchi #include "libi2c_impl.h"
28*32002227SRobert Mustacchi 
29*32002227SRobert Mustacchi static void
i2c_error_common(i2c_err_data_t * ep,i2c_err_t err,int32_t sys,const char * fmt,va_list ap)30*32002227SRobert Mustacchi i2c_error_common(i2c_err_data_t *ep, i2c_err_t err, int32_t sys,
31*32002227SRobert Mustacchi     const char *fmt, va_list ap)
32*32002227SRobert Mustacchi {
33*32002227SRobert Mustacchi 	int ret;
34*32002227SRobert Mustacchi 
35*32002227SRobert Mustacchi 	ep->ie_err = err;
36*32002227SRobert Mustacchi 	ep->ie_syserr = sys;
37*32002227SRobert Mustacchi 	ep->ie_ctrl_err = I2C_CTRL_E_OK;
38*32002227SRobert Mustacchi 	ret = vsnprintf(ep->ie_errmsg, sizeof (ep->ie_errmsg), fmt, ap);
39*32002227SRobert Mustacchi 	if (ret >= sizeof (ep->ie_errmsg)) {
40*32002227SRobert Mustacchi 		ep->ie_errlen = sizeof (ep->ie_errmsg) - 1;
41*32002227SRobert Mustacchi 	} else if (ret <= 0) {
42*32002227SRobert Mustacchi 		ep->ie_errlen = 0;
43*32002227SRobert Mustacchi 		ep->ie_errmsg[0] = '\0';
44*32002227SRobert Mustacchi 	} else {
45*32002227SRobert Mustacchi 		ep->ie_errlen = (size_t)ret;
46*32002227SRobert Mustacchi 	}
47*32002227SRobert Mustacchi }
48*32002227SRobert Mustacchi 
49*32002227SRobert Mustacchi bool
i2c_error(i2c_hdl_t * hdl,i2c_err_t err,int32_t sys,const char * fmt,...)50*32002227SRobert Mustacchi i2c_error(i2c_hdl_t *hdl, i2c_err_t err, int32_t sys, const char *fmt, ...)
51*32002227SRobert Mustacchi {
52*32002227SRobert Mustacchi 	va_list ap;
53*32002227SRobert Mustacchi 
54*32002227SRobert Mustacchi 	va_start(ap, fmt);
55*32002227SRobert Mustacchi 	i2c_error_common(&hdl->ih_err, err, sys, fmt, ap);
56*32002227SRobert Mustacchi 	va_end(ap);
57*32002227SRobert Mustacchi 
58*32002227SRobert Mustacchi 	return (false);
59*32002227SRobert Mustacchi }
60*32002227SRobert Mustacchi 
61*32002227SRobert Mustacchi static bool
i2c_success_common(i2c_err_data_t * err)62*32002227SRobert Mustacchi i2c_success_common(i2c_err_data_t *err)
63*32002227SRobert Mustacchi {
64*32002227SRobert Mustacchi 	err->ie_err = I2C_ERR_OK;
65*32002227SRobert Mustacchi 	err->ie_syserr = 0;
66*32002227SRobert Mustacchi 	err->ie_ctrl_err = I2C_CTRL_E_OK;
67*32002227SRobert Mustacchi 	err->ie_errmsg[0] = '\0';
68*32002227SRobert Mustacchi 	err->ie_errlen = 0;
69*32002227SRobert Mustacchi 
70*32002227SRobert Mustacchi 	return (true);
71*32002227SRobert Mustacchi }
72*32002227SRobert Mustacchi 
73*32002227SRobert Mustacchi bool
i2c_success(i2c_hdl_t * hdl)74*32002227SRobert Mustacchi i2c_success(i2c_hdl_t *hdl)
75*32002227SRobert Mustacchi {
76*32002227SRobert Mustacchi 	return (i2c_success_common(&hdl->ih_err));
77*32002227SRobert Mustacchi }
78*32002227SRobert Mustacchi 
79*32002227SRobert Mustacchi i2c_err_t
i2c_err(i2c_hdl_t * hdl)80*32002227SRobert Mustacchi i2c_err(i2c_hdl_t *hdl)
81*32002227SRobert Mustacchi {
82*32002227SRobert Mustacchi 	return (hdl->ih_err.ie_err);
83*32002227SRobert Mustacchi }
84*32002227SRobert Mustacchi 
85*32002227SRobert Mustacchi i2c_ctrl_error_t
i2c_ctrl_err(i2c_hdl_t * hdl)86*32002227SRobert Mustacchi i2c_ctrl_err(i2c_hdl_t *hdl)
87*32002227SRobert Mustacchi {
88*32002227SRobert Mustacchi 	return (hdl->ih_err.ie_ctrl_err);
89*32002227SRobert Mustacchi }
90*32002227SRobert Mustacchi 
91*32002227SRobert Mustacchi int32_t
i2c_syserr(i2c_hdl_t * hdl)92*32002227SRobert Mustacchi i2c_syserr(i2c_hdl_t *hdl)
93*32002227SRobert Mustacchi {
94*32002227SRobert Mustacchi 	return (hdl->ih_err.ie_syserr);
95*32002227SRobert Mustacchi }
96*32002227SRobert Mustacchi 
97*32002227SRobert Mustacchi const char *
i2c_errmsg(i2c_hdl_t * hdl)98*32002227SRobert Mustacchi i2c_errmsg(i2c_hdl_t *hdl)
99*32002227SRobert Mustacchi {
100*32002227SRobert Mustacchi 	return (hdl->ih_err.ie_errmsg);
101*32002227SRobert Mustacchi }
102*32002227SRobert Mustacchi 
103*32002227SRobert Mustacchi const char *
i2c_errtostr(i2c_hdl_t * hdl,i2c_err_t err)104*32002227SRobert Mustacchi i2c_errtostr(i2c_hdl_t *hdl, i2c_err_t err)
105*32002227SRobert Mustacchi {
106*32002227SRobert Mustacchi 	switch (err) {
107*32002227SRobert Mustacchi 	case I2C_ERR_OK:
108*32002227SRobert Mustacchi 		return ("I2C_ERR_OK");
109*32002227SRobert Mustacchi 	case I2C_ERR_CONTROLLER:
110*32002227SRobert Mustacchi 		return ("I2C_ERR_CONTROLLER");
111*32002227SRobert Mustacchi 	case I2C_ERR_BAD_PTR:
112*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_PTR");
113*32002227SRobert Mustacchi 	case I2C_ERR_NO_MEM:
114*32002227SRobert Mustacchi 		return ("I2C_ERR_NO_MEM");
115*32002227SRobert Mustacchi 	case I2C_ERR_LIBDEVINFO:
116*32002227SRobert Mustacchi 		return ("I2C_ERR_LIBDEVINFO");
117*32002227SRobert Mustacchi 	case I2C_ERR_BAD_DEVI:
118*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_DEVI");
119*32002227SRobert Mustacchi 	case I2C_ERR_INTERNAL:
120*32002227SRobert Mustacchi 		return ("I2C_ERR_INTERNAL");
121*32002227SRobert Mustacchi 	case I2C_ERR_PRIVS:
122*32002227SRobert Mustacchi 		return ("I2C_ERR_PRIVS");
123*32002227SRobert Mustacchi 	case I2C_ERR_OPEN_DEV:
124*32002227SRobert Mustacchi 		return ("I2C_ERR_OPEN_DEV");
125*32002227SRobert Mustacchi 	case I2C_ERR_BAD_CONTROLLER:
126*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_CONTROLLER");
127*32002227SRobert Mustacchi 	case I2C_ERR_BAD_PORT:
128*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_PORT");
129*32002227SRobert Mustacchi 	case I2C_ERR_BAD_DEVICE:
130*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_DEVICE");
131*32002227SRobert Mustacchi 	case I2C_ERR_BAD_ADDR_TYPE:
132*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_ADDR_TYPE");
133*32002227SRobert Mustacchi 	case I2C_ERR_BAD_ADDR:
134*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_ADDR");
135*32002227SRobert Mustacchi 	case I2C_ERR_UNSUP_ADDR_TYPE:
136*32002227SRobert Mustacchi 		return ("I2C_ERR_UNSUP_ADDR_TYPE");
137*32002227SRobert Mustacchi 	case I2C_ERR_ADDR_RSVD:
138*32002227SRobert Mustacchi 		return ("I2C_ERR_ADDR_RSVD");
139*32002227SRobert Mustacchi 	case I2C_ERR_ADDR_IN_USE:
140*32002227SRobert Mustacchi 		return ("I2C_ERR_ADDR_IN_USE");
141*32002227SRobert Mustacchi 	case I2C_ERR_ADDR_UNKNOWN:
142*32002227SRobert Mustacchi 		return ("I2C_ERR_ADDR_UNKNOWN");
143*32002227SRobert Mustacchi 	case I2C_ERR_IO_READ_LEN_RANGE:
144*32002227SRobert Mustacchi 		return ("I2C_ERR_IO_READ_LEN_RANGE");
145*32002227SRobert Mustacchi 	case I2C_ERR_IO_WRITE_LEN_RANGE:
146*32002227SRobert Mustacchi 		return ("I2C_ERR_IO_WRITE_LEN_RANGE");
147*32002227SRobert Mustacchi 	case I2C_ERR_IO_REQ_MISSING_FIELDS:
148*32002227SRobert Mustacchi 		return ("I2C_ERR_IO_REQ_MISSING_FIELDS");
149*32002227SRobert Mustacchi 	case I2C_ERR_IO_REQ_IO_INVALID:
150*32002227SRobert Mustacchi 		return ("I2C_ERR_IO_REQ_IO_INVALID");
151*32002227SRobert Mustacchi 	case I2C_ERR_CANT_XLATE_IO_REQ:
152*32002227SRobert Mustacchi 		return ("I2C_ERR_CANT_XLATE_IO_REQ");
153*32002227SRobert Mustacchi 	case I2C_ERR_SMBUS_OP_UNSUP:
154*32002227SRobert Mustacchi 		return ("I2C_ERR_SMBUS_OP_UNSUP");
155*32002227SRobert Mustacchi 	case I2C_ERR_LOCK_WAIT_SIGNAL:
156*32002227SRobert Mustacchi 		return ("I2C_ERR_LOCK_WAIT_SIGNAL");
157*32002227SRobert Mustacchi 	case I2C_ERR_LOCK_WOULD_BLOCK:
158*32002227SRobert Mustacchi 		return ("I2C_ERR_LOCK_WOULD_BLOCK");
159*32002227SRobert Mustacchi 	case I2C_ERR_NO_KERN_MEM:
160*32002227SRobert Mustacchi 		return ("I2C_ERR_NO_KERN_MEM");
161*32002227SRobert Mustacchi 	case I2C_ERR_BAD_DEV_NAME:
162*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_DEV_NAME");
163*32002227SRobert Mustacchi 	case I2C_ERR_COMPAT_LEN_RANGE:
164*32002227SRobert Mustacchi 		return ("I2C_ERR_COMPAT_LEN_RANGE");
165*32002227SRobert Mustacchi 	case I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS:
166*32002227SRobert Mustacchi 		return ("I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS");
167*32002227SRobert Mustacchi 	case I2C_ERR_NEXUS:
168*32002227SRobert Mustacchi 		return ("I2C_ERR_NEXUS");
169*32002227SRobert Mustacchi 	case I2C_ERR_OP_IN_PROGRESS:
170*32002227SRobert Mustacchi 		return ("I2C_ERR_OP_IN_PROGRESS");
171*32002227SRobert Mustacchi 	case I2C_ERR_PROP_UNSUP:
172*32002227SRobert Mustacchi 		return ("I2C_ERR_PROP_UNSUP");
173*32002227SRobert Mustacchi 	case I2C_ERR_BAD_PROP:
174*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_PROP");
175*32002227SRobert Mustacchi 	case I2C_ERR_SET_PROP_UNSUP:
176*32002227SRobert Mustacchi 		return ("I2C_ERR_SET_PROP_UNSUP");
177*32002227SRobert Mustacchi 	case I2C_ERR_PROP_READ_ONLY:
178*32002227SRobert Mustacchi 		return ("I2C_ERR_PROP_READ_ONLY");
179*32002227SRobert Mustacchi 	case I2C_ERR_PROP_BUF_TOO_SMALL:
180*32002227SRobert Mustacchi 		return ("I2C_ERR_PROP_BUF_TOO_SMALL");
181*32002227SRobert Mustacchi 	case I2C_ERR_PROP_BUF_TOO_BIG:
182*32002227SRobert Mustacchi 		return ("I2C_ERR_PROP_BUF_TOO_BIG");
183*32002227SRobert Mustacchi 	case I2C_ERR_BAD_PROP_VAL:
184*32002227SRobert Mustacchi 		return ("I2C_ERR_BAD_PROP_VAL");
185*32002227SRobert Mustacchi 	case I2C_ERR_NO_PROP_DEF_VAL:
186*32002227SRobert Mustacchi 		return ("I2C_ERR_NO_PROP_DEF_VAL");
187*32002227SRobert Mustacchi 	case I2C_ERR_PROP_TYPE_MISMATCH:
188*32002227SRobert Mustacchi 		return ("I2C_ERR_PROP_TYPE_MISMATCH");
189*32002227SRobert Mustacchi 	case I2C_ERR_BUF_TOO_SMALL:
190*32002227SRobert Mustacchi 		return ("I2C_ERR_BUF_TOO_SMALL");
191*32002227SRobert Mustacchi 	default:
192*32002227SRobert Mustacchi 		return ("unknown error");
193*32002227SRobert Mustacchi 	}
194*32002227SRobert Mustacchi }
195*32002227SRobert Mustacchi 
196*32002227SRobert Mustacchi const char *
i2c_ctrl_errtostr(i2c_hdl_t * hdl,i2c_ctrl_error_t err)197*32002227SRobert Mustacchi i2c_ctrl_errtostr(i2c_hdl_t *hdl, i2c_ctrl_error_t err)
198*32002227SRobert Mustacchi {
199*32002227SRobert Mustacchi 	switch (err) {
200*32002227SRobert Mustacchi 	case I2C_CTRL_E_OK:
201*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_OK");
202*32002227SRobert Mustacchi 	case I2C_CTRL_E_INTERNAL:
203*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_INTERNAL");
204*32002227SRobert Mustacchi 	case I2C_CTRL_E_DRIVER:
205*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_DRIVER");
206*32002227SRobert Mustacchi 	case I2C_CTRL_E_UNSUP_CMD:
207*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_UNSUP_CMD");
208*32002227SRobert Mustacchi 	case I2C_CTRL_E_BUS_BUSY:
209*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_BUS_BUSY");
210*32002227SRobert Mustacchi 	case I2C_CTRL_E_ADDR_NACK:
211*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_ADDR_NACK");
212*32002227SRobert Mustacchi 	case I2C_CTRL_E_DATA_NACK:
213*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_DATA_NACK");
214*32002227SRobert Mustacchi 	case I2C_CTRL_E_NACK:
215*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_NACK");
216*32002227SRobert Mustacchi 	case I2C_CTRL_E_ARB_LOST:
217*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_ARB_LOST");
218*32002227SRobert Mustacchi 	case I2C_CTRL_E_BAD_ACK:
219*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_BAD_ACK");
220*32002227SRobert Mustacchi 	case I2C_CTRL_E_REQ_TO:
221*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_REQ_TO");
222*32002227SRobert Mustacchi 	case I2C_CTRL_E_BAD_SMBUS_RLEN:
223*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_BAD_SMBUS_RLEN");
224*32002227SRobert Mustacchi 	case I2C_CTRL_E_SMBUS_CLOCK_LOW:
225*32002227SRobert Mustacchi 		return ("I2C_CTRL_E_SMBUS_CLOCK_LOW");
226*32002227SRobert Mustacchi 	default:
227*32002227SRobert Mustacchi 		return ("unkonwn error");
228*32002227SRobert Mustacchi 	}
229*32002227SRobert Mustacchi }
230*32002227SRobert Mustacchi 
231*32002227SRobert Mustacchi /*
232*32002227SRobert Mustacchi  * Most of our ioctls are designed to give us a semantic error. However, there
233*32002227SRobert Mustacchi  * are cases where we may fail outside of that. We opt to abort on a subset of
234*32002227SRobert Mustacchi  * these that represent gross library programmer error: mainly EBADF and EFAULT.
235*32002227SRobert Mustacchi  * Note, EFAULT generally covers the core ioctl structures and not any
236*32002227SRobert Mustacchi  * additional buffers that are passed in, therefore if this triggers then we
237*32002227SRobert Mustacchi  * have done something terribly wrong.
238*32002227SRobert Mustacchi  */
239*32002227SRobert Mustacchi bool
i2c_ioctl_syserror(i2c_hdl_t * hdl,int err,const char * desc)240*32002227SRobert Mustacchi i2c_ioctl_syserror(i2c_hdl_t *hdl, int err, const char *desc)
241*32002227SRobert Mustacchi {
242*32002227SRobert Mustacchi 	switch (err) {
243*32002227SRobert Mustacchi 	case EFAULT:
244*32002227SRobert Mustacchi 	case EBADF: {
245*32002227SRobert Mustacchi 		const char *base = "fatal libi2c internal programming error: "
246*32002227SRobert Mustacchi 		    "failed to issue ioctl";
247*32002227SRobert Mustacchi 		char msg[1024];
248*32002227SRobert Mustacchi 		int ret;
249*32002227SRobert Mustacchi 		const char *up;
250*32002227SRobert Mustacchi 		size_t ulen;
251*32002227SRobert Mustacchi 
252*32002227SRobert Mustacchi 		ret = snprintf(msg, sizeof (msg), "%s %s: %s (hdl %p)",
253*32002227SRobert Mustacchi 		    base, desc, strerror(err), hdl);
254*32002227SRobert Mustacchi 		if (ret >= sizeof (msg)) {
255*32002227SRobert Mustacchi 			ulen = sizeof (msg);
256*32002227SRobert Mustacchi 			up = msg;
257*32002227SRobert Mustacchi 		} else if (ret <= 0) {
258*32002227SRobert Mustacchi 			up = base;
259*32002227SRobert Mustacchi 			ulen = strlen(base) + 1;
260*32002227SRobert Mustacchi 		} else {
261*32002227SRobert Mustacchi 			ulen = (size_t)ret;
262*32002227SRobert Mustacchi 			up = msg;
263*32002227SRobert Mustacchi 		}
264*32002227SRobert Mustacchi 
265*32002227SRobert Mustacchi 		upanic(up, ulen);
266*32002227SRobert Mustacchi 	}
267*32002227SRobert Mustacchi 	case EPERM:
268*32002227SRobert Mustacchi 		return (i2c_error(hdl, I2C_ERR_PRIVS, err, "failed to issue %s "
269*32002227SRobert Mustacchi 		    "ioctl due to missing privileges", desc));
270*32002227SRobert Mustacchi 	default:
271*32002227SRobert Mustacchi 		return (i2c_error(hdl, I2C_ERR_INTERNAL, err,
272*32002227SRobert Mustacchi 		    "failed to issue %s ioctl due to unexpected system error: "
273*32002227SRobert Mustacchi 		    "%s", desc, strerrordesc_np(err)));
274*32002227SRobert Mustacchi 	}
275*32002227SRobert Mustacchi }
276*32002227SRobert Mustacchi 
277*32002227SRobert Mustacchi typedef struct {
278*32002227SRobert Mustacchi 	i2c_errno_t kl_kern;
279*32002227SRobert Mustacchi 	i2c_err_t kl_lib;
280*32002227SRobert Mustacchi 	const char *kl_desc;
281*32002227SRobert Mustacchi } i2c_ktolmap_t;
282*32002227SRobert Mustacchi 
283*32002227SRobert Mustacchi /*
284*32002227SRobert Mustacchi  * This facilitates mapping kernel errors to user library errors along with a
285*32002227SRobert Mustacchi  * short description. This is ordered based on the order of the kernel ioctls so
286*32002227SRobert Mustacchi  * we can more easily spot missing entries. The description is used to help
287*32002227SRobert Mustacchi  * users understand what happened.
288*32002227SRobert Mustacchi  */
289*32002227SRobert Mustacchi static const i2c_ktolmap_t i2c_ktolmap[] = {
290*32002227SRobert Mustacchi 	/*
291*32002227SRobert Mustacchi 	 * We skip I2C_CORE_E_OK because it not reach here. We also handle the
292*32002227SRobert Mustacchi 	 * controller error, I2C_CORE_E_CONTROLLER, specifically so it is not
293*32002227SRobert Mustacchi 	 * translated here
294*32002227SRobert Mustacchi 	 */
295*32002227SRobert Mustacchi 	{ I2C_CORE_E_BAD_ADDR_TYPE, I2C_ERR_BAD_ADDR_TYPE, "invalid I2C "
296*32002227SRobert Mustacchi 	    "address family type" },
297*32002227SRobert Mustacchi 	{ I2C_CORE_E_BAD_ADDR, I2C_ERR_BAD_ADDR, "invalid I2C address" },
298*32002227SRobert Mustacchi 	{ I2C_CORE_E_UNSUP_ADDR_TYPE, I2C_ERR_UNSUP_ADDR_TYPE, "address "
299*32002227SRobert Mustacchi 	    "family not supported by the controller" },
300*32002227SRobert Mustacchi 	{ I2C_CORE_E_ADDR_RSVD, I2C_ERR_ADDR_RSVD, "I2C address is reserved" },
301*32002227SRobert Mustacchi 	{ I2C_CORE_E_ADDR_IN_USE, I2C_ERR_ADDR_IN_USE, "I2C addrses is already "
302*32002227SRobert Mustacchi 	    "used" },
303*32002227SRobert Mustacchi 	{ I2C_CORE_E_ADDR_REFCNT, I2C_ERR_INTERNAL, "address could not be "
304*32002227SRobert Mustacchi 	    "assigned due to kernel reference count exhaustion" },
305*32002227SRobert Mustacchi 	{ I2C_CORE_E_UNKNOWN_ADDR, I2C_ERR_ADDR_UNKNOWN, "I2C address does not "
306*32002227SRobert Mustacchi 	    "map to a known device" },
307*32002227SRobert Mustacchi 	{ I2C_CORE_E_CANT_XLATE_REQ, I2C_ERR_CANT_XLATE_IO_REQ, "I/O request "
308*32002227SRobert Mustacchi 	    "could not be translated to something the controller supports" },
309*32002227SRobert Mustacchi 	{ I2C_CORE_E_NEED_READ_OR_WRITE, I2C_ERR_IO_REQ_IO_INVALID, "request "
310*32002227SRobert Mustacchi 	    "requires data to transmit or receive, but neither specified" },
311*32002227SRobert Mustacchi 	/*
312*32002227SRobert Mustacchi 	 * We have purposefully skipped I2C_CORE_E_BAD_I2C_REQ_FLAGS and
313*32002227SRobert Mustacchi 	 * I2C_CORE_E_BAD_SMBUS_REQ_FLAGS as these are not flags that users are
314*32002227SRobert Mustacchi 	 * able to set and therefore the only reason these should be wrong is if
315*32002227SRobert Mustacchi 	 * we screwed something up in the library.
316*32002227SRobert Mustacchi 	 */
317*32002227SRobert Mustacchi 	{ I2C_CORE_E_BAD_I2C_REQ_READ_LEN, I2C_ERR_IO_READ_LEN_RANGE, "invalid "
318*32002227SRobert Mustacchi 	    "receive length" },
319*32002227SRobert Mustacchi 	{ I2C_CORE_E_BAD_I2C_REQ_WRITE_LEN, I2C_ERR_IO_WRITE_LEN_RANGE,
320*32002227SRobert Mustacchi 	    "invalid transmit length" },
321*32002227SRobert Mustacchi 	{ I2C_CORE_E_BAD_SMBUS_READ_LEN, I2C_ERR_IO_READ_LEN_RANGE, "invalid "
322*32002227SRobert Mustacchi 	    "receive length" },
323*32002227SRobert Mustacchi 	{ I2C_CORE_E_BAD_SMBUS_WRITE_LEN, I2C_ERR_IO_WRITE_LEN_RANGE,
324*32002227SRobert Mustacchi 	    "invalid transmit length" },
325*32002227SRobert Mustacchi 	{ I2C_CORE_E_UNSUP_SMBUS_OP, I2C_ERR_SMBUS_OP_UNSUP, "SMBus operation "
326*32002227SRobert Mustacchi 	    "unsupported by controller or system" },
327*32002227SRobert Mustacchi 	{ I2C_CORE_E_LOCK_WOULD_BLOCK, I2C_ERR_LOCK_WOULD_BLOCK, "lock not "
328*32002227SRobert Mustacchi 	    "available and no blocking allowed" },
329*32002227SRobert Mustacchi 	{ I2C_CORE_E_LOCK_WAIT_SIGNAL, I2C_ERR_LOCK_WAIT_SIGNAL, "signal "
330*32002227SRobert Mustacchi 	    "received while blocking" },
331*32002227SRobert Mustacchi 	/*
332*32002227SRobert Mustacchi 	 * We have purposefully skipped the nvlist device related errors,
333*32002227SRobert Mustacchi 	 * I2C_IOCTL_E_NVL_TOO_BIG, I2C_IOCTL_E_NVL_INVALID,
334*32002227SRobert Mustacchi 	 * I2C_IOCTL_E_NVL_KEY_MISSING, I2C_IOCTL_E_NVL_KEY_UNKNOWN, and
335*32002227SRobert Mustacchi 	 * I2C_IOCTL_E_NVL_KEY_BAD_TYPE. These are things that generally only
336*32002227SRobert Mustacchi 	 * the library can screw up.
337*32002227SRobert Mustacchi 	 */
338*32002227SRobert Mustacchi 	{ I2C_IOCTL_E_BAD_USER_DATA, I2C_ERR_BAD_PTR, "the kernel detected an "
339*32002227SRobert Mustacchi 	    "invalid user buffer while trying to read/write the passed in "
340*32002227SRobert Mustacchi 	    "buffer" },
341*32002227SRobert Mustacchi 	{ I2C_IOCTL_E_NO_KERN_MEM, I2C_ERR_NO_KERN_MEM, "the kerenl failed "
342*32002227SRobert Mustacchi 	    "to allocate memory for this operation" },
343*32002227SRobert Mustacchi 	{ I2C_IOCTL_E_BAD_DEV_NAME, I2C_ERR_BAD_DEV_NAME, "invalid device "
344*32002227SRobert Mustacchi 	    "or compatible name" },
345*32002227SRobert Mustacchi 	{ I2C_IOCTL_E_COMPAT_LEN_RANGE, I2C_ERR_COMPAT_LEN_RANGE, "invalid "
346*32002227SRobert Mustacchi 	    "compatible string length" },
347*32002227SRobert Mustacchi 	{ I2C_IOCTL_E_NEXUS, I2C_ERR_NEXUS, "unexpected kernel nexus driver "
348*32002227SRobert Mustacchi 	    "error" },
349*32002227SRobert Mustacchi 	/*
350*32002227SRobert Mustacchi 	 * We have purposefully skipped I2C_IOCTL_E_NO_BUS_LOCK_NEXUS as there
351*32002227SRobert Mustacchi 	 * is no way to take an explicit lock in userland right now.
352*32002227SRobert Mustacchi 	 */
353*32002227SRobert Mustacchi 	{ I2C_IOCTL_E_IN_PROGRESS, I2C_ERR_OP_IN_PROGRESS, "cannot perform "
354*32002227SRobert Mustacchi 	    "requested operation, handle already performing one" },
355*32002227SRobert Mustacchi 	/*
356*32002227SRobert Mustacchi 	 * All I2C_CLIENT class errors are skipped as they should not be
357*32002227SRobert Mustacchi 	 * returned to userland.
358*32002227SRobert Mustacchi 	 */
359*32002227SRobert Mustacchi 	{ I2C_PROP_E_UNSUP, I2C_ERR_PROP_UNSUP, "property unsupported by "
360*32002227SRobert Mustacchi 	    "controller" },
361*32002227SRobert Mustacchi 	{ I2C_PROP_E_UNKNOWN, I2C_ERR_BAD_PROP, "unknown property" },
362*32002227SRobert Mustacchi 	{ I2C_PROP_E_READ_ONLY, I2C_ERR_PROP_READ_ONLY, "property is "
363*32002227SRobert Mustacchi 	    "read-only" },
364*32002227SRobert Mustacchi 	{ I2C_PROP_E_SMALL_BUF, I2C_ERR_PROP_BUF_TOO_SMALL, "data buffer too "
365*32002227SRobert Mustacchi 	    "small for property" },
366*32002227SRobert Mustacchi 	{ I2C_PROP_E_TOO_BIG_BUF, I2C_ERR_PROP_BUF_TOO_BIG, "data buffer too "
367*32002227SRobert Mustacchi 	    "big for property" },
368*32002227SRobert Mustacchi 	/*
369*32002227SRobert Mustacchi 	 * Indicates that the property value is invalid.
370*32002227SRobert Mustacchi 	 */
371*32002227SRobert Mustacchi 	{ I2C_PROP_E_BAD_VAL, I2C_ERR_BAD_PROP, "invalid property value" },
372*32002227SRobert Mustacchi 	/*
373*32002227SRobert Mustacchi 	 * Indicates that the controller doesn't support setting properties.
374*32002227SRobert Mustacchi 	 */
375*32002227SRobert Mustacchi 	{ I2C_PROP_E_SET_UNSUP, I2C_ERR_SET_PROP_UNSUP, "controller does not "
376*32002227SRobert Mustacchi 	    "support setting properties" },
377*32002227SRobert Mustacchi 	/*
378*32002227SRobert Mustacchi 	 * Currently all MUX class errors are skipped as they aren't really
379*32002227SRobert Mustacchi 	 * expected here.
380*32002227SRobert Mustacchi 	 */
381*32002227SRobert Mustacchi };
382*32002227SRobert Mustacchi 
383*32002227SRobert Mustacchi bool
i2c_ioctl_error(i2c_hdl_t * hdl,const i2c_error_t * ioc,const char * desc)384*32002227SRobert Mustacchi i2c_ioctl_error(i2c_hdl_t *hdl, const i2c_error_t *ioc, const char *desc)
385*32002227SRobert Mustacchi {
386*32002227SRobert Mustacchi 	int ret;
387*32002227SRobert Mustacchi 	i2c_err_data_t *err = &hdl->ih_err;
388*32002227SRobert Mustacchi 	VERIFY3U(ioc->i2c_error, !=, I2C_CORE_E_OK);
389*32002227SRobert Mustacchi 
390*32002227SRobert Mustacchi 	err->ie_syserr = 0;
391*32002227SRobert Mustacchi 
392*32002227SRobert Mustacchi 	if (ioc->i2c_error == I2C_CORE_E_CONTROLLER) {
393*32002227SRobert Mustacchi 		const char *code = i2c_ctrl_errtostr(hdl, ioc->i2c_ctrl);
394*32002227SRobert Mustacchi 
395*32002227SRobert Mustacchi 		err->ie_err = I2C_ERR_CONTROLLER;
396*32002227SRobert Mustacchi 		err->ie_ctrl_err = ioc->i2c_ctrl;
397*32002227SRobert Mustacchi 		ret = snprintf(err->ie_errmsg, sizeof (err->ie_errmsg),
398*32002227SRobert Mustacchi 		    "failed to execute %s command: received controller "
399*32002227SRobert Mustacchi 		    "error %s (0x%x)", desc, code, ioc->i2c_ctrl);
400*32002227SRobert Mustacchi 	} else {
401*32002227SRobert Mustacchi 		const i2c_ktolmap_t *map = NULL;
402*32002227SRobert Mustacchi 		for (size_t i = 0; i < ARRAY_SIZE(i2c_ktolmap); i++) {
403*32002227SRobert Mustacchi 			if (i2c_ktolmap[i].kl_kern == ioc->i2c_error) {
404*32002227SRobert Mustacchi 				map = &i2c_ktolmap[i];
405*32002227SRobert Mustacchi 				break;
406*32002227SRobert Mustacchi 			}
407*32002227SRobert Mustacchi 		}
408*32002227SRobert Mustacchi 
409*32002227SRobert Mustacchi 		if (map != NULL) {
410*32002227SRobert Mustacchi 			err->ie_err = map->kl_lib;
411*32002227SRobert Mustacchi 			ret = snprintf(err->ie_errmsg, sizeof (err->ie_errmsg),
412*32002227SRobert Mustacchi 			    "failed to execute %s command: %s", desc,
413*32002227SRobert Mustacchi 			    map->kl_desc);
414*32002227SRobert Mustacchi 		} else {
415*32002227SRobert Mustacchi 			err->ie_err = I2C_ERR_INTERNAL;
416*32002227SRobert Mustacchi 			ret = snprintf(err->ie_errmsg, sizeof (err->ie_errmsg),
417*32002227SRobert Mustacchi 			    "failed to execute %s command: failed to map "
418*32002227SRobert Mustacchi 			    "kernel error 0x%x to a known cause", desc,
419*32002227SRobert Mustacchi 			    ioc->i2c_error);
420*32002227SRobert Mustacchi 		}
421*32002227SRobert Mustacchi 	}
422*32002227SRobert Mustacchi 
423*32002227SRobert Mustacchi 	if (ret >= sizeof (err->ie_errmsg)) {
424*32002227SRobert Mustacchi 		err->ie_errlen = sizeof (err->ie_errlen) - 1;
425*32002227SRobert Mustacchi 	} else if (ret <= 0) {
426*32002227SRobert Mustacchi 		err->ie_errlen = 0;
427*32002227SRobert Mustacchi 		err->ie_errmsg[0] = '\0';
428*32002227SRobert Mustacchi 	} else {
429*32002227SRobert Mustacchi 		err->ie_errlen = (size_t)ret;
430*32002227SRobert Mustacchi 	}
431*32002227SRobert Mustacchi 
432*32002227SRobert Mustacchi 	return (false);
433*32002227SRobert Mustacchi }
434*32002227SRobert Mustacchi 
435*32002227SRobert Mustacchi bool
i2c_nvlist_error(i2c_hdl_t * hdl,int ret,const char * desc)436*32002227SRobert Mustacchi i2c_nvlist_error(i2c_hdl_t *hdl, int ret, const char *desc)
437*32002227SRobert Mustacchi {
438*32002227SRobert Mustacchi 	if (ret == 0) {
439*32002227SRobert Mustacchi 		return (true);
440*32002227SRobert Mustacchi 	}
441*32002227SRobert Mustacchi 
442*32002227SRobert Mustacchi 	if (ret == ENOMEM) {
443*32002227SRobert Mustacchi 		return (i2c_error(hdl, I2C_ERR_NO_MEM, ret, "failed to "
444*32002227SRobert Mustacchi 		    "allocate memory to %s", desc));
445*32002227SRobert Mustacchi 	}
446*32002227SRobert Mustacchi 
447*32002227SRobert Mustacchi 	return (i2c_error(hdl, I2C_ERR_INTERNAL, ret, "unexpected internal "
448*32002227SRobert Mustacchi 	    "error while trying to %s", desc));
449*32002227SRobert Mustacchi }
450