1*bf4558f8Sxtraeme /* $NetBSD: sysmon_envsys.c,v 1.18 2007/07/01 07:36:45 xtraeme Exp $ */ 2*bf4558f8Sxtraeme 3*bf4558f8Sxtraeme /*- 4*bf4558f8Sxtraeme * Copyright (c) 2007 The NetBSD Foundation, Inc. 5*bf4558f8Sxtraeme * All rights reserved. 6*bf4558f8Sxtraeme * 7*bf4558f8Sxtraeme * This code is derived from software contributed to The NetBSD Foundation 8*bf4558f8Sxtraeme * by Juan Romero Pardines. 9*bf4558f8Sxtraeme * 10*bf4558f8Sxtraeme * Redistribution and use in source and binary forms, with or without 11*bf4558f8Sxtraeme * modification, are permitted provided that the following conditions 12*bf4558f8Sxtraeme * are met: 13*bf4558f8Sxtraeme * 1. Redistributions of source code must retain the above copyright 14*bf4558f8Sxtraeme * notice, this list of conditions and the following disclaimer. 15*bf4558f8Sxtraeme * 2. Redistributions in binary form must reproduce the above copyright 16*bf4558f8Sxtraeme * notice, this list of conditions and the following disclaimer in the 17*bf4558f8Sxtraeme * documentation and/or other materials provided with the distribution. 18*bf4558f8Sxtraeme * 3. All advertising materials mentioning features or use of this software 19*bf4558f8Sxtraeme * must display the following acknowledgement: 20*bf4558f8Sxtraeme * This product includes software developed by Juan Romero Pardines 21*bf4558f8Sxtraeme * for the NetBSD Foundation, Inc. and its contributors. 22*bf4558f8Sxtraeme * 4. Neither the name of The NetBSD Foundation nor the names of its 23*bf4558f8Sxtraeme * contributors may be used to endorse or promote products derived 24*bf4558f8Sxtraeme * from this software without specific prior written permission. 25*bf4558f8Sxtraeme * 26*bf4558f8Sxtraeme * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27*bf4558f8Sxtraeme * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28*bf4558f8Sxtraeme * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29*bf4558f8Sxtraeme * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30*bf4558f8Sxtraeme * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31*bf4558f8Sxtraeme * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32*bf4558f8Sxtraeme * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33*bf4558f8Sxtraeme * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34*bf4558f8Sxtraeme * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35*bf4558f8Sxtraeme * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36*bf4558f8Sxtraeme * POSSIBILITY OF SUCH DAMAGE. 37*bf4558f8Sxtraeme */ 38e67f5e66Sthorpej 39e67f5e66Sthorpej /*- 40e67f5e66Sthorpej * Copyright (c) 2000 Zembu Labs, Inc. 41e67f5e66Sthorpej * All rights reserved. 42e67f5e66Sthorpej * 43e67f5e66Sthorpej * Author: Jason R. Thorpe <thorpej@zembu.com> 44e67f5e66Sthorpej * 45e67f5e66Sthorpej * Redistribution and use in source and binary forms, with or without 46e67f5e66Sthorpej * modification, are permitted provided that the following conditions 47e67f5e66Sthorpej * are met: 48e67f5e66Sthorpej * 1. Redistributions of source code must retain the above copyright 49e67f5e66Sthorpej * notice, this list of conditions and the following disclaimer. 50e67f5e66Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 51e67f5e66Sthorpej * notice, this list of conditions and the following disclaimer in the 52e67f5e66Sthorpej * documentation and/or other materials provided with the distribution. 53e67f5e66Sthorpej * 3. All advertising materials mentioning features or use of this software 54e67f5e66Sthorpej * must display the following acknowledgement: 55e67f5e66Sthorpej * This product includes software developed by Zembu Labs, Inc. 56e67f5e66Sthorpej * 4. Neither the name of Zembu Labs nor the names of its employees may 57e67f5e66Sthorpej * be used to endorse or promote products derived from this software 58e67f5e66Sthorpej * without specific prior written permission. 59e67f5e66Sthorpej * 60e67f5e66Sthorpej * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS 61e67f5e66Sthorpej * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR- 62e67f5e66Sthorpej * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS- 63e67f5e66Sthorpej * CLAIMED. IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT, 64e67f5e66Sthorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 65e67f5e66Sthorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 66e67f5e66Sthorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 67e67f5e66Sthorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 68e67f5e66Sthorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 69e67f5e66Sthorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 70e67f5e66Sthorpej */ 71e67f5e66Sthorpej 72e67f5e66Sthorpej /* 73*bf4558f8Sxtraeme * Environmental sensor framework for sysmon, exported to userland 74*bf4558f8Sxtraeme * with proplib(3). 75e67f5e66Sthorpej */ 76e67f5e66Sthorpej 77640249d1Slukem #include <sys/cdefs.h> 78*bf4558f8Sxtraeme __KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.18 2007/07/01 07:36:45 xtraeme Exp $"); 79640249d1Slukem 80e67f5e66Sthorpej #include <sys/param.h> 81*bf4558f8Sxtraeme #include <sys/types.h> 82e67f5e66Sthorpej #include <sys/conf.h> 83e67f5e66Sthorpej #include <sys/errno.h> 84e67f5e66Sthorpej #include <sys/kernel.h> 85e67f5e66Sthorpej #include <sys/systm.h> 86e67f5e66Sthorpej #include <sys/proc.h> 87*bf4558f8Sxtraeme #include <sys/mutex.h> 88*bf4558f8Sxtraeme #include <sys/kmem.h> 89e67f5e66Sthorpej 90e67f5e66Sthorpej #include <dev/sysmon/sysmonvar.h> 91*bf4558f8Sxtraeme #include <dev/sysmon/sysmon_envsysvar.h> 92*bf4558f8Sxtraeme #include <dev/sysmon/sysmon_taskq.h> 93*bf4558f8Sxtraeme 94*bf4558f8Sxtraeme #include "opt_compat_netbsd.h" 95*bf4558f8Sxtraeme 96*bf4558f8Sxtraeme struct sme_sensor_type { 97*bf4558f8Sxtraeme int type; 98*bf4558f8Sxtraeme int crittype; 99*bf4558f8Sxtraeme const char *desc; 100*bf4558f8Sxtraeme }; 101*bf4558f8Sxtraeme 102*bf4558f8Sxtraeme static const struct sme_sensor_type sme_sensor_type[] = { 103*bf4558f8Sxtraeme { ENVSYS_STEMP, PENVSYS_TYPE_TEMP, "Temperature" }, 104*bf4558f8Sxtraeme { ENVSYS_SFANRPM, PENVSYS_TYPE_FAN, "Fan" }, 105*bf4558f8Sxtraeme { ENVSYS_SVOLTS_AC, PENVSYS_TYPE_VOLTAGE, "Voltage AC" }, 106*bf4558f8Sxtraeme { ENVSYS_SVOLTS_DC, PENVSYS_TYPE_VOLTAGE, "Voltage DC" }, 107*bf4558f8Sxtraeme { ENVSYS_SOHMS, PENVSYS_TYPE_RESISTANCE,"Ohms" }, 108*bf4558f8Sxtraeme { ENVSYS_SWATTS, PENVSYS_TYPE_POWER, "Watts" }, 109*bf4558f8Sxtraeme { ENVSYS_SAMPS, PENVSYS_TYPE_POWER, "Ampere" }, 110*bf4558f8Sxtraeme { ENVSYS_SWATTHOUR, PENVSYS_TYPE_BATTERY, "Watt hour" }, 111*bf4558f8Sxtraeme { ENVSYS_SAMPHOUR, PENVSYS_TYPE_BATTERY, "Ampere hour" }, 112*bf4558f8Sxtraeme { ENVSYS_INDICATOR, -1, "Indicator" }, 113*bf4558f8Sxtraeme { ENVSYS_INTEGER, -1, "Integer" }, 114*bf4558f8Sxtraeme { ENVSYS_DRIVE, PENVSYS_TYPE_DRIVE, "Drive" }, 115*bf4558f8Sxtraeme { -1, -1, NULL } 116*bf4558f8Sxtraeme }; 117*bf4558f8Sxtraeme 118*bf4558f8Sxtraeme struct sme_sensor_state { 119*bf4558f8Sxtraeme int type; 120*bf4558f8Sxtraeme const char *desc; 121*bf4558f8Sxtraeme }; 122*bf4558f8Sxtraeme 123*bf4558f8Sxtraeme static const struct sme_sensor_state sme_sensor_state[] = { 124*bf4558f8Sxtraeme { ENVSYS_SVALID, "valid" }, 125*bf4558f8Sxtraeme { ENVSYS_SINVALID, "invalid" }, 126*bf4558f8Sxtraeme { ENVSYS_SCRITICAL, "critical" }, 127*bf4558f8Sxtraeme { ENVSYS_SCRITUNDER, "critical-under" }, 128*bf4558f8Sxtraeme { ENVSYS_SCRITOVER, "critical-over" }, 129*bf4558f8Sxtraeme { ENVSYS_SWARNUNDER, "warning-under" }, 130*bf4558f8Sxtraeme { ENVSYS_SWARNOVER, "warning-over" }, 131*bf4558f8Sxtraeme { -1, "unknown" } 132*bf4558f8Sxtraeme }; 133*bf4558f8Sxtraeme 134*bf4558f8Sxtraeme static const struct sme_sensor_state sme_sensor_drive_state[] = { 135*bf4558f8Sxtraeme { ENVSYS_DRIVE_EMPTY, "drive state is unknown" }, 136*bf4558f8Sxtraeme { ENVSYS_DRIVE_READY, "drive is ready" }, 137*bf4558f8Sxtraeme { ENVSYS_DRIVE_POWERUP, "drive is powering up" }, 138*bf4558f8Sxtraeme { ENVSYS_DRIVE_ONLINE, "drive is online" }, 139*bf4558f8Sxtraeme { ENVSYS_DRIVE_IDLE, "drive is idle" }, 140*bf4558f8Sxtraeme { ENVSYS_DRIVE_ACTIVE, "drive is active" }, 141*bf4558f8Sxtraeme { ENVSYS_DRIVE_REBUILD, "drive is rebuilding" }, 142*bf4558f8Sxtraeme { ENVSYS_DRIVE_POWERDOWN, "drive is powering down" }, 143*bf4558f8Sxtraeme { ENVSYS_DRIVE_FAIL, "drive failed" }, 144*bf4558f8Sxtraeme { ENVSYS_DRIVE_PFAIL, "drive degraded" }, 145*bf4558f8Sxtraeme { -1, "unknown" } 146*bf4558f8Sxtraeme }; 147*bf4558f8Sxtraeme 148*bf4558f8Sxtraeme static prop_dictionary_t sme_propd; 149*bf4558f8Sxtraeme static kmutex_t sme_list_mtx; 150*bf4558f8Sxtraeme static kcondvar_t sme_list_cv; 151*bf4558f8Sxtraeme 152*bf4558f8Sxtraeme #ifdef COMPAT_40 153*bf4558f8Sxtraeme static u_int sysmon_envsys_next_sensor_index = 0; 154*bf4558f8Sxtraeme static struct sysmon_envsys *sysmon_envsys_find_40(u_int); 155*bf4558f8Sxtraeme #endif 156*bf4558f8Sxtraeme 157*bf4558f8Sxtraeme static void sysmon_envsys_release(struct sysmon_envsys *); 158*bf4558f8Sxtraeme 159*bf4558f8Sxtraeme kmutex_t sme_mtx, sme_event_mtx; 160e67f5e66Sthorpej 161e67f5e66Sthorpej /* 162*bf4558f8Sxtraeme * sysmon_envsys_init: 163*bf4558f8Sxtraeme * 164*bf4558f8Sxtraeme * + Initialize global mutexes, dictionary and the linked lists. 165e67f5e66Sthorpej */ 166*bf4558f8Sxtraeme void 167*bf4558f8Sxtraeme sysmon_envsys_init(void) 168*bf4558f8Sxtraeme { 169*bf4558f8Sxtraeme LIST_INIT(&sysmon_envsys_list); 170*bf4558f8Sxtraeme LIST_INIT(&sme_events_list); 171*bf4558f8Sxtraeme mutex_init(&sme_mtx, MUTEX_DRIVER, IPL_NONE); 172*bf4558f8Sxtraeme mutex_init(&sme_list_mtx, MUTEX_DRIVER, IPL_NONE); 173*bf4558f8Sxtraeme mutex_init(&sme_event_mtx, MUTEX_DRIVER, IPL_NONE); 174*bf4558f8Sxtraeme mutex_init(&sme_event_init_mtx, MUTEX_DRIVER, IPL_NONE); 175*bf4558f8Sxtraeme cv_init(&sme_list_cv, "smefind"); 176*bf4558f8Sxtraeme sme_propd = prop_dictionary_create(); 177*bf4558f8Sxtraeme } 178e67f5e66Sthorpej 179e67f5e66Sthorpej /* 180e67f5e66Sthorpej * sysmonopen_envsys: 181e67f5e66Sthorpej * 182*bf4558f8Sxtraeme * + Open the system monitor device. 183e67f5e66Sthorpej */ 184e67f5e66Sthorpej int 185*bf4558f8Sxtraeme sysmonopen_envsys(dev_t dev, int flag, int mode, struct lwp *l) 186e67f5e66Sthorpej { 187*bf4558f8Sxtraeme return 0; 188e67f5e66Sthorpej } 189e67f5e66Sthorpej 190e67f5e66Sthorpej /* 191e67f5e66Sthorpej * sysmonclose_envsys: 192e67f5e66Sthorpej * 193*bf4558f8Sxtraeme * + Close the system monitor device. 194e67f5e66Sthorpej */ 195e67f5e66Sthorpej int 196*bf4558f8Sxtraeme sysmonclose_envsys(dev_t dev, int flag, int mode, struct lwp *l) 197e67f5e66Sthorpej { 19857b53bc9Sjdolecek /* Nothing to do */ 199*bf4558f8Sxtraeme return 0; 200e67f5e66Sthorpej } 201e67f5e66Sthorpej 202e67f5e66Sthorpej /* 203e67f5e66Sthorpej * sysmonioctl_envsys: 204e67f5e66Sthorpej * 205*bf4558f8Sxtraeme * + Perform an envsys control request. 206e67f5e66Sthorpej */ 207e67f5e66Sthorpej int 208*bf4558f8Sxtraeme sysmonioctl_envsys(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 209e67f5e66Sthorpej { 210*bf4558f8Sxtraeme struct sysmon_envsys *sme = NULL; 211e67f5e66Sthorpej int error = 0; 212*bf4558f8Sxtraeme #ifdef COMPAT_40 213e67f5e66Sthorpej u_int oidx; 214*bf4558f8Sxtraeme #endif 215e67f5e66Sthorpej 216e67f5e66Sthorpej switch (cmd) { 217*bf4558f8Sxtraeme case ENVSYS_GETDICTIONARY: 218e67f5e66Sthorpej { 219*bf4558f8Sxtraeme struct plistref *plist = (struct plistref *)data; 22059e0238fSexplorer 221*bf4558f8Sxtraeme /* 222*bf4558f8Sxtraeme * Update all sysmon envsys devices dictionaries with 223*bf4558f8Sxtraeme * new data if it's different than we have currently 224*bf4558f8Sxtraeme * in the dictionary. 225*bf4558f8Sxtraeme */ 226*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 227*bf4558f8Sxtraeme LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { 228*bf4558f8Sxtraeme if (sme == NULL) 229*bf4558f8Sxtraeme continue; 23059e0238fSexplorer 231*bf4558f8Sxtraeme error = sme_update_dictionary(sme); 232*bf4558f8Sxtraeme if (error) { 233*bf4558f8Sxtraeme DPRINTF(("%s: sme_update_dictionary, " 234*bf4558f8Sxtraeme "error=%d\n", __func__, error)); 235*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 236*bf4558f8Sxtraeme return error; 237*bf4558f8Sxtraeme } 238*bf4558f8Sxtraeme } 239*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 240*bf4558f8Sxtraeme /* 241*bf4558f8Sxtraeme * Copy global dictionary to userland. 242*bf4558f8Sxtraeme */ 243*bf4558f8Sxtraeme error = prop_dictionary_copyout_ioctl(plist, cmd, sme_propd); 244*bf4558f8Sxtraeme break; 245*bf4558f8Sxtraeme } 246*bf4558f8Sxtraeme case ENVSYS_SETDICTIONARY: 247*bf4558f8Sxtraeme { 248*bf4558f8Sxtraeme const struct plistref *plist = (const struct plistref *)data; 249*bf4558f8Sxtraeme prop_dictionary_t udict; 250*bf4558f8Sxtraeme prop_object_t obj; 251*bf4558f8Sxtraeme const char *devname = NULL; 25259e0238fSexplorer 253*bf4558f8Sxtraeme /* 254*bf4558f8Sxtraeme * Get dictionary from userland. 255*bf4558f8Sxtraeme */ 256*bf4558f8Sxtraeme error = prop_dictionary_copyin_ioctl(plist, cmd, &udict); 257*bf4558f8Sxtraeme DPRINTF(("%s: copyin_ioctl error=%d\n", __func__, error)); 258*bf4558f8Sxtraeme if (error) 259*bf4558f8Sxtraeme break; 260*bf4558f8Sxtraeme 261*bf4558f8Sxtraeme /* 262*bf4558f8Sxtraeme * Parse "driver-name" key to obtain the driver we 263*bf4558f8Sxtraeme * are searching for. 264*bf4558f8Sxtraeme */ 265*bf4558f8Sxtraeme obj = prop_dictionary_get(udict, "driver-name"); 266*bf4558f8Sxtraeme if (obj == NULL || prop_object_type(obj) != PROP_TYPE_STRING) { 267*bf4558f8Sxtraeme DPRINTF(("%s: driver-name failed\n", __func__)); 268*bf4558f8Sxtraeme prop_object_release(udict); 269*bf4558f8Sxtraeme error = EINVAL; 27059e0238fSexplorer break; 27159e0238fSexplorer } 272e67f5e66Sthorpej 273*bf4558f8Sxtraeme /* driver name */ 274*bf4558f8Sxtraeme devname = prop_string_cstring_nocopy(obj); 275*bf4558f8Sxtraeme 276*bf4558f8Sxtraeme /* find the correct sme device */ 277*bf4558f8Sxtraeme sme = sysmon_envsys_find(devname); 278e67f5e66Sthorpej if (sme == NULL) { 279*bf4558f8Sxtraeme DPRINTF(("%s: NULL sme\n", __func__)); 280*bf4558f8Sxtraeme prop_object_release(udict); 281*bf4558f8Sxtraeme error = EINVAL; 282e67f5e66Sthorpej break; 283e67f5e66Sthorpej } 284*bf4558f8Sxtraeme 285*bf4558f8Sxtraeme /* 286*bf4558f8Sxtraeme * Find the correct array object with the string supplied 287*bf4558f8Sxtraeme * by the userland dictionary. 288*bf4558f8Sxtraeme */ 289*bf4558f8Sxtraeme obj = prop_dictionary_get(sme_propd, devname); 290*bf4558f8Sxtraeme if (prop_object_type(obj) != PROP_TYPE_ARRAY) { 291*bf4558f8Sxtraeme DPRINTF(("%s: array device failed\n", __func__)); 292*bf4558f8Sxtraeme prop_object_release(udict); 293*bf4558f8Sxtraeme error = EINVAL; 29459e0238fSexplorer break; 29559e0238fSexplorer } 296*bf4558f8Sxtraeme 297*bf4558f8Sxtraeme /* do the real work now */ 298*bf4558f8Sxtraeme error = sme_userset_dictionary(sme, udict, obj); 299e67f5e66Sthorpej sysmon_envsys_release(sme); 300e67f5e66Sthorpej break; 301e67f5e66Sthorpej } 302*bf4558f8Sxtraeme /* 303*bf4558f8Sxtraeme * Compatibility functions with the old interface, only 304*bf4558f8Sxtraeme * implemented ENVSYS_GTREDATA and ENVSYS_GTREINFO; enough 305*bf4558f8Sxtraeme * to make old applications work. 306*bf4558f8Sxtraeme */ 307*bf4558f8Sxtraeme #ifdef COMPAT_40 308e67f5e66Sthorpej case ENVSYS_GTREDATA: 309e67f5e66Sthorpej { 310e67f5e66Sthorpej struct envsys_tre_data *tred = (void *)data; 311*bf4558f8Sxtraeme envsys_data_t *edata = NULL; 312e67f5e66Sthorpej 313e67f5e66Sthorpej tred->validflags = 0; 314e67f5e66Sthorpej 315*bf4558f8Sxtraeme sme = sysmon_envsys_find_40(tred->sensor); 316e67f5e66Sthorpej if (sme == NULL) 317e67f5e66Sthorpej break; 318*bf4558f8Sxtraeme 319*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 320e67f5e66Sthorpej oidx = tred->sensor; 321e67f5e66Sthorpej tred->sensor = SME_SENSOR_IDX(sme, tred->sensor); 322*bf4558f8Sxtraeme 323*bf4558f8Sxtraeme DPRINTFOBJ(("%s: sensor=%d oidx=%d dev=%s nsensors=%d\n", 324*bf4558f8Sxtraeme __func__, tred->sensor, oidx, sme->sme_name, 325*bf4558f8Sxtraeme sme->sme_nsensors)); 326*bf4558f8Sxtraeme 327*bf4558f8Sxtraeme edata = &sme->sme_sensor_data[tred->sensor]; 328*bf4558f8Sxtraeme 329*bf4558f8Sxtraeme if (tred->sensor < sme->sme_nsensors) { 330*bf4558f8Sxtraeme if ((sme->sme_flags & SME_DISABLE_GTREDATA) == 0) { 331*bf4558f8Sxtraeme error = (*sme->sme_gtredata)(sme, edata); 332*bf4558f8Sxtraeme if (error) { 333*bf4558f8Sxtraeme DPRINTF(("%s: sme_gtredata failed\n", 334*bf4558f8Sxtraeme __func__)); 335*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 336*bf4558f8Sxtraeme return error; 337*bf4558f8Sxtraeme } 338*bf4558f8Sxtraeme } 339*bf4558f8Sxtraeme 340*bf4558f8Sxtraeme /* copy required values to the old interface */ 341*bf4558f8Sxtraeme tred->sensor = edata->sensor; 342*bf4558f8Sxtraeme tred->cur.data_us = edata->value_cur; 343*bf4558f8Sxtraeme tred->cur.data_s = edata->value_cur; 344*bf4558f8Sxtraeme tred->max.data_us = edata->value_max; 345*bf4558f8Sxtraeme tred->max.data_s = edata->value_max; 346*bf4558f8Sxtraeme tred->min.data_us = edata->value_min; 347*bf4558f8Sxtraeme tred->min.data_s = edata->value_min; 348*bf4558f8Sxtraeme tred->avg.data_us = edata->value_avg; 349*bf4558f8Sxtraeme tred->avg.data_s = edata->value_avg; 350*bf4558f8Sxtraeme tred->units = edata->units; 351*bf4558f8Sxtraeme 352*bf4558f8Sxtraeme /* mark invalid sensors */ 353*bf4558f8Sxtraeme if (edata->state == ENVSYS_SINVALID) { 354*bf4558f8Sxtraeme tred->validflags &= 355*bf4558f8Sxtraeme ~(ENVSYS_FVALID|ENVSYS_FCURVALID); 356*bf4558f8Sxtraeme tred->validflags &= 357*bf4558f8Sxtraeme ~(ENVSYS_FMAXVALID|ENVSYS_FFRACVALID); 358*bf4558f8Sxtraeme tred->cur.data_us = tred->cur.data_s = 0; 359*bf4558f8Sxtraeme } 360*bf4558f8Sxtraeme 361*bf4558f8Sxtraeme tred->validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID); 362*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FPERCENT) 363*bf4558f8Sxtraeme tred->validflags |= 364*bf4558f8Sxtraeme (ENVSYS_FMAXVALID|ENVSYS_FFRACVALID); 365*bf4558f8Sxtraeme 366*bf4558f8Sxtraeme DPRINTFOBJ(("%s: sensor=%s tred->cur.data_s=%d\n", 367*bf4558f8Sxtraeme __func__, edata->desc, tred->cur.data_s)); 368*bf4558f8Sxtraeme DPRINTFOBJ(("%s: tred->validflags=%d tred->units=%d" 369*bf4558f8Sxtraeme " tred->sensor=%d\n", __func__, tred->validflags, 370*bf4558f8Sxtraeme tred->units, tred->sensor)); 37157b53bc9Sjdolecek } 372e67f5e66Sthorpej tred->sensor = oidx; 373*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 374*bf4558f8Sxtraeme 375e67f5e66Sthorpej break; 376e67f5e66Sthorpej } 377e67f5e66Sthorpej case ENVSYS_GTREINFO: 378e67f5e66Sthorpej { 379e67f5e66Sthorpej struct envsys_basic_info *binfo = (void *)data; 380*bf4558f8Sxtraeme envsys_data_t *edata = NULL; 381e67f5e66Sthorpej 382e67f5e66Sthorpej binfo->validflags = 0; 383e67f5e66Sthorpej 384*bf4558f8Sxtraeme sme = sysmon_envsys_find_40(binfo->sensor); 385e67f5e66Sthorpej if (sme == NULL) 386e67f5e66Sthorpej break; 387*bf4558f8Sxtraeme 388*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 389e67f5e66Sthorpej oidx = binfo->sensor; 390e67f5e66Sthorpej binfo->sensor = SME_SENSOR_IDX(sme, binfo->sensor); 391*bf4558f8Sxtraeme 392*bf4558f8Sxtraeme edata = &sme->sme_sensor_data[binfo->sensor]; 393*bf4558f8Sxtraeme 394*bf4558f8Sxtraeme /* skip invalid sensors */ 395*bf4558f8Sxtraeme if (edata->state == ENVSYS_SINVALID) { 396*bf4558f8Sxtraeme binfo->validflags &= ~(ENVSYS_FVALID|ENVSYS_FCURVALID); 397*bf4558f8Sxtraeme binfo->validflags &= 398*bf4558f8Sxtraeme ~(ENVSYS_FMAXVALID|ENVSYS_FFRACVALID); 399*bf4558f8Sxtraeme } 400*bf4558f8Sxtraeme 401*bf4558f8Sxtraeme if (binfo->sensor < sme->sme_nsensors) { 402*bf4558f8Sxtraeme binfo->validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID); 403*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FPERCENT) 404*bf4558f8Sxtraeme binfo->validflags |= 405*bf4558f8Sxtraeme (ENVSYS_FMAXVALID|ENVSYS_FFRACVALID); 406*bf4558f8Sxtraeme binfo->units = edata->units; 407*bf4558f8Sxtraeme (void)strlcpy(binfo->desc, edata->desc, 408*bf4558f8Sxtraeme sizeof(binfo->desc)); 409*bf4558f8Sxtraeme } 410*bf4558f8Sxtraeme 411*bf4558f8Sxtraeme DPRINTFOBJ(("%s: binfo->units=%d binfo->validflags=%d\n", 412*bf4558f8Sxtraeme __func__, binfo->units, binfo->validflags)); 413*bf4558f8Sxtraeme DPRINTFOBJ(("%s: binfo->desc=%s binfo->sensor=%d\n", 414*bf4558f8Sxtraeme __func__, binfo->desc, binfo->sensor)); 415*bf4558f8Sxtraeme 416e67f5e66Sthorpej binfo->sensor = oidx; 417*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 418*bf4558f8Sxtraeme 419*bf4558f8Sxtraeme break; 420*bf4558f8Sxtraeme } 421*bf4558f8Sxtraeme #endif /* COMPAT_40 */ 422*bf4558f8Sxtraeme default: 423*bf4558f8Sxtraeme error = ENOTTY; 424e67f5e66Sthorpej break; 425e67f5e66Sthorpej } 426e67f5e66Sthorpej 427*bf4558f8Sxtraeme return error; 428e67f5e66Sthorpej } 429e67f5e66Sthorpej 430e67f5e66Sthorpej /* 431e67f5e66Sthorpej * sysmon_envsys_register: 432e67f5e66Sthorpej * 433*bf4558f8Sxtraeme * + Register an envsys device. 434*bf4558f8Sxtraeme * + Create device dictionary. 435e67f5e66Sthorpej */ 436e67f5e66Sthorpej int 437e67f5e66Sthorpej sysmon_envsys_register(struct sysmon_envsys *sme) 438e67f5e66Sthorpej { 439*bf4558f8Sxtraeme struct sysmon_envsys *lsme; 440e67f5e66Sthorpej int error = 0; 441e67f5e66Sthorpej 442*bf4558f8Sxtraeme /* 443*bf4558f8Sxtraeme * sanity check 1, make sure the driver has initialized 444*bf4558f8Sxtraeme * the sensors count or the value is not too high. 445*bf4558f8Sxtraeme */ 446*bf4558f8Sxtraeme if (!sme->sme_nsensors || sme->sme_nsensors > ENVSYS_MAXSENSORS) 447*bf4558f8Sxtraeme return EINVAL; 448e67f5e66Sthorpej 449*bf4558f8Sxtraeme /* 450*bf4558f8Sxtraeme * sanity check 2, make sure that sme->sme_name and 451*bf4558f8Sxtraeme * sme->sme_data are not NULL. 452*bf4558f8Sxtraeme */ 453*bf4558f8Sxtraeme if (sme->sme_name == NULL || sme->sme_sensor_data == NULL) 454*bf4558f8Sxtraeme return EINVAL; 455*bf4558f8Sxtraeme 456*bf4558f8Sxtraeme /* 457*bf4558f8Sxtraeme * sanity check 3, if SME_DISABLE_GTREDATA is not set 458*bf4558f8Sxtraeme * the sme_gtredata function callback must be non NULL. 459*bf4558f8Sxtraeme */ 460*bf4558f8Sxtraeme if ((sme->sme_flags & SME_DISABLE_GTREDATA) == 0) { 461*bf4558f8Sxtraeme if (sme->sme_gtredata == NULL) 462*bf4558f8Sxtraeme return EINVAL; 463e67f5e66Sthorpej } 464e67f5e66Sthorpej 465*bf4558f8Sxtraeme /* 466*bf4558f8Sxtraeme * - check if requested sysmon_envsys device is valid 467*bf4558f8Sxtraeme * and does not exist already in the list. 468*bf4558f8Sxtraeme * - add device into the list. 469*bf4558f8Sxtraeme * - create the plist structure. 470*bf4558f8Sxtraeme */ 471*bf4558f8Sxtraeme mutex_enter(&sme_list_mtx); 472*bf4558f8Sxtraeme LIST_FOREACH(lsme, &sysmon_envsys_list, sme_list) { 473*bf4558f8Sxtraeme if (strcmp(lsme->sme_name, sme->sme_name) == 0) { 474*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 475*bf4558f8Sxtraeme error = EEXIST; 476*bf4558f8Sxtraeme goto out; 477*bf4558f8Sxtraeme } 478*bf4558f8Sxtraeme } 479*bf4558f8Sxtraeme #ifdef COMPAT_40 480e67f5e66Sthorpej sme->sme_fsensor = sysmon_envsys_next_sensor_index; 481e67f5e66Sthorpej sysmon_envsys_next_sensor_index += sme->sme_nsensors; 482*bf4558f8Sxtraeme #endif 483*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 484*bf4558f8Sxtraeme error = sysmon_envsys_createplist(sme); 485*bf4558f8Sxtraeme if (!error) { 486*bf4558f8Sxtraeme mutex_enter(&sme_list_mtx); 487e67f5e66Sthorpej LIST_INSERT_HEAD(&sysmon_envsys_list, sme, sme_list); 488*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 489*bf4558f8Sxtraeme } 490e67f5e66Sthorpej 491e67f5e66Sthorpej out: 492*bf4558f8Sxtraeme return error; 493e67f5e66Sthorpej } 494e67f5e66Sthorpej 495e67f5e66Sthorpej /* 496e67f5e66Sthorpej * sysmon_envsys_unregister: 497e67f5e66Sthorpej * 498*bf4558f8Sxtraeme * + Unregister an envsys device. 499*bf4558f8Sxtraeme * + Unregister all events associated with this device. 500*bf4558f8Sxtraeme * + Remove device dictionary. 501e67f5e66Sthorpej */ 502e67f5e66Sthorpej void 503e67f5e66Sthorpej sysmon_envsys_unregister(struct sysmon_envsys *sme) 504e67f5e66Sthorpej { 505*bf4558f8Sxtraeme sme_event_t *see; 506e67f5e66Sthorpej 507*bf4558f8Sxtraeme mutex_enter(&sme_list_mtx); 508104f2a80Syamt while (sme->sme_flags & SME_FLAG_BUSY) { 50944d0d572Syamt sme->sme_flags |= SME_FLAG_WANTED; 510*bf4558f8Sxtraeme cv_wait(&sme_list_cv, &sme_list_mtx); 511*bf4558f8Sxtraeme } 512*bf4558f8Sxtraeme prop_dictionary_remove(sme_propd, sme->sme_name); 513*bf4558f8Sxtraeme LIST_FOREACH(see, &sme_events_list, see_list) { 514*bf4558f8Sxtraeme if (strcmp(see->pes.pes_dvname, sme->sme_name) == 0) 515*bf4558f8Sxtraeme sme_event_unregister(see->pes.pes_sensname, 516*bf4558f8Sxtraeme see->type); 517104f2a80Syamt } 518e67f5e66Sthorpej LIST_REMOVE(sme, sme_list); 519*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 520e67f5e66Sthorpej } 521e67f5e66Sthorpej 522e67f5e66Sthorpej /* 523e67f5e66Sthorpej * sysmon_envsys_find: 524e67f5e66Sthorpej * 525*bf4558f8Sxtraeme * + Find an envsys device. 526e67f5e66Sthorpej */ 527e67f5e66Sthorpej struct sysmon_envsys * 528*bf4558f8Sxtraeme sysmon_envsys_find(const char *name) 529e67f5e66Sthorpej { 530e67f5e66Sthorpej struct sysmon_envsys *sme; 531e67f5e66Sthorpej 532*bf4558f8Sxtraeme mutex_enter(&sme_list_mtx); 533104f2a80Syamt again: 534e67f5e66Sthorpej for (sme = LIST_FIRST(&sysmon_envsys_list); sme != NULL; 535e67f5e66Sthorpej sme = LIST_NEXT(sme, sme_list)) { 536*bf4558f8Sxtraeme if (strcmp(sme->sme_name, name) == 0) { 537104f2a80Syamt if (sme->sme_flags & SME_FLAG_BUSY) { 53844d0d572Syamt sme->sme_flags |= SME_FLAG_WANTED; 539*bf4558f8Sxtraeme cv_wait(&sme_list_cv, &sme_list_mtx); 540104f2a80Syamt goto again; 541104f2a80Syamt } 542104f2a80Syamt sme->sme_flags |= SME_FLAG_BUSY; 543104f2a80Syamt break; 544104f2a80Syamt } 545e67f5e66Sthorpej } 546*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 547104f2a80Syamt return sme; 548e67f5e66Sthorpej } 549e67f5e66Sthorpej 550e67f5e66Sthorpej /* 551e67f5e66Sthorpej * sysmon_envsys_release: 552e67f5e66Sthorpej * 553*bf4558f8Sxtraeme * + Release an envsys device. 554e67f5e66Sthorpej */ 555e67f5e66Sthorpej void 556e67f5e66Sthorpej sysmon_envsys_release(struct sysmon_envsys *sme) 557e67f5e66Sthorpej { 558*bf4558f8Sxtraeme mutex_enter(&sme_list_mtx); 55944d0d572Syamt if (sme->sme_flags & SME_FLAG_WANTED) 560*bf4558f8Sxtraeme cv_broadcast(&sme_list_cv); 56144d0d572Syamt sme->sme_flags &= ~(SME_FLAG_BUSY | SME_FLAG_WANTED); 562*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 563*bf4558f8Sxtraeme } 564*bf4558f8Sxtraeme 565*bf4558f8Sxtraeme /* compatibility function */ 566*bf4558f8Sxtraeme #ifdef COMPAT_40 567*bf4558f8Sxtraeme struct sysmon_envsys * 568*bf4558f8Sxtraeme sysmon_envsys_find_40(u_int idx) 569*bf4558f8Sxtraeme { 570*bf4558f8Sxtraeme struct sysmon_envsys *sme; 571*bf4558f8Sxtraeme 572*bf4558f8Sxtraeme mutex_enter(&sme_list_mtx); 573*bf4558f8Sxtraeme for (sme = LIST_FIRST(&sysmon_envsys_list); sme != NULL; 574*bf4558f8Sxtraeme sme = LIST_NEXT(sme, sme_list)) { 575*bf4558f8Sxtraeme if (idx >= sme->sme_fsensor && 576*bf4558f8Sxtraeme idx < (sme->sme_fsensor + sme->sme_nsensors)) 577*bf4558f8Sxtraeme break; 578*bf4558f8Sxtraeme } 579*bf4558f8Sxtraeme mutex_exit(&sme_list_mtx); 580*bf4558f8Sxtraeme return sme; 581*bf4558f8Sxtraeme } 582*bf4558f8Sxtraeme #endif 583*bf4558f8Sxtraeme 584*bf4558f8Sxtraeme /* 585*bf4558f8Sxtraeme * sysmon_envsys_createplist: 586*bf4558f8Sxtraeme * 587*bf4558f8Sxtraeme * + Create the property list structure for a device. 588*bf4558f8Sxtraeme */ 589*bf4558f8Sxtraeme int 590*bf4558f8Sxtraeme sysmon_envsys_createplist(struct sysmon_envsys *sme) 591*bf4558f8Sxtraeme { 592*bf4558f8Sxtraeme envsys_data_t *edata; 593*bf4558f8Sxtraeme prop_array_t array; 594*bf4558f8Sxtraeme int i, error = 0; 595*bf4558f8Sxtraeme 596*bf4558f8Sxtraeme /* create the sysmon envsys device array. */ 597*bf4558f8Sxtraeme array = prop_array_create(); 598*bf4558f8Sxtraeme 599*bf4558f8Sxtraeme /* 600*bf4558f8Sxtraeme * <dict> 601*bf4558f8Sxtraeme * <key>foo0</key> 602*bf4558f8Sxtraeme * <array> 603*bf4558f8Sxtraeme * ... 604*bf4558f8Sxtraeme */ 605*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 606*bf4558f8Sxtraeme if (!prop_dictionary_set(sme_propd, sme->sme_name, array)) { 607*bf4558f8Sxtraeme DPRINTF(("%s: prop_dictionary_set\n", __func__)); 608*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 609*bf4558f8Sxtraeme error = EINVAL; 610*bf4558f8Sxtraeme goto out; 611*bf4558f8Sxtraeme } 612*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 613*bf4558f8Sxtraeme 614*bf4558f8Sxtraeme /* 615*bf4558f8Sxtraeme * Iterate over all sensors and create a dictionary with all 616*bf4558f8Sxtraeme * values specified by the sysmon envsys driver. 617*bf4558f8Sxtraeme */ 618*bf4558f8Sxtraeme for (i = 0; i < sme->sme_nsensors; i++) { 619*bf4558f8Sxtraeme edata = &sme->sme_sensor_data[i]; 620*bf4558f8Sxtraeme /* 621*bf4558f8Sxtraeme * refresh sensor data via sme_gtredata only if the 622*bf4558f8Sxtraeme * flag is not set. 623*bf4558f8Sxtraeme */ 624*bf4558f8Sxtraeme if ((sme->sme_flags & SME_DISABLE_GTREDATA) == 0) { 625*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 626*bf4558f8Sxtraeme error = (*sme->sme_gtredata)(sme, edata); 627*bf4558f8Sxtraeme if (error) { 628*bf4558f8Sxtraeme DPRINTF(("%s: sme->sme_gtredata[%d]\n", 629*bf4558f8Sxtraeme __func__, i)); 630*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 631*bf4558f8Sxtraeme continue; 632*bf4558f8Sxtraeme } 633*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 634*bf4558f8Sxtraeme } 635*bf4558f8Sxtraeme 636*bf4558f8Sxtraeme error = sme_make_dictionary(sme, array, edata); 637*bf4558f8Sxtraeme if (error) { 638*bf4558f8Sxtraeme DPRINTF(("%s: sme_make_dictionary[%d]\n", __func__, i)); 639*bf4558f8Sxtraeme goto out; 640*bf4558f8Sxtraeme } 641*bf4558f8Sxtraeme } 642*bf4558f8Sxtraeme 643*bf4558f8Sxtraeme out: 644*bf4558f8Sxtraeme prop_object_release(array); 645*bf4558f8Sxtraeme return error; 646*bf4558f8Sxtraeme } 647*bf4558f8Sxtraeme 648*bf4558f8Sxtraeme /* 649*bf4558f8Sxtraeme * sme_make_dictionary: 650*bf4558f8Sxtraeme * 651*bf4558f8Sxtraeme * + Create sensor's dictionary in device's dictionary array. 652*bf4558f8Sxtraeme */ 653*bf4558f8Sxtraeme int 654*bf4558f8Sxtraeme sme_make_dictionary(struct sysmon_envsys *sme, prop_array_t array, 655*bf4558f8Sxtraeme envsys_data_t *edata) 656*bf4558f8Sxtraeme { 657*bf4558f8Sxtraeme const struct sme_sensor_type *est = sme_sensor_type; 658*bf4558f8Sxtraeme const struct sme_sensor_state *ess = sme_sensor_state; 659*bf4558f8Sxtraeme const struct sme_sensor_state *esds = sme_sensor_drive_state; 660*bf4558f8Sxtraeme sme_event_drv_t *sme_evdrv_t = NULL; 661*bf4558f8Sxtraeme prop_dictionary_t dict; 662*bf4558f8Sxtraeme int i, j, k; 663*bf4558f8Sxtraeme 664*bf4558f8Sxtraeme i = j = k = 0; 665*bf4558f8Sxtraeme 666*bf4558f8Sxtraeme /* 667*bf4558f8Sxtraeme * <array> 668*bf4558f8Sxtraeme * <dict> 669*bf4558f8Sxtraeme * ... 670*bf4558f8Sxtraeme */ 671*bf4558f8Sxtraeme dict = prop_dictionary_create(); 672*bf4558f8Sxtraeme 673*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 674*bf4558f8Sxtraeme if (!prop_array_add(array, dict)) { 675*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 676*bf4558f8Sxtraeme DPRINTF(("%s: prop_array_add\n", __func__)); 677*bf4558f8Sxtraeme return EINVAL; 678*bf4558f8Sxtraeme } 679*bf4558f8Sxtraeme 680*bf4558f8Sxtraeme /* find the correct unit for this sensor. */ 681*bf4558f8Sxtraeme for (i = 0; est[i].type != -1; i++) 682*bf4558f8Sxtraeme if (est[i].type == edata->units) 683*bf4558f8Sxtraeme break; 684*bf4558f8Sxtraeme 685*bf4558f8Sxtraeme /* 686*bf4558f8Sxtraeme * ... 687*bf4558f8Sxtraeme * <key>type</key> 688*bf4558f8Sxtraeme * <string>foo</string> 689*bf4558f8Sxtraeme * <key>description</key> 690*bf4558f8Sxtraeme * <string>blah blah</string> 691*bf4558f8Sxtraeme * ... 692*bf4558f8Sxtraeme */ 693*bf4558f8Sxtraeme SENSOR_SSTRING(dict, "type", est[i].desc); 694*bf4558f8Sxtraeme SENSOR_SSTRING(dict, "description", edata->desc); 695*bf4558f8Sxtraeme 696*bf4558f8Sxtraeme /* 697*bf4558f8Sxtraeme * Add sensor's state description. 698*bf4558f8Sxtraeme * 699*bf4558f8Sxtraeme * ... 700*bf4558f8Sxtraeme * <key>state</key> 701*bf4558f8Sxtraeme * <string>valid</string> 702*bf4558f8Sxtraeme * ... 703*bf4558f8Sxtraeme */ 704*bf4558f8Sxtraeme for (j = 0; ess[j].type != -1; j++) 705*bf4558f8Sxtraeme if (ess[j].type == edata->state) 706*bf4558f8Sxtraeme break; 707*bf4558f8Sxtraeme 708*bf4558f8Sxtraeme SENSOR_SSTRING(dict, "state", ess[j].desc); 709*bf4558f8Sxtraeme 710*bf4558f8Sxtraeme /* 711*bf4558f8Sxtraeme * add the percentage boolean object: 712*bf4558f8Sxtraeme * 713*bf4558f8Sxtraeme * ... 714*bf4558f8Sxtraeme * <key>want-percentage</key> 715*bf4558f8Sxtraeme * <true/> 716*bf4558f8Sxtraeme * ... 717*bf4558f8Sxtraeme */ 718*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FPERCENT) 719*bf4558f8Sxtraeme SENSOR_SBOOL(dict, "want-percentage", true); 720*bf4558f8Sxtraeme 721*bf4558f8Sxtraeme /* 722*bf4558f8Sxtraeme * Add the monitoring boolean object: 723*bf4558f8Sxtraeme * 724*bf4558f8Sxtraeme * ... 725*bf4558f8Sxtraeme * <key>monitoring-supported</key> 726*bf4558f8Sxtraeme * <true/> 727*bf4558f8Sxtraeme * ... 728*bf4558f8Sxtraeme * 729*bf4558f8Sxtraeme * always false on Drive, Integer and Indicator types, they 730*bf4558f8Sxtraeme * cannot be monitored. 731*bf4558f8Sxtraeme * 732*bf4558f8Sxtraeme */ 733*bf4558f8Sxtraeme if ((edata->flags & ENVSYS_FMONNOTSUPP) || 734*bf4558f8Sxtraeme (edata->units == ENVSYS_INDICATOR) || 735*bf4558f8Sxtraeme (edata->units == ENVSYS_INTEGER) || 736*bf4558f8Sxtraeme (edata->units == ENVSYS_DRIVE)) { 737*bf4558f8Sxtraeme SENSOR_SBOOL(dict, "monitoring-supported", false); 738*bf4558f8Sxtraeme } else { 739*bf4558f8Sxtraeme SENSOR_SBOOL(dict, "monitoring-supported", true); 740*bf4558f8Sxtraeme } 741*bf4558f8Sxtraeme 742*bf4558f8Sxtraeme /* 743*bf4558f8Sxtraeme * Add the drive-state object for drive sensors: 744*bf4558f8Sxtraeme * 745*bf4558f8Sxtraeme * ... 746*bf4558f8Sxtraeme * <key>drive-state</key> 747*bf4558f8Sxtraeme * <string>drive is online</string> 748*bf4558f8Sxtraeme * ... 749*bf4558f8Sxtraeme */ 750*bf4558f8Sxtraeme if (edata->units == ENVSYS_DRIVE) { 751*bf4558f8Sxtraeme for (k = 0; esds[k].type != -1; k++) 752*bf4558f8Sxtraeme if (esds[k].type == edata->value_cur) 753*bf4558f8Sxtraeme break; 754*bf4558f8Sxtraeme SENSOR_SSTRING(dict, "drive-state", esds[k].desc); 755*bf4558f8Sxtraeme } 756*bf4558f8Sxtraeme 757*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 758*bf4558f8Sxtraeme /* 759*bf4558f8Sxtraeme * Add a new event if a monitoring flag was set. 760*bf4558f8Sxtraeme */ 761*bf4558f8Sxtraeme if (edata->monitor) { 762*bf4558f8Sxtraeme sme_evdrv_t = kmem_zalloc(sizeof(*sme_evdrv_t), KM_SLEEP); 763*bf4558f8Sxtraeme 764*bf4558f8Sxtraeme sme_evdrv_t->sdict = dict; 765*bf4558f8Sxtraeme sme_evdrv_t->edata = edata; 766*bf4558f8Sxtraeme sme_evdrv_t->sme = sme; 767*bf4558f8Sxtraeme sme_evdrv_t->powertype = est[i].crittype; 768*bf4558f8Sxtraeme 769*bf4558f8Sxtraeme sysmon_task_queue_init(); 770*bf4558f8Sxtraeme sysmon_task_queue_sched(0, sme_event_drvadd, sme_evdrv_t); 771*bf4558f8Sxtraeme } 772*bf4558f8Sxtraeme 773*bf4558f8Sxtraeme mutex_enter(&sme_mtx); 774*bf4558f8Sxtraeme /* if sensor is enabled, add the following properties... */ 775*bf4558f8Sxtraeme if (edata->state == ENVSYS_SVALID) { 776*bf4558f8Sxtraeme /* 777*bf4558f8Sxtraeme * ... 778*bf4558f8Sxtraeme * <key>rpms</key> 779*bf4558f8Sxtraeme * <integer>2500</integer> 780*bf4558f8Sxtraeme * <key>rfact</key> 781*bf4558f8Sxtraeme * <integer>10000</integer> 782*bf4558f8Sxtraeme * <key>cur-value</key> 783*bf4558f8Sxtraeme * <integer>1250</integer> 784*bf4558f8Sxtraeme * <key>min-value</key> 785*bf4558f8Sxtraeme * <integer>800</integer> 786*bf4558f8Sxtraeme * <key>max-value</integer> 787*bf4558f8Sxtraeme * <integer>3000</integer> 788*bf4558f8Sxtraeme * <key>avg-value</integer> 789*bf4558f8Sxtraeme * <integer>1400</integer> 790*bf4558f8Sxtraeme * </dict> 791*bf4558f8Sxtraeme */ 792*bf4558f8Sxtraeme if ((edata->units == ENVSYS_SFANRPM) && edata->rpms) 793*bf4558f8Sxtraeme SENSOR_SUINT32(dict, "rpms", edata->rpms); 794*bf4558f8Sxtraeme 795*bf4558f8Sxtraeme if ((edata->units == ENVSYS_SVOLTS_AC || 796*bf4558f8Sxtraeme edata->units == ENVSYS_SVOLTS_DC) && edata->rfact) 797*bf4558f8Sxtraeme SENSOR_SINT32(dict, "rfact", edata->rfact); 798*bf4558f8Sxtraeme 799*bf4558f8Sxtraeme if (edata->value_cur) 800*bf4558f8Sxtraeme SENSOR_SINT32(dict, "cur-value", edata->value_cur); 801*bf4558f8Sxtraeme 802*bf4558f8Sxtraeme if ((edata->flags & ENVSYS_FVALID_MIN) && edata->value_min) 803*bf4558f8Sxtraeme SENSOR_SINT32(dict, "min-value", edata->value_min); 804*bf4558f8Sxtraeme 805*bf4558f8Sxtraeme if ((edata->flags & ENVSYS_FVALID_MAX) && edata->value_max) 806*bf4558f8Sxtraeme SENSOR_SINT32(dict, "max-value", edata->value_max); 807*bf4558f8Sxtraeme 808*bf4558f8Sxtraeme if ((edata->flags & ENVSYS_FVALID_AVG) && edata->value_avg) 809*bf4558f8Sxtraeme SENSOR_SINT32(dict, "avg-value", edata->value_avg); 810*bf4558f8Sxtraeme } 811*bf4558f8Sxtraeme 812*bf4558f8Sxtraeme /* 813*bf4558f8Sxtraeme * ... 814*bf4558f8Sxtraeme * </array> 815*bf4558f8Sxtraeme */ 816*bf4558f8Sxtraeme out: 817*bf4558f8Sxtraeme mutex_exit(&sme_mtx); 818*bf4558f8Sxtraeme prop_object_release(dict); 819*bf4558f8Sxtraeme return 0; 820*bf4558f8Sxtraeme } 821*bf4558f8Sxtraeme 822*bf4558f8Sxtraeme /* 823*bf4558f8Sxtraeme * sme_update_dictionary: 824*bf4558f8Sxtraeme * 825*bf4558f8Sxtraeme * + Update per-sensor dictionaries with new values if there were 826*bf4558f8Sxtraeme * changes, otherwise the object in dictionary is untouched. 827*bf4558f8Sxtraeme * + Send a critical event if any sensor is in a critical condition. 828*bf4558f8Sxtraeme */ 829*bf4558f8Sxtraeme int 830*bf4558f8Sxtraeme sme_update_dictionary(struct sysmon_envsys *sme) 831*bf4558f8Sxtraeme { 832*bf4558f8Sxtraeme const struct sme_sensor_state *ess = sme_sensor_state; 833*bf4558f8Sxtraeme const struct sme_sensor_state *esds = sme_sensor_drive_state; 834*bf4558f8Sxtraeme envsys_data_t *edata = NULL; 835*bf4558f8Sxtraeme prop_object_t array, obj, dict = NULL; 836*bf4558f8Sxtraeme int i, j, error = 0; 837*bf4558f8Sxtraeme 838*bf4558f8Sxtraeme /* retrieve the array of dictionaries in device. */ 839*bf4558f8Sxtraeme array = prop_dictionary_get(sme_propd, sme->sme_name); 840*bf4558f8Sxtraeme if (prop_object_type(array) != PROP_TYPE_ARRAY) 841*bf4558f8Sxtraeme return EINVAL; 842*bf4558f8Sxtraeme 843*bf4558f8Sxtraeme /* 844*bf4558f8Sxtraeme * - iterate over all sensors. 845*bf4558f8Sxtraeme * - fetch new data. 846*bf4558f8Sxtraeme * - check if data in dictionary is different than new data. 847*bf4558f8Sxtraeme * - update dictionary if there were changes. 848*bf4558f8Sxtraeme */ 849*bf4558f8Sxtraeme for (i = 0; i < sme->sme_nsensors; i++) { 850*bf4558f8Sxtraeme edata = &sme->sme_sensor_data[i]; 851*bf4558f8Sxtraeme 852*bf4558f8Sxtraeme /* 853*bf4558f8Sxtraeme * refresh sensor data via sme_gtredata only if the 854*bf4558f8Sxtraeme * flag is not set. 855*bf4558f8Sxtraeme */ 856*bf4558f8Sxtraeme if ((sme->sme_flags & SME_DISABLE_GTREDATA) == 0) { 857*bf4558f8Sxtraeme error = (*sme->sme_gtredata)(sme, edata); 858*bf4558f8Sxtraeme if (error) { 859*bf4558f8Sxtraeme DPRINTF(("%s: gtredata[%d] failed\n", 860*bf4558f8Sxtraeme __func__, i)); 861*bf4558f8Sxtraeme return error; 862*bf4558f8Sxtraeme } 863*bf4558f8Sxtraeme } 864*bf4558f8Sxtraeme 865*bf4558f8Sxtraeme /* retrieve sensor's dictionary. */ 866*bf4558f8Sxtraeme dict = prop_array_get(array, i); 867*bf4558f8Sxtraeme if (prop_object_type(dict) != PROP_TYPE_DICTIONARY) 868*bf4558f8Sxtraeme return EINVAL; 869*bf4558f8Sxtraeme 870*bf4558f8Sxtraeme /* update state sensor. */ 871*bf4558f8Sxtraeme for (j = 0; ess[j].type != -1; j++) 872*bf4558f8Sxtraeme if (ess[j].type == edata->state) 873*bf4558f8Sxtraeme break; 874*bf4558f8Sxtraeme 875*bf4558f8Sxtraeme DPRINTFOBJ(("%s: state=%s type=%d flags=%d " 876*bf4558f8Sxtraeme "units=%d sensor=%d\n", __func__, ess[j].desc, 877*bf4558f8Sxtraeme ess[j].type, edata->flags, edata->units, edata->sensor)); 878*bf4558f8Sxtraeme 879*bf4558f8Sxtraeme /* update sensor state */ 880*bf4558f8Sxtraeme SENSOR_UPSTRING(dict, "state", ess[j].desc); 881*bf4558f8Sxtraeme 882*bf4558f8Sxtraeme /* update sensor current value */ 883*bf4558f8Sxtraeme SENSOR_UPINT32(dict, "cur-value", edata->value_cur); 884*bf4558f8Sxtraeme 885*bf4558f8Sxtraeme /* 886*bf4558f8Sxtraeme * Integer and Indicator types do not the following 887*bf4558f8Sxtraeme * values, so skip them. 888*bf4558f8Sxtraeme */ 889*bf4558f8Sxtraeme if (edata->units == ENVSYS_INTEGER || 890*bf4558f8Sxtraeme edata->units == ENVSYS_INDICATOR) 891*bf4558f8Sxtraeme continue; 892*bf4558f8Sxtraeme 893*bf4558f8Sxtraeme /* update sensor flags */ 894*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FPERCENT) 895*bf4558f8Sxtraeme SENSOR_SBOOL(dict, "want-percentage", true); 896*bf4558f8Sxtraeme else { 897*bf4558f8Sxtraeme obj = prop_dictionary_get(dict, "want-percentage"); 898*bf4558f8Sxtraeme if (obj) 899*bf4558f8Sxtraeme SENSOR_SBOOL(dict, "want-percentage", false); 900*bf4558f8Sxtraeme } 901*bf4558f8Sxtraeme 902*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FVALID_MAX) 903*bf4558f8Sxtraeme SENSOR_UPINT32(dict, "max-value", edata->value_max); 904*bf4558f8Sxtraeme 905*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FVALID_MIN) 906*bf4558f8Sxtraeme SENSOR_UPINT32(dict, "min-value", edata->value_min); 907*bf4558f8Sxtraeme 908*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FVALID_AVG) 909*bf4558f8Sxtraeme SENSOR_UPINT32(dict, "avg-value", edata->value_avg); 910*bf4558f8Sxtraeme 911*bf4558f8Sxtraeme /* update 'rpms' only in ENVSYS_SFANRPM. */ 912*bf4558f8Sxtraeme if (edata->units == ENVSYS_SFANRPM) 913*bf4558f8Sxtraeme SENSOR_UPUINT32(dict, "rpms", edata->rpms); 914*bf4558f8Sxtraeme 915*bf4558f8Sxtraeme /* update 'rfact' only in ENVSYS_SVOLTS_[AD]C. */ 916*bf4558f8Sxtraeme if (edata->units == ENVSYS_SVOLTS_AC || 917*bf4558f8Sxtraeme edata->units == ENVSYS_SVOLTS_DC) { 918*bf4558f8Sxtraeme SENSOR_UPINT32(dict, "rfact", edata->rfact); 919*bf4558f8Sxtraeme } 920*bf4558f8Sxtraeme 921*bf4558f8Sxtraeme /* update 'drive-state' only in ENVSYS_DRIVE. */ 922*bf4558f8Sxtraeme if (edata->units == ENVSYS_DRIVE) { 923*bf4558f8Sxtraeme for (j = 0; esds[j].type != -1; j++) 924*bf4558f8Sxtraeme if (esds[j].type == edata->value_cur) 925*bf4558f8Sxtraeme break; 926*bf4558f8Sxtraeme 927*bf4558f8Sxtraeme SENSOR_UPSTRING(dict, "drive-state", esds[j].desc); 928*bf4558f8Sxtraeme } 929*bf4558f8Sxtraeme } 930*bf4558f8Sxtraeme 931*bf4558f8Sxtraeme out: 932*bf4558f8Sxtraeme return error; 933*bf4558f8Sxtraeme } 934*bf4558f8Sxtraeme 935*bf4558f8Sxtraeme /* 936*bf4558f8Sxtraeme * sme_userset_dictionary: 937*bf4558f8Sxtraeme * 938*bf4558f8Sxtraeme * + Parses the userland dictionary and run the appropiate 939*bf4558f8Sxtraeme * tasks that were requested. 940*bf4558f8Sxtraeme */ 941*bf4558f8Sxtraeme int 942*bf4558f8Sxtraeme sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict, 943*bf4558f8Sxtraeme prop_array_t array) 944*bf4558f8Sxtraeme { 945*bf4558f8Sxtraeme const struct sme_sensor_type *sst = sme_sensor_type; 946*bf4558f8Sxtraeme envsys_data_t *edata; 947*bf4558f8Sxtraeme prop_dictionary_t dict; 948*bf4558f8Sxtraeme prop_object_t obj, obj1, obj2; 949*bf4558f8Sxtraeme int32_t critval; 950*bf4558f8Sxtraeme int i, error = 0; 951*bf4558f8Sxtraeme const char *blah, *sname; 952*bf4558f8Sxtraeme bool targetfound = false; 953*bf4558f8Sxtraeme 954*bf4558f8Sxtraeme blah = sname = NULL; 955*bf4558f8Sxtraeme 956*bf4558f8Sxtraeme /* get sensor's name from userland dictionary. */ 957*bf4558f8Sxtraeme obj = prop_dictionary_get(udict, "sensor-name"); 958*bf4558f8Sxtraeme if (prop_object_type(obj) != PROP_TYPE_STRING) { 959*bf4558f8Sxtraeme DPRINTF(("%s: sensor-name failed\n", __func__)); 960*bf4558f8Sxtraeme return EINVAL; 961*bf4558f8Sxtraeme } 962*bf4558f8Sxtraeme 963*bf4558f8Sxtraeme /* iterate over the sensors to find the right one */ 964*bf4558f8Sxtraeme for (i = 0; i < sme->sme_nsensors; i++) { 965*bf4558f8Sxtraeme edata = &sme->sme_sensor_data[i]; 966*bf4558f8Sxtraeme dict = prop_array_get(array, i); 967*bf4558f8Sxtraeme obj1 = prop_dictionary_get(dict, "description"); 968*bf4558f8Sxtraeme 969*bf4558f8Sxtraeme /* is it our sensor? */ 970*bf4558f8Sxtraeme if (!prop_string_equals(obj1, obj)) 971*bf4558f8Sxtraeme continue; 972*bf4558f8Sxtraeme 973*bf4558f8Sxtraeme /* 974*bf4558f8Sxtraeme * Check if a new description operation was 975*bf4558f8Sxtraeme * requested by the user and set new description. 976*bf4558f8Sxtraeme */ 977*bf4558f8Sxtraeme if ((obj2 = prop_dictionary_get(udict, "new-description"))) { 978*bf4558f8Sxtraeme targetfound = true; 979*bf4558f8Sxtraeme blah = prop_string_cstring_nocopy(obj2); 980*bf4558f8Sxtraeme SENSOR_UPSTRING(dict, "description", blah); 981*bf4558f8Sxtraeme break; 982*bf4558f8Sxtraeme } 983*bf4558f8Sxtraeme 984*bf4558f8Sxtraeme /* did the user want to remove a critical capacity limit? */ 985*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "remove-critical-cap"); 986*bf4558f8Sxtraeme if (obj2 != NULL) { 987*bf4558f8Sxtraeme targetfound = true; 988*bf4558f8Sxtraeme if ((edata->flags & ENVSYS_FMONNOTSUPP) || 989*bf4558f8Sxtraeme (edata->flags & ENVSYS_FPERCENT) == 0) { 990*bf4558f8Sxtraeme error = ENOTSUP; 991*bf4558f8Sxtraeme break; 992*bf4558f8Sxtraeme } 993*bf4558f8Sxtraeme 994*bf4558f8Sxtraeme sname = prop_string_cstring_nocopy(obj); 995*bf4558f8Sxtraeme error = sme_event_unregister(sname, 996*bf4558f8Sxtraeme PENVSYS_EVENT_BATT_USERCAP); 997*bf4558f8Sxtraeme if (error) 998*bf4558f8Sxtraeme break; 999*bf4558f8Sxtraeme 1000*bf4558f8Sxtraeme prop_dictionary_remove(dict, "critical-capacity"); 1001*bf4558f8Sxtraeme break; 1002*bf4558f8Sxtraeme } 1003*bf4558f8Sxtraeme 1004*bf4558f8Sxtraeme /* did the user want to remove a critical min limit? */ 1005*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "remove-cmin-limit"); 1006*bf4558f8Sxtraeme if (obj2 != NULL) { 1007*bf4558f8Sxtraeme targetfound = true; 1008*bf4558f8Sxtraeme sname = prop_string_cstring_nocopy(obj); 1009*bf4558f8Sxtraeme error = sme_event_unregister(sname, 1010*bf4558f8Sxtraeme PENVSYS_EVENT_USER_CRITMIN); 1011*bf4558f8Sxtraeme if (error) 1012*bf4558f8Sxtraeme break; 1013*bf4558f8Sxtraeme 1014*bf4558f8Sxtraeme prop_dictionary_remove(dict, "critical-min-limit"); 1015*bf4558f8Sxtraeme break; 1016*bf4558f8Sxtraeme } 1017*bf4558f8Sxtraeme 1018*bf4558f8Sxtraeme /* did the user want to remove a critical max limit? */ 1019*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "remove-cmax-limit"); 1020*bf4558f8Sxtraeme if (obj2 != NULL) { 1021*bf4558f8Sxtraeme targetfound = true; 1022*bf4558f8Sxtraeme sname = prop_string_cstring_nocopy(obj); 1023*bf4558f8Sxtraeme error = sme_event_unregister(sname, 1024*bf4558f8Sxtraeme PENVSYS_EVENT_USER_CRITMAX); 1025*bf4558f8Sxtraeme if (error) 1026*bf4558f8Sxtraeme break; 1027*bf4558f8Sxtraeme 1028*bf4558f8Sxtraeme prop_dictionary_remove(dict, "critical-max-limit"); 1029*bf4558f8Sxtraeme break; 1030*bf4558f8Sxtraeme } 1031*bf4558f8Sxtraeme 1032*bf4558f8Sxtraeme /* did the user want to change rfact? */ 1033*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "new-rfact"); 1034*bf4558f8Sxtraeme if (obj2 != NULL) { 1035*bf4558f8Sxtraeme targetfound = true; 1036*bf4558f8Sxtraeme if (edata->flags & ENVSYS_FCHANGERFACT) 1037*bf4558f8Sxtraeme edata->rfact = prop_number_integer_value(obj2); 1038*bf4558f8Sxtraeme else 1039*bf4558f8Sxtraeme error = ENOTSUP; 1040*bf4558f8Sxtraeme 1041*bf4558f8Sxtraeme break; 1042*bf4558f8Sxtraeme } 1043*bf4558f8Sxtraeme 1044*bf4558f8Sxtraeme for (i = 0; sst[i].type != -1; i++) 1045*bf4558f8Sxtraeme if (sst[i].type == edata->units) 1046*bf4558f8Sxtraeme break; 1047*bf4558f8Sxtraeme 1048*bf4558f8Sxtraeme /* did the user want to set a critical capacity event? */ 1049*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "critical-capacity"); 1050*bf4558f8Sxtraeme if (obj2 != NULL) { 1051*bf4558f8Sxtraeme targetfound = true; 1052*bf4558f8Sxtraeme if ((edata->flags & ENVSYS_FMONNOTSUPP) || 1053*bf4558f8Sxtraeme (edata->flags & ENVSYS_FPERCENT) == 0) { 1054*bf4558f8Sxtraeme error = ENOTSUP; 1055*bf4558f8Sxtraeme break; 1056*bf4558f8Sxtraeme } 1057*bf4558f8Sxtraeme 1058*bf4558f8Sxtraeme critval = prop_number_integer_value(obj2); 1059*bf4558f8Sxtraeme error = sme_event_add(dict, 1060*bf4558f8Sxtraeme edata, 1061*bf4558f8Sxtraeme sme->sme_name, 1062*bf4558f8Sxtraeme "critical-capacity", 1063*bf4558f8Sxtraeme critval, 1064*bf4558f8Sxtraeme PENVSYS_EVENT_BATT_USERCAP, 1065*bf4558f8Sxtraeme sst[i].crittype); 1066*bf4558f8Sxtraeme break; 1067*bf4558f8Sxtraeme } 1068*bf4558f8Sxtraeme 1069*bf4558f8Sxtraeme /* did the user want to set a critical max event? */ 1070*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "critical-max-limit"); 1071*bf4558f8Sxtraeme if (obj2 != NULL) { 1072*bf4558f8Sxtraeme targetfound = true; 1073*bf4558f8Sxtraeme if (edata->units == ENVSYS_INDICATOR || 1074*bf4558f8Sxtraeme edata->units == ENVSYS_INTEGER || 1075*bf4558f8Sxtraeme edata->flags & ENVSYS_FMONNOTSUPP) { 1076*bf4558f8Sxtraeme error = ENOTSUP; 1077*bf4558f8Sxtraeme break; 1078*bf4558f8Sxtraeme } 1079*bf4558f8Sxtraeme 1080*bf4558f8Sxtraeme critval = prop_number_integer_value(obj2); 1081*bf4558f8Sxtraeme error = sme_event_add(dict, 1082*bf4558f8Sxtraeme edata, 1083*bf4558f8Sxtraeme sme->sme_name, 1084*bf4558f8Sxtraeme "critical-max-limit", 1085*bf4558f8Sxtraeme critval, 1086*bf4558f8Sxtraeme PENVSYS_EVENT_USER_CRITMAX, 1087*bf4558f8Sxtraeme sst[i].crittype); 1088*bf4558f8Sxtraeme break; 1089*bf4558f8Sxtraeme } 1090*bf4558f8Sxtraeme 1091*bf4558f8Sxtraeme /* did the user want to set a critical min event? */ 1092*bf4558f8Sxtraeme obj2 = prop_dictionary_get(udict, "critical-min-limit"); 1093*bf4558f8Sxtraeme if (obj2 != NULL) { 1094*bf4558f8Sxtraeme targetfound = true; 1095*bf4558f8Sxtraeme if (edata->units == ENVSYS_INDICATOR || 1096*bf4558f8Sxtraeme edata->units == ENVSYS_INTEGER || 1097*bf4558f8Sxtraeme edata->flags & ENVSYS_FMONNOTSUPP) { 1098*bf4558f8Sxtraeme error = ENOTSUP; 1099*bf4558f8Sxtraeme break; 1100*bf4558f8Sxtraeme } 1101*bf4558f8Sxtraeme 1102*bf4558f8Sxtraeme critval = prop_number_integer_value(obj2); 1103*bf4558f8Sxtraeme error = sme_event_add(dict, 1104*bf4558f8Sxtraeme edata, 1105*bf4558f8Sxtraeme sme->sme_name, 1106*bf4558f8Sxtraeme "critical-min-limit", 1107*bf4558f8Sxtraeme critval, 1108*bf4558f8Sxtraeme PENVSYS_EVENT_USER_CRITMIN, 1109*bf4558f8Sxtraeme sst[i].crittype); 1110*bf4558f8Sxtraeme break; 1111*bf4558f8Sxtraeme } 1112*bf4558f8Sxtraeme } 1113*bf4558f8Sxtraeme 1114*bf4558f8Sxtraeme /* invalid target? return the error */ 1115*bf4558f8Sxtraeme if (!targetfound) 1116*bf4558f8Sxtraeme error = EINVAL; 1117*bf4558f8Sxtraeme 1118*bf4558f8Sxtraeme out: 1119*bf4558f8Sxtraeme return error; 1120e67f5e66Sthorpej } 1121