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 2020 Oxide Computer Company
14 */
15
16 /*
17 * This driver is used to implement parts of the ksensor test suite.
18 */
19
20 #include <sys/ddi.h>
21 #include <sys/sunddi.h>
22 #include <sys/modctl.h>
23 #include <sys/conf.h>
24 #include <sys/devops.h>
25 #include <sys/zone.h>
26 #include <sys/sensors.h>
27
28 typedef struct ksensor_test {
29 dev_info_t *kt_dip;
30 id_t kt_sensor1;
31 id_t kt_sensor2;
32 id_t kt_sensor3;
33 id_t kt_sensor4;
34 id_t kt_sensor5;
35 id_t kt_volt;
36 id_t kt_current;
37 } ksensor_test_t;
38
39 static int
ksensor_test_temp(void * arg,sensor_ioctl_scalar_t * scalar)40 ksensor_test_temp(void *arg, sensor_ioctl_scalar_t *scalar)
41 {
42 scalar->sis_unit = SENSOR_UNIT_CELSIUS;
43 scalar->sis_gran = 4;
44 scalar->sis_prec = -2;
45 scalar->sis_value = 23;
46 return (0);
47 }
48
49 static const ksensor_ops_t ksensor_test_temp_ops = {
50 .kso_kind = ksensor_kind_temperature,
51 .kso_scalar = ksensor_test_temp
52 };
53
54 static int
ksensor_test_volt(void * arg,sensor_ioctl_scalar_t * scalar)55 ksensor_test_volt(void *arg, sensor_ioctl_scalar_t *scalar)
56 {
57 scalar->sis_unit = SENSOR_UNIT_VOLTS;
58 scalar->sis_gran = 1000;
59 scalar->sis_prec = 0;
60 scalar->sis_value = 3300;
61 return (0);
62 }
63
64 static const ksensor_ops_t ksensor_test_volt_ops = {
65 .kso_kind = ksensor_kind_voltage,
66 .kso_scalar = ksensor_test_volt
67 };
68
69 static int
ksensor_test_current(void * arg,sensor_ioctl_scalar_t * scalar)70 ksensor_test_current(void *arg, sensor_ioctl_scalar_t *scalar)
71 {
72 scalar->sis_unit = SENSOR_UNIT_AMPS;
73 scalar->sis_gran = 10;
74 scalar->sis_prec = 0;
75 scalar->sis_value = 5;
76 return (0);
77 }
78
79 static const ksensor_ops_t ksensor_test_current_ops = {
80 .kso_kind = ksensor_kind_current,
81 .kso_scalar = ksensor_test_current
82 };
83
84 static int
ksensor_test_kind_eio(void * arg,sensor_ioctl_kind_t * kindp)85 ksensor_test_kind_eio(void *arg, sensor_ioctl_kind_t *kindp)
86 {
87 return (EIO);
88 }
89
90 static int
ksensor_test_temp_eio(void * arg,sensor_ioctl_scalar_t * scalar)91 ksensor_test_temp_eio(void *arg, sensor_ioctl_scalar_t *scalar)
92 {
93 return (EIO);
94 }
95
96 static const ksensor_ops_t ksensor_test_eio_ops = {
97 .kso_kind = ksensor_test_kind_eio,
98 .kso_scalar = ksensor_test_temp_eio
99 };
100
101 static int
ksensor_test_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)102 ksensor_test_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
103 {
104 int ret;
105 char buf[128];
106 ksensor_test_t *kt;
107
108 switch (cmd) {
109 case DDI_RESUME:
110 return (DDI_SUCCESS);
111 case DDI_ATTACH:
112 break;
113 default:
114 return (DDI_FAILURE);
115 }
116
117 kt = kmem_zalloc(sizeof (ksensor_test_t), KM_SLEEP);
118 kt->kt_dip = dip;
119
120 (void) snprintf(buf, sizeof (buf), "test.temp.%d.1",
121 ddi_get_instance(dip));
122 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
123 "ddi_sensor:test", &kt->kt_sensor1)) != 0) {
124 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf,
125 ret);
126 goto err;
127 }
128
129 (void) snprintf(buf, sizeof (buf), "test.temp.%d.2",
130 ddi_get_instance(dip));
131 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
132 "ddi_sensor:test", &kt->kt_sensor2)) != 0) {
133 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf,
134 ret);
135 goto err;
136 }
137
138 (void) snprintf(buf, sizeof (buf), "test.temp.%d.3",
139 ddi_get_instance(dip));
140 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
141 "ddi_sensor:test", &kt->kt_sensor3)) != 0) {
142 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
143 ret);
144 goto err;
145 }
146
147 (void) snprintf(buf, sizeof (buf), "test.temp.%d.4",
148 ddi_get_instance(dip));
149 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
150 "ddi_sensor:test", &kt->kt_sensor4)) != 0) {
151 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
152 ret);
153 goto err;
154 }
155
156 (void) snprintf(buf, sizeof (buf), "test.eio.%d",
157 ddi_get_instance(dip));
158 if ((ret = ksensor_create(dip, &ksensor_test_eio_ops, NULL, buf,
159 "ddi_sensor:test", &kt->kt_sensor5)) != 0) {
160 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
161 ret);
162 goto err;
163 }
164
165 (void) snprintf(buf, sizeof (buf), "test.volt.%d.1",
166 ddi_get_instance(dip));
167 if ((ret = ksensor_create(dip, &ksensor_test_volt_ops, NULL, buf,
168 "ddi_sensor:test", &kt->kt_volt)) != 0) {
169 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
170 ret);
171 goto err;
172 }
173
174 (void) snprintf(buf, sizeof (buf), "test.current.%d.1",
175 ddi_get_instance(dip));
176 if ((ret = ksensor_create(dip, &ksensor_test_current_ops, NULL, buf,
177 "ddi_sensor:test", &kt->kt_current)) != 0) {
178 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
179 ret);
180 goto err;
181 }
182
183 ddi_set_driver_private(dip, kt);
184
185 return (DDI_SUCCESS);
186 err:
187 (void) ksensor_remove(dip, KSENSOR_ALL_IDS);
188 kmem_free(kt, sizeof (ksensor_test_t));
189 return (DDI_FAILURE);
190 }
191
192 static int
ksensor_test_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)193 ksensor_test_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
194 {
195 ksensor_test_t *kt;
196
197 switch (cmd) {
198 case DDI_DETACH:
199 break;
200 case DDI_SUSPEND:
201 return (DDI_SUCCESS);
202 default:
203 return (DDI_FAILURE);
204 }
205
206 kt = ddi_get_driver_private(dip);
207 if (kt == NULL) {
208 dev_err(dip, CE_WARN, "failed to find ksensor_test_t");
209 return (DDI_FAILURE);
210 }
211
212 if (kt->kt_sensor3 != 0 &&
213 ksensor_remove(dip, kt->kt_sensor3) != 0) {
214 dev_err(dip, CE_WARN, "failed to remove sensor 3");
215 return (DDI_FAILURE);
216 }
217 kt->kt_sensor3 = 0;
218 if (ksensor_remove(dip, KSENSOR_ALL_IDS) != 0) {
219 dev_err(dip, CE_WARN, "failed to remove sensors");
220 return (DDI_FAILURE);
221 }
222 kmem_free(kt, sizeof (*kt));
223 ddi_set_driver_private(dip, NULL);
224 return (DDI_SUCCESS);
225 }
226
227 static struct dev_ops ksensor_test_dev_ops = {
228 .devo_rev = DEVO_REV,
229 .devo_refcnt = 0,
230 .devo_getinfo = nodev,
231 .devo_identify = nulldev,
232 .devo_probe = nulldev,
233 .devo_attach = ksensor_test_attach,
234 .devo_detach = ksensor_test_detach,
235 .devo_reset = nodev,
236 .devo_power = ddi_power,
237 .devo_quiesce = ddi_quiesce_not_needed,
238 };
239
240 static struct modldrv ksensor_test_modldrv = {
241 .drv_modops = &mod_driverops,
242 .drv_linkinfo = "Kernel Sensor test driver",
243 .drv_dev_ops = &ksensor_test_dev_ops
244 };
245
246 static struct modlinkage ksensor_test_modlinkage = {
247 .ml_rev = MODREV_1,
248 .ml_linkage = { &ksensor_test_modldrv, NULL }
249 };
250
251 int
_init(void)252 _init(void)
253 {
254 return (mod_install(&ksensor_test_modlinkage));
255 }
256
257 int
_info(struct modinfo * modinfop)258 _info(struct modinfo *modinfop)
259 {
260 return (mod_info(&ksensor_test_modlinkage, modinfop));
261 }
262
263 int
_fini(void)264 _fini(void)
265 {
266 return (mod_remove(&ksensor_test_modlinkage));
267 }
268