Annotation of sys/kern/kern_sensors.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: kern_sensors.c,v 1.21 2007/07/03 03:22:34 cnst Exp $ */
2:
3: /*
4: * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
5: * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/param.h>
21: #include <sys/proc.h>
22: #include <sys/systm.h>
23: #include <sys/kernel.h>
24: #include <sys/malloc.h>
25: #include <sys/queue.h>
26: #include <sys/types.h>
27: #include <sys/device.h>
28: #include <sys/hotplug.h>
29: #include <sys/timeout.h>
30: #include <sys/workq.h>
31:
32: #include <sys/sensors.h>
33: #include "hotplug.h"
34:
35: int sensordev_count = 0;
36: SLIST_HEAD(, ksensordev) sensordev_list =
37: SLIST_HEAD_INITIALIZER(sensordev_list);
38:
39: void
40: sensordev_install(struct ksensordev *sensdev)
41: {
42: struct ksensordev *v, *nv;
43: int s;
44:
45: s = splhigh();
46: if (sensordev_count == 0) {
47: sensdev->num = 0;
48: SLIST_INSERT_HEAD(&sensordev_list, sensdev, list);
49: } else {
50: for (v = SLIST_FIRST(&sensordev_list);
51: (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
52: if (nv->num - v->num > 1)
53: break;
54: sensdev->num = v->num + 1;
55: SLIST_INSERT_AFTER(v, sensdev, list);
56: }
57: sensordev_count++;
58: splx(s);
59:
60: #if NHOTPLUG > 0
61: hotplug_device_attach(DV_DULL, "sensordev");
62: #endif
63: }
64:
65: void
66: sensor_attach(struct ksensordev *sensdev, struct ksensor *sens)
67: {
68: struct ksensor *v, *nv;
69: struct ksensors_head *sh;
70: int s, i;
71:
72: s = splhigh();
73: sh = &sensdev->sensors_list;
74: if (sensdev->sensors_count == 0) {
75: for (i = 0; i < SENSOR_MAX_TYPES; i++)
76: sensdev->maxnumt[i] = 0;
77: sens->numt = 0;
78: SLIST_INSERT_HEAD(sh, sens, list);
79: } else {
80: for (v = SLIST_FIRST(sh);
81: (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
82: if (v->type == sens->type && (v->type != nv->type ||
83: (v->type == nv->type && nv->numt - v->numt > 1)))
84: break;
85: /* sensors of the same type go after each other */
86: if (v->type == sens->type)
87: sens->numt = v->numt + 1;
88: else
89: sens->numt = 0;
90: SLIST_INSERT_AFTER(v, sens, list);
91: }
92: /* we only increment maxnumt[] if the sensor was added
93: * to the last position of sensors of this type
94: */
95: if (sensdev->maxnumt[sens->type] == sens->numt)
96: sensdev->maxnumt[sens->type]++;
97: sensdev->sensors_count++;
98: splx(s);
99: }
100:
101: void
102: sensordev_deinstall(struct ksensordev *sensdev)
103: {
104: int s;
105:
106: s = splhigh();
107: sensordev_count--;
108: SLIST_REMOVE(&sensordev_list, sensdev, ksensordev, list);
109: splx(s);
110:
111: #if NHOTPLUG > 0
112: hotplug_device_detach(DV_DULL, "sensordev");
113: #endif
114: }
115:
116: void
117: sensor_detach(struct ksensordev *sensdev, struct ksensor *sens)
118: {
119: struct ksensors_head *sh;
120: int s;
121:
122: s = splhigh();
123: sh = &sensdev->sensors_list;
124: sensdev->sensors_count--;
125: SLIST_REMOVE(sh, sens, ksensor, list);
126: /* we only decrement maxnumt[] if this is the tail
127: * sensor of this type
128: */
129: if (sens->numt == sensdev->maxnumt[sens->type] - 1)
130: sensdev->maxnumt[sens->type]--;
131: splx(s);
132: }
133:
134: struct ksensordev *
135: sensordev_get(int num)
136: {
137: struct ksensordev *sd;
138:
139: SLIST_FOREACH(sd, &sensordev_list, list)
140: if (sd->num == num)
141: return (sd);
142:
143: return (NULL);
144: }
145:
146: struct ksensor *
147: sensor_find(int dev, enum sensor_type type, int numt)
148: {
149: struct ksensor *s;
150: struct ksensordev *sensdev;
151: struct ksensors_head *sh;
152:
153: sensdev = sensordev_get(dev);
154: if (sensdev == NULL)
155: return (NULL);
156:
157: sh = &sensdev->sensors_list;
158: SLIST_FOREACH(s, sh, list)
159: if (s->type == type && s->numt == numt)
160: return (s);
161:
162: return (NULL);
163: }
164:
165: struct sensor_task {
166: void (*func)(void *);
167: void *arg;
168:
169: int period;
170: struct timeout timeout;
171: volatile enum {
172: ST_TICKING,
173: ST_WORKQ,
174: ST_RUNNING,
175: ST_DYING,
176: ST_DEAD
177: } state;
178: };
179:
180: void sensor_task_tick(void *);
181: void sensor_task_work(void *, void *);
182:
183: struct sensor_task *
184: sensor_task_register(void *arg, void (*func)(void *), int period)
185: {
186: struct sensor_task *st;
187:
188: st = malloc(sizeof(struct sensor_task), M_DEVBUF, M_NOWAIT);
189: if (st == NULL)
190: return (NULL);
191:
192: st->func = func;
193: st->arg = arg;
194: st->period = period;
195: timeout_set(&st->timeout, sensor_task_tick, st);
196:
197: sensor_task_tick(st);
198:
199: return (st);
200: }
201:
202: void
203: sensor_task_unregister(struct sensor_task *st)
204: {
205: timeout_del(&st->timeout);
206:
207: switch (st->state) {
208: case ST_TICKING:
209: free(st, M_DEVBUF);
210: break;
211:
212: case ST_WORKQ:
213: st->state = ST_DYING;
214: break;
215:
216: case ST_RUNNING:
217: st->state = ST_DYING;
218: while (st->state != ST_DEAD)
219: tsleep(st, 0, "stunr", 0);
220: free(st, M_DEVBUF);
221: break;
222: default:
223: panic("sensor_task_unregister: unexpected state %d",
224: st->state);
225: }
226: }
227:
228: void
229: sensor_task_tick(void *arg)
230: {
231: struct sensor_task *st = arg;
232:
233: /* try to schedule the task */
234: if (workq_add_task(NULL, 0, sensor_task_work, st, NULL) != 0)
235: timeout_add(&st->timeout, hz/2);
236:
237: st->state = ST_WORKQ;
238: }
239:
240: void
241: sensor_task_work(void *xst, void *arg)
242: {
243: struct sensor_task *st = xst;
244:
245: if (st->state == ST_DYING) {
246: free(st, M_DEVBUF);
247: return;
248: }
249:
250: st->state = ST_RUNNING;
251: st->func(st->arg);
252:
253: if (st->state == ST_DYING) {
254: st->state = ST_DEAD;
255: wakeup(st);
256: } else {
257: st->state = ST_TICKING;
258: timeout_add(&st->timeout, hz * st->period);
259: }
260: }
CVSweb