xref: /onnv-gate/usr/src/cmd/picl/plugins/sun4u/envmon/piclenvmon.c (revision 1103:740fc334d84f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1103Sjbeloro  * Common Development and Distribution License (the "License").
6*1103Sjbeloro  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*1103Sjbeloro 
220Sstevel@tonic-gate /*
23*1103Sjbeloro  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * This plugin creates PICL nodes and properties for objects handled through
310Sstevel@tonic-gate  * the enhanced LOMV system-processor interface.
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  * All the nodes which may be accessible through the system-processor are
340Sstevel@tonic-gate  * included below the service-processor node  in the /platform tree.
350Sstevel@tonic-gate  * This plugin interrogates the system-processor to determine which of
360Sstevel@tonic-gate  * those nodes are actually available. Properties are added to such nodes and
370Sstevel@tonic-gate  * in the case of volatile properties like temperature, a call-back function
380Sstevel@tonic-gate  * is established for on-demand access to the current value.
390Sstevel@tonic-gate  * LEDs for which the system-processor provides write access are associated
400Sstevel@tonic-gate  * with read/write volatile properties.
410Sstevel@tonic-gate  *
420Sstevel@tonic-gate  * NOTE:
430Sstevel@tonic-gate  * Depends on PICL devtree plugin.
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #include <stdio.h>
470Sstevel@tonic-gate #include <stdlib.h>
480Sstevel@tonic-gate #include <unistd.h>
490Sstevel@tonic-gate #include <fcntl.h>
500Sstevel@tonic-gate #include <alloca.h>
510Sstevel@tonic-gate #include <syslog.h>
520Sstevel@tonic-gate #include <string.h>
530Sstevel@tonic-gate #include <libintl.h>
540Sstevel@tonic-gate #include <picl.h>
550Sstevel@tonic-gate #include <picltree.h>
560Sstevel@tonic-gate #include <libnvpair.h>
570Sstevel@tonic-gate #include <errno.h>
580Sstevel@tonic-gate #include <limits.h>
590Sstevel@tonic-gate #include <ctype.h>
600Sstevel@tonic-gate #include <sys/types.h>
610Sstevel@tonic-gate #include <sys/stat.h>
620Sstevel@tonic-gate #include <sys/obpdefs.h>
630Sstevel@tonic-gate #include <sys/envmon.h>
640Sstevel@tonic-gate #include <sys/systeminfo.h>
650Sstevel@tonic-gate #include <dirent.h>
660Sstevel@tonic-gate #include <time.h>
670Sstevel@tonic-gate #include <picldefs.h>
680Sstevel@tonic-gate #include <picld_pluginutil.h>
690Sstevel@tonic-gate #include <libdevinfo.h>
700Sstevel@tonic-gate #include "piclenvmon.h"
710Sstevel@tonic-gate 
720Sstevel@tonic-gate static void	piclenvmon_register(void);
730Sstevel@tonic-gate static void	piclenvmon_init(void);
740Sstevel@tonic-gate static void	piclenvmon_fini(void);
750Sstevel@tonic-gate static node_el_t	*create_node_el(picl_nodehdl_t nodeh);
760Sstevel@tonic-gate static void	delete_node_el(node_el_t *pel);
770Sstevel@tonic-gate static node_list_t	*create_node_list();
780Sstevel@tonic-gate static void	delete_node_list(node_list_t *pnl);
790Sstevel@tonic-gate static void	add_node_to_list(picl_nodehdl_t nodeh, node_list_t *listp);
800Sstevel@tonic-gate static void	get_node_list_by_class(picl_nodehdl_t nodeh,
810Sstevel@tonic-gate     const char *classname, node_list_t *listp);
820Sstevel@tonic-gate static int	get_envmon_limits(int envmon_fd, envmon_sysinfo_t *limits_p);
830Sstevel@tonic-gate static void	create_arrays();
840Sstevel@tonic-gate static int	get_envmon_node(picl_nodehdl_t *envmoninfh);
850Sstevel@tonic-gate static char	*create_envmon_pathname(picl_nodehdl_t envmoninfh);
860Sstevel@tonic-gate static int	get_child_by_name(picl_nodehdl_t nodeh, const char *name,
870Sstevel@tonic-gate     picl_nodehdl_t *childh);
880Sstevel@tonic-gate static int	add_regular_prop(picl_nodehdl_t nodeh, const char *name,
890Sstevel@tonic-gate     int type, int access, int size, const void *valbuf, picl_prophdl_t *prophp);
900Sstevel@tonic-gate static int	add_volatile_prop(picl_nodehdl_t nodeh, const char *name,
910Sstevel@tonic-gate     int type, int access, int size, ptree_vol_rdfunc_t rdfunc,
920Sstevel@tonic-gate     ptree_vol_wrfunc_t wrfunc, picl_prophdl_t *prophp);
930Sstevel@tonic-gate static int	get_sensor_data(int envmon_fd, envmon_handle_t *id, int cmd,
940Sstevel@tonic-gate     envmon_thresholds_t *lows, envmon_thresholds_t *highs, int16_t *value);
950Sstevel@tonic-gate static int	get_indicator_data(int envmon_fd, envmon_handle_t *id, int cmd,
960Sstevel@tonic-gate     int16_t *condition);
970Sstevel@tonic-gate static int	get_fan_data(int envmon_fd, envmon_handle_t *id, int cmd,
980Sstevel@tonic-gate     envmon_thresholds_t *lows, uint16_t *speed, char *units);
990Sstevel@tonic-gate static int	get_led_data(int envmon_fd, envmon_handle_t *id, int cmd,
1000Sstevel@tonic-gate     int8_t *state, int8_t *colour);
1010Sstevel@tonic-gate static int	get_keyswitch_data(int envmon_fd, envmon_handle_t *id, int cmd,
1020Sstevel@tonic-gate     envmon_keysw_pos_t *key_state);
1030Sstevel@tonic-gate static void	convert_node_name(char *ptr);
1040Sstevel@tonic-gate static void	convert_label_name(char *ptr);
1050Sstevel@tonic-gate static int	add_value_prop(picl_nodehdl_t node_hdl, const char *prop_name,
1060Sstevel@tonic-gate     int fru_type, int16_t value);
1070Sstevel@tonic-gate static int	find_picl_handle(picl_prophdl_t proph);
1080Sstevel@tonic-gate static int	lookup_led_status(int8_t state, const char **string);
1090Sstevel@tonic-gate static int	lookup_key_posn(envmon_keysw_pos_t pos, const char **string);
1100Sstevel@tonic-gate static int	get_config_file(char *filename);
1110Sstevel@tonic-gate static int	read_vol_data(ptree_rarg_t *r_arg, void *buf);
1120Sstevel@tonic-gate static int	write_led_data(ptree_warg_t *w_arg, const void *buf);
1130Sstevel@tonic-gate static int	add_env_nodes(int envmon_fd, uint8_t fru_type,
1140Sstevel@tonic-gate     picl_nodehdl_t envmonh);
1150Sstevel@tonic-gate static void	fixstate(uint8_t state, const char *string, int *max_len);
1160Sstevel@tonic-gate static void	fixkeyposn(envmon_keysw_pos_t keyposn, const char *string,
1170Sstevel@tonic-gate     int *max_len);
1180Sstevel@tonic-gate static void	setup_strings();
1190Sstevel@tonic-gate static void	free_vol_prop(picl_prophdl_t proph);
1200Sstevel@tonic-gate static void	envmon_evhandler(const char *ename, const void *earg,
1210Sstevel@tonic-gate     size_t size, void *cookie);
122*1103Sjbeloro static int	get_serial_num(int envmon_fd, envmon_handle_t *id, int cmd,
123*1103Sjbeloro     envmon_chassis_t *chassis);
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate #pragma	init(piclenvmon_register)
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate static picld_plugin_reg_t  my_reg_info = {
1280Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
1290Sstevel@tonic-gate 	PICLD_PLUGIN_NON_CRITICAL,
1300Sstevel@tonic-gate 	"SUNW_piclenvmon",
1310Sstevel@tonic-gate 	piclenvmon_init,
1320Sstevel@tonic-gate 	piclenvmon_fini
1330Sstevel@tonic-gate };
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate static	const char str_On[] = "on";
1360Sstevel@tonic-gate static	const char str_Off[] = "off";
137*1103Sjbeloro static  const char str_Blinking[] = "blinking";
138*1103Sjbeloro static  const char str_Flashing[] = "flashing";
1390Sstevel@tonic-gate static	const char str_SC[] = "SC";
1400Sstevel@tonic-gate static	char *envmon_device_name = NULL;
1410Sstevel@tonic-gate static	envmon_sysinfo_t	env_limits;
1420Sstevel@tonic-gate static	handle_array_t	handle_arr;
1430Sstevel@tonic-gate static	struct {
1440Sstevel@tonic-gate 	int		size;
1450Sstevel@tonic-gate 	char		*str_colour;
1460Sstevel@tonic-gate } colour_lkup[1 + ENVMON_LED_CLR_RED];
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate static	struct {
1490Sstevel@tonic-gate 	int8_t		state;
1500Sstevel@tonic-gate 	char		*str_ledstate;
1510Sstevel@tonic-gate } ledstate_lkup[] = {
1520Sstevel@tonic-gate 	{	ENVMON_LED_OFF			},
1530Sstevel@tonic-gate 	{	ENVMON_LED_ON			},
1540Sstevel@tonic-gate 	{	ENVMON_LED_BLINKING		},
1550Sstevel@tonic-gate 	{	ENVMON_LED_FLASHING		}
1560Sstevel@tonic-gate };
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate static	struct {
1590Sstevel@tonic-gate 	envmon_keysw_pos_t	pos;
1600Sstevel@tonic-gate 	char			*str_keyposn;
1610Sstevel@tonic-gate } keyposn_lkup[] = {
1620Sstevel@tonic-gate 	{	ENVMON_KEYSW_POS_UNKNOWN	},
1630Sstevel@tonic-gate 	{	ENVMON_KEYSW_POS_NORMAL		},
1640Sstevel@tonic-gate 	{	ENVMON_KEYSW_POS_DIAG		},
1650Sstevel@tonic-gate 	{	ENVMON_KEYSW_POS_LOCKED		},
1660Sstevel@tonic-gate 	{	ENVMON_KEYSW_POS_OFF		}
1670Sstevel@tonic-gate };
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * fru-type to ioctl cmd lookup
1710Sstevel@tonic-gate  */
1720Sstevel@tonic-gate int	fru_to_cmd[] = {
1730Sstevel@tonic-gate 	ENVMONIOCVOLTSENSOR,
1740Sstevel@tonic-gate 	ENVMONIOCVOLTIND,
1750Sstevel@tonic-gate 	ENVMONIOCAMPSENSOR,
1760Sstevel@tonic-gate 	ENVMONIOCAMPIND,
1770Sstevel@tonic-gate 	ENVMONIOCTEMPSENSOR,
1780Sstevel@tonic-gate 	ENVMONIOCTEMPIND,
1790Sstevel@tonic-gate 	ENVMONIOCFAN,
1800Sstevel@tonic-gate 	ENVMONIOCFANIND,
1810Sstevel@tonic-gate 	ENVMONIOCGETLED,
182*1103Sjbeloro 	ENVMONIOCGETKEYSW,
183*1103Sjbeloro 	ENVMONIOCCHASSISSERIALNUM
1840Sstevel@tonic-gate };
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate /*
1870Sstevel@tonic-gate  * fru-type to PICL CLASS
1880Sstevel@tonic-gate  */
1890Sstevel@tonic-gate const char *fru_to_class[] = {
1900Sstevel@tonic-gate 	PICL_CLASS_VOLTAGE_SENSOR,
1910Sstevel@tonic-gate 	PICL_CLASS_VOLTAGE_INDICATOR,
1920Sstevel@tonic-gate 	PICL_CLASS_CURRENT_SENSOR,
1930Sstevel@tonic-gate 	PICL_CLASS_CURRENT_INDICATOR,
1940Sstevel@tonic-gate 	PICL_CLASS_TEMPERATURE_SENSOR,
1950Sstevel@tonic-gate 	PICL_CLASS_TEMPERATURE_INDICATOR,
1960Sstevel@tonic-gate 	PICL_CLASS_FAN,
1970Sstevel@tonic-gate 	PICL_CLASS_FAN,
1980Sstevel@tonic-gate 	PICL_CLASS_LED,
199*1103Sjbeloro 	PICL_CLASS_KEYSWITCH,
200*1103Sjbeloro 	PICL_CLASS_CHASSIS_SERIAL_NUM
2010Sstevel@tonic-gate };
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate  * fru-type to PICL PROPERTY for volatile data
2050Sstevel@tonic-gate  */
2060Sstevel@tonic-gate const char *fru_to_prop[] = {
2070Sstevel@tonic-gate 	PICL_PROP_VOLTAGE,
2080Sstevel@tonic-gate 	PICL_PROP_CONDITION,
2090Sstevel@tonic-gate 	PICL_PROP_CURRENT,
2100Sstevel@tonic-gate 	PICL_PROP_CONDITION,
2110Sstevel@tonic-gate 	PICL_PROP_TEMPERATURE,
2120Sstevel@tonic-gate 	PICL_PROP_CONDITION,
2130Sstevel@tonic-gate 	PICL_PROP_FAN_SPEED,
2140Sstevel@tonic-gate 	PICL_PROP_FAN_SPEED_UNIT,
2150Sstevel@tonic-gate 	PICL_PROP_STATE,
216*1103Sjbeloro 	PICL_PROP_STATE,
217*1103Sjbeloro 	PICL_PROP_SERIAL_NUMBER
2180Sstevel@tonic-gate };
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate  * fru-type to PICL PTYPE
2220Sstevel@tonic-gate  */
2230Sstevel@tonic-gate int	fru_to_ptype[] = {
2240Sstevel@tonic-gate 	PICL_PTYPE_FLOAT,
2250Sstevel@tonic-gate 	PICL_PTYPE_CHARSTRING,
2260Sstevel@tonic-gate 	PICL_PTYPE_FLOAT,
2270Sstevel@tonic-gate 	PICL_PTYPE_CHARSTRING,
2280Sstevel@tonic-gate 	PICL_PTYPE_INT,
2290Sstevel@tonic-gate 	PICL_PTYPE_CHARSTRING,
2300Sstevel@tonic-gate 	PICL_PTYPE_UNSIGNED_INT,
2310Sstevel@tonic-gate 	PICL_PTYPE_CHARSTRING,
2320Sstevel@tonic-gate 	PICL_PTYPE_CHARSTRING,
233*1103Sjbeloro 	PICL_PTYPE_CHARSTRING,
2340Sstevel@tonic-gate 	PICL_PTYPE_CHARSTRING
2350Sstevel@tonic-gate };
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * condition strings
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate static char *cond_okay;
2410Sstevel@tonic-gate static char *cond_failed;
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate /*
2440Sstevel@tonic-gate  * fru-type to size of volatile property
2450Sstevel@tonic-gate  * the -1's are replaced by the max size of a condition string
2460Sstevel@tonic-gate  */
2470Sstevel@tonic-gate int	fru_to_size[] = {
248*1103Sjbeloro 	4, -1, 4, -1, 2, -1, 2, -1, -1, -1, -1
2490Sstevel@tonic-gate };
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate static node_el_t *
create_node_el(picl_nodehdl_t nodeh)2520Sstevel@tonic-gate create_node_el(picl_nodehdl_t nodeh)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate 	node_el_t *ptr = malloc(sizeof (node_el_t));
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	if (ptr != NULL) {
2570Sstevel@tonic-gate 		ptr->nodeh = nodeh;
2580Sstevel@tonic-gate 		ptr->next = NULL;
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	return (ptr);
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate static void
delete_node_el(node_el_t * pel)2650Sstevel@tonic-gate delete_node_el(node_el_t *pel)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate 	free(pel);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate static node_list_t *
create_node_list()2710Sstevel@tonic-gate create_node_list()
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate 	node_list_t *ptr = malloc(sizeof (node_list_t));
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	if (ptr != NULL) {
2760Sstevel@tonic-gate 		ptr->head = NULL;
2770Sstevel@tonic-gate 		ptr->tail = NULL;
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	return (ptr);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate static void
delete_node_list(node_list_t * pnl)2840Sstevel@tonic-gate delete_node_list(node_list_t *pnl)
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 	node_el_t	*pel;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	if (pnl == NULL)
2890Sstevel@tonic-gate 		return;
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	while ((pel = pnl->head) != NULL) {
2920Sstevel@tonic-gate 		pnl->head = pel->next;
2930Sstevel@tonic-gate 		delete_node_el(pel);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	/*
2970Sstevel@tonic-gate 	 * normally pnl->tail would be to NULL next,
2980Sstevel@tonic-gate 	 * but as it is about to be freed, this step can be skipped.
2990Sstevel@tonic-gate 	 */
3000Sstevel@tonic-gate 	free(pnl);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate /*
3040Sstevel@tonic-gate  * Get a linking element and add handle to end of chain
3050Sstevel@tonic-gate  */
3060Sstevel@tonic-gate static void
add_node_to_list(picl_nodehdl_t nodeh,node_list_t * listp)3070Sstevel@tonic-gate add_node_to_list(picl_nodehdl_t nodeh, node_list_t *listp)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate 	node_el_t	*pel = create_node_el(nodeh);
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	if (pel != NULL) {
3120Sstevel@tonic-gate 		if (listp->tail == NULL)
3130Sstevel@tonic-gate 			listp->head = pel;
3140Sstevel@tonic-gate 		else
3150Sstevel@tonic-gate 			listp->tail->next = pel;
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 		listp->tail = pel;
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate /*
3220Sstevel@tonic-gate  * Get a list of nodes of the specified classname under nodeh.
3230Sstevel@tonic-gate  * Once a node of the specified class is found, its children are not
3240Sstevel@tonic-gate  * searched.
3250Sstevel@tonic-gate  */
3260Sstevel@tonic-gate static void
get_node_list_by_class(picl_nodehdl_t nodeh,const char * classname,node_list_t * listp)3270Sstevel@tonic-gate get_node_list_by_class(picl_nodehdl_t nodeh, const char *classname,
3280Sstevel@tonic-gate     node_list_t *listp)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate 	int		err;
3310Sstevel@tonic-gate 	char		clname[PICL_CLASSNAMELEN_MAX+1];
3320Sstevel@tonic-gate 	picl_nodehdl_t	chdh;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/*
3350Sstevel@tonic-gate 	 * go through the children
3360Sstevel@tonic-gate 	 */
3370Sstevel@tonic-gate 	err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
3380Sstevel@tonic-gate 	    sizeof (picl_nodehdl_t));
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	while (err == PICL_SUCCESS) {
3410Sstevel@tonic-gate 		err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME,
3420Sstevel@tonic-gate 		    clname, strlen(classname) + 1);
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 		if ((err == PICL_SUCCESS) && (strcmp(clname, classname) == 0))
3450Sstevel@tonic-gate 			add_node_to_list(chdh, listp);
3460Sstevel@tonic-gate 		else
3470Sstevel@tonic-gate 			get_node_list_by_class(chdh, classname, listp);
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 		err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
3500Sstevel@tonic-gate 		    sizeof (picl_nodehdl_t));
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate static int
get_envmon_limits(int envmon_fd,envmon_sysinfo_t * limits_p)3550Sstevel@tonic-gate get_envmon_limits(int envmon_fd, envmon_sysinfo_t *limits_p)
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate 	return (ioctl(envmon_fd, ENVMONIOCSYSINFO, limits_p));
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate static int
re_create_arrays(int envmon_fd)3610Sstevel@tonic-gate re_create_arrays(int envmon_fd)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 	envmon_sysinfo_t	new_limits;
3640Sstevel@tonic-gate 	int			res;
3650Sstevel@tonic-gate 	int			maxnum;
3660Sstevel@tonic-gate 	uchar_t			*fru_types;
3670Sstevel@tonic-gate 	envmon_handle_t		*envhandles;
3680Sstevel@tonic-gate 	picl_prophdl_t		*piclprhdls;
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	res = get_envmon_limits(envmon_fd, &new_limits);
3710Sstevel@tonic-gate 	if (res != 0)
3720Sstevel@tonic-gate 		return (res);
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	maxnum = new_limits.maxVoltSens + new_limits.maxVoltInd +
3750Sstevel@tonic-gate 	    new_limits.maxAmpSens + new_limits.maxAmpInd +
3760Sstevel@tonic-gate 	    new_limits.maxTempSens + new_limits.maxTempInd +
3770Sstevel@tonic-gate 	    new_limits.maxFanSens + new_limits.maxFanInd +
3780Sstevel@tonic-gate 	    new_limits.maxLED + N_KEY_SWITCHES;
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	if (maxnum != handle_arr.maxnum) {
3810Sstevel@tonic-gate 		/*
3820Sstevel@tonic-gate 		 * space requirements have changed
3830Sstevel@tonic-gate 		 */
3840Sstevel@tonic-gate 		fru_types = calloc(maxnum, sizeof (uchar_t));
3850Sstevel@tonic-gate 		envhandles = calloc(maxnum, sizeof (envmon_handle_t));
3860Sstevel@tonic-gate 		piclprhdls = calloc(maxnum, sizeof (picl_prophdl_t));
3870Sstevel@tonic-gate 		if ((fru_types == NULL) || (envhandles == NULL) ||
3880Sstevel@tonic-gate 		    (piclprhdls == NULL)) {
3890Sstevel@tonic-gate 			free(fru_types);
3900Sstevel@tonic-gate 			free(envhandles);
3910Sstevel@tonic-gate 			free(piclprhdls);
3920Sstevel@tonic-gate 			return (-1);
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 		free(handle_arr.fru_types);
3950Sstevel@tonic-gate 		handle_arr.fru_types = fru_types;
3960Sstevel@tonic-gate 		free(handle_arr.envhandles);
3970Sstevel@tonic-gate 		handle_arr.envhandles = envhandles;
3980Sstevel@tonic-gate 		free(handle_arr.piclprhdls);
3990Sstevel@tonic-gate 		handle_arr.piclprhdls = piclprhdls;
4000Sstevel@tonic-gate 	} else {
4010Sstevel@tonic-gate 		(void) memset(handle_arr.fru_types, 0,
4020Sstevel@tonic-gate 		    maxnum * sizeof (uchar_t));
4030Sstevel@tonic-gate 		(void) memset(handle_arr.envhandles, 0,
4040Sstevel@tonic-gate 		    maxnum * sizeof (envmon_handle_t));
4050Sstevel@tonic-gate 		(void) memset(handle_arr.piclprhdls, 0,
4060Sstevel@tonic-gate 		    maxnum * sizeof (picl_prophdl_t));
4070Sstevel@tonic-gate 	}
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	handle_arr.num = 0;
4100Sstevel@tonic-gate 	handle_arr.maxnum = maxnum;
4110Sstevel@tonic-gate 	env_limits = new_limits;
4120Sstevel@tonic-gate 	return (0);
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate static void
create_arrays()4160Sstevel@tonic-gate create_arrays()
4170Sstevel@tonic-gate {
4180Sstevel@tonic-gate 	int maxnum = env_limits.maxVoltSens + env_limits.maxVoltInd +
4190Sstevel@tonic-gate 	    env_limits.maxAmpSens + env_limits.maxAmpInd +
4200Sstevel@tonic-gate 	    env_limits.maxTempSens + env_limits.maxTempInd +
4210Sstevel@tonic-gate 	    env_limits.maxFanSens + env_limits.maxFanInd +
4220Sstevel@tonic-gate 	    env_limits.maxLED + N_KEY_SWITCHES;
4230Sstevel@tonic-gate 	handle_arr.maxnum = maxnum;
4240Sstevel@tonic-gate 	handle_arr.num = 0;
4250Sstevel@tonic-gate 	handle_arr.fru_types = calloc(maxnum, sizeof (uchar_t));
4260Sstevel@tonic-gate 	handle_arr.envhandles = calloc(maxnum, sizeof (envmon_handle_t));
4270Sstevel@tonic-gate 	handle_arr.piclprhdls = calloc(maxnum, sizeof (picl_prophdl_t));
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate static int
get_envmon_node(picl_nodehdl_t * envmoninfh)4310Sstevel@tonic-gate get_envmon_node(picl_nodehdl_t *envmoninfh)
4320Sstevel@tonic-gate {
4330Sstevel@tonic-gate 	int			err = PICL_SUCCESS;
4340Sstevel@tonic-gate 	node_list_t		*listp;
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	listp = create_node_list();
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	if ((err = ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM,
4390Sstevel@tonic-gate 	    envmoninfh)) != PICL_SUCCESS) {
4400Sstevel@tonic-gate 		syslog(LOG_ERR, EM_MISSING_NODE,
4410Sstevel@tonic-gate 		    PICL_NODE_ROOT PICL_NODE_PLATFORM);
4420Sstevel@tonic-gate 		return (err);	/* no /platform ! */
4430Sstevel@tonic-gate 	}
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	get_node_list_by_class(*envmoninfh, PICL_CLASS_SERVICE_PROCESSOR,
4460Sstevel@tonic-gate 	    listp);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	if (listp->head == NULL) {
4490Sstevel@tonic-gate 		*envmoninfh = 0;
4500Sstevel@tonic-gate 		syslog(LOG_ERR, EM_MISSING_NODE, PICL_CLASS_SERVICE_PROCESSOR);
4510Sstevel@tonic-gate 		err = PICL_NODENOTFOUND;
4520Sstevel@tonic-gate 	} else {
4530Sstevel@tonic-gate 		*envmoninfh = listp->head->nodeh;
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	delete_node_list(listp);
4570Sstevel@tonic-gate 	return (err);
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate static char *
create_envmon_pathname(picl_nodehdl_t envmoninfh)4610Sstevel@tonic-gate create_envmon_pathname(picl_nodehdl_t envmoninfh)
4620Sstevel@tonic-gate {
4630Sstevel@tonic-gate 	char		*ptr;
4640Sstevel@tonic-gate 	char		namebuf[PATH_MAX];
4650Sstevel@tonic-gate 	size_t		len;
4660Sstevel@tonic-gate 	DIR		*dirp;
4670Sstevel@tonic-gate 	struct dirent	*dp;
4680Sstevel@tonic-gate 	struct stat	statbuf;
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	/* prefix devfs-path name with /devices */
4710Sstevel@tonic-gate 	(void) strlcpy(namebuf, "/devices", PATH_MAX);
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	/*
4740Sstevel@tonic-gate 	 * append devfs-path property
4750Sstevel@tonic-gate 	 */
4760Sstevel@tonic-gate 	len = strlen(namebuf);
4770Sstevel@tonic-gate 	if (ptree_get_propval_by_name(envmoninfh, PICL_PROP_DEVFS_PATH,
4780Sstevel@tonic-gate 	    namebuf + len, sizeof (namebuf) - len) != PICL_SUCCESS) {
4790Sstevel@tonic-gate 		syslog(LOG_ERR, EM_SC_NODE_INCOMPLETE);
4800Sstevel@tonic-gate 		return (NULL);
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	/* locate final component of name */
4840Sstevel@tonic-gate 	ptr = strrchr(namebuf, '/');
4850Sstevel@tonic-gate 	if (ptr == NULL)
4860Sstevel@tonic-gate 		return (NULL);
4870Sstevel@tonic-gate 	*ptr = '\0';		/* terminate at end of directory path */
4880Sstevel@tonic-gate 	len = strlen(ptr + 1);	/* length of terminal name */
4890Sstevel@tonic-gate 	dirp = opendir(namebuf);
4900Sstevel@tonic-gate 	if (dirp == NULL) {
4910Sstevel@tonic-gate 		syslog(LOG_ERR, EM_SC_NODE_MISSING);
4920Sstevel@tonic-gate 		return (NULL);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 	*ptr++ = '/';		/* restore '/' and advance to final name */
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	while ((dp = readdir(dirp)) != NULL) {
4970Sstevel@tonic-gate 		/*
4980Sstevel@tonic-gate 		 * look for a name which starts with the string at *ptr
4990Sstevel@tonic-gate 		 */
5000Sstevel@tonic-gate 		if (strlen(dp->d_name) < len)
5010Sstevel@tonic-gate 			continue;	/* skip short names */
5020Sstevel@tonic-gate 		if (strncmp(dp->d_name, ptr, len) == 0) {
5030Sstevel@tonic-gate 			/*
5040Sstevel@tonic-gate 			 * Got a match, restore full pathname and stat the
5050Sstevel@tonic-gate 			 * entry. Reject if not a char device
5060Sstevel@tonic-gate 			 */
5070Sstevel@tonic-gate 			(void) strlcpy(ptr, dp->d_name,
5080Sstevel@tonic-gate 			    sizeof (namebuf) - (ptr - namebuf));
5090Sstevel@tonic-gate 			if (stat(namebuf, &statbuf) < 0)
5100Sstevel@tonic-gate 				continue;	/* reject if can't stat it */
5110Sstevel@tonic-gate 			if (!S_ISCHR(statbuf.st_mode))
5120Sstevel@tonic-gate 				continue;	/* not a character device */
5130Sstevel@tonic-gate 			/*
5140Sstevel@tonic-gate 			 * go with this entry
5150Sstevel@tonic-gate 			 */
5160Sstevel@tonic-gate 			(void) closedir(dirp);
5170Sstevel@tonic-gate 			return (strdup(namebuf));
5180Sstevel@tonic-gate 		}
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 	syslog(LOG_ERR, EM_SC_NODE_MISSING);
5210Sstevel@tonic-gate 	(void) closedir(dirp);
5220Sstevel@tonic-gate 	return (NULL);
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate /*
5260Sstevel@tonic-gate  * look for named node as child of supplied handle
5270Sstevel@tonic-gate  */
5280Sstevel@tonic-gate static int
get_child_by_name(picl_nodehdl_t nodeh,const char * name,picl_nodehdl_t * childh)5290Sstevel@tonic-gate get_child_by_name(picl_nodehdl_t nodeh, const char *name,
5300Sstevel@tonic-gate     picl_nodehdl_t *childh)
5310Sstevel@tonic-gate {
5320Sstevel@tonic-gate 	int		err;
5330Sstevel@tonic-gate 	char		node_name[ENVMON_MAXNAMELEN];
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	if (strlen(name) >= ENVMON_MAXNAMELEN)
5360Sstevel@tonic-gate 		return (PICL_NODENOTFOUND);
5370Sstevel@tonic-gate 	err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, childh,
5380Sstevel@tonic-gate 	    sizeof (*childh));
5390Sstevel@tonic-gate 	while (err == PICL_SUCCESS) {
5400Sstevel@tonic-gate 		err = ptree_get_propval_by_name(*childh, PICL_PROP_NAME,
5410Sstevel@tonic-gate 		    node_name, sizeof (node_name));
5420Sstevel@tonic-gate 		if ((err == PICL_SUCCESS) &&
5430Sstevel@tonic-gate 		    (strncmp(name, node_name, ENVMON_MAXNAMELEN) == 0))
5440Sstevel@tonic-gate 			return (PICL_SUCCESS);
5450Sstevel@tonic-gate 		err = ptree_get_propval_by_name(*childh, PICL_PROP_PEER,
5460Sstevel@tonic-gate 		    childh, sizeof (*childh));
5470Sstevel@tonic-gate 	}
5480Sstevel@tonic-gate 	return (err);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate /*
5520Sstevel@tonic-gate  * Create and add the specified regular property
5530Sstevel@tonic-gate  */
5540Sstevel@tonic-gate static int
add_regular_prop(picl_nodehdl_t nodeh,const char * name,int type,int access,int size,const void * valbuf,picl_prophdl_t * prophp)5550Sstevel@tonic-gate add_regular_prop(picl_nodehdl_t nodeh, const char *name, int type, int access,
5560Sstevel@tonic-gate     int size, const void *valbuf, picl_prophdl_t *prophp)
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate 	int			err;
5590Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
5600Sstevel@tonic-gate 	picl_prophdl_t		proph;
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
5630Sstevel@tonic-gate 	    type, access, size, (char *)name, NULL, NULL);
5640Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5650Sstevel@tonic-gate 		return (err);
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, (void *)valbuf,
5680Sstevel@tonic-gate 	    &proph);
5690Sstevel@tonic-gate 	if (err == PICL_SUCCESS && prophp)
5700Sstevel@tonic-gate 		*prophp = proph;
5710Sstevel@tonic-gate 	return (err);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate /*
5760Sstevel@tonic-gate  * Create and add the specified volatile property
5770Sstevel@tonic-gate  */
5780Sstevel@tonic-gate static int
add_volatile_prop(picl_nodehdl_t nodeh,const char * name,int type,int access,int size,ptree_vol_rdfunc_t rdfunc,ptree_vol_wrfunc_t wrfunc,picl_prophdl_t * prophp)5790Sstevel@tonic-gate add_volatile_prop(picl_nodehdl_t nodeh, const char *name, int type, int access,
5800Sstevel@tonic-gate     int size, ptree_vol_rdfunc_t rdfunc, ptree_vol_wrfunc_t wrfunc,
5810Sstevel@tonic-gate     picl_prophdl_t *prophp)
5820Sstevel@tonic-gate {
5830Sstevel@tonic-gate 	int			err;
5840Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
5850Sstevel@tonic-gate 	picl_prophdl_t		proph;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
5880Sstevel@tonic-gate 	    type, (access|PICL_VOLATILE), size, (char *)name, rdfunc, wrfunc);
5890Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5900Sstevel@tonic-gate 		return (err);
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
5930Sstevel@tonic-gate 	if (err == PICL_SUCCESS && prophp)
5940Sstevel@tonic-gate 		*prophp = proph;
5950Sstevel@tonic-gate 	return (err);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate /*
5990Sstevel@tonic-gate  * There are 5 different structures used for reading environmental data
6000Sstevel@tonic-gate  * from the service-processor. A different function is used for each one.
6010Sstevel@tonic-gate  * Some functions cover several ioctls, so the desired ioctl is part of
6020Sstevel@tonic-gate  * the interface. In each case the id parameter is read/write, the
6030Sstevel@tonic-gate  * returned value being the next id for this fru type.
6040Sstevel@tonic-gate  */
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate /*
6070Sstevel@tonic-gate  * Function to read sensor data.
6080Sstevel@tonic-gate  */
6090Sstevel@tonic-gate static int
get_sensor_data(int envmon_fd,envmon_handle_t * id,int cmd,envmon_thresholds_t * lows,envmon_thresholds_t * highs,int16_t * value)6100Sstevel@tonic-gate get_sensor_data(int envmon_fd, envmon_handle_t *id, int cmd,
6110Sstevel@tonic-gate     envmon_thresholds_t *lows, envmon_thresholds_t *highs, int16_t *value)
6120Sstevel@tonic-gate {
6130Sstevel@tonic-gate 	int		res;
6140Sstevel@tonic-gate 	envmon_sensor_t	data;
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	(void) memset(&data, 0, sizeof (data));
6170Sstevel@tonic-gate 	data.id = *id;
6180Sstevel@tonic-gate 	res = ioctl(envmon_fd, cmd, &data);
6190Sstevel@tonic-gate 	if (res < 0) {
6200Sstevel@tonic-gate 		return (PICL_NOTREADABLE);
6210Sstevel@tonic-gate 	}
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	*id = data.next_id;
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0)
6260Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	/*
6290Sstevel@tonic-gate 	 * it is assumed that threshold data will be available,
6300Sstevel@tonic-gate 	 * even though the current sensor value may be inaccessible
6310Sstevel@tonic-gate 	 */
6320Sstevel@tonic-gate 	if (lows != NULL)
6330Sstevel@tonic-gate 		*lows = data.lowthresholds;
6340Sstevel@tonic-gate 	if (highs != NULL)
6350Sstevel@tonic-gate 		*highs = data.highthresholds;
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) {
6380Sstevel@tonic-gate 		if (value != NULL)
6390Sstevel@tonic-gate 			*value = ENVMON_VAL_UNAVAILABLE;
6400Sstevel@tonic-gate 		return (PICL_PROPVALUNAVAILABLE);
6410Sstevel@tonic-gate 	}
6420Sstevel@tonic-gate 	if (value != NULL)
6430Sstevel@tonic-gate 		*value = data.value;
6440Sstevel@tonic-gate 	return (PICL_SUCCESS);
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate /*
6480Sstevel@tonic-gate  * Function to read indicator data.
6490Sstevel@tonic-gate  */
6500Sstevel@tonic-gate static int
get_indicator_data(int envmon_fd,envmon_handle_t * id,int cmd,int16_t * condition)6510Sstevel@tonic-gate get_indicator_data(int envmon_fd, envmon_handle_t *id, int cmd,
6520Sstevel@tonic-gate     int16_t *condition)
6530Sstevel@tonic-gate {
6540Sstevel@tonic-gate 	int			res;
6550Sstevel@tonic-gate 	envmon_indicator_t	data;
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	data.id = *id;
6580Sstevel@tonic-gate 	res = ioctl(envmon_fd, cmd, &data);
6590Sstevel@tonic-gate 	if (res < 0)
6600Sstevel@tonic-gate 		return (PICL_NOTREADABLE);
6610Sstevel@tonic-gate 	*id = data.next_id;
6620Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0)
6630Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
6640Sstevel@tonic-gate 	if (condition != NULL)
6650Sstevel@tonic-gate 		*condition = data.condition;
6660Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) {
6670Sstevel@tonic-gate 		return (PICL_PROPVALUNAVAILABLE);
6680Sstevel@tonic-gate 	}
6690Sstevel@tonic-gate 	return (PICL_SUCCESS);
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate /*
6730Sstevel@tonic-gate  * Function to read fan data.
6740Sstevel@tonic-gate  */
6750Sstevel@tonic-gate static int
get_fan_data(int envmon_fd,envmon_handle_t * id,int cmd,envmon_thresholds_t * lows,uint16_t * speed,char * units)6760Sstevel@tonic-gate get_fan_data(int envmon_fd, envmon_handle_t *id, int cmd,
6770Sstevel@tonic-gate     envmon_thresholds_t *lows, uint16_t *speed, char *units)
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate 	int		res;
6800Sstevel@tonic-gate 	envmon_fan_t	data;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	data.id = *id;
6830Sstevel@tonic-gate 	res = ioctl(envmon_fd, cmd, &data);
6840Sstevel@tonic-gate 	if (res < 0)
6850Sstevel@tonic-gate 		return (PICL_NOTREADABLE);
6860Sstevel@tonic-gate 	*id = data.next_id;
6870Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0)
6880Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
6890Sstevel@tonic-gate 	if (lows != NULL)
6900Sstevel@tonic-gate 		*lows = data.lowthresholds;
6910Sstevel@tonic-gate 	if (units != NULL)
6920Sstevel@tonic-gate 		(void) strlcpy(units, data.units, sizeof (data.units));
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) {
6950Sstevel@tonic-gate 		if (speed != NULL)
6960Sstevel@tonic-gate 			*speed = ENVMON_VAL_UNAVAILABLE;
6970Sstevel@tonic-gate 		return (PICL_PROPVALUNAVAILABLE);
6980Sstevel@tonic-gate 	}
6990Sstevel@tonic-gate 	if (speed != NULL)
7000Sstevel@tonic-gate 		*speed = data.speed;
7010Sstevel@tonic-gate 	return (PICL_SUCCESS);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate /*
7050Sstevel@tonic-gate  * Function to read LED data.
7060Sstevel@tonic-gate  */
7070Sstevel@tonic-gate static int
get_led_data(int envmon_fd,envmon_handle_t * id,int cmd,int8_t * state,int8_t * colour)7080Sstevel@tonic-gate get_led_data(int envmon_fd, envmon_handle_t *id, int cmd,
7090Sstevel@tonic-gate     int8_t *state, int8_t *colour)
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate 	int			res;
7120Sstevel@tonic-gate 	envmon_led_info_t	data;
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 	data.id = *id;
7150Sstevel@tonic-gate 	res = ioctl(envmon_fd, cmd, &data);
7160Sstevel@tonic-gate 	if (res < 0)
7170Sstevel@tonic-gate 		return (PICL_NOTREADABLE);
7180Sstevel@tonic-gate 	*id = data.next_id;
7190Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_NOT_PRESENT) != 0)
7200Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
7210Sstevel@tonic-gate 	if (colour != NULL)
7220Sstevel@tonic-gate 		*colour = data.led_color;
7230Sstevel@tonic-gate 	if ((data.sensor_status & ENVMON_INACCESSIBLE) != 0) {
7240Sstevel@tonic-gate 		return (PICL_PROPVALUNAVAILABLE);
7250Sstevel@tonic-gate 	}
7260Sstevel@tonic-gate 	if (state != NULL)
7270Sstevel@tonic-gate 		*state = data.led_state;
7280Sstevel@tonic-gate 	return (PICL_SUCCESS);
7290Sstevel@tonic-gate }
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate /*
7320Sstevel@tonic-gate  * Function to read key-switch position
7330Sstevel@tonic-gate  * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails)
7340Sstevel@tonic-gate  */
7350Sstevel@tonic-gate static int
get_keyswitch_data(int envmon_fd,envmon_handle_t * id,int cmd,envmon_keysw_pos_t * key_state)7360Sstevel@tonic-gate get_keyswitch_data(int envmon_fd, envmon_handle_t *id, int cmd,
7370Sstevel@tonic-gate     envmon_keysw_pos_t *key_state)
7380Sstevel@tonic-gate {
7390Sstevel@tonic-gate 	int			res;
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (id->name[0] == '\0') {
7420Sstevel@tonic-gate 		(void) strlcpy(id->name, KEYSWITCH_NAME, sizeof (id->name));
7430Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
7440Sstevel@tonic-gate 	} else if (strncmp(id->name, KEYSWITCH_NAME, sizeof (id->name)) != 0) {
7450Sstevel@tonic-gate 		id->name[0] = '\0';
7460Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
7470Sstevel@tonic-gate 	} else {
7480Sstevel@tonic-gate 		res = ioctl(envmon_fd, cmd, key_state);
7490Sstevel@tonic-gate 		id->name[0] = '\0';
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 		if (res < 0)
7520Sstevel@tonic-gate 			return (PICL_INVALIDHANDLE);
7530Sstevel@tonic-gate 		return (PICL_SUCCESS);
7540Sstevel@tonic-gate 	}
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate /*
758*1103Sjbeloro  * Function to read the chassis serial number
759*1103Sjbeloro  * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails)
760*1103Sjbeloro  */
761*1103Sjbeloro static int
get_serial_num(int envmon_fd,envmon_handle_t * id,int cmd,envmon_chassis_t * chassis)762*1103Sjbeloro get_serial_num(int envmon_fd, envmon_handle_t *id, int cmd,
763*1103Sjbeloro     envmon_chassis_t *chassis)
764*1103Sjbeloro {
765*1103Sjbeloro 	int			res;
766*1103Sjbeloro 
767*1103Sjbeloro 	if (id->name[0] == '\0') {
768*1103Sjbeloro 		(void) strlcpy(id->name, CHASSIS_SERIAL_NUMBER,
769*1103Sjbeloro 		    sizeof (id->name));
770*1103Sjbeloro 		return (PICL_INVALIDHANDLE);
771*1103Sjbeloro 	} else if (strncmp(id->name, CHASSIS_SERIAL_NUMBER, sizeof (id->name))
772*1103Sjbeloro 	    != 0) {
773*1103Sjbeloro 		id->name[0] = '\0';
774*1103Sjbeloro 		return (PICL_INVALIDHANDLE);
775*1103Sjbeloro 	} else {
776*1103Sjbeloro 		res = ioctl(envmon_fd, cmd, chassis);
777*1103Sjbeloro 		id->name[0] = '\0';
778*1103Sjbeloro 
779*1103Sjbeloro 		if (res < 0)
780*1103Sjbeloro 			return (PICL_INVALIDHANDLE);
781*1103Sjbeloro 		return (PICL_SUCCESS);
782*1103Sjbeloro 	}
783*1103Sjbeloro }
784*1103Sjbeloro 
785*1103Sjbeloro /*
7860Sstevel@tonic-gate  * change to lower case and convert any spaces into hyphens,
7870Sstevel@tonic-gate  * and any dots or colons symbols into underscores
7880Sstevel@tonic-gate  */
7890Sstevel@tonic-gate static void
convert_node_name(char * ptr)7900Sstevel@tonic-gate convert_node_name(char *ptr)
7910Sstevel@tonic-gate {
7920Sstevel@tonic-gate 	char ch;
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate 	for (ch = *ptr; ch != '\0'; ch = *++ptr) {
7950Sstevel@tonic-gate 		if (isupper(ch)) {
7960Sstevel@tonic-gate 			*ptr = tolower(ch);
7970Sstevel@tonic-gate 		} else if (isspace(ch)) {
7980Sstevel@tonic-gate 			*ptr = '-';
7990Sstevel@tonic-gate 		} else if ((ch == '.') || (ch == ':')) {
8000Sstevel@tonic-gate 			*ptr = '_';
8010Sstevel@tonic-gate 		}
8020Sstevel@tonic-gate 	}
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate  * strip to the last '.' separator and keep the rest
8070Sstevel@tonic-gate  * change ':' to '/' within the last component
8080Sstevel@tonic-gate  */
8090Sstevel@tonic-gate static void
convert_label_name(char * name)8100Sstevel@tonic-gate convert_label_name(char *name)
8110Sstevel@tonic-gate {
8120Sstevel@tonic-gate 	const char	*cptr;
8130Sstevel@tonic-gate 	char		ch;
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	cptr = strrchr(name, '.');
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 	if (cptr == NULL)
8180Sstevel@tonic-gate 		cptr = name;
8190Sstevel@tonic-gate 	else
8200Sstevel@tonic-gate 		cptr++;			/* skip the '.' */
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	do {
8230Sstevel@tonic-gate 		ch = *cptr++;
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 		if (ch == ':')
8260Sstevel@tonic-gate 			ch = '/';
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 		*name++ = ch;
8290Sstevel@tonic-gate 	} while (ch != '\0');
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate /*
8330Sstevel@tonic-gate  * add a value property
8340Sstevel@tonic-gate  */
8350Sstevel@tonic-gate static int
add_value_prop(picl_nodehdl_t node_hdl,const char * prop_name,int fru_type,int16_t value)8360Sstevel@tonic-gate add_value_prop(picl_nodehdl_t node_hdl, const char *prop_name, int fru_type,
8370Sstevel@tonic-gate     int16_t value)
8380Sstevel@tonic-gate {
8390Sstevel@tonic-gate 	int err;
8400Sstevel@tonic-gate 	union {
8410Sstevel@tonic-gate 		float		u_f;
8420Sstevel@tonic-gate 		int16_t		u_i16;
8430Sstevel@tonic-gate 	} val_buf;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 	if (fru_to_ptype[fru_type] == PICL_PTYPE_FLOAT)
8460Sstevel@tonic-gate 		val_buf.u_f = (float)((float)value / (float)1000.0);
8470Sstevel@tonic-gate 	else
8480Sstevel@tonic-gate 		val_buf.u_i16 = value;
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	err = add_regular_prop(node_hdl, prop_name, fru_to_ptype[fru_type],
8510Sstevel@tonic-gate 	    PICL_READ, fru_to_size[fru_type], &val_buf, NULL);
8520Sstevel@tonic-gate 	return (err);
8530Sstevel@tonic-gate }
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate static int
find_picl_handle(picl_prophdl_t proph)8560Sstevel@tonic-gate find_picl_handle(picl_prophdl_t proph)
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate 	int	index;
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	for (index = 0; index < handle_arr.num; index++) {
8610Sstevel@tonic-gate 		if (handle_arr.piclprhdls[index] == proph)
8620Sstevel@tonic-gate 			return (index);
8630Sstevel@tonic-gate 	}
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 	return (-1);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate /*
8690Sstevel@tonic-gate  * look up function to convert led status into string
8700Sstevel@tonic-gate  */
8710Sstevel@tonic-gate static int
lookup_led_status(int8_t state,const char ** string)8720Sstevel@tonic-gate lookup_led_status(int8_t state, const char **string)
8730Sstevel@tonic-gate {
8740Sstevel@tonic-gate 	int	i;
8750Sstevel@tonic-gate 	int	lim = sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0]);
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	for (i = 0; i < lim; i++) {
8780Sstevel@tonic-gate 		if (ledstate_lkup[i].state == state) {
8790Sstevel@tonic-gate 			*string = ledstate_lkup[i].str_ledstate;
8800Sstevel@tonic-gate 			return (PICL_SUCCESS);
8810Sstevel@tonic-gate 		}
8820Sstevel@tonic-gate 	}
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate 	*string = "";
8850Sstevel@tonic-gate 	return (PICL_PROPVALUNAVAILABLE);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate static int
lookup_key_posn(envmon_keysw_pos_t pos,const char ** string)8890Sstevel@tonic-gate lookup_key_posn(envmon_keysw_pos_t pos, const char **string)
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate 	int	i;
8920Sstevel@tonic-gate 	int	lim = sizeof (keyposn_lkup) / sizeof (keyposn_lkup[0]);
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 	for (i = 0; i < lim; i++) {
8950Sstevel@tonic-gate 		if (keyposn_lkup[i].pos == pos) {
8960Sstevel@tonic-gate 			*string = keyposn_lkup[i].str_keyposn;
8970Sstevel@tonic-gate 			return (PICL_SUCCESS);
8980Sstevel@tonic-gate 		}
8990Sstevel@tonic-gate 	}
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	*string = "";
9020Sstevel@tonic-gate 	return (PICL_PROPVALUNAVAILABLE);
9030Sstevel@tonic-gate }
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate /*
9060Sstevel@tonic-gate  * function to read volatile data associated with a PICL property handle
9070Sstevel@tonic-gate  */
9080Sstevel@tonic-gate static int
read_vol_data(ptree_rarg_t * r_arg,void * buf)9090Sstevel@tonic-gate read_vol_data(ptree_rarg_t *r_arg, void *buf)
9100Sstevel@tonic-gate {
9110Sstevel@tonic-gate 	picl_prophdl_t		proph;
9120Sstevel@tonic-gate 	int			index;
9130Sstevel@tonic-gate 	uint8_t			fru_type;
9140Sstevel@tonic-gate 	envmon_handle_t		id;
9150Sstevel@tonic-gate 	int16_t			sensor_data;
9160Sstevel@tonic-gate 	int8_t			led_state;
9170Sstevel@tonic-gate 	envmon_keysw_pos_t	key_posn;
918*1103Sjbeloro 	envmon_chassis_t	chassis;
9190Sstevel@tonic-gate 	float			float_data;
9200Sstevel@tonic-gate 	int			cmd;
9210Sstevel@tonic-gate 	int			err;
9220Sstevel@tonic-gate 	int			envmon_fd;
9230Sstevel@tonic-gate 	const char		*cptr;
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	proph = r_arg->proph;
9260Sstevel@tonic-gate 	index = find_picl_handle(proph);
9270Sstevel@tonic-gate 	if (index < 0)
9280Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
9290Sstevel@tonic-gate 	fru_type = handle_arr.fru_types[index];
9300Sstevel@tonic-gate 	id = handle_arr.envhandles[index];
9310Sstevel@tonic-gate 	cmd = fru_to_cmd[fru_type];
9320Sstevel@tonic-gate 	envmon_fd = open(envmon_device_name, O_RDONLY);
9330Sstevel@tonic-gate 	if (envmon_fd < 0)
9340Sstevel@tonic-gate 		return (PICL_NOTREADABLE);
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	/*
9370Sstevel@tonic-gate 	 * read environmental data according to type
9380Sstevel@tonic-gate 	 */
9390Sstevel@tonic-gate 	switch (fru_type) {
9400Sstevel@tonic-gate 	case ENVMON_VOLT_SENS:
9410Sstevel@tonic-gate 		/*FALLTHROUGH*/
9420Sstevel@tonic-gate 	case ENVMON_AMP_SENS:
9430Sstevel@tonic-gate 		/*FALLTHROUGH*/
9440Sstevel@tonic-gate 	case ENVMON_TEMP_SENS:
9450Sstevel@tonic-gate 		err = get_sensor_data(envmon_fd, &id, cmd, NULL, NULL,
9460Sstevel@tonic-gate 		    &sensor_data);
9470Sstevel@tonic-gate 		break;
9480Sstevel@tonic-gate 	case ENVMON_VOLT_IND:
9490Sstevel@tonic-gate 		/*FALLTHROUGH*/
9500Sstevel@tonic-gate 	case ENVMON_AMP_IND:
9510Sstevel@tonic-gate 		/*FALLTHROUGH*/
9520Sstevel@tonic-gate 	case ENVMON_TEMP_IND:
9530Sstevel@tonic-gate 		/*FALLTHROUGH*/
9540Sstevel@tonic-gate 	case ENVMON_FAN_IND:
9550Sstevel@tonic-gate 		err = get_indicator_data(envmon_fd, &id, cmd, &sensor_data);
9560Sstevel@tonic-gate 		break;
9570Sstevel@tonic-gate 	case ENVMON_FAN_SENS:
9580Sstevel@tonic-gate 		err = get_fan_data(envmon_fd, &id, cmd, NULL,
9590Sstevel@tonic-gate 		    (uint16_t *)&sensor_data, NULL);
9600Sstevel@tonic-gate 		break;
9610Sstevel@tonic-gate 	case ENVMON_LED_IND:
9620Sstevel@tonic-gate 		err = get_led_data(envmon_fd, &id, cmd, &led_state, NULL);
9630Sstevel@tonic-gate 		break;
9640Sstevel@tonic-gate 	case ENVMON_KEY_SWITCH:
9650Sstevel@tonic-gate 		err = get_keyswitch_data(envmon_fd, &id, cmd, &key_posn);
9660Sstevel@tonic-gate 		break;
967*1103Sjbeloro 	case ENVMON_CHASSIS:
968*1103Sjbeloro 		err = get_serial_num(envmon_fd, &id, cmd, &chassis);
969*1103Sjbeloro 		break;
9700Sstevel@tonic-gate 	default:
9710Sstevel@tonic-gate 		err = PICL_FAILURE;
9720Sstevel@tonic-gate 		break;
9730Sstevel@tonic-gate 	}
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 	(void) close(envmon_fd);
9760Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
9770Sstevel@tonic-gate 		/*
9780Sstevel@tonic-gate 		 * PICL_INVALIDHANDLE is used internally, but it upsets
9790Sstevel@tonic-gate 		 * prtpicl; change it to PICL_PROPVALUNAVAILABLE
9800Sstevel@tonic-gate 		 */
9810Sstevel@tonic-gate 		if (err == PICL_INVALIDHANDLE)
9820Sstevel@tonic-gate 			err = PICL_PROPVALUNAVAILABLE;
9830Sstevel@tonic-gate 		return (err);
9840Sstevel@tonic-gate 	}
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 	/*
9870Sstevel@tonic-gate 	 * convert data and copy out
9880Sstevel@tonic-gate 	 */
9890Sstevel@tonic-gate 	switch (fru_type) {
9900Sstevel@tonic-gate 	case ENVMON_VOLT_SENS:
9910Sstevel@tonic-gate 		/*FALLTHROUGH*/
9920Sstevel@tonic-gate 	case ENVMON_AMP_SENS:
9930Sstevel@tonic-gate 		float_data = (float)((float)sensor_data / (float)1000.0);
9940Sstevel@tonic-gate 		(void) memcpy(buf, &float_data, sizeof (float_data));
9950Sstevel@tonic-gate 		break;
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	case ENVMON_TEMP_SENS:
9980Sstevel@tonic-gate 		/*FALLTHROUGH*/
9990Sstevel@tonic-gate 	case ENVMON_FAN_SENS:
10000Sstevel@tonic-gate 		(void) memcpy(buf, &sensor_data, sizeof (sensor_data));
10010Sstevel@tonic-gate 		break;
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 	case ENVMON_VOLT_IND:
10040Sstevel@tonic-gate 		/*FALLTHROUGH*/
10050Sstevel@tonic-gate 	case ENVMON_AMP_IND:
10060Sstevel@tonic-gate 		/*FALLTHROUGH*/
10070Sstevel@tonic-gate 	case ENVMON_TEMP_IND:
10080Sstevel@tonic-gate 		/*FALLTHROUGH*/
10090Sstevel@tonic-gate 	case ENVMON_FAN_IND:
10100Sstevel@tonic-gate 		(void) strlcpy(buf, sensor_data == 0 ? cond_okay : cond_failed,
10110Sstevel@tonic-gate 		    fru_to_size[fru_type]);
10120Sstevel@tonic-gate 		break;
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate 	case ENVMON_LED_IND:
10150Sstevel@tonic-gate 		err = lookup_led_status(led_state, &cptr);
10160Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
10170Sstevel@tonic-gate 			return (err);
10180Sstevel@tonic-gate 		(void) strlcpy(buf, cptr, fru_to_size[fru_type]);
10190Sstevel@tonic-gate 		break;
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	case ENVMON_KEY_SWITCH:
10220Sstevel@tonic-gate 		err = lookup_key_posn(key_posn, &cptr);
10230Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
10240Sstevel@tonic-gate 			return (err);
10250Sstevel@tonic-gate 		(void) strlcpy(buf, cptr, fru_to_size[fru_type]);
10260Sstevel@tonic-gate 		break;
1027*1103Sjbeloro 	case ENVMON_CHASSIS:
1028*1103Sjbeloro 		(void) memcpy(buf, chassis.serial_number,
1029*1103Sjbeloro 		    sizeof (chassis.serial_number));
1030*1103Sjbeloro 		break;
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate 	default:
10330Sstevel@tonic-gate 		return (PICL_FAILURE);
10340Sstevel@tonic-gate 	}
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	return (PICL_SUCCESS);
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate static int
write_led_data(ptree_warg_t * w_arg,const void * buf)10400Sstevel@tonic-gate write_led_data(ptree_warg_t *w_arg, const void *buf)
10410Sstevel@tonic-gate {
10420Sstevel@tonic-gate 	picl_prophdl_t		proph;
10430Sstevel@tonic-gate 	int			index;
10440Sstevel@tonic-gate 	uint8_t			fru_type;
10450Sstevel@tonic-gate 	int			err;
10460Sstevel@tonic-gate 	int			envmon_fd;
10470Sstevel@tonic-gate 	envmon_led_ctl_t	led_ctl;
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate 	proph = w_arg->proph;
10500Sstevel@tonic-gate 	index = find_picl_handle(proph);
10510Sstevel@tonic-gate 	if (index < 0)
10520Sstevel@tonic-gate 		return (PICL_INVALIDHANDLE);
10530Sstevel@tonic-gate 	fru_type = handle_arr.fru_types[index];
10540Sstevel@tonic-gate 	if (fru_type != ENVMON_LED_IND)
10550Sstevel@tonic-gate 		return (PICL_INVALIDARG);
10560Sstevel@tonic-gate 	if (w_arg->cred.dc_euid != SUPER_USER)
10570Sstevel@tonic-gate 		return (PICL_PERMDENIED);
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate 	/* see if the requested state is recognized */
10600Sstevel@tonic-gate 	if (strcasecmp(str_Off, buf) == 0)
10610Sstevel@tonic-gate 		led_ctl.led_state = ENVMON_LED_OFF;
10620Sstevel@tonic-gate 	else if (strcasecmp(str_On, buf) == 0)
10630Sstevel@tonic-gate 		led_ctl.led_state = ENVMON_LED_ON;
1064*1103Sjbeloro 	else if (strcasecmp(str_Blinking, buf) == 0)
1065*1103Sjbeloro 		led_ctl.led_state = ENVMON_LED_BLINKING;
1066*1103Sjbeloro 	else if (strcasecmp(str_Flashing, buf) == 0)
1067*1103Sjbeloro 		led_ctl.led_state = ENVMON_LED_FLASHING;
10680Sstevel@tonic-gate 	else
10690Sstevel@tonic-gate 		return (PICL_INVALIDARG);
10700Sstevel@tonic-gate 
10710Sstevel@tonic-gate 	envmon_fd = open(envmon_device_name, O_RDWR);
10720Sstevel@tonic-gate 	if (envmon_fd < 0)
10730Sstevel@tonic-gate 		return (PICL_FAILURE);
10740Sstevel@tonic-gate 	led_ctl.id = handle_arr.envhandles[index];
10750Sstevel@tonic-gate 	err = ioctl(envmon_fd, ENVMONIOCSETLED, &led_ctl);
10760Sstevel@tonic-gate 	(void) close(envmon_fd);
10770Sstevel@tonic-gate 	if (err < 0)
10780Sstevel@tonic-gate 		return (PICL_FAILURE);
10790Sstevel@tonic-gate 	return (PICL_SUCCESS);
10800Sstevel@tonic-gate }
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate /*
10830Sstevel@tonic-gate  * if colour information is not supplied by the service processor,
10840Sstevel@tonic-gate  * try to determine led colour from the handle name.
10850Sstevel@tonic-gate  */
10860Sstevel@tonic-gate static void
fix_led_colour(int8_t * colour_p,const char * id)10870Sstevel@tonic-gate fix_led_colour(int8_t *colour_p, const char *id)
10880Sstevel@tonic-gate {
10890Sstevel@tonic-gate 	const char	*cptr = strrchr(id, '.');
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate 	if ((*colour_p < ENVMON_LED_CLR_NONE) ||
10920Sstevel@tonic-gate 	    (*colour_p > ENVMON_LED_CLR_RED))
10930Sstevel@tonic-gate 		syslog(LOG_ERR, EM_INVALID_COLOR, *colour_p, id);
10940Sstevel@tonic-gate 	if (cptr == NULL) {
10950Sstevel@tonic-gate 		*colour_p = ENVMON_LED_CLR_NONE;
10960Sstevel@tonic-gate 		return;
10970Sstevel@tonic-gate 	}
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	cptr++;		/* step over '.' */
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	if (strcmp(cptr, LED_ACT) == 0)
11020Sstevel@tonic-gate 		    *colour_p = ENVMON_LED_CLR_GREEN;
11030Sstevel@tonic-gate 	else if (strcmp(cptr, LED_SERVICE) == 0)
11040Sstevel@tonic-gate 		*colour_p = ENVMON_LED_CLR_AMBER;
11050Sstevel@tonic-gate 	else if (strcmp(cptr, LED_LOCATE) == 0)
11060Sstevel@tonic-gate 		*colour_p = ENVMON_LED_CLR_WHITE;
11070Sstevel@tonic-gate 	else if (strcmp(cptr, LED_OK2RM) == 0)
11080Sstevel@tonic-gate 		*colour_p = ENVMON_LED_CLR_BLUE;
11090Sstevel@tonic-gate 	else
11100Sstevel@tonic-gate 		*colour_p = ENVMON_LED_CLR_NONE;
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate /*
11140Sstevel@tonic-gate  * Add nodes for environmental devices of type fru_type
11150Sstevel@tonic-gate  * below the supplied node.
11160Sstevel@tonic-gate  */
11170Sstevel@tonic-gate static int
add_env_nodes(int envmon_fd,uint8_t fru_type,picl_nodehdl_t envmonh)11180Sstevel@tonic-gate add_env_nodes(int envmon_fd, uint8_t fru_type, picl_nodehdl_t envmonh)
11190Sstevel@tonic-gate {
11200Sstevel@tonic-gate 	envmon_handle_t		id;
11210Sstevel@tonic-gate 	envmon_thresholds_t	lows;
11220Sstevel@tonic-gate 	envmon_thresholds_t	highs;
11230Sstevel@tonic-gate 	char			units[ENVMON_MAXNAMELEN];
11240Sstevel@tonic-gate 	char			platform_tree_name[ENVMON_MAXNAMELEN];
11250Sstevel@tonic-gate 	char			label_name[ENVMON_MAXNAMELEN];
11260Sstevel@tonic-gate 	int16_t			sensor_data;
11270Sstevel@tonic-gate 	int8_t			led_state;
11280Sstevel@tonic-gate 	int8_t			colour;
11290Sstevel@tonic-gate 	envmon_keysw_pos_t	key_state;
1130*1103Sjbeloro 	envmon_chassis_t	chassis_num;
11310Sstevel@tonic-gate 	int			cmd;
11320Sstevel@tonic-gate 	int			err;
11330Sstevel@tonic-gate 	int			index = handle_arr.num;
11340Sstevel@tonic-gate 	picl_nodehdl_t		node_hdl;
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate 	/*
11370Sstevel@tonic-gate 	 * catch table is full at start
11380Sstevel@tonic-gate 	 */
11390Sstevel@tonic-gate 	if (index >= handle_arr.maxnum)
11400Sstevel@tonic-gate 		return (PICL_FAILURE);
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	cmd = fru_to_cmd[fru_type];
11430Sstevel@tonic-gate 	id.name[0] = '\0';
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 	do {
11460Sstevel@tonic-gate 		lows.warning = lows.shutdown = lows.poweroff =
11470Sstevel@tonic-gate 		    ENVMON_VAL_UNAVAILABLE;
11480Sstevel@tonic-gate 		highs.warning = highs.shutdown = highs.poweroff =
11490Sstevel@tonic-gate 		    ENVMON_VAL_UNAVAILABLE;
11500Sstevel@tonic-gate 		handle_arr.fru_types[index] = fru_type;
11510Sstevel@tonic-gate 		/* must store id before reading data as it is then updated */
11520Sstevel@tonic-gate 		handle_arr.envhandles[index] = id;
11530Sstevel@tonic-gate 		/*
11540Sstevel@tonic-gate 		 * read environmental data according to type
11550Sstevel@tonic-gate 		 */
11560Sstevel@tonic-gate 		switch (fru_type) {
11570Sstevel@tonic-gate 		case ENVMON_VOLT_SENS:
11580Sstevel@tonic-gate 			/*FALLTHROUGH*/
11590Sstevel@tonic-gate 		case ENVMON_AMP_SENS:
11600Sstevel@tonic-gate 			/*FALLTHROUGH*/
11610Sstevel@tonic-gate 		case ENVMON_TEMP_SENS:
11620Sstevel@tonic-gate 			err = get_sensor_data(envmon_fd, &id, cmd, &lows,
11630Sstevel@tonic-gate 			    &highs, &sensor_data);
11640Sstevel@tonic-gate 			break;
11650Sstevel@tonic-gate 		case ENVMON_VOLT_IND:
11660Sstevel@tonic-gate 			/*FALLTHROUGH*/
11670Sstevel@tonic-gate 		case ENVMON_AMP_IND:
11680Sstevel@tonic-gate 			/*FALLTHROUGH*/
11690Sstevel@tonic-gate 		case ENVMON_TEMP_IND:
11700Sstevel@tonic-gate 			/*FALLTHROUGH*/
11710Sstevel@tonic-gate 		case ENVMON_FAN_IND:
11720Sstevel@tonic-gate 			err = get_indicator_data(envmon_fd, &id, cmd,
11730Sstevel@tonic-gate 			    &sensor_data);
11740Sstevel@tonic-gate 			break;
11750Sstevel@tonic-gate 		case ENVMON_FAN_SENS:
11760Sstevel@tonic-gate 			err = get_fan_data(envmon_fd, &id, cmd, &lows,
11770Sstevel@tonic-gate 			    (uint16_t *)&sensor_data, units);
11780Sstevel@tonic-gate 			break;
11790Sstevel@tonic-gate 		case ENVMON_LED_IND:
11800Sstevel@tonic-gate 			err = get_led_data(envmon_fd, &id, cmd, &led_state,
11810Sstevel@tonic-gate 			    &colour);
11820Sstevel@tonic-gate 			break;
11830Sstevel@tonic-gate 		case ENVMON_KEY_SWITCH:
11840Sstevel@tonic-gate 			err = get_keyswitch_data(envmon_fd, &id, cmd,
11850Sstevel@tonic-gate 			    &key_state);
11860Sstevel@tonic-gate 			break;
1187*1103Sjbeloro 		case ENVMON_CHASSIS:
1188*1103Sjbeloro 			err = get_serial_num(envmon_fd, &id, cmd,
1189*1103Sjbeloro 			    &chassis_num);
1190*1103Sjbeloro 			break;
11910Sstevel@tonic-gate 		default:
11920Sstevel@tonic-gate 			return (PICL_FAILURE);
11930Sstevel@tonic-gate 		}
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 		if (err == PICL_INVALIDHANDLE)
11960Sstevel@tonic-gate 			continue;
11970Sstevel@tonic-gate 		if ((err != PICL_SUCCESS) && (err != PICL_PROPVALUNAVAILABLE)) {
11980Sstevel@tonic-gate 			syslog(LOG_ERR, EM_NODE_ACCESS, id, fru_type, err);
11990Sstevel@tonic-gate 			continue;
12000Sstevel@tonic-gate 		}
12010Sstevel@tonic-gate 
12020Sstevel@tonic-gate 		/*
12030Sstevel@tonic-gate 		 * successfully read environmental data, add to PICL
12040Sstevel@tonic-gate 		 */
12050Sstevel@tonic-gate 		(void) strlcpy(platform_tree_name,
12060Sstevel@tonic-gate 		    handle_arr.envhandles[index].name,
12070Sstevel@tonic-gate 		    sizeof (platform_tree_name));
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 		(void) strlcpy(label_name, platform_tree_name,
12100Sstevel@tonic-gate 		    ENVMON_MAXNAMELEN);
12110Sstevel@tonic-gate 		convert_label_name(label_name);
12120Sstevel@tonic-gate 		convert_node_name(platform_tree_name);
12130Sstevel@tonic-gate 		/*
12140Sstevel@tonic-gate 		 * does this node already exist?
12150Sstevel@tonic-gate 		 */
12160Sstevel@tonic-gate 		err = get_child_by_name(envmonh, platform_tree_name, &node_hdl);
12170Sstevel@tonic-gate 		if (err == PICL_SUCCESS) {
12180Sstevel@tonic-gate 			/*
12190Sstevel@tonic-gate 			 * skip over existing node
12200Sstevel@tonic-gate 			 */
12210Sstevel@tonic-gate 			continue;
12220Sstevel@tonic-gate 		}
12230Sstevel@tonic-gate 		err = ptree_create_node(platform_tree_name,
12240Sstevel@tonic-gate 		    fru_to_class[fru_type], &node_hdl);
12250Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
12260Sstevel@tonic-gate 			break;
12270Sstevel@tonic-gate 		}
12280Sstevel@tonic-gate 		err = add_volatile_prop(node_hdl, fru_to_prop[fru_type],
12290Sstevel@tonic-gate 		    fru_to_ptype[fru_type],
12300Sstevel@tonic-gate 		    PICL_READ | (fru_type == ENVMON_LED_IND ? PICL_WRITE : 0),
12310Sstevel@tonic-gate 		    fru_to_size[fru_type], read_vol_data,
12320Sstevel@tonic-gate 		    fru_type == ENVMON_LED_IND ? write_led_data : NULL,
12330Sstevel@tonic-gate 		    &handle_arr.piclprhdls[index]);
12340Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
12350Sstevel@tonic-gate 			break;
12360Sstevel@tonic-gate 		}
1237*1103Sjbeloro 
12380Sstevel@tonic-gate 		/*
12390Sstevel@tonic-gate 		 * if any thresholds are defined add a property
12400Sstevel@tonic-gate 		 */
12410Sstevel@tonic-gate 		if (lows.warning != ENVMON_VAL_UNAVAILABLE) {
12420Sstevel@tonic-gate 			err = add_value_prop(node_hdl, PICL_PROP_LOW_WARNING,
12430Sstevel@tonic-gate 			    fru_type, lows.warning);
12440Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12450Sstevel@tonic-gate 				break;
12460Sstevel@tonic-gate 			}
12470Sstevel@tonic-gate 		}
12480Sstevel@tonic-gate 		if (lows.shutdown != ENVMON_VAL_UNAVAILABLE) {
12490Sstevel@tonic-gate 			err = add_value_prop(node_hdl, PICL_PROP_LOW_SHUTDOWN,
12500Sstevel@tonic-gate 			    fru_type, lows.shutdown);
12510Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12520Sstevel@tonic-gate 				break;
12530Sstevel@tonic-gate 			}
12540Sstevel@tonic-gate 		}
12550Sstevel@tonic-gate 		if (lows.poweroff != ENVMON_VAL_UNAVAILABLE) {
12560Sstevel@tonic-gate 			err = add_value_prop(node_hdl, PICL_PROP_LOW_POWER_OFF,
12570Sstevel@tonic-gate 			    fru_type, lows.poweroff);
12580Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12590Sstevel@tonic-gate 				break;
12600Sstevel@tonic-gate 			}
12610Sstevel@tonic-gate 		}
12620Sstevel@tonic-gate 		if (highs.warning != ENVMON_VAL_UNAVAILABLE) {
12630Sstevel@tonic-gate 			err = add_value_prop(node_hdl, PICL_PROP_HIGH_WARNING,
12640Sstevel@tonic-gate 			    fru_type, highs.warning);
12650Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12660Sstevel@tonic-gate 				break;
12670Sstevel@tonic-gate 			}
12680Sstevel@tonic-gate 		}
12690Sstevel@tonic-gate 		if (highs.shutdown != ENVMON_VAL_UNAVAILABLE) {
12700Sstevel@tonic-gate 			err = add_value_prop(node_hdl, PICL_PROP_HIGH_SHUTDOWN,
12710Sstevel@tonic-gate 			    fru_type, highs.shutdown);
12720Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12730Sstevel@tonic-gate 				break;
12740Sstevel@tonic-gate 			}
12750Sstevel@tonic-gate 		}
12760Sstevel@tonic-gate 		if (highs.poweroff != ENVMON_VAL_UNAVAILABLE) {
12770Sstevel@tonic-gate 			err = add_value_prop(node_hdl, PICL_PROP_HIGH_POWER_OFF,
12780Sstevel@tonic-gate 			    fru_type, highs.poweroff);
12790Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12800Sstevel@tonic-gate 				break;
12810Sstevel@tonic-gate 			}
12820Sstevel@tonic-gate 		}
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 		/*
12850Sstevel@tonic-gate 		 * if device is a fan sensor, add a speedunit property
12860Sstevel@tonic-gate 		 */
12870Sstevel@tonic-gate 		if (fru_type == ENVMON_FAN_SENS) {
12880Sstevel@tonic-gate 			err = add_regular_prop(node_hdl,
12890Sstevel@tonic-gate 			    PICL_PROP_FAN_SPEED_UNIT, PICL_PTYPE_CHARSTRING,
12900Sstevel@tonic-gate 			    PICL_READ, 1 + strlen(units), units, NULL);
12910Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
12920Sstevel@tonic-gate 				break;
12930Sstevel@tonic-gate 			}
12940Sstevel@tonic-gate 		}
12950Sstevel@tonic-gate 		/*
12960Sstevel@tonic-gate 		 * If device is a LED indicator and returns a colour,
12970Sstevel@tonic-gate 		 * add a colour property.
12980Sstevel@tonic-gate 		 */
12990Sstevel@tonic-gate 		if (fru_type == ENVMON_LED_IND) {
13000Sstevel@tonic-gate 			if (colour < 0 || colour == ENVMON_LED_CLR_ANY ||
13010Sstevel@tonic-gate 			    colour > ENVMON_LED_CLR_RED)
13020Sstevel@tonic-gate 				fix_led_colour(&colour,
13030Sstevel@tonic-gate 				    handle_arr.envhandles[index].name);
13040Sstevel@tonic-gate 			if (colour != ENVMON_LED_CLR_NONE) {
13050Sstevel@tonic-gate 				err = add_regular_prop(node_hdl,
13060Sstevel@tonic-gate 				    PICL_PROP_COLOR, PICL_PTYPE_CHARSTRING,
13070Sstevel@tonic-gate 				    PICL_READ, colour_lkup[colour].size,
13080Sstevel@tonic-gate 				    colour_lkup[colour].str_colour, NULL);
13090Sstevel@tonic-gate 				if (err != PICL_SUCCESS) {
13100Sstevel@tonic-gate 					break;
13110Sstevel@tonic-gate 				}
13120Sstevel@tonic-gate 			}
13130Sstevel@tonic-gate 		}
13140Sstevel@tonic-gate 		/*
1315*1103Sjbeloro 		 * add a label property unless it's a keyswitch or the
1316*1103Sjbeloro 		 * chassis serial number. keyswitch and chassis serial
1317*1103Sjbeloro 		 * number are labelled from a config file because the
13180Sstevel@tonic-gate 		 * ALOM interface doesn't supply a name for it)
13190Sstevel@tonic-gate 		 */
1320*1103Sjbeloro 		if ((fru_type != ENVMON_KEY_SWITCH) &&
1321*1103Sjbeloro 		    (fru_type != ENVMON_CHASSIS)) {
13220Sstevel@tonic-gate 			err = add_regular_prop(node_hdl, PICL_PROP_LABEL,
13230Sstevel@tonic-gate 			    PICL_PTYPE_CHARSTRING, PICL_READ,
13240Sstevel@tonic-gate 			    1 + strlen(label_name), label_name, NULL);
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
13270Sstevel@tonic-gate 				break;
13280Sstevel@tonic-gate 			}
13290Sstevel@tonic-gate 		}
13300Sstevel@tonic-gate 		/*
13310Sstevel@tonic-gate 		 * all properties added to this node, add the node below
13320Sstevel@tonic-gate 		 * the supplied anchor point
13330Sstevel@tonic-gate 		 */
13340Sstevel@tonic-gate 		err = ptree_add_node(envmonh, node_hdl);
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
13370Sstevel@tonic-gate 			break;
13380Sstevel@tonic-gate 		}
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 		/*
13410Sstevel@tonic-gate 		 * that node went in OK, advance index
13420Sstevel@tonic-gate 		 */
13430Sstevel@tonic-gate 		index++;
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 	} while ((id.name[0] != '\0') && (index < handle_arr.maxnum));
13460Sstevel@tonic-gate 
13470Sstevel@tonic-gate 	handle_arr.num = index;
13480Sstevel@tonic-gate 	return (err);
13490Sstevel@tonic-gate }
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate static void
fixstate(uint8_t state,const char * string,int * max_len)13520Sstevel@tonic-gate fixstate(uint8_t state, const char *string, int *max_len)
13530Sstevel@tonic-gate {
13540Sstevel@tonic-gate 	int		i;
13550Sstevel@tonic-gate 	int		len;
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	for (i = 0; i < (sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0]));
13580Sstevel@tonic-gate 	    i++) {
13590Sstevel@tonic-gate 		if (ledstate_lkup[i].state == state) {
13600Sstevel@tonic-gate 			if (ledstate_lkup[i].str_ledstate != NULL)
13610Sstevel@tonic-gate 				free(ledstate_lkup[i].str_ledstate);
13620Sstevel@tonic-gate 			ledstate_lkup[i].str_ledstate = strdup(string);
13630Sstevel@tonic-gate 			len = strlen(string);
13640Sstevel@tonic-gate 			if (len >= *max_len)
13650Sstevel@tonic-gate 				*max_len = len + 1;
13660Sstevel@tonic-gate 			break;
13670Sstevel@tonic-gate 		}
13680Sstevel@tonic-gate 	}
13690Sstevel@tonic-gate }
13700Sstevel@tonic-gate 
13710Sstevel@tonic-gate static void
fixkeyposn(envmon_keysw_pos_t keyposn,const char * string,int * max_len)13720Sstevel@tonic-gate fixkeyposn(envmon_keysw_pos_t keyposn, const char *string, int *max_len)
13730Sstevel@tonic-gate {
13740Sstevel@tonic-gate 	int		i;
13750Sstevel@tonic-gate 	int		len;
13760Sstevel@tonic-gate 
13770Sstevel@tonic-gate 	for (i = 0; i < (sizeof (keyposn_lkup) / sizeof (keyposn_lkup[0]));
13780Sstevel@tonic-gate 	    i++) {
13790Sstevel@tonic-gate 		if (keyposn_lkup[i].pos == keyposn) {
13800Sstevel@tonic-gate 			if (keyposn_lkup[i].str_keyposn != NULL)
13810Sstevel@tonic-gate 				free(keyposn_lkup[i].str_keyposn);
13820Sstevel@tonic-gate 			keyposn_lkup[i].str_keyposn = strdup(string);
13830Sstevel@tonic-gate 			len = strlen(string);
13840Sstevel@tonic-gate 			if (len >= *max_len)
13850Sstevel@tonic-gate 				*max_len = len + 1;
13860Sstevel@tonic-gate 			break;
13870Sstevel@tonic-gate 		}
13880Sstevel@tonic-gate 	}
13890Sstevel@tonic-gate }
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate static void
setup_strings()13920Sstevel@tonic-gate setup_strings()
13930Sstevel@tonic-gate {
13940Sstevel@tonic-gate 	int string_size;
13950Sstevel@tonic-gate 	int i;
13960Sstevel@tonic-gate 	int lim = sizeof (colour_lkup) / sizeof (colour_lkup[0]);
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 	/*
13990Sstevel@tonic-gate 	 * initialise led colours lookup
14000Sstevel@tonic-gate 	 */
14010Sstevel@tonic-gate 	for (i = 0; i < lim; i++) {
14020Sstevel@tonic-gate 		if (colour_lkup[i].str_colour != NULL)
14030Sstevel@tonic-gate 			free(colour_lkup[i].str_colour);
14040Sstevel@tonic-gate 	}
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	colour_lkup[ENVMON_LED_CLR_ANY].str_colour = strdup(gettext("any"));
14070Sstevel@tonic-gate 	colour_lkup[ENVMON_LED_CLR_WHITE].str_colour =
14080Sstevel@tonic-gate 	    strdup(gettext("white"));
14090Sstevel@tonic-gate 	colour_lkup[ENVMON_LED_CLR_BLUE].str_colour = strdup(gettext("blue"));
14100Sstevel@tonic-gate 	colour_lkup[ENVMON_LED_CLR_GREEN].str_colour =
14110Sstevel@tonic-gate 	    strdup(gettext("green"));
14120Sstevel@tonic-gate 	colour_lkup[ENVMON_LED_CLR_AMBER].str_colour =
14130Sstevel@tonic-gate 	    strdup(gettext("amber"));
14140Sstevel@tonic-gate 	colour_lkup[ENVMON_LED_CLR_RED].str_colour =
14150Sstevel@tonic-gate 	    strdup(gettext("red"));
14160Sstevel@tonic-gate 
14170Sstevel@tonic-gate 	for (i = 0; i < lim; i++) {
14180Sstevel@tonic-gate 		if (colour_lkup[i].str_colour != NULL)
14190Sstevel@tonic-gate 			colour_lkup[i].size =
14200Sstevel@tonic-gate 			    1 + strlen(colour_lkup[i].str_colour);
14210Sstevel@tonic-gate 	}
14220Sstevel@tonic-gate 
14230Sstevel@tonic-gate 	/*
14240Sstevel@tonic-gate 	 * initialise condition strings and note longest
14250Sstevel@tonic-gate 	 */
14260Sstevel@tonic-gate 	string_size = 0;
14270Sstevel@tonic-gate 	cond_okay = strdup(gettext("okay"));
14280Sstevel@tonic-gate 	if (strlen(cond_okay) >= string_size)
14290Sstevel@tonic-gate 		string_size = 1 + strlen(cond_okay);
14300Sstevel@tonic-gate 	cond_failed = strdup(gettext("failed"));
14310Sstevel@tonic-gate 	if (strlen(cond_failed) >= string_size)
14320Sstevel@tonic-gate 		string_size = 1 + strlen(cond_failed);
14330Sstevel@tonic-gate 
14340Sstevel@tonic-gate 	for (i = 0; i < sizeof (fru_to_size) / sizeof (fru_to_size[0]); i++)
14350Sstevel@tonic-gate 		if (fru_to_size[i] == -1)
14360Sstevel@tonic-gate 			fru_to_size[i] = string_size;
14370Sstevel@tonic-gate 
14380Sstevel@tonic-gate 	/*
14390Sstevel@tonic-gate 	 * initialise led state lookup strings
14400Sstevel@tonic-gate 	 */
14410Sstevel@tonic-gate 	string_size = 0;
14420Sstevel@tonic-gate 	fixstate(ENVMON_LED_OFF, gettext("off"), &string_size);
14430Sstevel@tonic-gate 	fixstate(ENVMON_LED_ON, gettext("on"), &string_size);
14440Sstevel@tonic-gate 	fixstate(ENVMON_LED_BLINKING, gettext("blinking"), &string_size);
14450Sstevel@tonic-gate 	fixstate(ENVMON_LED_FLASHING, gettext("flashing"), &string_size);
14460Sstevel@tonic-gate 	fru_to_size[ENVMON_LED_IND] = string_size;
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 	/*
14490Sstevel@tonic-gate 	 * initialise key position lookup strings
14500Sstevel@tonic-gate 	 */
14510Sstevel@tonic-gate 	string_size = 0;
14520Sstevel@tonic-gate 	fixkeyposn(ENVMON_KEYSW_POS_UNKNOWN, gettext("UNKNOWN"), &string_size);
14530Sstevel@tonic-gate 	fixkeyposn(ENVMON_KEYSW_POS_NORMAL, gettext("NORMAL"), &string_size);
14540Sstevel@tonic-gate 	fixkeyposn(ENVMON_KEYSW_POS_DIAG, gettext("DIAG"), &string_size);
14550Sstevel@tonic-gate 	fixkeyposn(ENVMON_KEYSW_POS_LOCKED, gettext("LOCKED"), &string_size);
14560Sstevel@tonic-gate 	fixkeyposn(ENVMON_KEYSW_POS_OFF, gettext("STBY"), &string_size);
14570Sstevel@tonic-gate 	fru_to_size[ENVMON_KEY_SWITCH] = string_size;
1458*1103Sjbeloro 
1459*1103Sjbeloro 	/*
1460*1103Sjbeloro 	 * initialise chassis serial number string
1461*1103Sjbeloro 	 */
1462*1103Sjbeloro 	fru_to_size[ENVMON_CHASSIS] = ENVMON_MAXNAMELEN;
14630Sstevel@tonic-gate }
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate /*
14660Sstevel@tonic-gate  * The size of outfilename must be PATH_MAX
14670Sstevel@tonic-gate  */
14680Sstevel@tonic-gate static int
get_config_file(char * filename)14690Sstevel@tonic-gate get_config_file(char *filename)
14700Sstevel@tonic-gate {
14710Sstevel@tonic-gate 	char	nmbuf[SYS_NMLN];
14720Sstevel@tonic-gate 	char	pname[PATH_MAX];
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
14750Sstevel@tonic-gate 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
14760Sstevel@tonic-gate 		(void) strlcat(pname, ENVMON_CONFFILE_NAME, PATH_MAX);
14770Sstevel@tonic-gate 		if (access(pname, R_OK) == 0) {
14780Sstevel@tonic-gate 			(void) strlcpy(filename, pname, PATH_MAX);
14790Sstevel@tonic-gate 			return (0);
14800Sstevel@tonic-gate 		}
14810Sstevel@tonic-gate 	}
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 	if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
14840Sstevel@tonic-gate 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
14850Sstevel@tonic-gate 		(void) strlcat(pname, ENVMON_CONFFILE_NAME, PATH_MAX);
14860Sstevel@tonic-gate 		if (access(pname, R_OK) == 0) {
14870Sstevel@tonic-gate 			(void) strlcpy(filename, pname, PATH_MAX);
14880Sstevel@tonic-gate 			return (0);
14890Sstevel@tonic-gate 		}
14900Sstevel@tonic-gate 	}
14910Sstevel@tonic-gate 
14920Sstevel@tonic-gate 	(void) snprintf(pname, PATH_MAX, "%s/%s",
14930Sstevel@tonic-gate 	    PICLD_COMMON_PLUGIN_DIR, ENVMON_CONFFILE_NAME);
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	if (access(pname, R_OK) == 0) {
14960Sstevel@tonic-gate 		(void) strlcpy(filename, pname, PATH_MAX);
14970Sstevel@tonic-gate 		return (0);
14980Sstevel@tonic-gate 	}
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate 	return (-1);
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate static void
free_vol_prop(picl_prophdl_t proph)15040Sstevel@tonic-gate free_vol_prop(picl_prophdl_t proph)
15050Sstevel@tonic-gate {
15060Sstevel@tonic-gate 	int	index;
15070Sstevel@tonic-gate 
15080Sstevel@tonic-gate 	index = find_picl_handle(proph);
15090Sstevel@tonic-gate 	if (index >= 0) {
15100Sstevel@tonic-gate 		handle_arr.num--;
15110Sstevel@tonic-gate 		if (index != handle_arr.num) {
15120Sstevel@tonic-gate 			/* relocate last entry into hole just created */
15130Sstevel@tonic-gate 			handle_arr.fru_types[index] =
15140Sstevel@tonic-gate 			    handle_arr.fru_types[handle_arr.num];
15150Sstevel@tonic-gate 			handle_arr.envhandles[index] =
15160Sstevel@tonic-gate 			    handle_arr.envhandles[handle_arr.num];
15170Sstevel@tonic-gate 			handle_arr.piclprhdls[index] =
15180Sstevel@tonic-gate 			    handle_arr.piclprhdls[handle_arr.num];
15190Sstevel@tonic-gate 		}
15200Sstevel@tonic-gate 	}
15210Sstevel@tonic-gate }
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate /*
15240Sstevel@tonic-gate  * handle PICL FRU ADDED and FRU REMOVED events
15250Sstevel@tonic-gate  */
15260Sstevel@tonic-gate /*ARGSUSED*/
15270Sstevel@tonic-gate static void
envmon_evhandler(const char * ename,const void * earg,size_t size,void * cookie)15280Sstevel@tonic-gate envmon_evhandler(const char *ename, const void *earg, size_t size,
15290Sstevel@tonic-gate     void *cookie)
15300Sstevel@tonic-gate {
15310Sstevel@tonic-gate 	char			path[MAXPATHLEN];
15320Sstevel@tonic-gate 	picl_nodehdl_t		locnodeh;
15330Sstevel@tonic-gate 	int			retval;
15340Sstevel@tonic-gate 	picl_nodehdl_t		childh;
15350Sstevel@tonic-gate 	picl_nodehdl_t		nodeh;
15360Sstevel@tonic-gate 	picl_prophdl_t		tableh;
15370Sstevel@tonic-gate 	picl_prophdl_t		tblh;
15380Sstevel@tonic-gate 	picl_prophdl_t		proph;
15390Sstevel@tonic-gate 	ptree_propinfo_t	pi;
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 	if (strcmp(ename, PICL_FRU_ADDED) == 0) {
15420Sstevel@tonic-gate 		retval = nvlist_lookup_uint64((nvlist_t *)earg,
15430Sstevel@tonic-gate 		    PICLEVENTARG_PARENTHANDLE, &locnodeh);
15440Sstevel@tonic-gate 
15450Sstevel@tonic-gate 		if (retval != 0) {
15460Sstevel@tonic-gate 			syslog(LOG_ERR, EM_EV_MISSING_ARG,
15470Sstevel@tonic-gate 			    PICLEVENTARG_PARENTHANDLE);
15480Sstevel@tonic-gate 			return;
15490Sstevel@tonic-gate 		}
15500Sstevel@tonic-gate 		retval = ptree_get_propval_by_name(locnodeh, PICL_PROP_NAME,
15510Sstevel@tonic-gate 		    path, sizeof (path));
15520Sstevel@tonic-gate 		if (retval == PICL_SUCCESS) {
15530Sstevel@tonic-gate 			/*
15540Sstevel@tonic-gate 			 * Open envmon device and interrogate
15550Sstevel@tonic-gate 			 */
15560Sstevel@tonic-gate 			int		envmon_fd;
15570Sstevel@tonic-gate 			int		fru_type;
15580Sstevel@tonic-gate 			picl_nodehdl_t	envmoninfh;
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 			if (get_envmon_node(&envmoninfh) != PICL_SUCCESS) {
15610Sstevel@tonic-gate 				syslog(LOG_ERR, EM_SC_NODE_MISSING);
15620Sstevel@tonic-gate 				return;
15630Sstevel@tonic-gate 			}
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate 			if ((envmon_fd = open(envmon_device_name, O_RDONLY)) <
15660Sstevel@tonic-gate 			    0) {
15670Sstevel@tonic-gate 				syslog(LOG_ERR, EM_SYS_ERR, envmon_device_name,
15680Sstevel@tonic-gate 				    strerror(errno));
15690Sstevel@tonic-gate 				return;
15700Sstevel@tonic-gate 			}
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 			if (strcmp(str_SC, path) == 0) {
15730Sstevel@tonic-gate 				/*
15740Sstevel@tonic-gate 				 * SC state change - re-assess platform tree
15750Sstevel@tonic-gate 				 */
15760Sstevel@tonic-gate 				if (re_create_arrays(envmon_fd) != 0) {
15770Sstevel@tonic-gate 					/*
15780Sstevel@tonic-gate 					 * out of memory - make no changes
15790Sstevel@tonic-gate 					 */
15800Sstevel@tonic-gate 					return;
15810Sstevel@tonic-gate 				}
15820Sstevel@tonic-gate 				/*
15830Sstevel@tonic-gate 				 * dropped memory of volatile prop handles
15840Sstevel@tonic-gate 				 * so drop the nodes also, then rebuild for
15850Sstevel@tonic-gate 				 * the newly loaded SC
15860Sstevel@tonic-gate 				 */
15870Sstevel@tonic-gate 				retval = ptree_get_propval_by_name(envmoninfh,
15880Sstevel@tonic-gate 				    PICL_PROP_PARENT, &nodeh, sizeof (nodeh));
15890Sstevel@tonic-gate 				if (retval != PICL_SUCCESS) {
15900Sstevel@tonic-gate 					(void) close(envmon_fd);
15910Sstevel@tonic-gate 					return;
15920Sstevel@tonic-gate 				}
15930Sstevel@tonic-gate 				retval = ptree_get_propval_by_name(envmoninfh,
15940Sstevel@tonic-gate 				    PICL_PROP_NAME, path, sizeof (path));
15950Sstevel@tonic-gate 				if (retval != PICL_SUCCESS) {
15960Sstevel@tonic-gate 					(void) close(envmon_fd);
15970Sstevel@tonic-gate 					return;
15980Sstevel@tonic-gate 				}
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 				retval = ptree_delete_node(envmoninfh);
16010Sstevel@tonic-gate 				if (retval == PICL_SUCCESS)
16020Sstevel@tonic-gate 				    (void) ptree_destroy_node(envmoninfh);
16030Sstevel@tonic-gate 				retval = ptree_create_node(path,
16040Sstevel@tonic-gate 				    PICL_CLASS_SERVICE_PROCESSOR, &envmoninfh);
16050Sstevel@tonic-gate 				if (retval != PICL_SUCCESS) {
16060Sstevel@tonic-gate 					(void) close(envmon_fd);
16070Sstevel@tonic-gate 					return;
16080Sstevel@tonic-gate 				}
16090Sstevel@tonic-gate 				retval = ptree_add_node(nodeh, envmoninfh);
16100Sstevel@tonic-gate 				if (retval != PICL_SUCCESS) {
16110Sstevel@tonic-gate 					(void) close(envmon_fd);
16120Sstevel@tonic-gate 					return;
16130Sstevel@tonic-gate 				}
16140Sstevel@tonic-gate 			}
16150Sstevel@tonic-gate 
16160Sstevel@tonic-gate 			for (fru_type = 0; fru_type < ENVMONTYPES;
16170Sstevel@tonic-gate 			    fru_type++) {
16180Sstevel@tonic-gate 				(void) add_env_nodes(envmon_fd, fru_type,
16190Sstevel@tonic-gate 				    envmoninfh);
16200Sstevel@tonic-gate 			}
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate 			(void) close(envmon_fd);
16230Sstevel@tonic-gate 		}
16240Sstevel@tonic-gate 	} else if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
16250Sstevel@tonic-gate 		retval = nvlist_lookup_uint64((nvlist_t *)earg,
16260Sstevel@tonic-gate 		    PICLEVENTARG_FRUHANDLE, &childh);
16270Sstevel@tonic-gate 
16280Sstevel@tonic-gate 		if (retval != 0) {
16290Sstevel@tonic-gate 			syslog(LOG_ERR, EM_EV_MISSING_ARG,
16300Sstevel@tonic-gate 			    PICLEVENTARG_FRUHANDLE);
16310Sstevel@tonic-gate 			return;
16320Sstevel@tonic-gate 		}
16330Sstevel@tonic-gate 		retval = ptree_get_propval_by_name(childh, PICL_PROP_NAME,
16340Sstevel@tonic-gate 		    path, sizeof (path));
16350Sstevel@tonic-gate 		if (retval == PICL_SUCCESS) {
16360Sstevel@tonic-gate 			retval = ptree_get_prop_by_name(childh,
16370Sstevel@tonic-gate 			    PICL_PROP_DEVICES, &tableh);
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 			if (retval != PICL_SUCCESS) {
16400Sstevel@tonic-gate 				/* no Devices table, nothing to do */
16410Sstevel@tonic-gate 				return;
16420Sstevel@tonic-gate 			}
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 			/*
16450Sstevel@tonic-gate 			 * follow all reference properties in the second
16460Sstevel@tonic-gate 			 * column of the table and delete the referenced node
16470Sstevel@tonic-gate 			 */
16480Sstevel@tonic-gate 			retval = ptree_get_propval(tableh, &tblh,
16490Sstevel@tonic-gate 			    sizeof (tblh));
16500Sstevel@tonic-gate 			if (retval != PICL_SUCCESS) {
16510Sstevel@tonic-gate 				/*
16520Sstevel@tonic-gate 				 * can't get value of table property
16530Sstevel@tonic-gate 				 */
16540Sstevel@tonic-gate 				return;
16550Sstevel@tonic-gate 			}
16560Sstevel@tonic-gate 			/* get first col, first row */
16570Sstevel@tonic-gate 			retval = ptree_get_next_by_col(tblh, &tblh);
16580Sstevel@tonic-gate 			if (retval != PICL_SUCCESS) {
16590Sstevel@tonic-gate 				/*
16600Sstevel@tonic-gate 				 * no rows?
16610Sstevel@tonic-gate 				 */
16620Sstevel@tonic-gate 				return;
16630Sstevel@tonic-gate 			}
16640Sstevel@tonic-gate 			/*
16650Sstevel@tonic-gate 			 * starting at next col, get every entry in the column
16660Sstevel@tonic-gate 			 */
16670Sstevel@tonic-gate 			for (retval = ptree_get_next_by_row(tblh, &tblh);
16680Sstevel@tonic-gate 			    retval == PICL_SUCCESS;
16690Sstevel@tonic-gate 			    retval = ptree_get_next_by_col(tblh, &tblh)) {
16700Sstevel@tonic-gate 				/*
16710Sstevel@tonic-gate 				 * should be a ref prop in our hands,
16720Sstevel@tonic-gate 				 * get the target node handle
16730Sstevel@tonic-gate 				 */
16740Sstevel@tonic-gate 				retval = ptree_get_propval(tblh, &nodeh,
16750Sstevel@tonic-gate 				    sizeof (nodeh));
16760Sstevel@tonic-gate 				if (retval != PICL_SUCCESS) {
16770Sstevel@tonic-gate 					continue;
16780Sstevel@tonic-gate 				}
16790Sstevel@tonic-gate 				/*
16800Sstevel@tonic-gate 				 * got the referenced node, has it got a
16810Sstevel@tonic-gate 				 * volatile property to clean up?
16820Sstevel@tonic-gate 				 */
16830Sstevel@tonic-gate 				retval = ptree_get_first_prop(nodeh, &proph);
16840Sstevel@tonic-gate 				while (retval == PICL_SUCCESS) {
16850Sstevel@tonic-gate 					retval = ptree_get_propinfo(proph, &pi);
16860Sstevel@tonic-gate 					if ((retval == PICL_SUCCESS) &&
16870Sstevel@tonic-gate 					    (pi.piclinfo.accessmode &
16880Sstevel@tonic-gate 					    PICL_VOLATILE))
16890Sstevel@tonic-gate 						free_vol_prop(proph);
16900Sstevel@tonic-gate 					retval = ptree_get_next_prop(proph,
16910Sstevel@tonic-gate 					    &proph);
16920Sstevel@tonic-gate 				}
16930Sstevel@tonic-gate 				/*
16940Sstevel@tonic-gate 				 * all volatile properties gone, remove node
16950Sstevel@tonic-gate 				 */
16960Sstevel@tonic-gate 				retval = ptree_delete_node(nodeh);
16970Sstevel@tonic-gate 				if (retval == PICL_SUCCESS)
16980Sstevel@tonic-gate 				    (void) ptree_destroy_node(nodeh);
16990Sstevel@tonic-gate 			}
17000Sstevel@tonic-gate 		}
17010Sstevel@tonic-gate 	}
17020Sstevel@tonic-gate }
17030Sstevel@tonic-gate 
17040Sstevel@tonic-gate /*
17050Sstevel@tonic-gate  * executed as part of .init when the plugin is dlopen()ed
17060Sstevel@tonic-gate  */
17070Sstevel@tonic-gate static void
piclenvmon_register(void)17080Sstevel@tonic-gate piclenvmon_register(void)
17090Sstevel@tonic-gate {
17100Sstevel@tonic-gate 	(void) picld_plugin_register(&my_reg_info);
17110Sstevel@tonic-gate }
17120Sstevel@tonic-gate 
17130Sstevel@tonic-gate /*
17140Sstevel@tonic-gate  * Init entry point of the plugin
17150Sstevel@tonic-gate  * Creates the PICL nodes and properties in the physical and logical aspects.
17160Sstevel@tonic-gate  */
17170Sstevel@tonic-gate static void
piclenvmon_init(void)17180Sstevel@tonic-gate piclenvmon_init(void)
17190Sstevel@tonic-gate {
17200Sstevel@tonic-gate 	picl_nodehdl_t		rooth;
17210Sstevel@tonic-gate 	picl_nodehdl_t		plfh;
17220Sstevel@tonic-gate 	picl_nodehdl_t		envmoninfh;
17230Sstevel@tonic-gate 	int			res;
17240Sstevel@tonic-gate 	int			envmon_fd;
17250Sstevel@tonic-gate 	int			fru_type;
17260Sstevel@tonic-gate 	char			pathname[PATH_MAX];
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 	/*
17290Sstevel@tonic-gate 	 * locate and parse config file
17300Sstevel@tonic-gate 	 */
17310Sstevel@tonic-gate 	if (get_config_file(pathname) < 0)
17320Sstevel@tonic-gate 		return;
17330Sstevel@tonic-gate 
17340Sstevel@tonic-gate 	if ((ptree_get_root(&rooth) != PICL_SUCCESS) ||
17350Sstevel@tonic-gate 	    (picld_pluginutil_parse_config_file(rooth, pathname) !=
17360Sstevel@tonic-gate 	    PICL_SUCCESS)) {
17370Sstevel@tonic-gate 		syslog(LOG_ERR, EM_INIT_FAILED);
17380Sstevel@tonic-gate 	}
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate 	/*
17410Sstevel@tonic-gate 	 * Get platform node
17420Sstevel@tonic-gate 	 */
17430Sstevel@tonic-gate 	if (ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM, &plfh)
17440Sstevel@tonic-gate 	    != PICL_SUCCESS) {
17450Sstevel@tonic-gate 		syslog(LOG_ERR, EM_MISSING_NODE, PICL_NODE_PLATFORM);
17460Sstevel@tonic-gate 		syslog(LOG_ERR, EM_INIT_FAILED);
17470Sstevel@tonic-gate 		return;
17480Sstevel@tonic-gate 	}
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 	/*
17510Sstevel@tonic-gate 	 * Get service-processor node
17520Sstevel@tonic-gate 	 */
17530Sstevel@tonic-gate 	if (get_envmon_node(&envmoninfh) != PICL_SUCCESS)
17540Sstevel@tonic-gate 		return;
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 	/*
17570Sstevel@tonic-gate 	 * We may have been restarted, make sure we don't leak
17580Sstevel@tonic-gate 	 */
17590Sstevel@tonic-gate 	if (envmon_device_name != NULL) {
17600Sstevel@tonic-gate 		free(envmon_device_name);
17610Sstevel@tonic-gate 	}
17620Sstevel@tonic-gate 
17630Sstevel@tonic-gate 	if ((envmon_device_name = create_envmon_pathname(envmoninfh)) == NULL)
17640Sstevel@tonic-gate 		return;
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 	/*
17670Sstevel@tonic-gate 	 * Open envmon device and interrogate for devices it monitors
17680Sstevel@tonic-gate 	 */
17690Sstevel@tonic-gate 	if ((envmon_fd = open(envmon_device_name, O_RDONLY)) < 0) {
17700Sstevel@tonic-gate 		syslog(LOG_ERR, EM_SYS_ERR, envmon_device_name,
17710Sstevel@tonic-gate 		    strerror(errno));
17720Sstevel@tonic-gate 		return;
17730Sstevel@tonic-gate 	}
17740Sstevel@tonic-gate 
17750Sstevel@tonic-gate 	if (get_envmon_limits(envmon_fd, &env_limits) < 0)
17760Sstevel@tonic-gate 		return;
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate 	/*
17790Sstevel@tonic-gate 	 * A set of arrays are used whose bounds are determined by the
17800Sstevel@tonic-gate 	 * response to get_envmon_limits. Establish these arrays now.
17810Sstevel@tonic-gate 	 */
17820Sstevel@tonic-gate 	create_arrays();
17830Sstevel@tonic-gate 	setup_strings();
17840Sstevel@tonic-gate 
17850Sstevel@tonic-gate 	for (fru_type = 0; fru_type < ENVMONTYPES; fru_type++) {
17860Sstevel@tonic-gate 		(void) add_env_nodes(envmon_fd, fru_type, envmoninfh);
17870Sstevel@tonic-gate 	}
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	(void) close(envmon_fd);
17900Sstevel@tonic-gate 
17910Sstevel@tonic-gate 	res = ptree_register_handler(PICL_FRU_ADDED, envmon_evhandler, NULL);
17920Sstevel@tonic-gate 	if (res != PICL_SUCCESS) {
17930Sstevel@tonic-gate 		syslog(LOG_ERR, EM_EVREG_FAILED, res);
17940Sstevel@tonic-gate 	}
17950Sstevel@tonic-gate 	res = ptree_register_handler(PICL_FRU_REMOVED, envmon_evhandler, NULL);
17960Sstevel@tonic-gate 	if (res != PICL_SUCCESS) {
17970Sstevel@tonic-gate 		syslog(LOG_ERR, EM_EVREG_FAILED, res);
17980Sstevel@tonic-gate 	}
17990Sstevel@tonic-gate }
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate /*
18020Sstevel@tonic-gate  * fini entry point of the plugin
18030Sstevel@tonic-gate  */
18040Sstevel@tonic-gate static void
piclenvmon_fini(void)18050Sstevel@tonic-gate piclenvmon_fini(void)
18060Sstevel@tonic-gate {
18070Sstevel@tonic-gate 	if (envmon_device_name != NULL) {
18080Sstevel@tonic-gate 		free(envmon_device_name);
18090Sstevel@tonic-gate 		envmon_device_name = NULL;
18100Sstevel@tonic-gate 	}
18110Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICL_FRU_ADDED,
18120Sstevel@tonic-gate 	    envmon_evhandler, NULL);
18130Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICL_FRU_REMOVED,
18140Sstevel@tonic-gate 	    envmon_evhandler, NULL);
18150Sstevel@tonic-gate }
1816