1*fd71220bSRobert Mustacchi /*
2*fd71220bSRobert Mustacchi * This file and its contents are supplied under the terms of the
3*fd71220bSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*fd71220bSRobert Mustacchi * You may only use this file in accordance with the terms of version
5*fd71220bSRobert Mustacchi * 1.0 of the CDDL.
6*fd71220bSRobert Mustacchi *
7*fd71220bSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*fd71220bSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*fd71220bSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*fd71220bSRobert Mustacchi */
11*fd71220bSRobert Mustacchi
12*fd71220bSRobert Mustacchi /*
13*fd71220bSRobert Mustacchi * Copyright 2023 Oxide Computer Company
14*fd71220bSRobert Mustacchi */
15*fd71220bSRobert Mustacchi
16*fd71220bSRobert Mustacchi /*
17*fd71220bSRobert Mustacchi * This test verifies that we can look up names across the gpio_sim controllers
18*fd71220bSRobert Mustacchi * and that all three return the same results for a given pin.
19*fd71220bSRobert Mustacchi */
20*fd71220bSRobert Mustacchi
21*fd71220bSRobert Mustacchi #include <err.h>
22*fd71220bSRobert Mustacchi #include <sys/stat.h>
23*fd71220bSRobert Mustacchi #include <sys/types.h>
24*fd71220bSRobert Mustacchi #include <fcntl.h>
25*fd71220bSRobert Mustacchi #include <stdlib.h>
26*fd71220bSRobert Mustacchi #include <sys/sysmacros.h>
27*fd71220bSRobert Mustacchi #include <stdbool.h>
28*fd71220bSRobert Mustacchi #include <string.h>
29*fd71220bSRobert Mustacchi #include <unistd.h>
30*fd71220bSRobert Mustacchi #include <errno.h>
31*fd71220bSRobert Mustacchi
32*fd71220bSRobert Mustacchi #include <sys/gpio/kgpio.h>
33*fd71220bSRobert Mustacchi
34*fd71220bSRobert Mustacchi static int gpio_lookup_ret = EXIT_SUCCESS;
35*fd71220bSRobert Mustacchi static const char *gpio_paths[] = {
36*fd71220bSRobert Mustacchi "/devices/pseudo/kgpio@0:gpio_sim0",
37*fd71220bSRobert Mustacchi "/devices/pseudo/kgpio@0:gpio_sim1",
38*fd71220bSRobert Mustacchi "/devices/pseudo/kgpio@0:gpio_sim2"
39*fd71220bSRobert Mustacchi };
40*fd71220bSRobert Mustacchi
41*fd71220bSRobert Mustacchi static const char *gpio_names[] = {
42*fd71220bSRobert Mustacchi "3v3",
43*fd71220bSRobert Mustacchi "periodic-500ms",
44*fd71220bSRobert Mustacchi "open-drain"
45*fd71220bSRobert Mustacchi };
46*fd71220bSRobert Mustacchi
47*fd71220bSRobert Mustacchi static void
gpio_lookup(int fd,const char * name,uint32_t * idp)48*fd71220bSRobert Mustacchi gpio_lookup(int fd, const char *name, uint32_t *idp)
49*fd71220bSRobert Mustacchi {
50*fd71220bSRobert Mustacchi kgpio_ioc_name2id_t kin;
51*fd71220bSRobert Mustacchi
52*fd71220bSRobert Mustacchi (void) memset(&kin, 0, sizeof (kin));
53*fd71220bSRobert Mustacchi if (strlcpy(kin.kin_name, name, sizeof (kin.kin_name)) >=
54*fd71220bSRobert Mustacchi sizeof (kin.kin_name)) {
55*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "would have exceeded kin_name with %s",
56*fd71220bSRobert Mustacchi name);
57*fd71220bSRobert Mustacchi }
58*fd71220bSRobert Mustacchi
59*fd71220bSRobert Mustacchi if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) != 0) {
60*fd71220bSRobert Mustacchi warn("TEST FAILED: failed to translate %s", name);
61*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
62*fd71220bSRobert Mustacchi } else {
63*fd71220bSRobert Mustacchi *idp = kin.kin_id;
64*fd71220bSRobert Mustacchi }
65*fd71220bSRobert Mustacchi }
66*fd71220bSRobert Mustacchi
67*fd71220bSRobert Mustacchi /*
68*fd71220bSRobert Mustacchi * Generate a few different error cases that we know to expect:
69*fd71220bSRobert Mustacchi *
70*fd71220bSRobert Mustacchi * o Invalid name due to no '\0'
71*fd71220bSRobert Mustacchi * o Invalid name of length 0
72*fd71220bSRobert Mustacchi * o An unkonwn name
73*fd71220bSRobert Mustacchi */
74*fd71220bSRobert Mustacchi static void
gpio_lookup_errs(int fd)75*fd71220bSRobert Mustacchi gpio_lookup_errs(int fd)
76*fd71220bSRobert Mustacchi {
77*fd71220bSRobert Mustacchi kgpio_ioc_name2id_t kin;
78*fd71220bSRobert Mustacchi
79*fd71220bSRobert Mustacchi (void) memset(&kin, 0, sizeof (kin));
80*fd71220bSRobert Mustacchi if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) == 0) {
81*fd71220bSRobert Mustacchi warnx("TEST FAILED: zero length lookup passed, expected "
82*fd71220bSRobert Mustacchi "EINVAL");
83*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
84*fd71220bSRobert Mustacchi } else if (errno != EINVAL) {
85*fd71220bSRobert Mustacchi warn("TEST FAILED: zero length lookup had wrong errno, "
86*fd71220bSRobert Mustacchi "expected EINVAL, found");
87*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
88*fd71220bSRobert Mustacchi }
89*fd71220bSRobert Mustacchi
90*fd71220bSRobert Mustacchi (void) memset(kin.kin_name, 'a', sizeof (kin.kin_name));
91*fd71220bSRobert Mustacchi if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) == 0) {
92*fd71220bSRobert Mustacchi warnx("TEST FAILED: no '\\0' lookup passed, expected "
93*fd71220bSRobert Mustacchi "EINVAL");
94*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
95*fd71220bSRobert Mustacchi } else if (errno != EINVAL) {
96*fd71220bSRobert Mustacchi warn("TEST FAILED: no '\\0' lookup had wrong errno, "
97*fd71220bSRobert Mustacchi "expected EINVAL, found");
98*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
99*fd71220bSRobert Mustacchi }
100*fd71220bSRobert Mustacchi
101*fd71220bSRobert Mustacchi (void) strlcpy(kin.kin_name, "three rings for elven kings",
102*fd71220bSRobert Mustacchi sizeof (kin.kin_name));
103*fd71220bSRobert Mustacchi if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) == 0) {
104*fd71220bSRobert Mustacchi warnx("TEST FAILED: found rings for elven kings, expected "
105*fd71220bSRobert Mustacchi "ENOENT");
106*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
107*fd71220bSRobert Mustacchi } else if (errno != ENOENT) {
108*fd71220bSRobert Mustacchi warn("TEST FAILED: rings for elven kings had wrong errno, "
109*fd71220bSRobert Mustacchi "expected ENOENT, found");
110*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
111*fd71220bSRobert Mustacchi }
112*fd71220bSRobert Mustacchi }
113*fd71220bSRobert Mustacchi
114*fd71220bSRobert Mustacchi int
main(void)115*fd71220bSRobert Mustacchi main(void)
116*fd71220bSRobert Mustacchi {
117*fd71220bSRobert Mustacchi int fds[ARRAY_SIZE(gpio_paths)];
118*fd71220bSRobert Mustacchi uint32_t found_ids[ARRAY_SIZE(gpio_paths)];
119*fd71220bSRobert Mustacchi
120*fd71220bSRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(gpio_paths); i++) {
121*fd71220bSRobert Mustacchi fds[i] = open(gpio_paths[i], O_RDONLY);
122*fd71220bSRobert Mustacchi if (fds[i] < 0) {
123*fd71220bSRobert Mustacchi err(EXIT_FAILURE, "failed to open controller %s",
124*fd71220bSRobert Mustacchi gpio_paths[i]);
125*fd71220bSRobert Mustacchi }
126*fd71220bSRobert Mustacchi }
127*fd71220bSRobert Mustacchi
128*fd71220bSRobert Mustacchi /*
129*fd71220bSRobert Mustacchi * We expect all of these to be successful.
130*fd71220bSRobert Mustacchi */
131*fd71220bSRobert Mustacchi for (size_t name = 0; name < ARRAY_SIZE(gpio_names); name++) {
132*fd71220bSRobert Mustacchi uint32_t id0;
133*fd71220bSRobert Mustacchi
134*fd71220bSRobert Mustacchi for (size_t ctrl = 0; ctrl < ARRAY_SIZE(gpio_paths); ctrl++) {
135*fd71220bSRobert Mustacchi gpio_lookup(fds[ctrl], gpio_names[name],
136*fd71220bSRobert Mustacchi &found_ids[ctrl]);
137*fd71220bSRobert Mustacchi }
138*fd71220bSRobert Mustacchi
139*fd71220bSRobert Mustacchi id0 = found_ids[0];
140*fd71220bSRobert Mustacchi for (size_t ctrl = 0; ctrl < ARRAY_SIZE(gpio_paths); ctrl++) {
141*fd71220bSRobert Mustacchi if (found_ids[ctrl] != id0) {
142*fd71220bSRobert Mustacchi warnx("ID Mismatch for %s: got %u on "
143*fd71220bSRobert Mustacchi "%s and %u on %s", gpio_names[name],
144*fd71220bSRobert Mustacchi id0, gpio_paths[0], found_ids[ctrl],
145*fd71220bSRobert Mustacchi gpio_paths[ctrl]);
146*fd71220bSRobert Mustacchi gpio_lookup_ret = EXIT_FAILURE;
147*fd71220bSRobert Mustacchi }
148*fd71220bSRobert Mustacchi }
149*fd71220bSRobert Mustacchi
150*fd71220bSRobert Mustacchi }
151*fd71220bSRobert Mustacchi
152*fd71220bSRobert Mustacchi gpio_lookup_errs(fds[0]);
153*fd71220bSRobert Mustacchi
154*fd71220bSRobert Mustacchi return (gpio_lookup_ret);
155*fd71220bSRobert Mustacchi }
156