swsensor.c revision 1.7.6.2 1 1.7.6.2 rmind /* $NetBSD: swsensor.c,v 1.7.6.2 2011/03/05 20:54:08 rmind Exp $ */
2 1.7.6.2 rmind /*
3 1.7.6.2 rmind * Copyright (c) 2008 The NetBSD Foundation, Inc.
4 1.7.6.2 rmind * All rights reserved.
5 1.7.6.2 rmind *
6 1.7.6.2 rmind * Redistribution and use in source and binary forms, with or without
7 1.7.6.2 rmind * modification, are permitted provided that the following conditions
8 1.7.6.2 rmind * are met:
9 1.7.6.2 rmind * 1. Redistributions of source code must retain the above copyright
10 1.7.6.2 rmind * notice, this list of conditions and the following disclaimer.
11 1.7.6.2 rmind * 2. Redistributions in binary form must reproduce the above copyright
12 1.7.6.2 rmind * notice, this list of conditions and the following disclaimer in the
13 1.7.6.2 rmind * documentation and/or other materials provided with the distribution.
14 1.7.6.2 rmind *
15 1.7.6.2 rmind * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
16 1.7.6.2 rmind * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 1.7.6.2 rmind * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 1.7.6.2 rmind * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.7.6.2 rmind * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
20 1.7.6.2 rmind * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.7.6.2 rmind * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 1.7.6.2 rmind * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.7.6.2 rmind * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24 1.7.6.2 rmind * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 1.7.6.2 rmind * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 1.7.6.2 rmind * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.7.6.2 rmind */
28 1.7.6.2 rmind
29 1.7.6.2 rmind #include <sys/cdefs.h>
30 1.7.6.2 rmind __KERNEL_RCSID(0, "$NetBSD: swsensor.c,v 1.7.6.2 2011/03/05 20:54:08 rmind Exp $");
31 1.7.6.2 rmind
32 1.7.6.2 rmind #include <sys/param.h>
33 1.7.6.2 rmind #include <sys/kernel.h>
34 1.7.6.2 rmind #include <sys/module.h>
35 1.7.6.2 rmind #include <sys/sysctl.h>
36 1.7.6.2 rmind
37 1.7.6.2 rmind #include <dev/sysmon/sysmonvar.h>
38 1.7.6.2 rmind
39 1.7.6.2 rmind #include <prop/proplib.h>
40 1.7.6.2 rmind
41 1.7.6.2 rmind #ifndef _MODULE
42 1.7.6.2 rmind #include "opt_modular.h"
43 1.7.6.2 rmind #endif
44 1.7.6.2 rmind
45 1.7.6.2 rmind int swsensorattach(int);
46 1.7.6.2 rmind
47 1.7.6.2 rmind static struct sysctllog *swsensor_sysctllog = NULL;
48 1.7.6.2 rmind
49 1.7.6.2 rmind static int sensor_value_sysctl = 0;
50 1.7.6.2 rmind
51 1.7.6.2 rmind static struct sysmon_envsys *swsensor_sme;
52 1.7.6.2 rmind static envsys_data_t swsensor_edata;
53 1.7.6.2 rmind
54 1.7.6.2 rmind static int32_t sw_sensor_value;
55 1.7.6.2 rmind static int32_t sw_sensor_limit;
56 1.7.6.2 rmind static int32_t sw_sensor_mode;
57 1.7.6.2 rmind static int32_t sw_sensor_defprops;
58 1.7.6.2 rmind sysmon_envsys_lim_t sw_sensor_deflims;
59 1.7.6.2 rmind
60 1.7.6.2 rmind MODULE(MODULE_CLASS_DRIVER, swsensor, NULL);
61 1.7.6.2 rmind
62 1.7.6.2 rmind /*
63 1.7.6.2 rmind * Set-up the sysctl interface for setting the sensor's cur_value
64 1.7.6.2 rmind */
65 1.7.6.2 rmind
66 1.7.6.2 rmind static
67 1.7.6.2 rmind void
68 1.7.6.2 rmind sysctl_swsensor_setup(void)
69 1.7.6.2 rmind {
70 1.7.6.2 rmind int ret;
71 1.7.6.2 rmind int node_sysctl_num;
72 1.7.6.2 rmind const struct sysctlnode *me = NULL;
73 1.7.6.2 rmind
74 1.7.6.2 rmind KASSERT(swsensor_sysctllog == NULL);
75 1.7.6.2 rmind
76 1.7.6.2 rmind ret = sysctl_createv(&swsensor_sysctllog, 0, NULL, &me,
77 1.7.6.2 rmind CTLFLAG_READWRITE,
78 1.7.6.2 rmind CTLTYPE_NODE, "swsensor", NULL,
79 1.7.6.2 rmind NULL, 0, NULL, 0,
80 1.7.6.2 rmind CTL_HW, CTL_CREATE, CTL_EOL);
81 1.7.6.2 rmind if (ret != 0)
82 1.7.6.2 rmind return;
83 1.7.6.2 rmind
84 1.7.6.2 rmind node_sysctl_num = me->sysctl_num;
85 1.7.6.2 rmind ret = sysctl_createv(&swsensor_sysctllog, 0, NULL, &me,
86 1.7.6.2 rmind CTLFLAG_READWRITE,
87 1.7.6.2 rmind CTLTYPE_INT, "cur_value", NULL,
88 1.7.6.2 rmind NULL, 0, &sw_sensor_value, 0,
89 1.7.6.2 rmind CTL_HW, node_sysctl_num, CTL_CREATE, CTL_EOL);
90 1.7.6.2 rmind
91 1.7.6.2 rmind if (ret == 0)
92 1.7.6.2 rmind sensor_value_sysctl = me->sysctl_num;
93 1.7.6.2 rmind }
94 1.7.6.2 rmind
95 1.7.6.2 rmind /*
96 1.7.6.2 rmind * "Polling" routine to update sensor value
97 1.7.6.2 rmind */
98 1.7.6.2 rmind static
99 1.7.6.2 rmind void
100 1.7.6.2 rmind swsensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
101 1.7.6.2 rmind {
102 1.7.6.2 rmind
103 1.7.6.2 rmind edata->value_cur = sw_sensor_value;
104 1.7.6.2 rmind
105 1.7.6.2 rmind /*
106 1.7.6.2 rmind * Set state. If we're handling the limits ourselves, do the
107 1.7.6.2 rmind * compare; otherwise just assume the value is valid.
108 1.7.6.2 rmind */
109 1.7.6.2 rmind if ((sw_sensor_mode == 2) && (edata->upropset & PROP_CRITMIN) &&
110 1.7.6.2 rmind (edata->upropset & PROP_DRIVER_LIMITS) &&
111 1.7.6.2 rmind (edata->value_cur < edata->limits.sel_critmin))
112 1.7.6.2 rmind edata->state = ENVSYS_SCRITUNDER;
113 1.7.6.2 rmind else
114 1.7.6.2 rmind edata->state = ENVSYS_SVALID;
115 1.7.6.2 rmind }
116 1.7.6.2 rmind
117 1.7.6.2 rmind /*
118 1.7.6.2 rmind * Sensor get/set limit routines
119 1.7.6.2 rmind */
120 1.7.6.2 rmind
121 1.7.6.2 rmind static void
122 1.7.6.2 rmind swsensor_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
123 1.7.6.2 rmind sysmon_envsys_lim_t *limits, uint32_t *props)
124 1.7.6.2 rmind {
125 1.7.6.2 rmind
126 1.7.6.2 rmind *props = PROP_CRITMIN | PROP_DRIVER_LIMITS;
127 1.7.6.2 rmind limits->sel_critmin = sw_sensor_limit;
128 1.7.6.2 rmind }
129 1.7.6.2 rmind
130 1.7.6.2 rmind static void
131 1.7.6.2 rmind swsensor_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
132 1.7.6.2 rmind sysmon_envsys_lim_t *limits, uint32_t *props)
133 1.7.6.2 rmind {
134 1.7.6.2 rmind
135 1.7.6.2 rmind if (limits == NULL) {
136 1.7.6.2 rmind limits = &sw_sensor_deflims;
137 1.7.6.2 rmind props = &sw_sensor_defprops;
138 1.7.6.2 rmind }
139 1.7.6.2 rmind if (*props & PROP_CRITMIN)
140 1.7.6.2 rmind sw_sensor_limit = limits->sel_critmin;
141 1.7.6.2 rmind
142 1.7.6.2 rmind /*
143 1.7.6.2 rmind * If the limit we can handle (crit-min) is set, and no
144 1.7.6.2 rmind * other limit is set, tell sysmon that the driver will
145 1.7.6.2 rmind * handle the limit checking.
146 1.7.6.2 rmind */
147 1.7.6.2 rmind if ((*props & PROP_LIMITS) == PROP_CRITMIN)
148 1.7.6.2 rmind *props |= PROP_DRIVER_LIMITS;
149 1.7.6.2 rmind else
150 1.7.6.2 rmind *props &= ~PROP_DRIVER_LIMITS;
151 1.7.6.2 rmind }
152 1.7.6.2 rmind
153 1.7.6.2 rmind /*
154 1.7.6.2 rmind * Module management
155 1.7.6.2 rmind */
156 1.7.6.2 rmind
157 1.7.6.2 rmind static
158 1.7.6.2 rmind int
159 1.7.6.2 rmind swsensor_init(void *arg)
160 1.7.6.2 rmind {
161 1.7.6.2 rmind int error;
162 1.7.6.2 rmind prop_dictionary_t pd = (prop_dictionary_t)arg;
163 1.7.6.2 rmind prop_object_t po = NULL;
164 1.7.6.2 rmind
165 1.7.6.2 rmind swsensor_sme = sysmon_envsys_create();
166 1.7.6.2 rmind if (swsensor_sme == NULL)
167 1.7.6.2 rmind return ENOTTY;
168 1.7.6.2 rmind
169 1.7.6.2 rmind swsensor_sme->sme_name = "swsensor";
170 1.7.6.2 rmind swsensor_sme->sme_cookie = &swsensor_edata;
171 1.7.6.2 rmind swsensor_sme->sme_refresh = swsensor_refresh;
172 1.7.6.2 rmind swsensor_sme->sme_set_limits = NULL;
173 1.7.6.2 rmind swsensor_sme->sme_get_limits = NULL;
174 1.7.6.2 rmind
175 1.7.6.2 rmind /* See if prop dictionary supplies a sensor type */
176 1.7.6.2 rmind if (pd != NULL)
177 1.7.6.2 rmind po = prop_dictionary_get(pd, "type");
178 1.7.6.2 rmind
179 1.7.6.2 rmind if (po != NULL && prop_object_type(po) == PROP_TYPE_NUMBER)
180 1.7.6.2 rmind swsensor_edata.units = prop_number_integer_value(po);
181 1.7.6.2 rmind else
182 1.7.6.2 rmind swsensor_edata.units = ENVSYS_INTEGER;
183 1.7.6.2 rmind
184 1.7.6.2 rmind /* See if prop dictionary supplies sensor flags */
185 1.7.6.2 rmind if (pd != NULL)
186 1.7.6.2 rmind po = prop_dictionary_get(pd, "flags");
187 1.7.6.2 rmind
188 1.7.6.2 rmind if (po != NULL && prop_object_type(po) == PROP_TYPE_NUMBER)
189 1.7.6.2 rmind swsensor_edata.flags = prop_number_integer_value(po);
190 1.7.6.2 rmind else
191 1.7.6.2 rmind swsensor_edata.flags = 0;
192 1.7.6.2 rmind
193 1.7.6.2 rmind /*
194 1.7.6.2 rmind * Get requested sensor limit behavior
195 1.7.6.2 rmind * 0 - simple sensor, no hw limits
196 1.7.6.2 rmind * 1 - simple sensor, hw provides an initial limit
197 1.7.6.2 rmind * 2 - complex sensor, hw provides settable limits and
198 1.7.6.2 rmind * does its own limit checking
199 1.7.6.2 rmind */
200 1.7.6.2 rmind if (pd != NULL)
201 1.7.6.2 rmind po = prop_dictionary_get(pd, "mode");
202 1.7.6.2 rmind
203 1.7.6.2 rmind if (po != NULL && prop_object_type(po) == PROP_TYPE_NUMBER) {
204 1.7.6.2 rmind sw_sensor_mode = prop_number_integer_value(po);
205 1.7.6.2 rmind if (sw_sensor_mode > 2)
206 1.7.6.2 rmind sw_sensor_mode = 2;
207 1.7.6.2 rmind } else
208 1.7.6.2 rmind sw_sensor_mode = 0;
209 1.7.6.2 rmind
210 1.7.6.2 rmind if (sw_sensor_mode >= 1)
211 1.7.6.2 rmind swsensor_sme->sme_get_limits = swsensor_get_limits;
212 1.7.6.2 rmind
213 1.7.6.2 rmind if (sw_sensor_mode == 2)
214 1.7.6.2 rmind swsensor_sme->sme_set_limits = swsensor_set_limits;
215 1.7.6.2 rmind
216 1.7.6.2 rmind /* See if a limit value was provided - if not, use 0 */
217 1.7.6.2 rmind if (sw_sensor_mode != 0) {
218 1.7.6.2 rmind swsensor_edata.flags |= ENVSYS_FMONLIMITS;
219 1.7.6.2 rmind sw_sensor_limit = 0;
220 1.7.6.2 rmind if (pd != NULL)
221 1.7.6.2 rmind po = prop_dictionary_get(pd, "limit");
222 1.7.6.2 rmind
223 1.7.6.2 rmind if (po != NULL && prop_object_type(po) == PROP_TYPE_NUMBER)
224 1.7.6.2 rmind sw_sensor_limit = prop_number_integer_value(po);
225 1.7.6.2 rmind
226 1.7.6.2 rmind swsensor_get_limits(swsensor_sme, &swsensor_edata,
227 1.7.6.2 rmind &sw_sensor_deflims, &sw_sensor_defprops);
228 1.7.6.2 rmind }
229 1.7.6.2 rmind
230 1.7.6.2 rmind /* See if an initial value was specified */
231 1.7.6.2 rmind if (pd != NULL)
232 1.7.6.2 rmind po = prop_dictionary_get(pd, "value");
233 1.7.6.2 rmind
234 1.7.6.2 rmind if (po != NULL && prop_object_type(po) == PROP_TYPE_NUMBER)
235 1.7.6.2 rmind sw_sensor_value = prop_number_integer_value(po);
236 1.7.6.2 rmind
237 1.7.6.2 rmind swsensor_edata.value_cur = 0;
238 1.7.6.2 rmind
239 1.7.6.2 rmind strlcpy(swsensor_edata.desc, "sensor", ENVSYS_DESCLEN);
240 1.7.6.2 rmind
241 1.7.6.2 rmind error = sysmon_envsys_sensor_attach(swsensor_sme, &swsensor_edata);
242 1.7.6.2 rmind
243 1.7.6.2 rmind if (error == 0)
244 1.7.6.2 rmind error = sysmon_envsys_register(swsensor_sme);
245 1.7.6.2 rmind else {
246 1.7.6.2 rmind aprint_error("sysmon_envsys_sensor_attach failed: %d\n", error);
247 1.7.6.2 rmind return error;
248 1.7.6.2 rmind }
249 1.7.6.2 rmind
250 1.7.6.2 rmind if (error == 0)
251 1.7.6.2 rmind sysctl_swsensor_setup();
252 1.7.6.2 rmind else
253 1.7.6.2 rmind aprint_error("sysmon_envsys_register failed: %d\n", error);
254 1.7.6.2 rmind
255 1.7.6.2 rmind if (error == 0)
256 1.7.6.2 rmind aprint_normal("swsensor: initialized\n");
257 1.7.6.2 rmind return error;
258 1.7.6.2 rmind }
259 1.7.6.2 rmind
260 1.7.6.2 rmind static
261 1.7.6.2 rmind int
262 1.7.6.2 rmind swsensor_fini(void *arg)
263 1.7.6.2 rmind {
264 1.7.6.2 rmind
265 1.7.6.2 rmind sysmon_envsys_unregister(swsensor_sme);
266 1.7.6.2 rmind
267 1.7.6.2 rmind sysctl_teardown(&swsensor_sysctllog);
268 1.7.6.2 rmind
269 1.7.6.2 rmind return 0;
270 1.7.6.2 rmind }
271 1.7.6.2 rmind
272 1.7.6.2 rmind static
273 1.7.6.2 rmind int
274 1.7.6.2 rmind swsensor_modcmd(modcmd_t cmd, void *arg)
275 1.7.6.2 rmind {
276 1.7.6.2 rmind int ret;
277 1.7.6.2 rmind
278 1.7.6.2 rmind switch (cmd) {
279 1.7.6.2 rmind case MODULE_CMD_INIT:
280 1.7.6.2 rmind ret = swsensor_init(arg);
281 1.7.6.2 rmind break;
282 1.7.6.2 rmind
283 1.7.6.2 rmind case MODULE_CMD_FINI:
284 1.7.6.2 rmind ret = swsensor_fini(arg);
285 1.7.6.2 rmind break;
286 1.7.6.2 rmind
287 1.7.6.2 rmind case MODULE_CMD_STAT:
288 1.7.6.2 rmind default:
289 1.7.6.2 rmind ret = ENOTTY;
290 1.7.6.2 rmind }
291 1.7.6.2 rmind
292 1.7.6.2 rmind return ret;
293 1.7.6.2 rmind }
294 1.7.6.2 rmind
295 1.7.6.2 rmind int
296 1.7.6.2 rmind swsensorattach(int n __unused)
297 1.7.6.2 rmind {
298 1.7.6.2 rmind
299 1.7.6.2 rmind #ifdef MODULAR
300 1.7.6.2 rmind /*
301 1.7.6.2 rmind * Modular kernels will automatically load any built-in modules
302 1.7.6.2 rmind * and call their modcmd() routine, so we don't need to do it
303 1.7.6.2 rmind * again as part of pseudo-device configuration.
304 1.7.6.2 rmind */
305 1.7.6.2 rmind return 0;
306 1.7.6.2 rmind #else
307 1.7.6.2 rmind return swsensor_init(NULL);
308 1.7.6.2 rmind #endif
309 1.7.6.2 rmind }
310