[BACK]Return to kern_sensors.c CVS log [TXT][DIR] Up to [local] / sys / kern

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