xref: /illumos-gate/usr/src/lib/libi2c/common/libi2c.c (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 /*
17  * libi2c, a magical place that deals with everyone's favorite device class to
18  * hate.
19  */
20 
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <strings.h>
24 #include <sys/debug.h>
25 #include <sys/ilstr.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <sys/obpdefs.h>
29 
30 #include "libi2c_impl.h"
31 
32 void
33 i2c_fini(i2c_hdl_t *hdl)
34 {
35 	freelocale(hdl->ih_c_loc);
36 	(void) close(hdl->ih_devfd);
37 	free(hdl);
38 }
39 
40 i2c_hdl_t *
41 i2c_init(void)
42 {
43 	i2c_hdl_t *hdl;
44 
45 	hdl = calloc(1, sizeof (i2c_hdl_t));
46 	if (hdl == NULL) {
47 		return (NULL);
48 	}
49 
50 	hdl->ih_devfd = open("/devices", O_RDONLY | O_DIRECTORY);
51 	if (hdl->ih_devfd < 0) {
52 		free(hdl);
53 		return (NULL);
54 	}
55 
56 	hdl->ih_c_loc = newlocale(LC_ALL_MASK, "C", NULL);
57 	return (hdl);
58 }
59 
60 /*
61  * Provide a simple answer as to whether or not an address is a reserved
62  * address. This function is a bit awkward as invalid addresses are technically
63  * not reserved.
64  */
65 bool
66 i2c_addr_reserved(const i2c_addr_t *addr)
67 {
68 	switch (addr->ia_type) {
69 	case I2C_ADDR_7BIT:
70 		if (addr->ia_addr >= (1 << 7)) {
71 			return (false);
72 		}
73 		break;
74 	case I2C_ADDR_10BIT:
75 		if (addr->ia_addr >= (1 << 10)) {
76 			return (false);
77 		}
78 		break;
79 	default:
80 		return (false);
81 	}
82 
83 	/*
84 	 * Because we've already done a size check up above we know illegal
85 	 * 7-bit addresses that are reserved 10-bit addresses will have already
86 	 * been checked.
87 	 */
88 	switch (addr->ia_addr) {
89 	case I2C_RSVD_ADDR_GEN_CALL:
90 	case I2C_RSVD_ADDR_C_BUS:
91 	case I2C_RSVD_ADDR_DIFF_BUS:
92 	case I2C_RSVD_ADDR_FUTURE:
93 	case I2C_RSVD_ADDR_HS_0:
94 	case I2C_RSVD_ADDR_HS_1:
95 	case I2C_RSVD_ADDR_HS_2:
96 	case I2C_RSVD_ADDR_HS_3:
97 	case I2C_RSVD_ADDR_10B_0:
98 	case I2C_RSVD_ADDR_10B_1:
99 	case I2C_RSVD_ADDR_10B_2:
100 	case I2C_RSVD_ADDR_10B_3:
101 	case I2C_RSVD_ADDR_DID_0:
102 	case I2C_RSVD_ADDR_DID_1:
103 	case I2C_RSVD_ADDR_DID_2:
104 	case I2C_RSVD_ADDR_DID_3:
105 		return (true);
106 	default:
107 		return (false);
108 	}
109 }
110 
111 bool
112 i2c_addr_validate(i2c_hdl_t *hdl, const i2c_addr_t *addr)
113 {
114 	uint16_t max;
115 
116 	if (addr == NULL) {
117 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
118 		    "invalid i2c_addr_t pointer: %p", addr));
119 	}
120 
121 	switch (addr->ia_type) {
122 	case I2C_ADDR_7BIT:
123 		max = 1 << 7;
124 		break;
125 	case I2C_ADDR_10BIT:
126 		max = 1 << 10;
127 		break;
128 	default:
129 		return (i2c_error(hdl, I2C_ERR_BAD_ADDR_TYPE, 0, "invalid "
130 		    "address type family 0x%x", addr->ia_type));
131 	}
132 
133 	if (addr->ia_addr >= max) {
134 		return (i2c_error(hdl, I2C_ERR_BAD_ADDR, 0, "address 0x%x is "
135 		    "outside the valid range for the address type: [0x00, "
136 		    "0x%02x]", addr->ia_addr, max - 1));
137 	}
138 
139 	return (true);
140 }
141 
142 /*
143  * The set of valid characters for the 'name' and 'compatible' properties comes
144  * from IEEE 1275 (which was carried forward into device tree). A name must be
145  * at most 31 characters. It is allowed to contain lower case, upper case,
146  * numbers, and ",.+-_". We require the first character to be a letter. We check
147  * all of this against our copy of the C locale to ensure that a program in a
148  * different locale doesn't get a different answer.
149  */
150 CTASSERT(I2C_NAME_MAX == OBP_MAXDRVNAME);
151 bool
152 i2c_name_validate(i2c_hdl_t *hdl, const char *name, const char *desc)
153 {
154 	size_t len;
155 
156 	if (name == NULL) {
157 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
158 		    "invalid %s pointer: %p", desc, name));
159 	}
160 
161 	len = strnlen(name, I2C_NAME_MAX);
162 	if (len >= I2C_NAME_MAX) {
163 		return (i2c_error(hdl, I2C_ERR_BAD_DEV_NAME, 0, "%s exceeds "
164 		    "%u character length limit, including NUL", desc,
165 		    I2C_NAME_MAX));
166 	} else if (len == 0) {
167 		return (i2c_error(hdl, I2C_ERR_BAD_DEV_NAME, 0, "%s cannot "
168 		    "have zero length", desc));
169 	}
170 
171 	if (isalpha_l(name[0], hdl->ih_c_loc) == 0) {
172 		return (i2c_error(hdl, I2C_ERR_BAD_DEV_NAME, 0, "%s must "
173 		    "have an ASCII upper or lowercase first letter: found 0x%x",
174 		    desc, name[0]));
175 	}
176 
177 	for (size_t i = 1; i < len; i++) {
178 		if (isalpha_l(name[i], hdl->ih_c_loc) ||
179 		    isdigit_l(name[i], hdl->ih_c_loc)) {
180 			continue;
181 		}
182 
183 		if (name[i] == ',' || name[i] == '.' || name[i] == '+' ||
184 		    name[i] == '-' || name[i] == '_') {
185 			continue;
186 		}
187 
188 		return (i2c_error(hdl, I2C_ERR_BAD_DEV_NAME, 0, "%s character "
189 		    "%zu is not from the valid set: found 0x%x", desc, i,
190 		    name[i]));
191 	}
192 
193 	return (true);
194 }
195 
196 i2c_node_type_t
197 i2c_node_type(di_node_t dn)
198 {
199 	const char *drv = di_driver_name(dn);
200 	char *strs;
201 	int nstrs;
202 
203 	nstrs = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, "device_type",
204 	    &strs);
205 	if (nstrs == 1 && strcmp(strs, "i2c") == 0) {
206 		return (I2C_NODE_T_DEV);
207 	}
208 
209 	if (drv == NULL || strcmp(drv, I2C_NEX_DRV) != 0) {
210 		return (I2C_NODE_T_OTHER);
211 	}
212 
213 	nstrs = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, I2C_NEXUS_TYPE_PROP,
214 	    &strs);
215 	if (nstrs != 1) {
216 		return (I2C_NODE_T_OTHER);
217 	}
218 
219 	if (strcmp(strs, I2C_NEXUS_TYPE_PORT) == 0) {
220 		return (I2C_NODE_T_PORT);
221 	} else if (strcmp(strs, I2C_NEXUS_TYPE_CTRL) == 0) {
222 		return (I2C_NODE_T_CTRL);
223 	} else if (strcmp(strs, I2C_NEXUS_TYPE_MUX) == 0) {
224 		return (I2C_NODE_T_MUX);
225 	}
226 
227 	return (I2C_NODE_T_OTHER);
228 }
229 
230 /*
231  * Given a device node, find the corresponding minor node in its parent port.
232  * This node will be named after the kernel form of the device, which is going
233  * to be the type,addr aka reg[0],reg[1].
234  */
235 static di_minor_t
236 i2c_node_minor_device(di_node_t dn)
237 {
238 	int nreg, *reg;
239 	char name[32];
240 
241 	nreg = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", &reg);
242 	if (nreg == 0 || (nreg % 2) != 0) {
243 		return (DI_MINOR_NIL);
244 	}
245 
246 	(void) snprintf(name, sizeof (name), "%x,%x", reg[0], reg[1]);
247 	dn = di_parent_node(dn);
248 	if (i2c_node_type(dn) != I2C_NODE_T_PORT) {
249 		return (DI_MINOR_NIL);
250 	}
251 
252 	for (di_minor_t m = di_minor_next(dn, DI_MINOR_NIL); m != DI_MINOR_NIL;
253 	    m = di_minor_next(dn, m)) {
254 		if (strcmp(di_minor_nodetype(m), DDI_NT_I2C_DEV) == 0 &&
255 		    strcmp(di_minor_name(m), name) == 0) {
256 			return (m);
257 		}
258 	}
259 
260 	return (DI_MINOR_NIL);
261 }
262 
263 di_minor_t
264 i2c_node_minor(di_node_t dn)
265 {
266 	const char *nt;
267 	i2c_node_type_t type = i2c_node_type(dn);
268 
269 	switch (type) {
270 	case I2C_NODE_T_CTRL:
271 		nt = DDI_NT_I2C_CTRL;
272 		break;
273 	case I2C_NODE_T_PORT:
274 		nt = DDI_NT_I2C_PORT;
275 		break;
276 	case I2C_NODE_T_MUX:
277 		nt = DDI_NT_I2C_MUX;
278 		break;
279 	/*
280 	 * Device's don't have their control minor under them. The parent port
281 	 * has it, so when we need that, change this around to go search the
282 	 * parent for it.
283 	 */
284 	case I2C_NODE_T_DEV:
285 		return (i2c_node_minor_device(dn));
286 	default:
287 		return (DI_MINOR_NIL);
288 	}
289 
290 	for (di_minor_t m = di_minor_next(dn, DI_MINOR_NIL); m != DI_MINOR_NIL;
291 	    m = di_minor_next(dn, m)) {
292 		if (strcmp(di_minor_nodetype(m), nt) == 0) {
293 			return (m);
294 		}
295 	}
296 
297 	return (DI_MINOR_NIL);
298 }
299 
300 bool
301 i2c_node_is_type(di_node_t dn, i2c_node_type_t type)
302 {
303 	return (i2c_node_type(dn) == type);
304 }
305 
306 
307 /*
308  * This constructs the named i2c path that can be used to get to the node dn
309  * through a series of '/' delineated pieces. The canonical name to use varies
310  * based on the node type and stop once we hit a controller:
311  *
312  *  - controllers: controller name in the di_node_t address
313  *  - ports: port name in the di_node_t address
314  *  - devices: primary i2c address
315  */
316 bool
317 i2c_node_to_path(i2c_hdl_t *hdl, di_node_t dn, char *buf, size_t buflen)
318 {
319 	ilstr_t ils;
320 	bool first = true;
321 	i2c_addr_t addr;
322 	char addrstr[32];
323 
324 	ilstr_init_prealloc(&ils, buf, buflen);
325 
326 	for (;;) {
327 		i2c_node_type_t type = i2c_node_type(dn);
328 
329 		switch (type) {
330 		case I2C_NODE_T_CTRL:
331 		case I2C_NODE_T_PORT:
332 			if (!first) {
333 				ilstr_prepend_str(&ils, "/");
334 			}
335 			ilstr_prepend_str(&ils, di_bus_addr(dn));
336 			first = false;
337 			break;
338 		case I2C_NODE_T_MUX:
339 			/*
340 			 * The i2cnex that represents a mux today is not used in
341 			 * the logical path that we use with humans.
342 			 */
343 			break;
344 		case I2C_NODE_T_DEV:
345 			if (!first) {
346 				ilstr_prepend_str(&ils, "/");
347 			}
348 
349 			/*
350 			 * While it is tempting to use the bus address here, we
351 			 * cannot actually assume that a device address is
352 			 * valid. A device will only be addressed on the bus if
353 			 * a driver is attached to it.
354 			 *
355 			 * Therefore a device is identified with the primary
356 			 * address that it has, e.g. regs[0]. We use the
357 			 * somewhat more user firendly form of the address where
358 			 * 10-bit addresses have the leading '1,' to indicate
359 			 * the class, but 7-bit do not. As in practice that's
360 			 * what we'll be dealing with 99% of the time.
361 			 */
362 			if (!i2c_reg_to_addr(hdl, dn, &addr, 0)) {
363 				return (false);
364 			}
365 
366 			VERIFY(i2c_addr_to_string(hdl, &addr, addrstr,
367 			    sizeof (addrstr)));
368 			ilstr_prepend_str(&ils, addrstr);
369 			first = false;
370 			break;
371 		default:
372 			return (i2c_error(hdl, I2C_ERR_INTERNAL, 0,
373 			    "encountered unknown node type constructing path: "
374 			    "0x%x", type));
375 		}
376 
377 		/*
378 		 * If we've hit a controller we're done. However, look out in
379 		 * case we haven't and make sure we have a parent before
380 		 * continuing.
381 		 */
382 		if (type == I2C_NODE_T_CTRL)
383 			break;
384 
385 		dn = di_parent_node(dn);
386 		if (dn == DI_NODE_NIL)
387 			break;
388 	}
389 
390 	if (ilstr_errno(&ils) != ILSTR_ERROR_OK) {
391 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "failed to "
392 		    "construct string for node %s: %s", di_node_name(dn),
393 		    ilstr_errstr(&ils)));
394 	}
395 
396 	return (true);
397 }
398 
399 /*
400  * Parse the kernel's I2C device address style, <type>,<address>. The only
401  * thing assumed about str is that it is null terminated. The kernel integers
402  * for type and address are always in hex regardless of whether or not they
403  * have a leading 0x.
404  */
405 bool
406 i2c_kernel_address_parse(i2c_hdl_t *hdl, const char *str, i2c_addr_t *addr)
407 {
408 	char *eptr;
409 	unsigned long ul;
410 
411 	errno = 0;
412 	ul = strtoul(str, &eptr, 16);
413 	if (errno != 0 || *eptr != ',') {
414 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "kernel string %s "
415 		    "did not have a valid leading type", str));
416 	}
417 
418 	if (ul == I2C_ADDR_7BIT) {
419 		addr->ia_type = I2C_ADDR_7BIT;
420 	} else if (ul == I2C_ADDR_10BIT) {
421 		addr->ia_type = I2C_ADDR_10BIT;
422 	} else {
423 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "kernel string %s "
424 		    "did not have a valid type, found 0x%lx", str, ul));
425 	}
426 
427 	errno = 0;
428 	ul = strtoul(eptr + 1, &eptr, 16);
429 	if (errno != 0 || *eptr != '\0') {
430 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "kernel string %s "
431 		    "did not have a valid address", str));
432 	}
433 
434 	if ((addr->ia_type == I2C_ADDR_7BIT && ul >= 1 << 7) ||
435 	    (addr->ia_type == I2C_ADDR_10BIT && ul >= 1 << 10)) {
436 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "kernel string %s "
437 		    "address 0x%lx is too large for type", str, ul));
438 	}
439 
440 	addr->ia_addr = (uint16_t)ul;
441 	return (true);
442 }
443 
444 /*
445  * Parse a user address as compared to a kernel address. The main difference
446  * here is that the user address does not use a prefix for the 7-bit addresses
447  * and the 10-bit addresses use the "10b," prefix.
448  */
449 bool
450 i2c_addr_parse(i2c_hdl_t *hdl, const char *buf, i2c_addr_t *addr)
451 {
452 	char *eptr;
453 	unsigned long ul;
454 	const char *comma;
455 	uint16_t max;
456 
457 	if (buf == NULL) {
458 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
459 		    "invalid address string pointer: %p", buf));
460 	}
461 
462 	if (addr == NULL) {
463 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
464 		    "invalid i2c_addr_t pointer: %p", addr));
465 	}
466 
467 	comma = strchr(buf, ',');
468 	if (comma != NULL) {
469 		size_t len = (uintptr_t)comma - (uintptr_t)buf;
470 		if (len != 3 || strncmp("10b", buf, len) != 0) {
471 			return (i2c_error(hdl, I2C_ERR_BAD_ADDR_TYPE, 0,
472 			    "found invalid address type on %s", buf));
473 		}
474 		addr->ia_type = I2C_ADDR_10BIT;
475 		buf = comma + 1;
476 		max = 1 << 10;
477 	} else {
478 		addr->ia_type = I2C_ADDR_7BIT;
479 		max = 1 << 7;
480 	}
481 
482 	errno = 0;
483 	ul = strtoul(buf, &eptr, 0);
484 	if (errno != 0 || *eptr != '\0') {
485 		return (i2c_error(hdl, I2C_ERR_BAD_ADDR, 0, "address %s could "
486 		    "not be parsed", buf));
487 	}
488 
489 	if (ul >= max) {
490 		return (i2c_error(hdl, I2C_ERR_BAD_ADDR, 0, "address 0x%lx is "
491 		    "outside the valid range for the address type: [0x00, "
492 		    "0x%02x]", ul, max - 1));
493 	}
494 
495 	addr->ia_addr = (uint16_t)ul;
496 	return (true);
497 }
498 
499 bool
500 i2c_addr_to_string(i2c_hdl_t *hdl, const i2c_addr_t *addr, char *buf,
501     size_t len)
502 {
503 	size_t ret;
504 
505 	if (buf == NULL) {
506 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
507 		    "invalid address string pointer: %p", buf));
508 	}
509 
510 	if (addr == NULL) {
511 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
512 		    "invalid i2c_addr_t pointer: %p", addr));
513 	}
514 
515 	if (!i2c_addr_validate(hdl, addr)) {
516 		return (false);
517 	}
518 
519 	if (addr->ia_type == I2C_ADDR_10BIT) {
520 		ret = snprintf(buf, len, "10b,0x%03x", addr->ia_addr);
521 	} else {
522 		ret = snprintf(buf, len, "0x%02x", addr->ia_addr);
523 	}
524 	if (ret >= len) {
525 		return (i2c_error(hdl, I2C_ERR_BUF_TOO_SMALL, 0, "output "
526 		    "buffer is too small: need %zu bytes, have %zu", ret,
527 		    len));
528 	}
529 
530 	return (true);
531 }
532 
533 /*
534  * Convert the specified index for a device into an address.
535  */
536 bool
537 i2c_reg_to_addr(i2c_hdl_t *hdl, di_node_t dn, i2c_addr_t *addr, uint32_t n)
538 {
539 	int nreg, *reg;
540 	uint32_t type_idx = n * 2;
541 	uint32_t addr_idx = n * 2 + 1;
542 
543 	nreg = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", &reg);
544 	if (nreg == 0 || (nreg % 2) != 0) {
545 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "device %s@%s "
546 		    "does not have a valid i2c reg[] property",
547 		    di_node_name(dn), di_bus_addr(dn)));
548 	}
549 
550 	if (addr_idx >= nreg) {
551 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "device %s@%s "
552 		    "does not have a valid i2c reg[] property",
553 		    di_node_name(dn), di_bus_addr(dn)));
554 	}
555 
556 	if (reg[type_idx] == I2C_ADDR_7BIT) {
557 		addr->ia_type = I2C_ADDR_7BIT;
558 	} else if (reg[type_idx] == I2C_ADDR_10BIT) {
559 		addr->ia_type = I2C_ADDR_10BIT;
560 	} else {
561 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "device %s@%s "
562 		    "does not have a valid i2c address type, found 0x%x",
563 		    di_node_name(dn), di_bus_addr(dn), reg[type_idx]));
564 	}
565 
566 	if ((addr->ia_type == I2C_ADDR_7BIT && reg[addr_idx] >= 1 << 7) ||
567 	    (addr->ia_type == I2C_ADDR_10BIT && reg[addr_idx] >= 1 << 10)) {
568 		return (i2c_error(hdl, I2C_ERR_INTERNAL, 0, "device %s@%s "
569 		    "address 0x%x is too large for type", di_node_name(dn),
570 		    di_bus_addr(dn), reg[addr_idx]));
571 	}
572 
573 	addr->ia_addr = (uint16_t)reg[1];
574 
575 	return (true);
576 }
577 
578 bool
579 i2c_addr_equal(const i2c_addr_t *a, const i2c_addr_t *b)
580 {
581 	return (a->ia_type == b->ia_type && a->ia_addr == b->ia_addr);
582 }
583 
584 di_node_t
585 i2c_path_find_ctrl(di_node_t root, const char *name)
586 {
587 	for (di_node_t di = di_drv_first_node(I2C_NEX_DRV, root); di != NULL;
588 	    di = di_drv_next_node(di)) {
589 		if (!i2c_node_is_type(di, I2C_NODE_T_CTRL)) {
590 			continue;
591 		}
592 
593 		if (strcmp(name, di_bus_addr(di)) == 0) {
594 			return (di);
595 		}
596 	}
597 
598 	return (DI_NODE_NIL);
599 }
600 
601 di_node_t
602 i2c_path_find_mux(di_node_t dev)
603 {
604 	for (di_node_t dn = di_child_node(dev); dn != NULL;
605 	    dn = di_sibling_node(dn)) {
606 		if (i2c_node_type(dn) == I2C_NODE_T_MUX) {
607 			return (dn);
608 		}
609 	}
610 
611 	return (DI_NODE_NIL);
612 }
613 
614 di_node_t
615 i2c_path_find_port(di_node_t parent, const char *name)
616 {
617 	for (di_node_t dn = di_child_node(parent); dn != NULL;
618 	    dn = di_sibling_node(dn)) {
619 		if (!i2c_node_is_type(dn, I2C_NODE_T_PORT)) {
620 			continue;
621 		}
622 
623 		if (strcmp(di_bus_addr(dn), name) == 0) {
624 			return (dn);
625 		}
626 	}
627 
628 	return (DI_NODE_NIL);
629 }
630 
631 /*
632  * When parsing a device, there are three different options that we accept:
633  *
634  *  - The device's name@address
635  *  - The device's address
636  *  - The device's driver and instance (e.g. spd511x2)
637  *
638  * The address is always reg[0] because the aactual node address may not exist
639  * at this time. Similarly, we cannot assume that a driver is bound and attached
640  * to the node.
641  */
642 di_node_t
643 i2c_path_find_device(i2c_hdl_t *hdl, di_node_t port, const char *name)
644 {
645 	for (di_node_t dn = di_child_node(port); dn != NULL;
646 	    dn = di_sibling_node(dn)) {
647 		i2c_addr_t daddr;
648 		char daddrstr[32];
649 
650 		if (i2c_node_type(dn) != I2C_NODE_T_DEV) {
651 			continue;
652 		}
653 
654 		if (!i2c_reg_to_addr(hdl, dn, &daddr, 0)) {
655 			continue;
656 		}
657 
658 		if (!i2c_addr_to_string(hdl, &daddr, daddrstr,
659 		    sizeof (daddrstr))) {
660 			continue;
661 		}
662 
663 		/*
664 		 * Always check if we match on the converted address.
665 		 */
666 		if (strcmp(name, daddrstr) == 0) {
667 			return (dn);
668 		}
669 
670 		/*
671 		 * We didn't match on that, is there a driver?
672 		 */
673 		if (di_driver_name(dn) != NULL && di_instance(dn) != -1) {
674 			char buf[128];
675 
676 			(void) snprintf(buf, sizeof (buf), "%s%d",
677 			    di_driver_name(dn), di_instance(dn));
678 			if (strcmp(name, buf) == 0) {
679 				return (dn);
680 			}
681 		}
682 
683 		/*
684 		 * Finally check if we match name@addr. Only do this if we have
685 		 * an actual @ in the user bit.
686 		 */
687 		const char *at = strchr(name, '@');
688 		if (at != NULL) {
689 			char buf[128];
690 
691 			(void) snprintf(buf, sizeof (buf), "%s@%s",
692 			    di_node_name(dn), daddrstr);
693 			if (strcmp(name, buf) == 0) {
694 				return (dn);
695 			}
696 		}
697 	}
698 
699 	return (DI_NODE_NIL);
700 }
701 
702 bool
703 i2c_path_parse(i2c_hdl_t *hdl, const char *path, di_node_t root, di_node_t *dnp,
704     i2c_node_type_t *typep, i2c_err_t err)
705 {
706 	di_node_t cur_devi;
707 	char *dup, *state;
708 	i2c_node_type_t cur;
709 	bool ret = false;
710 
711 	if (path == NULL) {
712 		return (i2c_error(hdl, I2C_ERR_BAD_PTR, 0, "encountered "
713 		    "invalid I2C path pointer: %p", path));
714 	}
715 
716 	dup = strdup(path);
717 	if (dup == NULL) {
718 		int e = errno;
719 		return (i2c_error(hdl, I2C_ERR_NO_MEM, e, "failed to duplicate "
720 		    "I2C path"));
721 	}
722 
723 	cur = I2C_NODE_T_OTHER;
724 	cur_devi = NULL;
725 	for (const char *ent = strtok_r(dup, "/", &state); ent != NULL;
726 	    ent = strtok_r(NULL, "/", &state)) {
727 		switch (cur) {
728 		case I2C_NODE_T_OTHER:
729 			/*
730 			 * This is our top-level state. We need to find a
731 			 * controller that matches this name.
732 			 */
733 			cur_devi = i2c_path_find_ctrl(root, ent);
734 			if (cur_devi == DI_NODE_NIL) {
735 				(void) i2c_error(hdl, err, 0,
736 				    "failed to find controller %s as part of "
737 				    "parsing I2C path %s", ent, path);
738 				goto err;
739 			}
740 			cur = I2C_NODE_T_CTRL;
741 			break;
742 		case I2C_NODE_T_DEV:
743 			/*
744 			 * Today we expect a device to only ever have a single
745 			 * node under it which is a mux. We walk all the
746 			 * children and look for this. This is because muxes
747 			 * aren't named. It's possible someone has created more
748 			 * than one node, so that's why we don't just go
749 			 * directly. After we do this, we explicitly fall
750 			 * through to the controller handling logic, as it has
751 			 * to do the same class.
752 			 */
753 			cur_devi = i2c_path_find_mux(cur_devi);
754 			if (cur_devi == DI_NODE_NIL) {
755 				(void) i2c_error(hdl, err, 0,
756 				    "failed to find mux %s as part of "
757 				    "parsing I2C path %s", ent, path);
758 				goto err;
759 			}
760 			/* FALLTHROUGH */
761 		case I2C_NODE_T_CTRL:
762 			cur_devi = i2c_path_find_port(cur_devi, ent);
763 			if (cur_devi == DI_NODE_NIL) {
764 				(void) i2c_error(hdl, err, 0,
765 				    "failed to find port %s as part of "
766 				    "parsing I2C path %s", ent, path);
767 				goto err;
768 			}
769 			cur = I2C_NODE_T_PORT;
770 			break;
771 		case I2C_NODE_T_PORT:
772 			cur_devi = i2c_path_find_device(hdl, cur_devi, ent);
773 			if (cur_devi == DI_NODE_NIL) {
774 				(void) i2c_error(hdl, err, 0,
775 				    "failed to find device %s as part of "
776 				    "parsing I2C path %s", ent, path);
777 				goto err;
778 			}
779 			cur = I2C_NODE_T_DEV;
780 			break;
781 		default:
782 			abort();
783 		}
784 	}
785 
786 	*dnp = cur_devi;
787 	*typep = cur;
788 	ret = true;
789 
790 err:
791 	free(dup);
792 	return (ret);
793 }
794