[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     ! 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