1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * This plugin creates PICL nodes and properties for objects handled through 31*0Sstevel@tonic-gate * the enhanced LOMV system-processor interface. 32*0Sstevel@tonic-gate * 33*0Sstevel@tonic-gate * All the nodes which may be accessible through the system-processor are 34*0Sstevel@tonic-gate * included below the service-processor node in the /platform tree. 35*0Sstevel@tonic-gate * This plugin interrogates the system-processor to determine which of 36*0Sstevel@tonic-gate * those nodes are actually available. Properties are added to such nodes and 37*0Sstevel@tonic-gate * in the case of volatile properties like temperature, a call-back function 38*0Sstevel@tonic-gate * is established for on-demand access to the current value. 39*0Sstevel@tonic-gate * LEDs for which the system-processor provides write access are associated 40*0Sstevel@tonic-gate * with read/write volatile properties. 41*0Sstevel@tonic-gate * 42*0Sstevel@tonic-gate * NOTE: 43*0Sstevel@tonic-gate * Depends on PICL devtree plugin. 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include <stdio.h> 47*0Sstevel@tonic-gate #include <stdlib.h> 48*0Sstevel@tonic-gate #include <unistd.h> 49*0Sstevel@tonic-gate #include <fcntl.h> 50*0Sstevel@tonic-gate #include <alloca.h> 51*0Sstevel@tonic-gate #include <syslog.h> 52*0Sstevel@tonic-gate #include <string.h> 53*0Sstevel@tonic-gate #include <libintl.h> 54*0Sstevel@tonic-gate #include <picl.h> 55*0Sstevel@tonic-gate #include <picltree.h> 56*0Sstevel@tonic-gate #include <libnvpair.h> 57*0Sstevel@tonic-gate #include <errno.h> 58*0Sstevel@tonic-gate #include <limits.h> 59*0Sstevel@tonic-gate #include <ctype.h> 60*0Sstevel@tonic-gate #include <sys/types.h> 61*0Sstevel@tonic-gate #include <sys/stat.h> 62*0Sstevel@tonic-gate #include <sys/obpdefs.h> 63*0Sstevel@tonic-gate #include <sys/envmon.h> 64*0Sstevel@tonic-gate #include <sys/systeminfo.h> 65*0Sstevel@tonic-gate #include <dirent.h> 66*0Sstevel@tonic-gate #include <time.h> 67*0Sstevel@tonic-gate #include <picldefs.h> 68*0Sstevel@tonic-gate #include <picld_pluginutil.h> 69*0Sstevel@tonic-gate #include <libdevinfo.h> 70*0Sstevel@tonic-gate #include "piclenvmon.h" 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate static void piclenvmon_register(void); 73*0Sstevel@tonic-gate static void piclenvmon_init(void); 74*0Sstevel@tonic-gate static void piclenvmon_fini(void); 75*0Sstevel@tonic-gate static node_el_t *create_node_el(picl_nodehdl_t nodeh); 76*0Sstevel@tonic-gate static void delete_node_el(node_el_t *pel); 77*0Sstevel@tonic-gate static node_list_t *create_node_list(); 78*0Sstevel@tonic-gate static void delete_node_list(node_list_t *pnl); 79*0Sstevel@tonic-gate static void add_node_to_list(picl_nodehdl_t nodeh, node_list_t *listp); 80*0Sstevel@tonic-gate static void get_node_list_by_class(picl_nodehdl_t nodeh, 81*0Sstevel@tonic-gate const char *classname, node_list_t *listp); 82*0Sstevel@tonic-gate static int get_envmon_limits(int envmon_fd, envmon_sysinfo_t *limits_p); 83*0Sstevel@tonic-gate static void create_arrays(); 84*0Sstevel@tonic-gate static int get_envmon_node(picl_nodehdl_t *envmoninfh); 85*0Sstevel@tonic-gate static char *create_envmon_pathname(picl_nodehdl_t envmoninfh); 86*0Sstevel@tonic-gate static int get_child_by_name(picl_nodehdl_t nodeh, const char *name, 87*0Sstevel@tonic-gate picl_nodehdl_t *childh); 88*0Sstevel@tonic-gate static int add_regular_prop(picl_nodehdl_t nodeh, const char *name, 89*0Sstevel@tonic-gate int type, int access, int size, const void *valbuf, picl_prophdl_t *prophp); 90*0Sstevel@tonic-gate static int add_volatile_prop(picl_nodehdl_t nodeh, const char *name, 91*0Sstevel@tonic-gate int type, int access, int size, ptree_vol_rdfunc_t rdfunc, 92*0Sstevel@tonic-gate ptree_vol_wrfunc_t wrfunc, picl_prophdl_t *prophp); 93*0Sstevel@tonic-gate static int get_sensor_data(int envmon_fd, envmon_handle_t *id, int cmd, 94*0Sstevel@tonic-gate envmon_thresholds_t *lows, envmon_thresholds_t *highs, int16_t *value); 95*0Sstevel@tonic-gate static int get_indicator_data(int envmon_fd, envmon_handle_t *id, int cmd, 96*0Sstevel@tonic-gate int16_t *condition); 97*0Sstevel@tonic-gate static int get_fan_data(int envmon_fd, envmon_handle_t *id, int cmd, 98*0Sstevel@tonic-gate envmon_thresholds_t *lows, uint16_t *speed, char *units); 99*0Sstevel@tonic-gate static int get_led_data(int envmon_fd, envmon_handle_t *id, int cmd, 100*0Sstevel@tonic-gate int8_t *state, int8_t *colour); 101*0Sstevel@tonic-gate static int get_keyswitch_data(int envmon_fd, envmon_handle_t *id, int cmd, 102*0Sstevel@tonic-gate envmon_keysw_pos_t *key_state); 103*0Sstevel@tonic-gate static void convert_node_name(char *ptr); 104*0Sstevel@tonic-gate static void convert_label_name(char *ptr); 105*0Sstevel@tonic-gate static int add_value_prop(picl_nodehdl_t node_hdl, const char *prop_name, 106*0Sstevel@tonic-gate int fru_type, int16_t value); 107*0Sstevel@tonic-gate static int find_picl_handle(picl_prophdl_t proph); 108*0Sstevel@tonic-gate static int lookup_led_status(int8_t state, const char **string); 109*0Sstevel@tonic-gate static int lookup_key_posn(envmon_keysw_pos_t pos, const char **string); 110*0Sstevel@tonic-gate static int get_config_file(char *filename); 111*0Sstevel@tonic-gate static int read_vol_data(ptree_rarg_t *r_arg, void *buf); 112*0Sstevel@tonic-gate static int write_led_data(ptree_warg_t *w_arg, const void *buf); 113*0Sstevel@tonic-gate static int add_env_nodes(int envmon_fd, uint8_t fru_type, 114*0Sstevel@tonic-gate picl_nodehdl_t envmonh); 115*0Sstevel@tonic-gate static void fixstate(uint8_t state, const char *string, int *max_len); 116*0Sstevel@tonic-gate static void fixkeyposn(envmon_keysw_pos_t keyposn, const char *string, 117*0Sstevel@tonic-gate int *max_len); 118*0Sstevel@tonic-gate static void setup_strings(); 119*0Sstevel@tonic-gate static void free_vol_prop(picl_prophdl_t proph); 120*0Sstevel@tonic-gate static void envmon_evhandler(const char *ename, const void *earg, 121*0Sstevel@tonic-gate size_t size, void *cookie); 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate #pragma init(piclenvmon_register) 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate static picld_plugin_reg_t my_reg_info = { 126*0Sstevel@tonic-gate PICLD_PLUGIN_VERSION_1, 127*0Sstevel@tonic-gate PICLD_PLUGIN_NON_CRITICAL, 128*0Sstevel@tonic-gate "SUNW_piclenvmon", 129*0Sstevel@tonic-gate piclenvmon_init, 130*0Sstevel@tonic-gate piclenvmon_fini 131*0Sstevel@tonic-gate }; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate static const char str_On[] = "on"; 134*0Sstevel@tonic-gate static const char str_Off[] = "off"; 135*0Sstevel@tonic-gate static const char str_SC[] = "SC"; 136*0Sstevel@tonic-gate static char *envmon_device_name = NULL; 137*0Sstevel@tonic-gate static envmon_sysinfo_t env_limits; 138*0Sstevel@tonic-gate static handle_array_t handle_arr; 139*0Sstevel@tonic-gate static struct { 140*0Sstevel@tonic-gate int size; 141*0Sstevel@tonic-gate char *str_colour; 142*0Sstevel@tonic-gate } colour_lkup[1 + ENVMON_LED_CLR_RED]; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate static struct { 145*0Sstevel@tonic-gate int8_t state; 146*0Sstevel@tonic-gate char *str_ledstate; 147*0Sstevel@tonic-gate } ledstate_lkup[] = { 148*0Sstevel@tonic-gate { ENVMON_LED_OFF }, 149*0Sstevel@tonic-gate { ENVMON_LED_ON }, 150*0Sstevel@tonic-gate { ENVMON_LED_BLINKING }, 151*0Sstevel@tonic-gate { ENVMON_LED_FLASHING } 152*0Sstevel@tonic-gate }; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate static struct { 155*0Sstevel@tonic-gate envmon_keysw_pos_t pos; 156*0Sstevel@tonic-gate char *str_keyposn; 157*0Sstevel@tonic-gate } keyposn_lkup[] = { 158*0Sstevel@tonic-gate { ENVMON_KEYSW_POS_UNKNOWN }, 159*0Sstevel@tonic-gate { ENVMON_KEYSW_POS_NORMAL }, 160*0Sstevel@tonic-gate { ENVMON_KEYSW_POS_DIAG }, 161*0Sstevel@tonic-gate { ENVMON_KEYSW_POS_LOCKED }, 162*0Sstevel@tonic-gate { ENVMON_KEYSW_POS_OFF } 163*0Sstevel@tonic-gate }; 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* 166*0Sstevel@tonic-gate * fru-type to ioctl cmd lookup 167*0Sstevel@tonic-gate */ 168*0Sstevel@tonic-gate int fru_to_cmd[] = { 169*0Sstevel@tonic-gate ENVMONIOCVOLTSENSOR, 170*0Sstevel@tonic-gate ENVMONIOCVOLTIND, 171*0Sstevel@tonic-gate ENVMONIOCAMPSENSOR, 172*0Sstevel@tonic-gate ENVMONIOCAMPIND, 173*0Sstevel@tonic-gate ENVMONIOCTEMPSENSOR, 174*0Sstevel@tonic-gate ENVMONIOCTEMPIND, 175*0Sstevel@tonic-gate ENVMONIOCFAN, 176*0Sstevel@tonic-gate ENVMONIOCFANIND, 177*0Sstevel@tonic-gate ENVMONIOCGETLED, 178*0Sstevel@tonic-gate ENVMONIOCGETKEYSW 179*0Sstevel@tonic-gate }; 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate /* 182*0Sstevel@tonic-gate * fru-type to PICL CLASS 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate const char *fru_to_class[] = { 185*0Sstevel@tonic-gate PICL_CLASS_VOLTAGE_SENSOR, 186*0Sstevel@tonic-gate PICL_CLASS_VOLTAGE_INDICATOR, 187*0Sstevel@tonic-gate PICL_CLASS_CURRENT_SENSOR, 188*0Sstevel@tonic-gate PICL_CLASS_CURRENT_INDICATOR, 189*0Sstevel@tonic-gate PICL_CLASS_TEMPERATURE_SENSOR, 190*0Sstevel@tonic-gate PICL_CLASS_TEMPERATURE_INDICATOR, 191*0Sstevel@tonic-gate PICL_CLASS_FAN, 192*0Sstevel@tonic-gate PICL_CLASS_FAN, 193*0Sstevel@tonic-gate PICL_CLASS_LED, 194*0Sstevel@tonic-gate PICL_CLASS_KEYSWITCH 195*0Sstevel@tonic-gate }; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* 198*0Sstevel@tonic-gate * fru-type to PICL PROPERTY for volatile data 199*0Sstevel@tonic-gate */ 200*0Sstevel@tonic-gate const char *fru_to_prop[] = { 201*0Sstevel@tonic-gate PICL_PROP_VOLTAGE, 202*0Sstevel@tonic-gate PICL_PROP_CONDITION, 203*0Sstevel@tonic-gate PICL_PROP_CURRENT, 204*0Sstevel@tonic-gate PICL_PROP_CONDITION, 205*0Sstevel@tonic-gate PICL_PROP_TEMPERATURE, 206*0Sstevel@tonic-gate PICL_PROP_CONDITION, 207*0Sstevel@tonic-gate PICL_PROP_FAN_SPEED, 208*0Sstevel@tonic-gate PICL_PROP_FAN_SPEED_UNIT, 209*0Sstevel@tonic-gate PICL_PROP_STATE, 210*0Sstevel@tonic-gate PICL_PROP_STATE 211*0Sstevel@tonic-gate }; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * fru-type to PICL PTYPE 215*0Sstevel@tonic-gate */ 216*0Sstevel@tonic-gate int fru_to_ptype[] = { 217*0Sstevel@tonic-gate PICL_PTYPE_FLOAT, 218*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, 219*0Sstevel@tonic-gate PICL_PTYPE_FLOAT, 220*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, 221*0Sstevel@tonic-gate PICL_PTYPE_INT, 222*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, 223*0Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, 224*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, 225*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, 226*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING 227*0Sstevel@tonic-gate }; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* 230*0Sstevel@tonic-gate * condition strings 231*0Sstevel@tonic-gate */ 232*0Sstevel@tonic-gate static char *cond_okay; 233*0Sstevel@tonic-gate static char *cond_failed; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * fru-type to size of volatile property 237*0Sstevel@tonic-gate * the -1's are replaced by the max size of a condition string 238*0Sstevel@tonic-gate */ 239*0Sstevel@tonic-gate int fru_to_size[] = { 240*0Sstevel@tonic-gate 4, -1, 4, -1, 2, -1, 2, -1, -1, -1 241*0Sstevel@tonic-gate }; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate static node_el_t * 244*0Sstevel@tonic-gate create_node_el(picl_nodehdl_t nodeh) 245*0Sstevel@tonic-gate { 246*0Sstevel@tonic-gate node_el_t *ptr = malloc(sizeof (node_el_t)); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (ptr != NULL) { 249*0Sstevel@tonic-gate ptr->nodeh = nodeh; 250*0Sstevel@tonic-gate ptr->next = NULL; 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate return (ptr); 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate static void 257*0Sstevel@tonic-gate delete_node_el(node_el_t *pel) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate free(pel); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate static node_list_t * 263*0Sstevel@tonic-gate create_node_list() 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate node_list_t *ptr = malloc(sizeof (node_list_t)); 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate if (ptr != NULL) { 268*0Sstevel@tonic-gate ptr->head = NULL; 269*0Sstevel@tonic-gate ptr->tail = NULL; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate return (ptr); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate static void 276*0Sstevel@tonic-gate delete_node_list(node_list_t *pnl) 277*0Sstevel@tonic-gate { 278*0Sstevel@tonic-gate node_el_t *pel; 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (pnl == NULL) 281*0Sstevel@tonic-gate return; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate while ((pel = pnl->head) != NULL) { 284*0Sstevel@tonic-gate pnl->head = pel->next; 285*0Sstevel@tonic-gate delete_node_el(pel); 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* 289*0Sstevel@tonic-gate * normally pnl->tail would be to NULL next, 290*0Sstevel@tonic-gate * but as it is about to be freed, this step can be skipped. 291*0Sstevel@tonic-gate */ 292*0Sstevel@tonic-gate free(pnl); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * Get a linking element and add handle to end of chain 297*0Sstevel@tonic-gate */ 298*0Sstevel@tonic-gate static void 299*0Sstevel@tonic-gate add_node_to_list(picl_nodehdl_t nodeh, node_list_t *listp) 300*0Sstevel@tonic-gate { 301*0Sstevel@tonic-gate node_el_t *pel = create_node_el(nodeh); 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate if (pel != NULL) { 304*0Sstevel@tonic-gate if (listp->tail == NULL) 305*0Sstevel@tonic-gate listp->head = pel; 306*0Sstevel@tonic-gate else 307*0Sstevel@tonic-gate listp->tail->next = pel; 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate listp->tail = pel; 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate /* 314*0Sstevel@tonic-gate * Get a list of nodes of the specified classname under nodeh. 315*0Sstevel@tonic-gate * Once a node of the specified class is found, its children are not 316*0Sstevel@tonic-gate * searched. 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate static void 319*0Sstevel@tonic-gate get_node_list_by_class(picl_nodehdl_t nodeh, const char *classname, 320*0Sstevel@tonic-gate node_list_t *listp) 321*0Sstevel@tonic-gate { 322*0Sstevel@tonic-gate int err; 323*0Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX+1]; 324*0Sstevel@tonic-gate picl_nodehdl_t chdh; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * go through the children 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 330*0Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate while (err == PICL_SUCCESS) { 333*0Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME, 334*0Sstevel@tonic-gate clname, strlen(classname) + 1); 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate if ((err == PICL_SUCCESS) && (strcmp(clname, classname) == 0)) 337*0Sstevel@tonic-gate add_node_to_list(chdh, listp); 338*0Sstevel@tonic-gate else 339*0Sstevel@tonic-gate get_node_list_by_class(chdh, classname, listp); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 342*0Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate static int 347*0Sstevel@tonic-gate get_envmon_limits(int envmon_fd, envmon_sysinfo_t *limits_p) 348*0Sstevel@tonic-gate { 349*0Sstevel@tonic-gate return (ioctl(envmon_fd, ENVMONIOCSYSINFO, limits_p)); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate static int 353*0Sstevel@tonic-gate re_create_arrays(int envmon_fd) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate envmon_sysinfo_t new_limits; 356*0Sstevel@tonic-gate int res; 357*0Sstevel@tonic-gate int maxnum; 358*0Sstevel@tonic-gate uchar_t *fru_types; 359*0Sstevel@tonic-gate envmon_handle_t *envhandles; 360*0Sstevel@tonic-gate picl_prophdl_t *piclprhdls; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate res = get_envmon_limits(envmon_fd, &new_limits); 363*0Sstevel@tonic-gate if (res != 0) 364*0Sstevel@tonic-gate return (res); 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate maxnum = new_limits.maxVoltSens + new_limits.maxVoltInd + 367*0Sstevel@tonic-gate new_limits.maxAmpSens + new_limits.maxAmpInd + 368*0Sstevel@tonic-gate new_limits.maxTempSens + new_limits.maxTempInd + 369*0Sstevel@tonic-gate new_limits.maxFanSens + new_limits.maxFanInd + 370*0Sstevel@tonic-gate new_limits.maxLED + N_KEY_SWITCHES; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if (maxnum != handle_arr.maxnum) { 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * space requirements have changed 375*0Sstevel@tonic-gate */ 376*0Sstevel@tonic-gate fru_types = calloc(maxnum, sizeof (uchar_t)); 377*0Sstevel@tonic-gate envhandles = calloc(maxnum, sizeof (envmon_handle_t)); 378*0Sstevel@tonic-gate piclprhdls = calloc(maxnum, sizeof (picl_prophdl_t)); 379*0Sstevel@tonic-gate if ((fru_types == NULL) || (envhandles == NULL) || 380*0Sstevel@tonic-gate (piclprhdls == NULL)) { 381*0Sstevel@tonic-gate free(fru_types); 382*0Sstevel@tonic-gate free(envhandles); 383*0Sstevel@tonic-gate free(piclprhdls); 384*0Sstevel@tonic-gate return (-1); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate free(handle_arr.fru_types); 387*0Sstevel@tonic-gate handle_arr.fru_types = fru_types; 388*0Sstevel@tonic-gate free(handle_arr.envhandles); 389*0Sstevel@tonic-gate handle_arr.envhandles = envhandles; 390*0Sstevel@tonic-gate free(handle_arr.piclprhdls); 391*0Sstevel@tonic-gate handle_arr.piclprhdls = piclprhdls; 392*0Sstevel@tonic-gate } else { 393*0Sstevel@tonic-gate (void) memset(handle_arr.fru_types, 0, 394*0Sstevel@tonic-gate maxnum * sizeof (uchar_t)); 395*0Sstevel@tonic-gate (void) memset(handle_arr.envhandles, 0, 396*0Sstevel@tonic-gate maxnum * sizeof (envmon_handle_t)); 397*0Sstevel@tonic-gate (void) memset(handle_arr.piclprhdls, 0, 398*0Sstevel@tonic-gate maxnum * sizeof (picl_prophdl_t)); 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate handle_arr.num = 0; 402*0Sstevel@tonic-gate handle_arr.maxnum = maxnum; 403*0Sstevel@tonic-gate env_limits = new_limits; 404*0Sstevel@tonic-gate return (0); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate static void 408*0Sstevel@tonic-gate create_arrays() 409*0Sstevel@tonic-gate { 410*0Sstevel@tonic-gate int maxnum = env_limits.maxVoltSens + env_limits.maxVoltInd + 411*0Sstevel@tonic-gate env_limits.maxAmpSens + env_limits.maxAmpInd + 412*0Sstevel@tonic-gate env_limits.maxTempSens + env_limits.maxTempInd + 413*0Sstevel@tonic-gate env_limits.maxFanSens + env_limits.maxFanInd + 414*0Sstevel@tonic-gate env_limits.maxLED + N_KEY_SWITCHES; 415*0Sstevel@tonic-gate handle_arr.maxnum = maxnum; 416*0Sstevel@tonic-gate handle_arr.num = 0; 417*0Sstevel@tonic-gate handle_arr.fru_types = calloc(maxnum, sizeof (uchar_t)); 418*0Sstevel@tonic-gate handle_arr.envhandles = calloc(maxnum, sizeof (envmon_handle_t)); 419*0Sstevel@tonic-gate handle_arr.piclprhdls = calloc(maxnum, sizeof (picl_prophdl_t)); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate static int 423*0Sstevel@tonic-gate get_envmon_node(picl_nodehdl_t *envmoninfh) 424*0Sstevel@tonic-gate { 425*0Sstevel@tonic-gate int err = PICL_SUCCESS; 426*0Sstevel@tonic-gate node_list_t *listp; 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate listp = create_node_list(); 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate if ((err = ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM, 431*0Sstevel@tonic-gate envmoninfh)) != PICL_SUCCESS) { 432*0Sstevel@tonic-gate syslog(LOG_ERR, EM_MISSING_NODE, 433*0Sstevel@tonic-gate PICL_NODE_ROOT PICL_NODE_PLATFORM); 434*0Sstevel@tonic-gate return (err); /* no /platform ! */ 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate get_node_list_by_class(*envmoninfh, PICL_CLASS_SERVICE_PROCESSOR, 438*0Sstevel@tonic-gate listp); 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate if (listp->head == NULL) { 441*0Sstevel@tonic-gate *envmoninfh = 0; 442*0Sstevel@tonic-gate syslog(LOG_ERR, EM_MISSING_NODE, PICL_CLASS_SERVICE_PROCESSOR); 443*0Sstevel@tonic-gate err = PICL_NODENOTFOUND; 444*0Sstevel@tonic-gate } else { 445*0Sstevel@tonic-gate *envmoninfh = listp->head->nodeh; 446*0Sstevel@tonic-gate } 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate delete_node_list(listp); 449*0Sstevel@tonic-gate return (err); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate static char * 453*0Sstevel@tonic-gate create_envmon_pathname(picl_nodehdl_t envmoninfh) 454*0Sstevel@tonic-gate { 455*0Sstevel@tonic-gate char *ptr; 456*0Sstevel@tonic-gate char namebuf[PATH_MAX]; 457*0Sstevel@tonic-gate size_t len; 458*0Sstevel@tonic-gate DIR *dirp; 459*0Sstevel@tonic-gate struct dirent *dp; 460*0Sstevel@tonic-gate struct stat statbuf; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* prefix devfs-path name with /devices */ 463*0Sstevel@tonic-gate (void) strlcpy(namebuf, "/devices", PATH_MAX); 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * append devfs-path property 467*0Sstevel@tonic-gate */ 468*0Sstevel@tonic-gate len = strlen(namebuf); 469*0Sstevel@tonic-gate if (ptree_get_propval_by_name(envmoninfh, PICL_PROP_DEVFS_PATH, 470*0Sstevel@tonic-gate namebuf + len, sizeof (namebuf) - len) != PICL_SUCCESS) { 471*0Sstevel@tonic-gate syslog(LOG_ERR, EM_SC_NODE_INCOMPLETE); 472*0Sstevel@tonic-gate return (NULL); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate /* locate final component of name */ 476*0Sstevel@tonic-gate ptr = strrchr(namebuf, '/'); 477*0Sstevel@tonic-gate if (ptr == NULL) 478*0Sstevel@tonic-gate return (NULL); 479*0Sstevel@tonic-gate *ptr = '\0'; /* terminate at end of directory path */ 480*0Sstevel@tonic-gate len = strlen(ptr + 1); /* length of terminal name */ 481*0Sstevel@tonic-gate dirp = opendir(namebuf); 482*0Sstevel@tonic-gate if (dirp == NULL) { 483*0Sstevel@tonic-gate syslog(LOG_ERR, EM_SC_NODE_MISSING); 484*0Sstevel@tonic-gate return (NULL); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate *ptr++ = '/'; /* restore '/' and advance to final name */ 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * look for a name which starts with the string at *ptr 491*0Sstevel@tonic-gate */ 492*0Sstevel@tonic-gate if (strlen(dp->d_name) < len) 493*0Sstevel@tonic-gate continue; /* skip short names */ 494*0Sstevel@tonic-gate if (strncmp(dp->d_name, ptr, len) == 0) { 495*0Sstevel@tonic-gate /* 496*0Sstevel@tonic-gate * Got a match, restore full pathname and stat the 497*0Sstevel@tonic-gate * entry. Reject if not a char device 498*0Sstevel@tonic-gate */ 499*0Sstevel@tonic-gate (void) strlcpy(ptr, dp->d_name, 500*0Sstevel@tonic-gate sizeof (namebuf) - (ptr - namebuf)); 501*0Sstevel@tonic-gate if (stat(namebuf, &statbuf) < 0) 502*0Sstevel@tonic-gate continue; /* reject if can't stat it */ 503*0Sstevel@tonic-gate if (!S_ISCHR(statbuf.st_mode)) 504*0Sstevel@tonic-gate continue; /* not a character device */ 505*0Sstevel@tonic-gate /* 506*0Sstevel@tonic-gate * go with this entry 507*0Sstevel@tonic-gate */ 508*0Sstevel@tonic-gate (void) closedir(dirp); 509*0Sstevel@tonic-gate return (strdup(namebuf)); 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate syslog(LOG_ERR, EM_SC_NODE_MISSING); 513*0Sstevel@tonic-gate (void) closedir(dirp); 514*0Sstevel@tonic-gate return (NULL); 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * look for named node as child of supplied handle 519*0Sstevel@tonic-gate */ 520*0Sstevel@tonic-gate static int 521*0Sstevel@tonic-gate get_child_by_name(picl_nodehdl_t nodeh, const char *name, 522*0Sstevel@tonic-gate picl_nodehdl_t *childh) 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate int err; 525*0Sstevel@tonic-gate char node_name[ENVMON_MAXNAMELEN]; 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate if (strlen(name) >= ENVMON_MAXNAMELEN) 528*0Sstevel@tonic-gate return (PICL_NODENOTFOUND); 529*0Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, childh, 530*0Sstevel@tonic-gate sizeof (*childh)); 531*0Sstevel@tonic-gate while (err == PICL_SUCCESS) { 532*0Sstevel@tonic-gate err = ptree_get_propval_by_name(*childh, PICL_PROP_NAME, 533*0Sstevel@tonic-gate node_name, sizeof (node_name)); 534*0Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 535*0Sstevel@tonic-gate (strncmp(name, node_name, ENVMON_MAXNAMELEN) == 0)) 536*0Sstevel@tonic-gate return (PICL_SUCCESS); 537*0Sstevel@tonic-gate err = ptree_get_propval_by_name(*childh, PICL_PROP_PEER, 538*0Sstevel@tonic-gate childh, sizeof (*childh)); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate return (err); 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate /* 544*0Sstevel@tonic-gate * Create and add the specified regular property 545*0Sstevel@tonic-gate */ 546*0Sstevel@tonic-gate static int 547*0Sstevel@tonic-gate add_regular_prop(picl_nodehdl_t nodeh, const char *name, int type, int access, 548*0Sstevel@tonic-gate int size, const void *valbuf, picl_prophdl_t *prophp) 549*0Sstevel@tonic-gate { 550*0Sstevel@tonic-gate int err; 551*0Sstevel@tonic-gate ptree_propinfo_t propinfo; 552*0Sstevel@tonic-gate picl_prophdl_t proph; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 555*0Sstevel@tonic-gate type, access, size, (char *)name, NULL, NULL); 556*0Sstevel@tonic-gate if (err != PICL_SUCCESS) 557*0Sstevel@tonic-gate return (err); 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, (void *)valbuf, 560*0Sstevel@tonic-gate &proph); 561*0Sstevel@tonic-gate if (err == PICL_SUCCESS && prophp) 562*0Sstevel@tonic-gate *prophp = proph; 563*0Sstevel@tonic-gate return (err); 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate /* 568*0Sstevel@tonic-gate * Create and add the specified volatile property 569*0Sstevel@tonic-gate */ 570*0Sstevel@tonic-gate static int 571*0Sstevel@tonic-gate add_volatile_prop(picl_nodehdl_t nodeh, const char *name, int type, int access, 572*0Sstevel@tonic-gate int size, ptree_vol_rdfunc_t rdfunc, ptree_vol_wrfunc_t wrfunc, 573*0Sstevel@tonic-gate picl_prophdl_t *prophp) 574*0Sstevel@tonic-gate { 575*0Sstevel@tonic-gate int err; 576*0Sstevel@tonic-gate ptree_propinfo_t propinfo; 577*0Sstevel@tonic-gate picl_prophdl_t proph; 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 580*0Sstevel@tonic-gate type, (access|PICL_VOLATILE), size, (char *)name, rdfunc, wrfunc); 581*0Sstevel@tonic-gate if (err != PICL_SUCCESS) 582*0Sstevel@tonic-gate return (err); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph); 585*0Sstevel@tonic-gate if (err == PICL_SUCCESS && prophp) 586*0Sstevel@tonic-gate *prophp = proph; 587*0Sstevel@tonic-gate return (err); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate /* 591*0Sstevel@tonic-gate * There are 5 different structures used for reading environmental data 592*0Sstevel@tonic-gate * from the service-processor. A different function is used for each one. 593*0Sstevel@tonic-gate * Some functions cover several ioctls, so the desired ioctl is part of 594*0Sstevel@tonic-gate * the interface. In each case the id parameter is read/write, the 595*0Sstevel@tonic-gate * returned value being the next id for this fru type. 596*0Sstevel@tonic-gate */ 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* 599*0Sstevel@tonic-gate * Function to read sensor data. 600*0Sstevel@tonic-gate */ 601*0Sstevel@tonic-gate static int 602*0Sstevel@tonic-gate get_sensor_data(int envmon_fd, envmon_handle_t *id, int cmd, 603*0Sstevel@tonic-gate envmon_thresholds_t *lows, envmon_thresholds_t *highs, int16_t *value) 604*0Sstevel@tonic-gate { 605*0Sstevel@tonic-gate int res; 606*0Sstevel@tonic-gate envmon_sensor_t data; 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate (void) memset(&data, 0, sizeof (data)); 609*0Sstevel@tonic-gate data.id = *id; 610*0Sstevel@tonic-gate res = ioctl(envmon_fd, cmd, &data); 611*0Sstevel@tonic-gate if (res < 0) { 612*0Sstevel@tonic-gate return (PICL_NOTREADABLE); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate *id = data.next_id; 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0) 618*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate /* 621*0Sstevel@tonic-gate * it is assumed that threshold data will be available, 622*0Sstevel@tonic-gate * even though the current sensor value may be inaccessible 623*0Sstevel@tonic-gate */ 624*0Sstevel@tonic-gate if (lows != NULL) 625*0Sstevel@tonic-gate *lows = data.lowthresholds; 626*0Sstevel@tonic-gate if (highs != NULL) 627*0Sstevel@tonic-gate *highs = data.highthresholds; 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) { 630*0Sstevel@tonic-gate if (value != NULL) 631*0Sstevel@tonic-gate *value = ENVMON_VAL_UNAVAILABLE; 632*0Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate if (value != NULL) 635*0Sstevel@tonic-gate *value = data.value; 636*0Sstevel@tonic-gate return (PICL_SUCCESS); 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate /* 640*0Sstevel@tonic-gate * Function to read indicator data. 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate static int 643*0Sstevel@tonic-gate get_indicator_data(int envmon_fd, envmon_handle_t *id, int cmd, 644*0Sstevel@tonic-gate int16_t *condition) 645*0Sstevel@tonic-gate { 646*0Sstevel@tonic-gate int res; 647*0Sstevel@tonic-gate envmon_indicator_t data; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate data.id = *id; 650*0Sstevel@tonic-gate res = ioctl(envmon_fd, cmd, &data); 651*0Sstevel@tonic-gate if (res < 0) 652*0Sstevel@tonic-gate return (PICL_NOTREADABLE); 653*0Sstevel@tonic-gate *id = data.next_id; 654*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0) 655*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 656*0Sstevel@tonic-gate if (condition != NULL) 657*0Sstevel@tonic-gate *condition = data.condition; 658*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) { 659*0Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE); 660*0Sstevel@tonic-gate } 661*0Sstevel@tonic-gate return (PICL_SUCCESS); 662*0Sstevel@tonic-gate } 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate /* 665*0Sstevel@tonic-gate * Function to read fan data. 666*0Sstevel@tonic-gate */ 667*0Sstevel@tonic-gate static int 668*0Sstevel@tonic-gate get_fan_data(int envmon_fd, envmon_handle_t *id, int cmd, 669*0Sstevel@tonic-gate envmon_thresholds_t *lows, uint16_t *speed, char *units) 670*0Sstevel@tonic-gate { 671*0Sstevel@tonic-gate int res; 672*0Sstevel@tonic-gate envmon_fan_t data; 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate data.id = *id; 675*0Sstevel@tonic-gate res = ioctl(envmon_fd, cmd, &data); 676*0Sstevel@tonic-gate if (res < 0) 677*0Sstevel@tonic-gate return (PICL_NOTREADABLE); 678*0Sstevel@tonic-gate *id = data.next_id; 679*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0) 680*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 681*0Sstevel@tonic-gate if (lows != NULL) 682*0Sstevel@tonic-gate *lows = data.lowthresholds; 683*0Sstevel@tonic-gate if (units != NULL) 684*0Sstevel@tonic-gate (void) strlcpy(units, data.units, sizeof (data.units)); 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) { 687*0Sstevel@tonic-gate if (speed != NULL) 688*0Sstevel@tonic-gate *speed = ENVMON_VAL_UNAVAILABLE; 689*0Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE); 690*0Sstevel@tonic-gate } 691*0Sstevel@tonic-gate if (speed != NULL) 692*0Sstevel@tonic-gate *speed = data.speed; 693*0Sstevel@tonic-gate return (PICL_SUCCESS); 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate /* 697*0Sstevel@tonic-gate * Function to read LED data. 698*0Sstevel@tonic-gate */ 699*0Sstevel@tonic-gate static int 700*0Sstevel@tonic-gate get_led_data(int envmon_fd, envmon_handle_t *id, int cmd, 701*0Sstevel@tonic-gate int8_t *state, int8_t *colour) 702*0Sstevel@tonic-gate { 703*0Sstevel@tonic-gate int res; 704*0Sstevel@tonic-gate envmon_led_info_t data; 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate data.id = *id; 707*0Sstevel@tonic-gate res = ioctl(envmon_fd, cmd, &data); 708*0Sstevel@tonic-gate if (res < 0) 709*0Sstevel@tonic-gate return (PICL_NOTREADABLE); 710*0Sstevel@tonic-gate *id = data.next_id; 711*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0) 712*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 713*0Sstevel@tonic-gate if (colour != NULL) 714*0Sstevel@tonic-gate *colour = data.led_color; 715*0Sstevel@tonic-gate if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) { 716*0Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE); 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate if (state != NULL) 719*0Sstevel@tonic-gate *state = data.led_state; 720*0Sstevel@tonic-gate return (PICL_SUCCESS); 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate /* 724*0Sstevel@tonic-gate * Function to read key-switch position 725*0Sstevel@tonic-gate * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails) 726*0Sstevel@tonic-gate */ 727*0Sstevel@tonic-gate static int 728*0Sstevel@tonic-gate get_keyswitch_data(int envmon_fd, envmon_handle_t *id, int cmd, 729*0Sstevel@tonic-gate envmon_keysw_pos_t *key_state) 730*0Sstevel@tonic-gate { 731*0Sstevel@tonic-gate int res; 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate if (id->name[0] == '\0') { 734*0Sstevel@tonic-gate (void) strlcpy(id->name, KEYSWITCH_NAME, sizeof (id->name)); 735*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 736*0Sstevel@tonic-gate } else if (strncmp(id->name, KEYSWITCH_NAME, sizeof (id->name)) != 0) { 737*0Sstevel@tonic-gate id->name[0] = '\0'; 738*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 739*0Sstevel@tonic-gate } else { 740*0Sstevel@tonic-gate res = ioctl(envmon_fd, cmd, key_state); 741*0Sstevel@tonic-gate id->name[0] = '\0'; 742*0Sstevel@tonic-gate 743*0Sstevel@tonic-gate if (res < 0) 744*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 745*0Sstevel@tonic-gate return (PICL_SUCCESS); 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate /* 750*0Sstevel@tonic-gate * change to lower case and convert any spaces into hyphens, 751*0Sstevel@tonic-gate * and any dots or colons symbols into underscores 752*0Sstevel@tonic-gate */ 753*0Sstevel@tonic-gate static void 754*0Sstevel@tonic-gate convert_node_name(char *ptr) 755*0Sstevel@tonic-gate { 756*0Sstevel@tonic-gate char ch; 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gate for (ch = *ptr; ch != '\0'; ch = *++ptr) { 759*0Sstevel@tonic-gate if (isupper(ch)) { 760*0Sstevel@tonic-gate *ptr = tolower(ch); 761*0Sstevel@tonic-gate } else if (isspace(ch)) { 762*0Sstevel@tonic-gate *ptr = '-'; 763*0Sstevel@tonic-gate } else if ((ch == '.') || (ch == ':')) { 764*0Sstevel@tonic-gate *ptr = '_'; 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate /* 770*0Sstevel@tonic-gate * strip to the last '.' separator and keep the rest 771*0Sstevel@tonic-gate * change ':' to '/' within the last component 772*0Sstevel@tonic-gate */ 773*0Sstevel@tonic-gate static void 774*0Sstevel@tonic-gate convert_label_name(char *name) 775*0Sstevel@tonic-gate { 776*0Sstevel@tonic-gate const char *cptr; 777*0Sstevel@tonic-gate char ch; 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate cptr = strrchr(name, '.'); 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate if (cptr == NULL) 782*0Sstevel@tonic-gate cptr = name; 783*0Sstevel@tonic-gate else 784*0Sstevel@tonic-gate cptr++; /* skip the '.' */ 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate do { 787*0Sstevel@tonic-gate ch = *cptr++; 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate if (ch == ':') 790*0Sstevel@tonic-gate ch = '/'; 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate *name++ = ch; 793*0Sstevel@tonic-gate } while (ch != '\0'); 794*0Sstevel@tonic-gate } 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate /* 797*0Sstevel@tonic-gate * add a value property 798*0Sstevel@tonic-gate */ 799*0Sstevel@tonic-gate static int 800*0Sstevel@tonic-gate add_value_prop(picl_nodehdl_t node_hdl, const char *prop_name, int fru_type, 801*0Sstevel@tonic-gate int16_t value) 802*0Sstevel@tonic-gate { 803*0Sstevel@tonic-gate int err; 804*0Sstevel@tonic-gate union { 805*0Sstevel@tonic-gate float u_f; 806*0Sstevel@tonic-gate int16_t u_i16; 807*0Sstevel@tonic-gate } val_buf; 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate if (fru_to_ptype[fru_type] == PICL_PTYPE_FLOAT) 810*0Sstevel@tonic-gate val_buf.u_f = (float)((float)value / (float)1000.0); 811*0Sstevel@tonic-gate else 812*0Sstevel@tonic-gate val_buf.u_i16 = value; 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate err = add_regular_prop(node_hdl, prop_name, fru_to_ptype[fru_type], 815*0Sstevel@tonic-gate PICL_READ, fru_to_size[fru_type], &val_buf, NULL); 816*0Sstevel@tonic-gate return (err); 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate static int 820*0Sstevel@tonic-gate find_picl_handle(picl_prophdl_t proph) 821*0Sstevel@tonic-gate { 822*0Sstevel@tonic-gate int index; 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate for (index = 0; index < handle_arr.num; index++) { 825*0Sstevel@tonic-gate if (handle_arr.piclprhdls[index] == proph) 826*0Sstevel@tonic-gate return (index); 827*0Sstevel@tonic-gate } 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate return (-1); 830*0Sstevel@tonic-gate } 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate /* 833*0Sstevel@tonic-gate * look up function to convert led status into string 834*0Sstevel@tonic-gate */ 835*0Sstevel@tonic-gate static int 836*0Sstevel@tonic-gate lookup_led_status(int8_t state, const char **string) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate int i; 839*0Sstevel@tonic-gate int lim = sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0]); 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate for (i = 0; i < lim; i++) { 842*0Sstevel@tonic-gate if (ledstate_lkup[i].state == state) { 843*0Sstevel@tonic-gate *string = ledstate_lkup[i].str_ledstate; 844*0Sstevel@tonic-gate return (PICL_SUCCESS); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate *string = ""; 849*0Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE); 850*0Sstevel@tonic-gate } 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate static int 853*0Sstevel@tonic-gate lookup_key_posn(envmon_keysw_pos_t pos, const char **string) 854*0Sstevel@tonic-gate { 855*0Sstevel@tonic-gate int i; 856*0Sstevel@tonic-gate int lim = sizeof (keyposn_lkup) / sizeof (keyposn_lkup[0]); 857*0Sstevel@tonic-gate 858*0Sstevel@tonic-gate for (i = 0; i < lim; i++) { 859*0Sstevel@tonic-gate if (keyposn_lkup[i].pos == pos) { 860*0Sstevel@tonic-gate *string = keyposn_lkup[i].str_keyposn; 861*0Sstevel@tonic-gate return (PICL_SUCCESS); 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate } 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate *string = ""; 866*0Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE); 867*0Sstevel@tonic-gate } 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate /* 870*0Sstevel@tonic-gate * function to read volatile data associated with a PICL property handle 871*0Sstevel@tonic-gate */ 872*0Sstevel@tonic-gate static int 873*0Sstevel@tonic-gate read_vol_data(ptree_rarg_t *r_arg, void *buf) 874*0Sstevel@tonic-gate { 875*0Sstevel@tonic-gate picl_prophdl_t proph; 876*0Sstevel@tonic-gate int index; 877*0Sstevel@tonic-gate uint8_t fru_type; 878*0Sstevel@tonic-gate envmon_handle_t id; 879*0Sstevel@tonic-gate int16_t sensor_data; 880*0Sstevel@tonic-gate int8_t led_state; 881*0Sstevel@tonic-gate envmon_keysw_pos_t key_posn; 882*0Sstevel@tonic-gate float float_data; 883*0Sstevel@tonic-gate int cmd; 884*0Sstevel@tonic-gate int err; 885*0Sstevel@tonic-gate int envmon_fd; 886*0Sstevel@tonic-gate const char *cptr; 887*0Sstevel@tonic-gate 888*0Sstevel@tonic-gate proph = r_arg->proph; 889*0Sstevel@tonic-gate index = find_picl_handle(proph); 890*0Sstevel@tonic-gate if (index < 0) 891*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 892*0Sstevel@tonic-gate fru_type = handle_arr.fru_types[index]; 893*0Sstevel@tonic-gate id = handle_arr.envhandles[index]; 894*0Sstevel@tonic-gate cmd = fru_to_cmd[fru_type]; 895*0Sstevel@tonic-gate envmon_fd = open(envmon_device_name, O_RDONLY); 896*0Sstevel@tonic-gate if (envmon_fd < 0) 897*0Sstevel@tonic-gate return (PICL_NOTREADABLE); 898*0Sstevel@tonic-gate 899*0Sstevel@tonic-gate /* 900*0Sstevel@tonic-gate * read environmental data according to type 901*0Sstevel@tonic-gate */ 902*0Sstevel@tonic-gate switch (fru_type) { 903*0Sstevel@tonic-gate case ENVMON_VOLT_SENS: 904*0Sstevel@tonic-gate /*FALLTHROUGH*/ 905*0Sstevel@tonic-gate case ENVMON_AMP_SENS: 906*0Sstevel@tonic-gate /*FALLTHROUGH*/ 907*0Sstevel@tonic-gate case ENVMON_TEMP_SENS: 908*0Sstevel@tonic-gate err = get_sensor_data(envmon_fd, &id, cmd, NULL, NULL, 909*0Sstevel@tonic-gate &sensor_data); 910*0Sstevel@tonic-gate break; 911*0Sstevel@tonic-gate case ENVMON_VOLT_IND: 912*0Sstevel@tonic-gate /*FALLTHROUGH*/ 913*0Sstevel@tonic-gate case ENVMON_AMP_IND: 914*0Sstevel@tonic-gate /*FALLTHROUGH*/ 915*0Sstevel@tonic-gate case ENVMON_TEMP_IND: 916*0Sstevel@tonic-gate /*FALLTHROUGH*/ 917*0Sstevel@tonic-gate case ENVMON_FAN_IND: 918*0Sstevel@tonic-gate err = get_indicator_data(envmon_fd, &id, cmd, &sensor_data); 919*0Sstevel@tonic-gate break; 920*0Sstevel@tonic-gate case ENVMON_FAN_SENS: 921*0Sstevel@tonic-gate err = get_fan_data(envmon_fd, &id, cmd, NULL, 922*0Sstevel@tonic-gate (uint16_t *)&sensor_data, NULL); 923*0Sstevel@tonic-gate break; 924*0Sstevel@tonic-gate case ENVMON_LED_IND: 925*0Sstevel@tonic-gate err = get_led_data(envmon_fd, &id, cmd, &led_state, NULL); 926*0Sstevel@tonic-gate break; 927*0Sstevel@tonic-gate case ENVMON_KEY_SWITCH: 928*0Sstevel@tonic-gate err = get_keyswitch_data(envmon_fd, &id, cmd, &key_posn); 929*0Sstevel@tonic-gate break; 930*0Sstevel@tonic-gate default: 931*0Sstevel@tonic-gate err = PICL_FAILURE; 932*0Sstevel@tonic-gate break; 933*0Sstevel@tonic-gate } 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate (void) close(envmon_fd); 936*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 937*0Sstevel@tonic-gate /* 938*0Sstevel@tonic-gate * PICL_INVALIDHANDLE is used internally, but it upsets 939*0Sstevel@tonic-gate * prtpicl; change it to PICL_PROPVALUNAVAILABLE 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate if (err == PICL_INVALIDHANDLE) 942*0Sstevel@tonic-gate err = PICL_PROPVALUNAVAILABLE; 943*0Sstevel@tonic-gate return (err); 944*0Sstevel@tonic-gate } 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate /* 947*0Sstevel@tonic-gate * convert data and copy out 948*0Sstevel@tonic-gate */ 949*0Sstevel@tonic-gate switch (fru_type) { 950*0Sstevel@tonic-gate case ENVMON_VOLT_SENS: 951*0Sstevel@tonic-gate /*FALLTHROUGH*/ 952*0Sstevel@tonic-gate case ENVMON_AMP_SENS: 953*0Sstevel@tonic-gate float_data = (float)((float)sensor_data / (float)1000.0); 954*0Sstevel@tonic-gate (void) memcpy(buf, &float_data, sizeof (float_data)); 955*0Sstevel@tonic-gate break; 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate case ENVMON_TEMP_SENS: 958*0Sstevel@tonic-gate /*FALLTHROUGH*/ 959*0Sstevel@tonic-gate case ENVMON_FAN_SENS: 960*0Sstevel@tonic-gate (void) memcpy(buf, &sensor_data, sizeof (sensor_data)); 961*0Sstevel@tonic-gate break; 962*0Sstevel@tonic-gate 963*0Sstevel@tonic-gate case ENVMON_VOLT_IND: 964*0Sstevel@tonic-gate /*FALLTHROUGH*/ 965*0Sstevel@tonic-gate case ENVMON_AMP_IND: 966*0Sstevel@tonic-gate /*FALLTHROUGH*/ 967*0Sstevel@tonic-gate case ENVMON_TEMP_IND: 968*0Sstevel@tonic-gate /*FALLTHROUGH*/ 969*0Sstevel@tonic-gate case ENVMON_FAN_IND: 970*0Sstevel@tonic-gate (void) strlcpy(buf, sensor_data == 0 ? cond_okay : cond_failed, 971*0Sstevel@tonic-gate fru_to_size[fru_type]); 972*0Sstevel@tonic-gate break; 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate case ENVMON_LED_IND: 975*0Sstevel@tonic-gate err = lookup_led_status(led_state, &cptr); 976*0Sstevel@tonic-gate if (err != PICL_SUCCESS) 977*0Sstevel@tonic-gate return (err); 978*0Sstevel@tonic-gate (void) strlcpy(buf, cptr, fru_to_size[fru_type]); 979*0Sstevel@tonic-gate break; 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate case ENVMON_KEY_SWITCH: 982*0Sstevel@tonic-gate err = lookup_key_posn(key_posn, &cptr); 983*0Sstevel@tonic-gate if (err != PICL_SUCCESS) 984*0Sstevel@tonic-gate return (err); 985*0Sstevel@tonic-gate (void) strlcpy(buf, cptr, fru_to_size[fru_type]); 986*0Sstevel@tonic-gate break; 987*0Sstevel@tonic-gate 988*0Sstevel@tonic-gate default: 989*0Sstevel@tonic-gate return (PICL_FAILURE); 990*0Sstevel@tonic-gate } 991*0Sstevel@tonic-gate 992*0Sstevel@tonic-gate return (PICL_SUCCESS); 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate 995*0Sstevel@tonic-gate static int 996*0Sstevel@tonic-gate write_led_data(ptree_warg_t *w_arg, const void *buf) 997*0Sstevel@tonic-gate { 998*0Sstevel@tonic-gate picl_prophdl_t proph; 999*0Sstevel@tonic-gate int index; 1000*0Sstevel@tonic-gate uint8_t fru_type; 1001*0Sstevel@tonic-gate int err; 1002*0Sstevel@tonic-gate int envmon_fd; 1003*0Sstevel@tonic-gate envmon_led_ctl_t led_ctl; 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gate proph = w_arg->proph; 1006*0Sstevel@tonic-gate index = find_picl_handle(proph); 1007*0Sstevel@tonic-gate if (index < 0) 1008*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE); 1009*0Sstevel@tonic-gate fru_type = handle_arr.fru_types[index]; 1010*0Sstevel@tonic-gate if (fru_type != ENVMON_LED_IND) 1011*0Sstevel@tonic-gate return (PICL_INVALIDARG); 1012*0Sstevel@tonic-gate if (w_arg->cred.dc_euid != SUPER_USER) 1013*0Sstevel@tonic-gate return (PICL_PERMDENIED); 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate /* see if the requested state is recognized */ 1016*0Sstevel@tonic-gate if (strcasecmp(str_Off, buf) == 0) 1017*0Sstevel@tonic-gate led_ctl.led_state = ENVMON_LED_OFF; 1018*0Sstevel@tonic-gate else if (strcasecmp(str_On, buf) == 0) 1019*0Sstevel@tonic-gate led_ctl.led_state = ENVMON_LED_ON; 1020*0Sstevel@tonic-gate else 1021*0Sstevel@tonic-gate return (PICL_INVALIDARG); 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate envmon_fd = open(envmon_device_name, O_RDWR); 1024*0Sstevel@tonic-gate if (envmon_fd < 0) 1025*0Sstevel@tonic-gate return (PICL_FAILURE); 1026*0Sstevel@tonic-gate led_ctl.id = handle_arr.envhandles[index]; 1027*0Sstevel@tonic-gate err = ioctl(envmon_fd, ENVMONIOCSETLED, &led_ctl); 1028*0Sstevel@tonic-gate (void) close(envmon_fd); 1029*0Sstevel@tonic-gate if (err < 0) 1030*0Sstevel@tonic-gate return (PICL_FAILURE); 1031*0Sstevel@tonic-gate return (PICL_SUCCESS); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate /* 1035*0Sstevel@tonic-gate * if colour information is not supplied by the service processor, 1036*0Sstevel@tonic-gate * try to determine led colour from the handle name. 1037*0Sstevel@tonic-gate */ 1038*0Sstevel@tonic-gate static void 1039*0Sstevel@tonic-gate fix_led_colour(int8_t *colour_p, const char *id) 1040*0Sstevel@tonic-gate { 1041*0Sstevel@tonic-gate const char *cptr = strrchr(id, '.'); 1042*0Sstevel@tonic-gate 1043*0Sstevel@tonic-gate if ((*colour_p < ENVMON_LED_CLR_NONE) || 1044*0Sstevel@tonic-gate (*colour_p > ENVMON_LED_CLR_RED)) 1045*0Sstevel@tonic-gate syslog(LOG_ERR, EM_INVALID_COLOR, *colour_p, id); 1046*0Sstevel@tonic-gate if (cptr == NULL) { 1047*0Sstevel@tonic-gate *colour_p = ENVMON_LED_CLR_NONE; 1048*0Sstevel@tonic-gate return; 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate cptr++; /* step over '.' */ 1052*0Sstevel@tonic-gate 1053*0Sstevel@tonic-gate if (strcmp(cptr, LED_ACT) == 0) 1054*0Sstevel@tonic-gate *colour_p = ENVMON_LED_CLR_GREEN; 1055*0Sstevel@tonic-gate else if (strcmp(cptr, LED_SERVICE) == 0) 1056*0Sstevel@tonic-gate *colour_p = ENVMON_LED_CLR_AMBER; 1057*0Sstevel@tonic-gate else if (strcmp(cptr, LED_LOCATE) == 0) 1058*0Sstevel@tonic-gate *colour_p = ENVMON_LED_CLR_WHITE; 1059*0Sstevel@tonic-gate else if (strcmp(cptr, LED_OK2RM) == 0) 1060*0Sstevel@tonic-gate *colour_p = ENVMON_LED_CLR_BLUE; 1061*0Sstevel@tonic-gate else 1062*0Sstevel@tonic-gate *colour_p = ENVMON_LED_CLR_NONE; 1063*0Sstevel@tonic-gate } 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate /* 1066*0Sstevel@tonic-gate * Add nodes for environmental devices of type fru_type 1067*0Sstevel@tonic-gate * below the supplied node. 1068*0Sstevel@tonic-gate */ 1069*0Sstevel@tonic-gate static int 1070*0Sstevel@tonic-gate add_env_nodes(int envmon_fd, uint8_t fru_type, picl_nodehdl_t envmonh) 1071*0Sstevel@tonic-gate { 1072*0Sstevel@tonic-gate envmon_handle_t id; 1073*0Sstevel@tonic-gate envmon_thresholds_t lows; 1074*0Sstevel@tonic-gate envmon_thresholds_t highs; 1075*0Sstevel@tonic-gate char units[ENVMON_MAXNAMELEN]; 1076*0Sstevel@tonic-gate char platform_tree_name[ENVMON_MAXNAMELEN]; 1077*0Sstevel@tonic-gate char label_name[ENVMON_MAXNAMELEN]; 1078*0Sstevel@tonic-gate int16_t sensor_data; 1079*0Sstevel@tonic-gate int8_t led_state; 1080*0Sstevel@tonic-gate int8_t colour; 1081*0Sstevel@tonic-gate envmon_keysw_pos_t key_state; 1082*0Sstevel@tonic-gate int cmd; 1083*0Sstevel@tonic-gate int err; 1084*0Sstevel@tonic-gate int index = handle_arr.num; 1085*0Sstevel@tonic-gate picl_nodehdl_t node_hdl; 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate /* 1088*0Sstevel@tonic-gate * catch table is full at start 1089*0Sstevel@tonic-gate */ 1090*0Sstevel@tonic-gate if (index >= handle_arr.maxnum) 1091*0Sstevel@tonic-gate return (PICL_FAILURE); 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate cmd = fru_to_cmd[fru_type]; 1094*0Sstevel@tonic-gate id.name[0] = '\0'; 1095*0Sstevel@tonic-gate 1096*0Sstevel@tonic-gate do { 1097*0Sstevel@tonic-gate lows.warning = lows.shutdown = lows.poweroff = 1098*0Sstevel@tonic-gate ENVMON_VAL_UNAVAILABLE; 1099*0Sstevel@tonic-gate highs.warning = highs.shutdown = highs.poweroff = 1100*0Sstevel@tonic-gate ENVMON_VAL_UNAVAILABLE; 1101*0Sstevel@tonic-gate handle_arr.fru_types[index] = fru_type; 1102*0Sstevel@tonic-gate /* must store id before reading data as it is then updated */ 1103*0Sstevel@tonic-gate handle_arr.envhandles[index] = id; 1104*0Sstevel@tonic-gate /* 1105*0Sstevel@tonic-gate * read environmental data according to type 1106*0Sstevel@tonic-gate */ 1107*0Sstevel@tonic-gate switch (fru_type) { 1108*0Sstevel@tonic-gate case ENVMON_VOLT_SENS: 1109*0Sstevel@tonic-gate /*FALLTHROUGH*/ 1110*0Sstevel@tonic-gate case ENVMON_AMP_SENS: 1111*0Sstevel@tonic-gate /*FALLTHROUGH*/ 1112*0Sstevel@tonic-gate case ENVMON_TEMP_SENS: 1113*0Sstevel@tonic-gate err = get_sensor_data(envmon_fd, &id, cmd, &lows, 1114*0Sstevel@tonic-gate &highs, &sensor_data); 1115*0Sstevel@tonic-gate break; 1116*0Sstevel@tonic-gate case ENVMON_VOLT_IND: 1117*0Sstevel@tonic-gate /*FALLTHROUGH*/ 1118*0Sstevel@tonic-gate case ENVMON_AMP_IND: 1119*0Sstevel@tonic-gate /*FALLTHROUGH*/ 1120*0Sstevel@tonic-gate case ENVMON_TEMP_IND: 1121*0Sstevel@tonic-gate /*FALLTHROUGH*/ 1122*0Sstevel@tonic-gate case ENVMON_FAN_IND: 1123*0Sstevel@tonic-gate err = get_indicator_data(envmon_fd, &id, cmd, 1124*0Sstevel@tonic-gate &sensor_data); 1125*0Sstevel@tonic-gate break; 1126*0Sstevel@tonic-gate case ENVMON_FAN_SENS: 1127*0Sstevel@tonic-gate err = get_fan_data(envmon_fd, &id, cmd, &lows, 1128*0Sstevel@tonic-gate (uint16_t *)&sensor_data, units); 1129*0Sstevel@tonic-gate break; 1130*0Sstevel@tonic-gate case ENVMON_LED_IND: 1131*0Sstevel@tonic-gate err = get_led_data(envmon_fd, &id, cmd, &led_state, 1132*0Sstevel@tonic-gate &colour); 1133*0Sstevel@tonic-gate break; 1134*0Sstevel@tonic-gate case ENVMON_KEY_SWITCH: 1135*0Sstevel@tonic-gate err = get_keyswitch_data(envmon_fd, &id, cmd, 1136*0Sstevel@tonic-gate &key_state); 1137*0Sstevel@tonic-gate break; 1138*0Sstevel@tonic-gate default: 1139*0Sstevel@tonic-gate return (PICL_FAILURE); 1140*0Sstevel@tonic-gate } 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate if (err == PICL_INVALIDHANDLE) 1143*0Sstevel@tonic-gate continue; 1144*0Sstevel@tonic-gate if ((err != PICL_SUCCESS) && (err != PICL_PROPVALUNAVAILABLE)) { 1145*0Sstevel@tonic-gate syslog(LOG_ERR, EM_NODE_ACCESS, id, fru_type, err); 1146*0Sstevel@tonic-gate continue; 1147*0Sstevel@tonic-gate } 1148*0Sstevel@tonic-gate 1149*0Sstevel@tonic-gate /* 1150*0Sstevel@tonic-gate * successfully read environmental data, add to PICL 1151*0Sstevel@tonic-gate */ 1152*0Sstevel@tonic-gate (void) strlcpy(platform_tree_name, 1153*0Sstevel@tonic-gate handle_arr.envhandles[index].name, 1154*0Sstevel@tonic-gate sizeof (platform_tree_name)); 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate (void) strlcpy(label_name, platform_tree_name, 1157*0Sstevel@tonic-gate ENVMON_MAXNAMELEN); 1158*0Sstevel@tonic-gate convert_label_name(label_name); 1159*0Sstevel@tonic-gate convert_node_name(platform_tree_name); 1160*0Sstevel@tonic-gate /* 1161*0Sstevel@tonic-gate * does this node already exist? 1162*0Sstevel@tonic-gate */ 1163*0Sstevel@tonic-gate err = get_child_by_name(envmonh, platform_tree_name, &node_hdl); 1164*0Sstevel@tonic-gate if (err == PICL_SUCCESS) { 1165*0Sstevel@tonic-gate /* 1166*0Sstevel@tonic-gate * skip over existing node 1167*0Sstevel@tonic-gate */ 1168*0Sstevel@tonic-gate continue; 1169*0Sstevel@tonic-gate } 1170*0Sstevel@tonic-gate err = ptree_create_node(platform_tree_name, 1171*0Sstevel@tonic-gate fru_to_class[fru_type], &node_hdl); 1172*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1173*0Sstevel@tonic-gate break; 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate err = add_volatile_prop(node_hdl, fru_to_prop[fru_type], 1176*0Sstevel@tonic-gate fru_to_ptype[fru_type], 1177*0Sstevel@tonic-gate PICL_READ | (fru_type == ENVMON_LED_IND ? PICL_WRITE : 0), 1178*0Sstevel@tonic-gate fru_to_size[fru_type], read_vol_data, 1179*0Sstevel@tonic-gate fru_type == ENVMON_LED_IND ? write_led_data : NULL, 1180*0Sstevel@tonic-gate &handle_arr.piclprhdls[index]); 1181*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1182*0Sstevel@tonic-gate break; 1183*0Sstevel@tonic-gate } 1184*0Sstevel@tonic-gate /* 1185*0Sstevel@tonic-gate * if any thresholds are defined add a property 1186*0Sstevel@tonic-gate */ 1187*0Sstevel@tonic-gate if (lows.warning != ENVMON_VAL_UNAVAILABLE) { 1188*0Sstevel@tonic-gate err = add_value_prop(node_hdl, PICL_PROP_LOW_WARNING, 1189*0Sstevel@tonic-gate fru_type, lows.warning); 1190*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1191*0Sstevel@tonic-gate break; 1192*0Sstevel@tonic-gate } 1193*0Sstevel@tonic-gate } 1194*0Sstevel@tonic-gate if (lows.shutdown != ENVMON_VAL_UNAVAILABLE) { 1195*0Sstevel@tonic-gate err = add_value_prop(node_hdl, PICL_PROP_LOW_SHUTDOWN, 1196*0Sstevel@tonic-gate fru_type, lows.shutdown); 1197*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1198*0Sstevel@tonic-gate break; 1199*0Sstevel@tonic-gate } 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate if (lows.poweroff != ENVMON_VAL_UNAVAILABLE) { 1202*0Sstevel@tonic-gate err = add_value_prop(node_hdl, PICL_PROP_LOW_POWER_OFF, 1203*0Sstevel@tonic-gate fru_type, lows.poweroff); 1204*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1205*0Sstevel@tonic-gate break; 1206*0Sstevel@tonic-gate } 1207*0Sstevel@tonic-gate } 1208*0Sstevel@tonic-gate if (highs.warning != ENVMON_VAL_UNAVAILABLE) { 1209*0Sstevel@tonic-gate err = add_value_prop(node_hdl, PICL_PROP_HIGH_WARNING, 1210*0Sstevel@tonic-gate fru_type, highs.warning); 1211*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1212*0Sstevel@tonic-gate break; 1213*0Sstevel@tonic-gate } 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate if (highs.shutdown != ENVMON_VAL_UNAVAILABLE) { 1216*0Sstevel@tonic-gate err = add_value_prop(node_hdl, PICL_PROP_HIGH_SHUTDOWN, 1217*0Sstevel@tonic-gate fru_type, highs.shutdown); 1218*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1219*0Sstevel@tonic-gate break; 1220*0Sstevel@tonic-gate } 1221*0Sstevel@tonic-gate } 1222*0Sstevel@tonic-gate if (highs.poweroff != ENVMON_VAL_UNAVAILABLE) { 1223*0Sstevel@tonic-gate err = add_value_prop(node_hdl, PICL_PROP_HIGH_POWER_OFF, 1224*0Sstevel@tonic-gate fru_type, highs.poweroff); 1225*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1226*0Sstevel@tonic-gate break; 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate } 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate /* 1231*0Sstevel@tonic-gate * if device is a fan sensor, add a speedunit property 1232*0Sstevel@tonic-gate */ 1233*0Sstevel@tonic-gate if (fru_type == ENVMON_FAN_SENS) { 1234*0Sstevel@tonic-gate err = add_regular_prop(node_hdl, 1235*0Sstevel@tonic-gate PICL_PROP_FAN_SPEED_UNIT, PICL_PTYPE_CHARSTRING, 1236*0Sstevel@tonic-gate PICL_READ, 1 + strlen(units), units, NULL); 1237*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1238*0Sstevel@tonic-gate break; 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate } 1241*0Sstevel@tonic-gate /* 1242*0Sstevel@tonic-gate * If device is a LED indicator and returns a colour, 1243*0Sstevel@tonic-gate * add a colour property. 1244*0Sstevel@tonic-gate */ 1245*0Sstevel@tonic-gate if (fru_type == ENVMON_LED_IND) { 1246*0Sstevel@tonic-gate if (colour < 0 || colour == ENVMON_LED_CLR_ANY || 1247*0Sstevel@tonic-gate colour > ENVMON_LED_CLR_RED) 1248*0Sstevel@tonic-gate fix_led_colour(&colour, 1249*0Sstevel@tonic-gate handle_arr.envhandles[index].name); 1250*0Sstevel@tonic-gate if (colour != ENVMON_LED_CLR_NONE) { 1251*0Sstevel@tonic-gate err = add_regular_prop(node_hdl, 1252*0Sstevel@tonic-gate PICL_PROP_COLOR, PICL_PTYPE_CHARSTRING, 1253*0Sstevel@tonic-gate PICL_READ, colour_lkup[colour].size, 1254*0Sstevel@tonic-gate colour_lkup[colour].str_colour, NULL); 1255*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1256*0Sstevel@tonic-gate break; 1257*0Sstevel@tonic-gate } 1258*0Sstevel@tonic-gate } 1259*0Sstevel@tonic-gate } 1260*0Sstevel@tonic-gate /* 1261*0Sstevel@tonic-gate * add a label property unless it's a keyswitch 1262*0Sstevel@tonic-gate * (keyswitch is labelled from a config file because the 1263*0Sstevel@tonic-gate * ALOM interface doesn't supply a name for it) 1264*0Sstevel@tonic-gate */ 1265*0Sstevel@tonic-gate if (fru_type != ENVMON_KEY_SWITCH) { 1266*0Sstevel@tonic-gate err = add_regular_prop(node_hdl, PICL_PROP_LABEL, 1267*0Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 1268*0Sstevel@tonic-gate 1 + strlen(label_name), label_name, NULL); 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1271*0Sstevel@tonic-gate break; 1272*0Sstevel@tonic-gate } 1273*0Sstevel@tonic-gate } 1274*0Sstevel@tonic-gate /* 1275*0Sstevel@tonic-gate * all properties added to this node, add the node below 1276*0Sstevel@tonic-gate * the supplied anchor point 1277*0Sstevel@tonic-gate */ 1278*0Sstevel@tonic-gate err = ptree_add_node(envmonh, node_hdl); 1279*0Sstevel@tonic-gate 1280*0Sstevel@tonic-gate if (err != PICL_SUCCESS) { 1281*0Sstevel@tonic-gate break; 1282*0Sstevel@tonic-gate } 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate /* 1285*0Sstevel@tonic-gate * that node went in OK, advance index 1286*0Sstevel@tonic-gate */ 1287*0Sstevel@tonic-gate index++; 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate } while ((id.name[0] != '\0') && (index < handle_arr.maxnum)); 1290*0Sstevel@tonic-gate 1291*0Sstevel@tonic-gate handle_arr.num = index; 1292*0Sstevel@tonic-gate return (err); 1293*0Sstevel@tonic-gate } 1294*0Sstevel@tonic-gate 1295*0Sstevel@tonic-gate static void 1296*0Sstevel@tonic-gate fixstate(uint8_t state, const char *string, int *max_len) 1297*0Sstevel@tonic-gate { 1298*0Sstevel@tonic-gate int i; 1299*0Sstevel@tonic-gate int len; 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate for (i = 0; i < (sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0])); 1302*0Sstevel@tonic-gate i++) { 1303*0Sstevel@tonic-gate if (ledstate_lkup[i].state == state) { 1304*0Sstevel@tonic-gate if (ledstate_lkup[i].str_ledstate != NULL) 1305*0Sstevel@tonic-gate free(ledstate_lkup[i].str_ledstate); 1306*0Sstevel@tonic-gate ledstate_lkup[i].str_ledstate = strdup(string); 1307*0Sstevel@tonic-gate len = strlen(string); 1308*0Sstevel@tonic-gate if (len >= *max_len) 1309*0Sstevel@tonic-gate *max_len = len + 1; 1310*0Sstevel@tonic-gate break; 1311*0Sstevel@tonic-gate } 1312*0Sstevel@tonic-gate } 1313*0Sstevel@tonic-gate } 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate static void 1316*0Sstevel@tonic-gate fixkeyposn(envmon_keysw_pos_t keyposn, const char *string, int *max_len) 1317*0Sstevel@tonic-gate { 1318*0Sstevel@tonic-gate int i; 1319*0Sstevel@tonic-gate int len; 1320*0Sstevel@tonic-gate 1321*0Sstevel@tonic-gate for (i = 0; i < (sizeof (keyposn_lkup) / sizeof (keyposn_lkup[0])); 1322*0Sstevel@tonic-gate i++) { 1323*0Sstevel@tonic-gate if (keyposn_lkup[i].pos == keyposn) { 1324*0Sstevel@tonic-gate if (keyposn_lkup[i].str_keyposn != NULL) 1325*0Sstevel@tonic-gate free(keyposn_lkup[i].str_keyposn); 1326*0Sstevel@tonic-gate keyposn_lkup[i].str_keyposn = strdup(string); 1327*0Sstevel@tonic-gate len = strlen(string); 1328*0Sstevel@tonic-gate if (len >= *max_len) 1329*0Sstevel@tonic-gate *max_len = len + 1; 1330*0Sstevel@tonic-gate break; 1331*0Sstevel@tonic-gate } 1332*0Sstevel@tonic-gate } 1333*0Sstevel@tonic-gate } 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate static void 1336*0Sstevel@tonic-gate setup_strings() 1337*0Sstevel@tonic-gate { 1338*0Sstevel@tonic-gate int string_size; 1339*0Sstevel@tonic-gate int i; 1340*0Sstevel@tonic-gate int lim = sizeof (colour_lkup) / sizeof (colour_lkup[0]); 1341*0Sstevel@tonic-gate 1342*0Sstevel@tonic-gate /* 1343*0Sstevel@tonic-gate * initialise led colours lookup 1344*0Sstevel@tonic-gate */ 1345*0Sstevel@tonic-gate for (i = 0; i < lim; i++) { 1346*0Sstevel@tonic-gate if (colour_lkup[i].str_colour != NULL) 1347*0Sstevel@tonic-gate free(colour_lkup[i].str_colour); 1348*0Sstevel@tonic-gate } 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate colour_lkup[ENVMON_LED_CLR_ANY].str_colour = strdup(gettext("any")); 1351*0Sstevel@tonic-gate colour_lkup[ENVMON_LED_CLR_WHITE].str_colour = 1352*0Sstevel@tonic-gate strdup(gettext("white")); 1353*0Sstevel@tonic-gate colour_lkup[ENVMON_LED_CLR_BLUE].str_colour = strdup(gettext("blue")); 1354*0Sstevel@tonic-gate colour_lkup[ENVMON_LED_CLR_GREEN].str_colour = 1355*0Sstevel@tonic-gate strdup(gettext("green")); 1356*0Sstevel@tonic-gate colour_lkup[ENVMON_LED_CLR_AMBER].str_colour = 1357*0Sstevel@tonic-gate strdup(gettext("amber")); 1358*0Sstevel@tonic-gate colour_lkup[ENVMON_LED_CLR_RED].str_colour = 1359*0Sstevel@tonic-gate strdup(gettext("red")); 1360*0Sstevel@tonic-gate 1361*0Sstevel@tonic-gate for (i = 0; i < lim; i++) { 1362*0Sstevel@tonic-gate if (colour_lkup[i].str_colour != NULL) 1363*0Sstevel@tonic-gate colour_lkup[i].size = 1364*0Sstevel@tonic-gate 1 + strlen(colour_lkup[i].str_colour); 1365*0Sstevel@tonic-gate } 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate /* 1368*0Sstevel@tonic-gate * initialise condition strings and note longest 1369*0Sstevel@tonic-gate */ 1370*0Sstevel@tonic-gate string_size = 0; 1371*0Sstevel@tonic-gate cond_okay = strdup(gettext("okay")); 1372*0Sstevel@tonic-gate if (strlen(cond_okay) >= string_size) 1373*0Sstevel@tonic-gate string_size = 1 + strlen(cond_okay); 1374*0Sstevel@tonic-gate cond_failed = strdup(gettext("failed")); 1375*0Sstevel@tonic-gate if (strlen(cond_failed) >= string_size) 1376*0Sstevel@tonic-gate string_size = 1 + strlen(cond_failed); 1377*0Sstevel@tonic-gate 1378*0Sstevel@tonic-gate for (i = 0; i < sizeof (fru_to_size) / sizeof (fru_to_size[0]); i++) 1379*0Sstevel@tonic-gate if (fru_to_size[i] == -1) 1380*0Sstevel@tonic-gate fru_to_size[i] = string_size; 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate /* 1383*0Sstevel@tonic-gate * initialise led state lookup strings 1384*0Sstevel@tonic-gate */ 1385*0Sstevel@tonic-gate string_size = 0; 1386*0Sstevel@tonic-gate fixstate(ENVMON_LED_OFF, gettext("off"), &string_size); 1387*0Sstevel@tonic-gate fixstate(ENVMON_LED_ON, gettext("on"), &string_size); 1388*0Sstevel@tonic-gate fixstate(ENVMON_LED_BLINKING, gettext("blinking"), &string_size); 1389*0Sstevel@tonic-gate fixstate(ENVMON_LED_FLASHING, gettext("flashing"), &string_size); 1390*0Sstevel@tonic-gate fru_to_size[ENVMON_LED_IND] = string_size; 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate /* 1393*0Sstevel@tonic-gate * initialise key position lookup strings 1394*0Sstevel@tonic-gate */ 1395*0Sstevel@tonic-gate string_size = 0; 1396*0Sstevel@tonic-gate fixkeyposn(ENVMON_KEYSW_POS_UNKNOWN, gettext("UNKNOWN"), &string_size); 1397*0Sstevel@tonic-gate fixkeyposn(ENVMON_KEYSW_POS_NORMAL, gettext("NORMAL"), &string_size); 1398*0Sstevel@tonic-gate fixkeyposn(ENVMON_KEYSW_POS_DIAG, gettext("DIAG"), &string_size); 1399*0Sstevel@tonic-gate fixkeyposn(ENVMON_KEYSW_POS_LOCKED, gettext("LOCKED"), &string_size); 1400*0Sstevel@tonic-gate fixkeyposn(ENVMON_KEYSW_POS_OFF, gettext("STBY"), &string_size); 1401*0Sstevel@tonic-gate fru_to_size[ENVMON_KEY_SWITCH] = string_size; 1402*0Sstevel@tonic-gate } 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate /* 1405*0Sstevel@tonic-gate * The size of outfilename must be PATH_MAX 1406*0Sstevel@tonic-gate */ 1407*0Sstevel@tonic-gate static int 1408*0Sstevel@tonic-gate get_config_file(char *filename) 1409*0Sstevel@tonic-gate { 1410*0Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 1411*0Sstevel@tonic-gate char pname[PATH_MAX]; 1412*0Sstevel@tonic-gate 1413*0Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 1414*0Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 1415*0Sstevel@tonic-gate (void) strlcat(pname, ENVMON_CONFFILE_NAME, PATH_MAX); 1416*0Sstevel@tonic-gate if (access(pname, R_OK) == 0) { 1417*0Sstevel@tonic-gate (void) strlcpy(filename, pname, PATH_MAX); 1418*0Sstevel@tonic-gate return (0); 1419*0Sstevel@tonic-gate } 1420*0Sstevel@tonic-gate } 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 1423*0Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 1424*0Sstevel@tonic-gate (void) strlcat(pname, ENVMON_CONFFILE_NAME, PATH_MAX); 1425*0Sstevel@tonic-gate if (access(pname, R_OK) == 0) { 1426*0Sstevel@tonic-gate (void) strlcpy(filename, pname, PATH_MAX); 1427*0Sstevel@tonic-gate return (0); 1428*0Sstevel@tonic-gate } 1429*0Sstevel@tonic-gate } 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", 1432*0Sstevel@tonic-gate PICLD_COMMON_PLUGIN_DIR, ENVMON_CONFFILE_NAME); 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate if (access(pname, R_OK) == 0) { 1435*0Sstevel@tonic-gate (void) strlcpy(filename, pname, PATH_MAX); 1436*0Sstevel@tonic-gate return (0); 1437*0Sstevel@tonic-gate } 1438*0Sstevel@tonic-gate 1439*0Sstevel@tonic-gate return (-1); 1440*0Sstevel@tonic-gate } 1441*0Sstevel@tonic-gate 1442*0Sstevel@tonic-gate static void 1443*0Sstevel@tonic-gate free_vol_prop(picl_prophdl_t proph) 1444*0Sstevel@tonic-gate { 1445*0Sstevel@tonic-gate int index; 1446*0Sstevel@tonic-gate 1447*0Sstevel@tonic-gate index = find_picl_handle(proph); 1448*0Sstevel@tonic-gate if (index >= 0) { 1449*0Sstevel@tonic-gate handle_arr.num--; 1450*0Sstevel@tonic-gate if (index != handle_arr.num) { 1451*0Sstevel@tonic-gate /* relocate last entry into hole just created */ 1452*0Sstevel@tonic-gate handle_arr.fru_types[index] = 1453*0Sstevel@tonic-gate handle_arr.fru_types[handle_arr.num]; 1454*0Sstevel@tonic-gate handle_arr.envhandles[index] = 1455*0Sstevel@tonic-gate handle_arr.envhandles[handle_arr.num]; 1456*0Sstevel@tonic-gate handle_arr.piclprhdls[index] = 1457*0Sstevel@tonic-gate handle_arr.piclprhdls[handle_arr.num]; 1458*0Sstevel@tonic-gate } 1459*0Sstevel@tonic-gate } 1460*0Sstevel@tonic-gate } 1461*0Sstevel@tonic-gate 1462*0Sstevel@tonic-gate /* 1463*0Sstevel@tonic-gate * handle PICL FRU ADDED and FRU REMOVED events 1464*0Sstevel@tonic-gate */ 1465*0Sstevel@tonic-gate /*ARGSUSED*/ 1466*0Sstevel@tonic-gate static void 1467*0Sstevel@tonic-gate envmon_evhandler(const char *ename, const void *earg, size_t size, 1468*0Sstevel@tonic-gate void *cookie) 1469*0Sstevel@tonic-gate { 1470*0Sstevel@tonic-gate char path[MAXPATHLEN]; 1471*0Sstevel@tonic-gate picl_nodehdl_t locnodeh; 1472*0Sstevel@tonic-gate int retval; 1473*0Sstevel@tonic-gate picl_nodehdl_t childh; 1474*0Sstevel@tonic-gate picl_nodehdl_t nodeh; 1475*0Sstevel@tonic-gate picl_prophdl_t tableh; 1476*0Sstevel@tonic-gate picl_prophdl_t tblh; 1477*0Sstevel@tonic-gate picl_prophdl_t proph; 1478*0Sstevel@tonic-gate ptree_propinfo_t pi; 1479*0Sstevel@tonic-gate 1480*0Sstevel@tonic-gate if (strcmp(ename, PICL_FRU_ADDED) == 0) { 1481*0Sstevel@tonic-gate retval = nvlist_lookup_uint64((nvlist_t *)earg, 1482*0Sstevel@tonic-gate PICLEVENTARG_PARENTHANDLE, &locnodeh); 1483*0Sstevel@tonic-gate 1484*0Sstevel@tonic-gate if (retval != 0) { 1485*0Sstevel@tonic-gate syslog(LOG_ERR, EM_EV_MISSING_ARG, 1486*0Sstevel@tonic-gate PICLEVENTARG_PARENTHANDLE); 1487*0Sstevel@tonic-gate return; 1488*0Sstevel@tonic-gate } 1489*0Sstevel@tonic-gate retval = ptree_get_propval_by_name(locnodeh, PICL_PROP_NAME, 1490*0Sstevel@tonic-gate path, sizeof (path)); 1491*0Sstevel@tonic-gate if (retval == PICL_SUCCESS) { 1492*0Sstevel@tonic-gate /* 1493*0Sstevel@tonic-gate * Open envmon device and interrogate 1494*0Sstevel@tonic-gate */ 1495*0Sstevel@tonic-gate int envmon_fd; 1496*0Sstevel@tonic-gate int fru_type; 1497*0Sstevel@tonic-gate picl_nodehdl_t envmoninfh; 1498*0Sstevel@tonic-gate 1499*0Sstevel@tonic-gate if (get_envmon_node(&envmoninfh) != PICL_SUCCESS) { 1500*0Sstevel@tonic-gate syslog(LOG_ERR, EM_SC_NODE_MISSING); 1501*0Sstevel@tonic-gate return; 1502*0Sstevel@tonic-gate } 1503*0Sstevel@tonic-gate 1504*0Sstevel@tonic-gate if ((envmon_fd = open(envmon_device_name, O_RDONLY)) < 1505*0Sstevel@tonic-gate 0) { 1506*0Sstevel@tonic-gate syslog(LOG_ERR, EM_SYS_ERR, envmon_device_name, 1507*0Sstevel@tonic-gate strerror(errno)); 1508*0Sstevel@tonic-gate return; 1509*0Sstevel@tonic-gate } 1510*0Sstevel@tonic-gate 1511*0Sstevel@tonic-gate if (strcmp(str_SC, path) == 0) { 1512*0Sstevel@tonic-gate /* 1513*0Sstevel@tonic-gate * SC state change - re-assess platform tree 1514*0Sstevel@tonic-gate */ 1515*0Sstevel@tonic-gate if (re_create_arrays(envmon_fd) != 0) { 1516*0Sstevel@tonic-gate /* 1517*0Sstevel@tonic-gate * out of memory - make no changes 1518*0Sstevel@tonic-gate */ 1519*0Sstevel@tonic-gate return; 1520*0Sstevel@tonic-gate } 1521*0Sstevel@tonic-gate /* 1522*0Sstevel@tonic-gate * dropped memory of volatile prop handles 1523*0Sstevel@tonic-gate * so drop the nodes also, then rebuild for 1524*0Sstevel@tonic-gate * the newly loaded SC 1525*0Sstevel@tonic-gate */ 1526*0Sstevel@tonic-gate retval = ptree_get_propval_by_name(envmoninfh, 1527*0Sstevel@tonic-gate PICL_PROP_PARENT, &nodeh, sizeof (nodeh)); 1528*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1529*0Sstevel@tonic-gate (void) close(envmon_fd); 1530*0Sstevel@tonic-gate return; 1531*0Sstevel@tonic-gate } 1532*0Sstevel@tonic-gate retval = ptree_get_propval_by_name(envmoninfh, 1533*0Sstevel@tonic-gate PICL_PROP_NAME, path, sizeof (path)); 1534*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1535*0Sstevel@tonic-gate (void) close(envmon_fd); 1536*0Sstevel@tonic-gate return; 1537*0Sstevel@tonic-gate } 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate retval = ptree_delete_node(envmoninfh); 1540*0Sstevel@tonic-gate if (retval == PICL_SUCCESS) 1541*0Sstevel@tonic-gate (void) ptree_destroy_node(envmoninfh); 1542*0Sstevel@tonic-gate retval = ptree_create_node(path, 1543*0Sstevel@tonic-gate PICL_CLASS_SERVICE_PROCESSOR, &envmoninfh); 1544*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1545*0Sstevel@tonic-gate (void) close(envmon_fd); 1546*0Sstevel@tonic-gate return; 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate retval = ptree_add_node(nodeh, envmoninfh); 1549*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1550*0Sstevel@tonic-gate (void) close(envmon_fd); 1551*0Sstevel@tonic-gate return; 1552*0Sstevel@tonic-gate } 1553*0Sstevel@tonic-gate } 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gate for (fru_type = 0; fru_type < ENVMONTYPES; 1556*0Sstevel@tonic-gate fru_type++) { 1557*0Sstevel@tonic-gate (void) add_env_nodes(envmon_fd, fru_type, 1558*0Sstevel@tonic-gate envmoninfh); 1559*0Sstevel@tonic-gate } 1560*0Sstevel@tonic-gate 1561*0Sstevel@tonic-gate (void) close(envmon_fd); 1562*0Sstevel@tonic-gate } 1563*0Sstevel@tonic-gate } else if (strcmp(ename, PICL_FRU_REMOVED) == 0) { 1564*0Sstevel@tonic-gate retval = nvlist_lookup_uint64((nvlist_t *)earg, 1565*0Sstevel@tonic-gate PICLEVENTARG_FRUHANDLE, &childh); 1566*0Sstevel@tonic-gate 1567*0Sstevel@tonic-gate if (retval != 0) { 1568*0Sstevel@tonic-gate syslog(LOG_ERR, EM_EV_MISSING_ARG, 1569*0Sstevel@tonic-gate PICLEVENTARG_FRUHANDLE); 1570*0Sstevel@tonic-gate return; 1571*0Sstevel@tonic-gate } 1572*0Sstevel@tonic-gate retval = ptree_get_propval_by_name(childh, PICL_PROP_NAME, 1573*0Sstevel@tonic-gate path, sizeof (path)); 1574*0Sstevel@tonic-gate if (retval == PICL_SUCCESS) { 1575*0Sstevel@tonic-gate retval = ptree_get_prop_by_name(childh, 1576*0Sstevel@tonic-gate PICL_PROP_DEVICES, &tableh); 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1579*0Sstevel@tonic-gate /* no Devices table, nothing to do */ 1580*0Sstevel@tonic-gate return; 1581*0Sstevel@tonic-gate } 1582*0Sstevel@tonic-gate 1583*0Sstevel@tonic-gate /* 1584*0Sstevel@tonic-gate * follow all reference properties in the second 1585*0Sstevel@tonic-gate * column of the table and delete the referenced node 1586*0Sstevel@tonic-gate */ 1587*0Sstevel@tonic-gate retval = ptree_get_propval(tableh, &tblh, 1588*0Sstevel@tonic-gate sizeof (tblh)); 1589*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1590*0Sstevel@tonic-gate /* 1591*0Sstevel@tonic-gate * can't get value of table property 1592*0Sstevel@tonic-gate */ 1593*0Sstevel@tonic-gate return; 1594*0Sstevel@tonic-gate } 1595*0Sstevel@tonic-gate /* get first col, first row */ 1596*0Sstevel@tonic-gate retval = ptree_get_next_by_col(tblh, &tblh); 1597*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1598*0Sstevel@tonic-gate /* 1599*0Sstevel@tonic-gate * no rows? 1600*0Sstevel@tonic-gate */ 1601*0Sstevel@tonic-gate return; 1602*0Sstevel@tonic-gate } 1603*0Sstevel@tonic-gate /* 1604*0Sstevel@tonic-gate * starting at next col, get every entry in the column 1605*0Sstevel@tonic-gate */ 1606*0Sstevel@tonic-gate for (retval = ptree_get_next_by_row(tblh, &tblh); 1607*0Sstevel@tonic-gate retval == PICL_SUCCESS; 1608*0Sstevel@tonic-gate retval = ptree_get_next_by_col(tblh, &tblh)) { 1609*0Sstevel@tonic-gate /* 1610*0Sstevel@tonic-gate * should be a ref prop in our hands, 1611*0Sstevel@tonic-gate * get the target node handle 1612*0Sstevel@tonic-gate */ 1613*0Sstevel@tonic-gate retval = ptree_get_propval(tblh, &nodeh, 1614*0Sstevel@tonic-gate sizeof (nodeh)); 1615*0Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 1616*0Sstevel@tonic-gate continue; 1617*0Sstevel@tonic-gate } 1618*0Sstevel@tonic-gate /* 1619*0Sstevel@tonic-gate * got the referenced node, has it got a 1620*0Sstevel@tonic-gate * volatile property to clean up? 1621*0Sstevel@tonic-gate */ 1622*0Sstevel@tonic-gate retval = ptree_get_first_prop(nodeh, &proph); 1623*0Sstevel@tonic-gate while (retval == PICL_SUCCESS) { 1624*0Sstevel@tonic-gate retval = ptree_get_propinfo(proph, &pi); 1625*0Sstevel@tonic-gate if ((retval == PICL_SUCCESS) && 1626*0Sstevel@tonic-gate (pi.piclinfo.accessmode & 1627*0Sstevel@tonic-gate PICL_VOLATILE)) 1628*0Sstevel@tonic-gate free_vol_prop(proph); 1629*0Sstevel@tonic-gate retval = ptree_get_next_prop(proph, 1630*0Sstevel@tonic-gate &proph); 1631*0Sstevel@tonic-gate } 1632*0Sstevel@tonic-gate /* 1633*0Sstevel@tonic-gate * all volatile properties gone, remove node 1634*0Sstevel@tonic-gate */ 1635*0Sstevel@tonic-gate retval = ptree_delete_node(nodeh); 1636*0Sstevel@tonic-gate if (retval == PICL_SUCCESS) 1637*0Sstevel@tonic-gate (void) ptree_destroy_node(nodeh); 1638*0Sstevel@tonic-gate } 1639*0Sstevel@tonic-gate } 1640*0Sstevel@tonic-gate } 1641*0Sstevel@tonic-gate } 1642*0Sstevel@tonic-gate 1643*0Sstevel@tonic-gate /* 1644*0Sstevel@tonic-gate * executed as part of .init when the plugin is dlopen()ed 1645*0Sstevel@tonic-gate */ 1646*0Sstevel@tonic-gate static void 1647*0Sstevel@tonic-gate piclenvmon_register(void) 1648*0Sstevel@tonic-gate { 1649*0Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info); 1650*0Sstevel@tonic-gate } 1651*0Sstevel@tonic-gate 1652*0Sstevel@tonic-gate /* 1653*0Sstevel@tonic-gate * Init entry point of the plugin 1654*0Sstevel@tonic-gate * Creates the PICL nodes and properties in the physical and logical aspects. 1655*0Sstevel@tonic-gate */ 1656*0Sstevel@tonic-gate static void 1657*0Sstevel@tonic-gate piclenvmon_init(void) 1658*0Sstevel@tonic-gate { 1659*0Sstevel@tonic-gate picl_nodehdl_t rooth; 1660*0Sstevel@tonic-gate picl_nodehdl_t plfh; 1661*0Sstevel@tonic-gate picl_nodehdl_t envmoninfh; 1662*0Sstevel@tonic-gate int res; 1663*0Sstevel@tonic-gate int envmon_fd; 1664*0Sstevel@tonic-gate int fru_type; 1665*0Sstevel@tonic-gate char pathname[PATH_MAX]; 1666*0Sstevel@tonic-gate 1667*0Sstevel@tonic-gate /* 1668*0Sstevel@tonic-gate * locate and parse config file 1669*0Sstevel@tonic-gate */ 1670*0Sstevel@tonic-gate if (get_config_file(pathname) < 0) 1671*0Sstevel@tonic-gate return; 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate if ((ptree_get_root(&rooth) != PICL_SUCCESS) || 1674*0Sstevel@tonic-gate (picld_pluginutil_parse_config_file(rooth, pathname) != 1675*0Sstevel@tonic-gate PICL_SUCCESS)) { 1676*0Sstevel@tonic-gate syslog(LOG_ERR, EM_INIT_FAILED); 1677*0Sstevel@tonic-gate } 1678*0Sstevel@tonic-gate 1679*0Sstevel@tonic-gate /* 1680*0Sstevel@tonic-gate * Get platform node 1681*0Sstevel@tonic-gate */ 1682*0Sstevel@tonic-gate if (ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM, &plfh) 1683*0Sstevel@tonic-gate != PICL_SUCCESS) { 1684*0Sstevel@tonic-gate syslog(LOG_ERR, EM_MISSING_NODE, PICL_NODE_PLATFORM); 1685*0Sstevel@tonic-gate syslog(LOG_ERR, EM_INIT_FAILED); 1686*0Sstevel@tonic-gate return; 1687*0Sstevel@tonic-gate } 1688*0Sstevel@tonic-gate 1689*0Sstevel@tonic-gate /* 1690*0Sstevel@tonic-gate * Get service-processor node 1691*0Sstevel@tonic-gate */ 1692*0Sstevel@tonic-gate if (get_envmon_node(&envmoninfh) != PICL_SUCCESS) 1693*0Sstevel@tonic-gate return; 1694*0Sstevel@tonic-gate 1695*0Sstevel@tonic-gate /* 1696*0Sstevel@tonic-gate * We may have been restarted, make sure we don't leak 1697*0Sstevel@tonic-gate */ 1698*0Sstevel@tonic-gate if (envmon_device_name != NULL) { 1699*0Sstevel@tonic-gate free(envmon_device_name); 1700*0Sstevel@tonic-gate } 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate if ((envmon_device_name = create_envmon_pathname(envmoninfh)) == NULL) 1703*0Sstevel@tonic-gate return; 1704*0Sstevel@tonic-gate 1705*0Sstevel@tonic-gate /* 1706*0Sstevel@tonic-gate * Open envmon device and interrogate for devices it monitors 1707*0Sstevel@tonic-gate */ 1708*0Sstevel@tonic-gate if ((envmon_fd = open(envmon_device_name, O_RDONLY)) < 0) { 1709*0Sstevel@tonic-gate syslog(LOG_ERR, EM_SYS_ERR, envmon_device_name, 1710*0Sstevel@tonic-gate strerror(errno)); 1711*0Sstevel@tonic-gate return; 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate 1714*0Sstevel@tonic-gate if (get_envmon_limits(envmon_fd, &env_limits) < 0) 1715*0Sstevel@tonic-gate return; 1716*0Sstevel@tonic-gate 1717*0Sstevel@tonic-gate /* 1718*0Sstevel@tonic-gate * A set of arrays are used whose bounds are determined by the 1719*0Sstevel@tonic-gate * response to get_envmon_limits. Establish these arrays now. 1720*0Sstevel@tonic-gate */ 1721*0Sstevel@tonic-gate create_arrays(); 1722*0Sstevel@tonic-gate setup_strings(); 1723*0Sstevel@tonic-gate 1724*0Sstevel@tonic-gate for (fru_type = 0; fru_type < ENVMONTYPES; fru_type++) { 1725*0Sstevel@tonic-gate (void) add_env_nodes(envmon_fd, fru_type, envmoninfh); 1726*0Sstevel@tonic-gate } 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate (void) close(envmon_fd); 1729*0Sstevel@tonic-gate 1730*0Sstevel@tonic-gate res = ptree_register_handler(PICL_FRU_ADDED, envmon_evhandler, NULL); 1731*0Sstevel@tonic-gate if (res != PICL_SUCCESS) { 1732*0Sstevel@tonic-gate syslog(LOG_ERR, EM_EVREG_FAILED, res); 1733*0Sstevel@tonic-gate } 1734*0Sstevel@tonic-gate res = ptree_register_handler(PICL_FRU_REMOVED, envmon_evhandler, NULL); 1735*0Sstevel@tonic-gate if (res != PICL_SUCCESS) { 1736*0Sstevel@tonic-gate syslog(LOG_ERR, EM_EVREG_FAILED, res); 1737*0Sstevel@tonic-gate } 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate /* 1741*0Sstevel@tonic-gate * fini entry point of the plugin 1742*0Sstevel@tonic-gate */ 1743*0Sstevel@tonic-gate static void 1744*0Sstevel@tonic-gate piclenvmon_fini(void) 1745*0Sstevel@tonic-gate { 1746*0Sstevel@tonic-gate if (envmon_device_name != NULL) { 1747*0Sstevel@tonic-gate free(envmon_device_name); 1748*0Sstevel@tonic-gate envmon_device_name = NULL; 1749*0Sstevel@tonic-gate } 1750*0Sstevel@tonic-gate (void) ptree_unregister_handler(PICL_FRU_ADDED, 1751*0Sstevel@tonic-gate envmon_evhandler, NULL); 1752*0Sstevel@tonic-gate (void) ptree_unregister_handler(PICL_FRU_REMOVED, 1753*0Sstevel@tonic-gate envmon_evhandler, NULL); 1754*0Sstevel@tonic-gate } 1755