Annotation of sys/kern/kern_sensors.c, Revision 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