1*0cbe4818SRobert Mustacchi /*
2*0cbe4818SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*0cbe4818SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*0cbe4818SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*0cbe4818SRobert Mustacchi * 1.0 of the CDDL.
6*0cbe4818SRobert Mustacchi *
7*0cbe4818SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*0cbe4818SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*0cbe4818SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*0cbe4818SRobert Mustacchi */
11*0cbe4818SRobert Mustacchi
12*0cbe4818SRobert Mustacchi /*
13*0cbe4818SRobert Mustacchi * Copyright 2025 Oxide Computer Company
14*0cbe4818SRobert Mustacchi */
15*0cbe4818SRobert Mustacchi
16*0cbe4818SRobert Mustacchi /*
17*0cbe4818SRobert Mustacchi * Test various aspects of creating and removing devices. This operates on the
18*0cbe4818SRobert Mustacchi * smbussim1/0 port where there are no devices by default. In particular we
19*0cbe4818SRobert Mustacchi * want to verify a few different properties:
20*0cbe4818SRobert Mustacchi *
21*0cbe4818SRobert Mustacchi * - Invalid nvlists and missing nvlist fields are caught
22*0cbe4818SRobert Mustacchi * - The device name and compatible array are correctly populated
23*0cbe4818SRobert Mustacchi * - Address allocation across ports is sensible, meaning that something on the
24*0cbe4818SRobert Mustacchi * top-level port stops allocations on downstream ports and vice-versa
25*0cbe4818SRobert Mustacchi *
26*0cbe4818SRobert Mustacchi * Unlike the i2cadm tests, we care about the specific kernel ioctl return
27*0cbe4818SRobert Mustacchi * values.
28*0cbe4818SRobert Mustacchi */
29*0cbe4818SRobert Mustacchi
30*0cbe4818SRobert Mustacchi #include <stdlib.h>
31*0cbe4818SRobert Mustacchi #include <unistd.h>
32*0cbe4818SRobert Mustacchi #include <err.h>
33*0cbe4818SRobert Mustacchi #include <sys/debug.h>
34*0cbe4818SRobert Mustacchi #include <sys/stat.h>
35*0cbe4818SRobert Mustacchi #include <fcntl.h>
36*0cbe4818SRobert Mustacchi #include <string.h>
37*0cbe4818SRobert Mustacchi #include <errno.h>
38*0cbe4818SRobert Mustacchi #include <sys/mman.h>
39*0cbe4818SRobert Mustacchi #include <sys/nvpair.h>
40*0cbe4818SRobert Mustacchi #include <sys/sysmacros.h>
41*0cbe4818SRobert Mustacchi #include <libdevinfo.h>
42*0cbe4818SRobert Mustacchi
43*0cbe4818SRobert Mustacchi #include <sys/i2c/ioctl.h>
44*0cbe4818SRobert Mustacchi #include "i2c_ioctl_util.h"
45*0cbe4818SRobert Mustacchi
46*0cbe4818SRobert Mustacchi static const char *bad_names[] = {
47*0cbe4818SRobert Mustacchi "",
48*0cbe4818SRobert Mustacchi "thisisalongstringthatshouldbetoolongbuthasvalidchars",
49*0cbe4818SRobert Mustacchi "0nonum",
50*0cbe4818SRobert Mustacchi "42",
51*0cbe4818SRobert Mustacchi "help#",
52*0cbe4818SRobert Mustacchi "!at24c32",
53*0cbe4818SRobert Mustacchi "at24%c32",
54*0cbe4818SRobert Mustacchi "at@24xc32",
55*0cbe4818SRobert Mustacchi "three rings",
56*0cbe4818SRobert Mustacchi "elven(kings)",
57*0cbe4818SRobert Mustacchi "ゼルダの伝説"
58*0cbe4818SRobert Mustacchi };
59*0cbe4818SRobert Mustacchi
60*0cbe4818SRobert Mustacchi static bool
test_add(int fd,const void * arg,size_t len,i2c_errno_t err,const char * desc)61*0cbe4818SRobert Mustacchi test_add(int fd, const void *arg, size_t len, i2c_errno_t err, const char *desc)
62*0cbe4818SRobert Mustacchi {
63*0cbe4818SRobert Mustacchi bool ret = true;
64*0cbe4818SRobert Mustacchi ui2c_dev_add_t add = {
65*0cbe4818SRobert Mustacchi .uda_error = {
66*0cbe4818SRobert Mustacchi /*
67*0cbe4818SRobert Mustacchi * We use token values here to make sure that they're
68*0cbe4818SRobert Mustacchi * always set by the target.
69*0cbe4818SRobert Mustacchi */
70*0cbe4818SRobert Mustacchi INT32_MIN,
71*0cbe4818SRobert Mustacchi INT32_MIN
72*0cbe4818SRobert Mustacchi },
73*0cbe4818SRobert Mustacchi .uda_nvl = (uintptr_t)arg,
74*0cbe4818SRobert Mustacchi .uda_nvl_len = len
75*0cbe4818SRobert Mustacchi };
76*0cbe4818SRobert Mustacchi
77*0cbe4818SRobert Mustacchi if (ioctl(fd, UI2C_IOCTL_DEVICE_ADD, &add) != 0) {
78*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s: add ioctl failed unexpectedly with "
79*0cbe4818SRobert Mustacchi "errno %s", desc, strerrorname_np(errno));
80*0cbe4818SRobert Mustacchi return (false);
81*0cbe4818SRobert Mustacchi }
82*0cbe4818SRobert Mustacchi
83*0cbe4818SRobert Mustacchi if (add.uda_error.i2c_error != err) {
84*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s: ioctl failed with I2C error 0x%x, "
85*0cbe4818SRobert Mustacchi "expected 0x%x", desc, add.uda_error.i2c_error, err);
86*0cbe4818SRobert Mustacchi ret = false;
87*0cbe4818SRobert Mustacchi }
88*0cbe4818SRobert Mustacchi
89*0cbe4818SRobert Mustacchi if (add.uda_error.i2c_ctrl != I2C_CTRL_E_OK) {
90*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s: ioctl has unexpected controller "
91*0cbe4818SRobert Mustacchi "error 0x%x", desc, add.uda_error.i2c_ctrl);
92*0cbe4818SRobert Mustacchi ret = false;
93*0cbe4818SRobert Mustacchi }
94*0cbe4818SRobert Mustacchi
95*0cbe4818SRobert Mustacchi if (ret) {
96*0cbe4818SRobert Mustacchi if (err == I2C_CORE_E_OK) {
97*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: %s correctly created "
98*0cbe4818SRobert Mustacchi "device\n", desc);
99*0cbe4818SRobert Mustacchi } else {
100*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: %s correctly failed with "
101*0cbe4818SRobert Mustacchi "0x%x\n", desc, err);
102*0cbe4818SRobert Mustacchi }
103*0cbe4818SRobert Mustacchi }
104*0cbe4818SRobert Mustacchi
105*0cbe4818SRobert Mustacchi return (ret);
106*0cbe4818SRobert Mustacchi }
107*0cbe4818SRobert Mustacchi
108*0cbe4818SRobert Mustacchi static bool
test_add_nvlist(int fd,nvlist_t * nvl,i2c_errno_t err,const char * desc)109*0cbe4818SRobert Mustacchi test_add_nvlist(int fd, nvlist_t *nvl, i2c_errno_t err, const char *desc)
110*0cbe4818SRobert Mustacchi {
111*0cbe4818SRobert Mustacchi size_t len;
112*0cbe4818SRobert Mustacchi char *data = fnvlist_pack(nvl, &len);
113*0cbe4818SRobert Mustacchi bool ret = test_add(fd, data, len, err, desc);
114*0cbe4818SRobert Mustacchi fnvlist_pack_free(data, len);
115*0cbe4818SRobert Mustacchi return (ret);
116*0cbe4818SRobert Mustacchi }
117*0cbe4818SRobert Mustacchi
118*0cbe4818SRobert Mustacchi static bool
test_bad_nvlists(int fd)119*0cbe4818SRobert Mustacchi test_bad_nvlists(int fd)
120*0cbe4818SRobert Mustacchi {
121*0cbe4818SRobert Mustacchi bool ret = true;
122*0cbe4818SRobert Mustacchi const char *str = "I promise I'm an nvlist_t";
123*0cbe4818SRobert Mustacchi
124*0cbe4818SRobert Mustacchi if (!test_add(fd, NULL, 4 * 1024 * 1024, I2C_IOCTL_E_NVL_TOO_BIG,
125*0cbe4818SRobert Mustacchi "nvlist_t too large to copy in")) {
126*0cbe4818SRobert Mustacchi ret = false;
127*0cbe4818SRobert Mustacchi }
128*0cbe4818SRobert Mustacchi
129*0cbe4818SRobert Mustacchi size_t pgsz = (size_t)sysconf(_SC_PAGESIZE);
130*0cbe4818SRobert Mustacchi void *addr = mmap(NULL, pgsz, PROT_NONE, MAP_PRIVATE | MAP_ANON,
131*0cbe4818SRobert Mustacchi -1, 0);
132*0cbe4818SRobert Mustacchi VERIFY3P(addr, !=, NULL);
133*0cbe4818SRobert Mustacchi if (!test_add(fd, addr, pgsz, I2C_IOCTL_E_BAD_USER_DATA, "unreadable "
134*0cbe4818SRobert Mustacchi "user data")) {
135*0cbe4818SRobert Mustacchi ret = false;
136*0cbe4818SRobert Mustacchi }
137*0cbe4818SRobert Mustacchi VERIFY0(munmap(addr, pgsz));
138*0cbe4818SRobert Mustacchi
139*0cbe4818SRobert Mustacchi if (!test_add(fd, str, strlen(str) + 1, I2C_IOCTL_E_NVL_INVALID,
140*0cbe4818SRobert Mustacchi "unparseable nvlist_t")) {
141*0cbe4818SRobert Mustacchi ret = false;
142*0cbe4818SRobert Mustacchi }
143*0cbe4818SRobert Mustacchi
144*0cbe4818SRobert Mustacchi /*
145*0cbe4818SRobert Mustacchi * Go through and test all of the missing keys cases.
146*0cbe4818SRobert Mustacchi */
147*0cbe4818SRobert Mustacchi nvlist_t *nvl = fnvlist_alloc();
148*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_MISSING, "missing "
149*0cbe4818SRobert Mustacchi "keys (all)")) {
150*0cbe4818SRobert Mustacchi ret = false;
151*0cbe4818SRobert Mustacchi }
152*0cbe4818SRobert Mustacchi
153*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x00);
154*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
155*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_MISSING, "missing "
156*0cbe4818SRobert Mustacchi "keys (name)")) {
157*0cbe4818SRobert Mustacchi ret = false;
158*0cbe4818SRobert Mustacchi }
159*0cbe4818SRobert Mustacchi nvlist_free(nvl);
160*0cbe4818SRobert Mustacchi
161*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
162*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x00);
163*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
164*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_MISSING, "missing "
165*0cbe4818SRobert Mustacchi "keys (type)")) {
166*0cbe4818SRobert Mustacchi ret = false;
167*0cbe4818SRobert Mustacchi }
168*0cbe4818SRobert Mustacchi nvlist_free(nvl);
169*0cbe4818SRobert Mustacchi
170*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
171*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
172*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
173*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_MISSING, "missing "
174*0cbe4818SRobert Mustacchi "keys (type)")) {
175*0cbe4818SRobert Mustacchi ret = false;
176*0cbe4818SRobert Mustacchi }
177*0cbe4818SRobert Mustacchi nvlist_free(nvl);
178*0cbe4818SRobert Mustacchi
179*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
180*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x00);
181*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
182*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_NAME, 0x42);
183*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_BAD_TYPE, "bad key "
184*0cbe4818SRobert Mustacchi "type (name)")) {
185*0cbe4818SRobert Mustacchi ret = false;
186*0cbe4818SRobert Mustacchi }
187*0cbe4818SRobert Mustacchi nvlist_free(nvl);
188*0cbe4818SRobert Mustacchi
189*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
190*0cbe4818SRobert Mustacchi fnvlist_add_uint32(nvl, UI2C_IOCTL_NVL_ADDR, 0x00);
191*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
192*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
193*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_BAD_TYPE, "bad key "
194*0cbe4818SRobert Mustacchi "type (addr)")) {
195*0cbe4818SRobert Mustacchi ret = false;
196*0cbe4818SRobert Mustacchi }
197*0cbe4818SRobert Mustacchi nvlist_free(nvl);
198*0cbe4818SRobert Mustacchi
199*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
200*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x00);
201*0cbe4818SRobert Mustacchi fnvlist_add_int64(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
202*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
203*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_BAD_TYPE, "bad key "
204*0cbe4818SRobert Mustacchi "type (type)")) {
205*0cbe4818SRobert Mustacchi ret = false;
206*0cbe4818SRobert Mustacchi }
207*0cbe4818SRobert Mustacchi nvlist_free(nvl);
208*0cbe4818SRobert Mustacchi
209*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
210*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x00);
211*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
212*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
213*0cbe4818SRobert Mustacchi fnvlist_add_byte_array(nvl, UI2C_IOCTL_NVL_COMPAT, (uchar_t *)str,
214*0cbe4818SRobert Mustacchi strlen(str));
215*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_BAD_TYPE, "bad key "
216*0cbe4818SRobert Mustacchi "type (compat)")) {
217*0cbe4818SRobert Mustacchi ret = false;
218*0cbe4818SRobert Mustacchi }
219*0cbe4818SRobert Mustacchi nvlist_free(nvl);
220*0cbe4818SRobert Mustacchi
221*0cbe4818SRobert Mustacchi for (size_t i = 0; i < nbad_addrs; i++) {
222*0cbe4818SRobert Mustacchi char desc[128];
223*0cbe4818SRobert Mustacchi
224*0cbe4818SRobert Mustacchi (void) snprintf(desc, sizeof (desc), "bad address %zu "
225*0cbe4818SRobert Mustacchi "(0x%x,0x%x)", i, bad_addrs[i].ba_type,
226*0cbe4818SRobert Mustacchi bad_addrs[i].ba_addr);
227*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
228*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE,
229*0cbe4818SRobert Mustacchi bad_addrs[i].ba_type);
230*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR,
231*0cbe4818SRobert Mustacchi bad_addrs[i].ba_addr);
232*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
233*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, bad_addrs[i].ba_error, desc)) {
234*0cbe4818SRobert Mustacchi ret = false;
235*0cbe4818SRobert Mustacchi }
236*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
237*0cbe4818SRobert Mustacchi }
238*0cbe4818SRobert Mustacchi
239*0cbe4818SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(bad_names); i++) {
240*0cbe4818SRobert Mustacchi char desc[128];
241*0cbe4818SRobert Mustacchi
242*0cbe4818SRobert Mustacchi (void) snprintf(desc, sizeof (desc), "bad names %zu", i);
243*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
244*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
245*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x42);
246*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, bad_names[i]);
247*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_BAD_DEV_NAME, desc)) {
248*0cbe4818SRobert Mustacchi ret = false;
249*0cbe4818SRobert Mustacchi }
250*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
251*0cbe4818SRobert Mustacchi }
252*0cbe4818SRobert Mustacchi
253*0cbe4818SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(bad_names); i++) {
254*0cbe4818SRobert Mustacchi char desc[128];
255*0cbe4818SRobert Mustacchi
256*0cbe4818SRobert Mustacchi (void) snprintf(desc, sizeof (desc), "bad compat %zu", i);
257*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
258*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
259*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x42);
260*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
261*0cbe4818SRobert Mustacchi fnvlist_add_string_array(nvl, UI2C_IOCTL_NVL_COMPAT,
262*0cbe4818SRobert Mustacchi (char * const *)&bad_names[i], 1);
263*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_BAD_DEV_NAME, desc)) {
264*0cbe4818SRobert Mustacchi ret = false;
265*0cbe4818SRobert Mustacchi }
266*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
267*0cbe4818SRobert Mustacchi }
268*0cbe4818SRobert Mustacchi
269*0cbe4818SRobert Mustacchi char *compat[42];
270*0cbe4818SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(compat); i++) {
271*0cbe4818SRobert Mustacchi compat[i] = "at24c32";
272*0cbe4818SRobert Mustacchi }
273*0cbe4818SRobert Mustacchi
274*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
275*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
276*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x42);
277*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
278*0cbe4818SRobert Mustacchi fnvlist_add_string_array(nvl, UI2C_IOCTL_NVL_COMPAT, compat,
279*0cbe4818SRobert Mustacchi ARRAY_SIZE(compat));
280*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_COMPAT_LEN_RANGE,
281*0cbe4818SRobert Mustacchi "compat[] too long")) {
282*0cbe4818SRobert Mustacchi ret = false;
283*0cbe4818SRobert Mustacchi }
284*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
285*0cbe4818SRobert Mustacchi
286*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
287*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
288*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x42);
289*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "foobar");
290*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, "magicite", "materia");
291*0cbe4818SRobert Mustacchi
292*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_IOCTL_E_NVL_KEY_UNKNOWN,
293*0cbe4818SRobert Mustacchi "extra keys")) {
294*0cbe4818SRobert Mustacchi ret = false;
295*0cbe4818SRobert Mustacchi }
296*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
297*0cbe4818SRobert Mustacchi
298*0cbe4818SRobert Mustacchi return (ret);
299*0cbe4818SRobert Mustacchi }
300*0cbe4818SRobert Mustacchi
301*0cbe4818SRobert Mustacchi static bool
test_add_device(int fd,const char * name,uint8_t addr,i2c_errno_t err,const char * desc)302*0cbe4818SRobert Mustacchi test_add_device(int fd, const char *name, uint8_t addr, i2c_errno_t err,
303*0cbe4818SRobert Mustacchi const char *desc)
304*0cbe4818SRobert Mustacchi {
305*0cbe4818SRobert Mustacchi nvlist_t *nvl = fnvlist_alloc();
306*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
307*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, addr);
308*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, name);
309*0cbe4818SRobert Mustacchi bool ret = test_add_nvlist(fd, nvl, err, desc);
310*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
311*0cbe4818SRobert Mustacchi return (ret);
312*0cbe4818SRobert Mustacchi }
313*0cbe4818SRobert Mustacchi
314*0cbe4818SRobert Mustacchi static bool
test_address_conflicts(int fd)315*0cbe4818SRobert Mustacchi test_address_conflicts(int fd)
316*0cbe4818SRobert Mustacchi {
317*0cbe4818SRobert Mustacchi bool ret = true;
318*0cbe4818SRobert Mustacchi
319*0cbe4818SRobert Mustacchi if (!test_add_device(fd, "pca9548", 0x70, I2C_CORE_E_OK, "create "
320*0cbe4818SRobert Mustacchi "pca9548")) {
321*0cbe4818SRobert Mustacchi ret = false;
322*0cbe4818SRobert Mustacchi }
323*0cbe4818SRobert Mustacchi
324*0cbe4818SRobert Mustacchi if (!test_add_device(fd, "fake-device", 0x70, I2C_CORE_E_ADDR_IN_USE,
325*0cbe4818SRobert Mustacchi "address in use fails (0x70)")) {
326*0cbe4818SRobert Mustacchi ret = false;
327*0cbe4818SRobert Mustacchi }
328*0cbe4818SRobert Mustacchi
329*0cbe4818SRobert Mustacchi int pfd0 = i2c_ioctl_test_get_fd(I2C_D_PORT, "smbussim1/0/0x70/mux/0",
330*0cbe4818SRobert Mustacchi O_RDWR);
331*0cbe4818SRobert Mustacchi int pfd4 = i2c_ioctl_test_get_fd(I2C_D_PORT, "smbussim1/0/0x70/mux/4",
332*0cbe4818SRobert Mustacchi O_RDWR);
333*0cbe4818SRobert Mustacchi
334*0cbe4818SRobert Mustacchi /*
335*0cbe4818SRobert Mustacchi * Verify that an address used downstream on the mux cannot be used
336*0cbe4818SRobert Mustacchi * upstream of it.
337*0cbe4818SRobert Mustacchi */
338*0cbe4818SRobert Mustacchi if (!test_add_device(pfd0, "fake-device", 0x42, I2C_CORE_E_OK, "create "
339*0cbe4818SRobert Mustacchi "fake device (ox42) on mux port 0")) {
340*0cbe4818SRobert Mustacchi ret = false;
341*0cbe4818SRobert Mustacchi }
342*0cbe4818SRobert Mustacchi
343*0cbe4818SRobert Mustacchi if (!test_add_device(pfd4, "fake-device", 0x42, I2C_CORE_E_OK, "create "
344*0cbe4818SRobert Mustacchi "fake device (ox42) on mux port 4")) {
345*0cbe4818SRobert Mustacchi ret = false;
346*0cbe4818SRobert Mustacchi }
347*0cbe4818SRobert Mustacchi
348*0cbe4818SRobert Mustacchi if (!test_add_device(fd, "fake-device", 0x42, I2C_CORE_E_ADDR_IN_USE,
349*0cbe4818SRobert Mustacchi "cannot create device on upstream port used on downstream ports")) {
350*0cbe4818SRobert Mustacchi ret = false;
351*0cbe4818SRobert Mustacchi }
352*0cbe4818SRobert Mustacchi
353*0cbe4818SRobert Mustacchi /*
354*0cbe4818SRobert Mustacchi * Verify that an address used on the top-level port cannot be used
355*0cbe4818SRobert Mustacchi * downstream of it.
356*0cbe4818SRobert Mustacchi */
357*0cbe4818SRobert Mustacchi if (test_add_device(fd, "fake-device", 0x23, I2C_CORE_E_OK, "create "
358*0cbe4818SRobert Mustacchi "fake device (0x23)")) {
359*0cbe4818SRobert Mustacchi if (!test_add_device(pfd0, "fake-device", 0x23,
360*0cbe4818SRobert Mustacchi I2C_CORE_E_ADDR_IN_USE, "cannot allocate address on "
361*0cbe4818SRobert Mustacchi "downstream port when used upstream (1)")) {
362*0cbe4818SRobert Mustacchi ret = false;
363*0cbe4818SRobert Mustacchi }
364*0cbe4818SRobert Mustacchi
365*0cbe4818SRobert Mustacchi if (!test_add_device(pfd4, "fake-device", 0x23,
366*0cbe4818SRobert Mustacchi I2C_CORE_E_ADDR_IN_USE, "cannot allocate address on "
367*0cbe4818SRobert Mustacchi "downstream port when used upstream (2)")) {
368*0cbe4818SRobert Mustacchi ret = false;
369*0cbe4818SRobert Mustacchi }
370*0cbe4818SRobert Mustacchi } else {
371*0cbe4818SRobert Mustacchi ret = false;
372*0cbe4818SRobert Mustacchi }
373*0cbe4818SRobert Mustacchi
374*0cbe4818SRobert Mustacchi VERIFY0(close(pfd4));
375*0cbe4818SRobert Mustacchi VERIFY0(close(pfd0));
376*0cbe4818SRobert Mustacchi return (ret);
377*0cbe4818SRobert Mustacchi }
378*0cbe4818SRobert Mustacchi
379*0cbe4818SRobert Mustacchi typedef struct {
380*0cbe4818SRobert Mustacchi bool tcc_ret;
381*0cbe4818SRobert Mustacchi bool tcc_compat0;
382*0cbe4818SRobert Mustacchi bool tcc_compat1;
383*0cbe4818SRobert Mustacchi char **tcc_compat;
384*0cbe4818SRobert Mustacchi } test_compat_cb_t;
385*0cbe4818SRobert Mustacchi
386*0cbe4818SRobert Mustacchi static int
test_compat_walk_cb(di_node_t di,void * arg)387*0cbe4818SRobert Mustacchi test_compat_walk_cb(di_node_t di, void *arg)
388*0cbe4818SRobert Mustacchi {
389*0cbe4818SRobert Mustacchi test_compat_cb_t *cb = arg;
390*0cbe4818SRobert Mustacchi const char *name = di_node_name(di);
391*0cbe4818SRobert Mustacchi int exp;
392*0cbe4818SRobert Mustacchi
393*0cbe4818SRobert Mustacchi if (strcmp(name, "fake-compat-0") == 0) {
394*0cbe4818SRobert Mustacchi cb->tcc_compat0 = true;
395*0cbe4818SRobert Mustacchi exp = 1;
396*0cbe4818SRobert Mustacchi } else if (strcmp(name, "fake-compat-1") == 0) {
397*0cbe4818SRobert Mustacchi cb->tcc_compat1 = true;
398*0cbe4818SRobert Mustacchi exp = 32;
399*0cbe4818SRobert Mustacchi } else {
400*0cbe4818SRobert Mustacchi return (DI_WALK_CONTINUE);
401*0cbe4818SRobert Mustacchi }
402*0cbe4818SRobert Mustacchi
403*0cbe4818SRobert Mustacchi char *compat;
404*0cbe4818SRobert Mustacchi int nents = di_prop_lookup_strings(DDI_DEV_T_ANY, di, "compatible",
405*0cbe4818SRobert Mustacchi &compat);
406*0cbe4818SRobert Mustacchi if (nents == exp) {
407*0cbe4818SRobert Mustacchi bool valid = true;
408*0cbe4818SRobert Mustacchi for (int i = 0; i < exp; i++) {
409*0cbe4818SRobert Mustacchi if (strcmp(compat, cb->tcc_compat[i]) != 0) {
410*0cbe4818SRobert Mustacchi valid = false;
411*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s has incorrect "
412*0cbe4818SRobert Mustacchi "compatible[%d] entry: expected %s, found "
413*0cbe4818SRobert Mustacchi "%s", name, i, compat, cb->tcc_compat[i]);
414*0cbe4818SRobert Mustacchi }
415*0cbe4818SRobert Mustacchi
416*0cbe4818SRobert Mustacchi compat += strlen(compat) + 1;
417*0cbe4818SRobert Mustacchi }
418*0cbe4818SRobert Mustacchi
419*0cbe4818SRobert Mustacchi if (valid) {
420*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: devi %s has correct "
421*0cbe4818SRobert Mustacchi "comaptible[%d]\n", name, nents);
422*0cbe4818SRobert Mustacchi }
423*0cbe4818SRobert Mustacchi } else {
424*0cbe4818SRobert Mustacchi warnx("TEST FAILED: node %s has wrong compatible[] count: "
425*0cbe4818SRobert Mustacchi "found %d, expected %d", name, nents, exp);
426*0cbe4818SRobert Mustacchi cb->tcc_ret = false;
427*0cbe4818SRobert Mustacchi }
428*0cbe4818SRobert Mustacchi
429*0cbe4818SRobert Mustacchi return (DI_WALK_PRUNECHILD);
430*0cbe4818SRobert Mustacchi }
431*0cbe4818SRobert Mustacchi
432*0cbe4818SRobert Mustacchi static bool
test_compat(int fd)433*0cbe4818SRobert Mustacchi test_compat(int fd)
434*0cbe4818SRobert Mustacchi {
435*0cbe4818SRobert Mustacchi bool ret = true;
436*0cbe4818SRobert Mustacchi char *compat[32];
437*0cbe4818SRobert Mustacchi
438*0cbe4818SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(compat); i++) {
439*0cbe4818SRobert Mustacchi if (asprintf(&compat[i], "bad,compat%zu", i) < 0) {
440*0cbe4818SRobert Mustacchi err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to "
441*0cbe4818SRobert Mustacchi "construct compat entry %zu", i);
442*0cbe4818SRobert Mustacchi }
443*0cbe4818SRobert Mustacchi }
444*0cbe4818SRobert Mustacchi
445*0cbe4818SRobert Mustacchi nvlist_t *nvl = fnvlist_alloc();
446*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
447*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x30);
448*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "fake-compat-0");
449*0cbe4818SRobert Mustacchi fnvlist_add_string_array(nvl, UI2C_IOCTL_NVL_COMPAT, compat,
450*0cbe4818SRobert Mustacchi 1);
451*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_CORE_E_OK, "1-entry compat[]")) {
452*0cbe4818SRobert Mustacchi ret = false;
453*0cbe4818SRobert Mustacchi }
454*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
455*0cbe4818SRobert Mustacchi
456*0cbe4818SRobert Mustacchi nvl = fnvlist_alloc();
457*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_TYPE, I2C_ADDR_7BIT);
458*0cbe4818SRobert Mustacchi fnvlist_add_uint16(nvl, UI2C_IOCTL_NVL_ADDR, 0x31);
459*0cbe4818SRobert Mustacchi fnvlist_add_string(nvl, UI2C_IOCTL_NVL_NAME, "fake-compat-1");
460*0cbe4818SRobert Mustacchi fnvlist_add_string_array(nvl, UI2C_IOCTL_NVL_COMPAT, compat,
461*0cbe4818SRobert Mustacchi ARRAY_SIZE(compat));
462*0cbe4818SRobert Mustacchi if (!test_add_nvlist(fd, nvl, I2C_CORE_E_OK, "32-entry compat[]")) {
463*0cbe4818SRobert Mustacchi ret = false;
464*0cbe4818SRobert Mustacchi }
465*0cbe4818SRobert Mustacchi fnvlist_free(nvl);
466*0cbe4818SRobert Mustacchi
467*0cbe4818SRobert Mustacchi test_compat_cb_t cb = {
468*0cbe4818SRobert Mustacchi .tcc_ret = true,
469*0cbe4818SRobert Mustacchi .tcc_compat0 = false,
470*0cbe4818SRobert Mustacchi .tcc_compat1 = false,
471*0cbe4818SRobert Mustacchi .tcc_compat = compat
472*0cbe4818SRobert Mustacchi };
473*0cbe4818SRobert Mustacchi
474*0cbe4818SRobert Mustacchi di_node_t root = di_init(i2c_sim_dipath, DINFOCPYALL);
475*0cbe4818SRobert Mustacchi (void) di_walk_node(root, DI_WALK_CLDFIRST, &cb, test_compat_walk_cb);
476*0cbe4818SRobert Mustacchi di_fini(root);
477*0cbe4818SRobert Mustacchi
478*0cbe4818SRobert Mustacchi if (!cb.tcc_ret) {
479*0cbe4818SRobert Mustacchi ret = false;
480*0cbe4818SRobert Mustacchi }
481*0cbe4818SRobert Mustacchi
482*0cbe4818SRobert Mustacchi if (!cb.tcc_compat0) {
483*0cbe4818SRobert Mustacchi warnx("TEST FAILED: failed to find devi fake-compat-0");
484*0cbe4818SRobert Mustacchi ret = false;
485*0cbe4818SRobert Mustacchi }
486*0cbe4818SRobert Mustacchi
487*0cbe4818SRobert Mustacchi if (!cb.tcc_compat1) {
488*0cbe4818SRobert Mustacchi warnx("TEST FAILED: failed to find devi fake-compat-1");
489*0cbe4818SRobert Mustacchi ret = false;
490*0cbe4818SRobert Mustacchi }
491*0cbe4818SRobert Mustacchi
492*0cbe4818SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(compat); i++) {
493*0cbe4818SRobert Mustacchi free(compat[i]);
494*0cbe4818SRobert Mustacchi }
495*0cbe4818SRobert Mustacchi
496*0cbe4818SRobert Mustacchi return (ret);
497*0cbe4818SRobert Mustacchi }
498*0cbe4818SRobert Mustacchi
499*0cbe4818SRobert Mustacchi static bool
test_rm(int fd,uint16_t family,uint16_t addr,i2c_errno_t err,const char * desc)500*0cbe4818SRobert Mustacchi test_rm(int fd, uint16_t family, uint16_t addr, i2c_errno_t err,
501*0cbe4818SRobert Mustacchi const char *desc)
502*0cbe4818SRobert Mustacchi {
503*0cbe4818SRobert Mustacchi bool ret = true;
504*0cbe4818SRobert Mustacchi ui2c_dev_rem_t rm = {
505*0cbe4818SRobert Mustacchi .udr_error = {
506*0cbe4818SRobert Mustacchi /* Token errors to ensure this is set by copyout. */
507*0cbe4818SRobert Mustacchi INT32_MAX,
508*0cbe4818SRobert Mustacchi INT32_MAX
509*0cbe4818SRobert Mustacchi },
510*0cbe4818SRobert Mustacchi .udr_addr = { family, addr }
511*0cbe4818SRobert Mustacchi };
512*0cbe4818SRobert Mustacchi
513*0cbe4818SRobert Mustacchi if (ioctl(fd, UI2C_IOCTL_DEVICE_REMOVE, &rm) != 0) {
514*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s: removal ioctl failed unexpectedly with "
515*0cbe4818SRobert Mustacchi "errno %s", desc, strerrorname_np(errno));
516*0cbe4818SRobert Mustacchi return (false);
517*0cbe4818SRobert Mustacchi }
518*0cbe4818SRobert Mustacchi
519*0cbe4818SRobert Mustacchi if (rm.udr_error.i2c_error != err) {
520*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s: ioctl failed with I2C error 0x%x, "
521*0cbe4818SRobert Mustacchi "expected 0x%x", desc, rm.udr_error.i2c_error, err);
522*0cbe4818SRobert Mustacchi ret = false;
523*0cbe4818SRobert Mustacchi }
524*0cbe4818SRobert Mustacchi
525*0cbe4818SRobert Mustacchi if (rm.udr_error.i2c_ctrl != I2C_CTRL_E_OK) {
526*0cbe4818SRobert Mustacchi warnx("TEST FAILED: %s: ioctl has unexpected controller "
527*0cbe4818SRobert Mustacchi "error 0x%x", desc, rm.udr_error.i2c_ctrl);
528*0cbe4818SRobert Mustacchi ret = false;
529*0cbe4818SRobert Mustacchi }
530*0cbe4818SRobert Mustacchi
531*0cbe4818SRobert Mustacchi if (ret) {
532*0cbe4818SRobert Mustacchi if (err == I2C_CORE_E_OK) {
533*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: %s correctly removed "
534*0cbe4818SRobert Mustacchi "device\n", desc);
535*0cbe4818SRobert Mustacchi } else {
536*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: %s correctly failed with "
537*0cbe4818SRobert Mustacchi "0x%x\n", desc, err);
538*0cbe4818SRobert Mustacchi }
539*0cbe4818SRobert Mustacchi }
540*0cbe4818SRobert Mustacchi
541*0cbe4818SRobert Mustacchi return (ret);
542*0cbe4818SRobert Mustacchi }
543*0cbe4818SRobert Mustacchi
544*0cbe4818SRobert Mustacchi static bool
test_teardown(int fd)545*0cbe4818SRobert Mustacchi test_teardown(int fd)
546*0cbe4818SRobert Mustacchi {
547*0cbe4818SRobert Mustacchi bool ret = true;
548*0cbe4818SRobert Mustacchi
549*0cbe4818SRobert Mustacchi for (size_t i = 0; i < nbad_addrs; i++) {
550*0cbe4818SRobert Mustacchi char desc[128];
551*0cbe4818SRobert Mustacchi
552*0cbe4818SRobert Mustacchi (void) snprintf(desc, sizeof (desc), "remove bad address %zu",
553*0cbe4818SRobert Mustacchi i);
554*0cbe4818SRobert Mustacchi if (!test_rm(fd, bad_addrs[i].ba_type, bad_addrs[i].ba_addr,
555*0cbe4818SRobert Mustacchi bad_addrs[i].ba_error, desc)) {
556*0cbe4818SRobert Mustacchi ret = false;
557*0cbe4818SRobert Mustacchi }
558*0cbe4818SRobert Mustacchi }
559*0cbe4818SRobert Mustacchi
560*0cbe4818SRobert Mustacchi if (!test_rm(fd, I2C_ADDR_7BIT, 0x70, I2C_IOCTL_E_NEXUS,
561*0cbe4818SRobert Mustacchi "cannot tear down mux with devices under it")) {
562*0cbe4818SRobert Mustacchi ret = false;
563*0cbe4818SRobert Mustacchi }
564*0cbe4818SRobert Mustacchi
565*0cbe4818SRobert Mustacchi if (!test_rm(fd, I2C_ADDR_7BIT, 0x30, I2C_CORE_E_OK, "tear down device "
566*0cbe4818SRobert Mustacchi "unrelated to mux (0x30)")) {
567*0cbe4818SRobert Mustacchi ret = false;
568*0cbe4818SRobert Mustacchi }
569*0cbe4818SRobert Mustacchi
570*0cbe4818SRobert Mustacchi if (!test_rm(fd, I2C_ADDR_7BIT, 0x31, I2C_CORE_E_OK, "tear down device "
571*0cbe4818SRobert Mustacchi "unrelated to mux (0x31)")) {
572*0cbe4818SRobert Mustacchi ret = false;
573*0cbe4818SRobert Mustacchi }
574*0cbe4818SRobert Mustacchi
575*0cbe4818SRobert Mustacchi int pfd0 = i2c_ioctl_test_get_fd(I2C_D_PORT, "smbussim1/0/0x70/mux/0",
576*0cbe4818SRobert Mustacchi O_RDWR);
577*0cbe4818SRobert Mustacchi if (!test_rm(pfd0, I2C_ADDR_7BIT, 0x42, I2C_CORE_E_OK, "tear down "
578*0cbe4818SRobert Mustacchi "device under mux (0/0x42)")) {
579*0cbe4818SRobert Mustacchi ret = false;
580*0cbe4818SRobert Mustacchi }
581*0cbe4818SRobert Mustacchi
582*0cbe4818SRobert Mustacchi if (!test_rm(pfd0, I2C_ADDR_7BIT, 0x42, I2C_CORE_E_UNKNOWN_ADDR,
583*0cbe4818SRobert Mustacchi "cannot remove 0/0x42 a second time on same port")) {
584*0cbe4818SRobert Mustacchi ret = false;
585*0cbe4818SRobert Mustacchi }
586*0cbe4818SRobert Mustacchi VERIFY0(close(pfd0));
587*0cbe4818SRobert Mustacchi
588*0cbe4818SRobert Mustacchi int pfd2 = i2c_ioctl_test_get_fd(I2C_D_PORT, "smbussim1/0/0x70/mux/2",
589*0cbe4818SRobert Mustacchi O_RDWR);
590*0cbe4818SRobert Mustacchi if (!test_rm(pfd2, I2C_ADDR_7BIT, 0x42, I2C_CORE_E_UNKNOWN_ADDR,
591*0cbe4818SRobert Mustacchi "cannot remove non-existent 2/0x42")) {
592*0cbe4818SRobert Mustacchi ret = false;
593*0cbe4818SRobert Mustacchi }
594*0cbe4818SRobert Mustacchi VERIFY0(close(pfd2));
595*0cbe4818SRobert Mustacchi
596*0cbe4818SRobert Mustacchi int pdf4 = i2c_ioctl_test_get_fd(I2C_D_PORT, "smbussim1/0/0x70/mux/4",
597*0cbe4818SRobert Mustacchi O_RDWR);
598*0cbe4818SRobert Mustacchi if (!test_rm(pdf4, I2C_ADDR_7BIT, 0x42, I2C_CORE_E_OK, "tear down "
599*0cbe4818SRobert Mustacchi "device under mux (4/0x42)")) {
600*0cbe4818SRobert Mustacchi ret = false;
601*0cbe4818SRobert Mustacchi }
602*0cbe4818SRobert Mustacchi
603*0cbe4818SRobert Mustacchi if (!test_rm(pdf4, I2C_ADDR_7BIT, 0x42, I2C_CORE_E_UNKNOWN_ADDR,
604*0cbe4818SRobert Mustacchi "cannot remove 4/0x42 a second time on same port")) {
605*0cbe4818SRobert Mustacchi ret = false;
606*0cbe4818SRobert Mustacchi }
607*0cbe4818SRobert Mustacchi VERIFY0(close(pdf4));
608*0cbe4818SRobert Mustacchi
609*0cbe4818SRobert Mustacchi if (!test_rm(fd, I2C_ADDR_7BIT, 0x70, I2C_CORE_E_OK, "tear down empty "
610*0cbe4818SRobert Mustacchi "mux")) {
611*0cbe4818SRobert Mustacchi ret = false;
612*0cbe4818SRobert Mustacchi }
613*0cbe4818SRobert Mustacchi
614*0cbe4818SRobert Mustacchi if (!test_rm(fd, I2C_ADDR_7BIT, 0x23, I2C_CORE_E_OK, "tear down device "
615*0cbe4818SRobert Mustacchi "(0x23)")) {
616*0cbe4818SRobert Mustacchi ret = false;
617*0cbe4818SRobert Mustacchi }
618*0cbe4818SRobert Mustacchi return (ret);
619*0cbe4818SRobert Mustacchi }
620*0cbe4818SRobert Mustacchi
621*0cbe4818SRobert Mustacchi int
main(void)622*0cbe4818SRobert Mustacchi main(void)
623*0cbe4818SRobert Mustacchi {
624*0cbe4818SRobert Mustacchi int ret = EXIT_SUCCESS;
625*0cbe4818SRobert Mustacchi int fd = i2c_ioctl_test_get_fd(I2C_D_PORT, "smbussim1/0", O_RDWR);
626*0cbe4818SRobert Mustacchi
627*0cbe4818SRobert Mustacchi if (!test_bad_nvlists(fd)) {
628*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
629*0cbe4818SRobert Mustacchi }
630*0cbe4818SRobert Mustacchi
631*0cbe4818SRobert Mustacchi if (!test_address_conflicts(fd)) {
632*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
633*0cbe4818SRobert Mustacchi }
634*0cbe4818SRobert Mustacchi
635*0cbe4818SRobert Mustacchi if (!test_compat(fd)) {
636*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
637*0cbe4818SRobert Mustacchi }
638*0cbe4818SRobert Mustacchi
639*0cbe4818SRobert Mustacchi if (!test_teardown(fd)) {
640*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
641*0cbe4818SRobert Mustacchi }
642*0cbe4818SRobert Mustacchi
643*0cbe4818SRobert Mustacchi VERIFY0(close(fd));
644*0cbe4818SRobert Mustacchi if (ret == EXIT_SUCCESS) {
645*0cbe4818SRobert Mustacchi (void) printf("All tests passed successfully\n");
646*0cbe4818SRobert Mustacchi }
647*0cbe4818SRobert Mustacchi return (ret);
648*0cbe4818SRobert Mustacchi }
649