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*13093SRoger.Faulkner@Oracle.COM * Common Development and Distribution License (the "License").
6*13093SRoger.Faulkner@Oracle.COM * 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*13093SRoger.Faulkner@Oracle.COM
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * This plugin creates PICL nodes and properties for objects handled through
280Sstevel@tonic-gate * the blade support chip (BSC). The BSC Solaris land device driver exposes
290Sstevel@tonic-gate * information to the plugin and other clients through an existing LOM
300Sstevel@tonic-gate * (Lights Out Management) ioctl interface. The plugin only exercises
310Sstevel@tonic-gate * a subset of the interface which is known to be supported by the bsc.
320Sstevel@tonic-gate *
330Sstevel@tonic-gate * All the nodes which may be accessible through the BSC are included below
340Sstevel@tonic-gate * the SUNW,bscv node (class system-controller) in the /platform tree.
350Sstevel@tonic-gate * This plugin interrogates the BSC 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 *
400Sstevel@tonic-gate * NOTE:
410Sstevel@tonic-gate * Depends on PICL devtree plugin.
420Sstevel@tonic-gate */
430Sstevel@tonic-gate
440Sstevel@tonic-gate #include <stdio.h>
450Sstevel@tonic-gate #include <stdlib.h>
460Sstevel@tonic-gate #include <unistd.h>
470Sstevel@tonic-gate #include <fcntl.h>
480Sstevel@tonic-gate #include <alloca.h>
490Sstevel@tonic-gate #include <syslog.h>
500Sstevel@tonic-gate #include <string.h>
510Sstevel@tonic-gate #include <libintl.h>
520Sstevel@tonic-gate #include <picl.h>
530Sstevel@tonic-gate #include <picltree.h>
540Sstevel@tonic-gate #include <errno.h>
550Sstevel@tonic-gate #include <limits.h>
560Sstevel@tonic-gate #include <ctype.h>
570Sstevel@tonic-gate #include <sys/types.h>
580Sstevel@tonic-gate #include <sys/obpdefs.h>
590Sstevel@tonic-gate #include <sys/lom_io.h>
600Sstevel@tonic-gate #include <sys/systeminfo.h>
610Sstevel@tonic-gate #include <time.h>
620Sstevel@tonic-gate #include <picldefs.h>
630Sstevel@tonic-gate #include <picld_pluginutil.h>
640Sstevel@tonic-gate #include "picllom.h"
650Sstevel@tonic-gate
660Sstevel@tonic-gate static void picllom_register(void);
670Sstevel@tonic-gate static void picllom_init(void);
680Sstevel@tonic-gate static void picllom_fini(void);
690Sstevel@tonic-gate static node_el_t *create_node_el(picl_nodehdl_t nodeh);
700Sstevel@tonic-gate static void delete_node_el(node_el_t *pel);
710Sstevel@tonic-gate static node_list_t *create_node_list();
720Sstevel@tonic-gate static void delete_node_list_contents(node_list_t *pnl);
730Sstevel@tonic-gate static void delete_node_list(node_list_t *pnl);
740Sstevel@tonic-gate static void add_node_to_list(picl_nodehdl_t nodeh,
750Sstevel@tonic-gate node_list_t *listp);
760Sstevel@tonic-gate static void get_node_list_by_class(picl_nodehdl_t nodeh,
770Sstevel@tonic-gate const char *classname, node_list_t *listp);
780Sstevel@tonic-gate static int get_lom_node(picl_nodehdl_t *lominfh);
790Sstevel@tonic-gate static int get_lom_device_path(picl_nodehdl_t *lominfh);
800Sstevel@tonic-gate static int get_node_by_name_and_class(picl_nodehdl_t srchnodeh,
810Sstevel@tonic-gate const char *nodename, const char *classname, picl_nodehdl_t *chdh);
820Sstevel@tonic-gate static int add_regular_prop(picl_nodehdl_t nodeh, const char *name,
830Sstevel@tonic-gate int type, int access, int size, const void *valbuf, picl_prophdl_t *prophp);
840Sstevel@tonic-gate static int add_volatile_prop(picl_nodehdl_t nodeh, char *name,
850Sstevel@tonic-gate int type, int access, int size, ptree_vol_rdfunc_t rdfunc,
860Sstevel@tonic-gate ptree_vol_wrfunc_t wrfunc, picl_prophdl_t *prophp);
870Sstevel@tonic-gate static int open_lom_rd(int *lom_fd);
880Sstevel@tonic-gate static int get_lom_temp(int index, tempr_t *temp_p);
890Sstevel@tonic-gate static int update_voltage_stats();
900Sstevel@tonic-gate static int get_lom_volts_status(int index, int *voltsStatus_p);
910Sstevel@tonic-gate static int get_lom_volts_shutdown(int index, int *voltsShutdown_p);
920Sstevel@tonic-gate static int update_fan_stats();
930Sstevel@tonic-gate static int get_lom_fan_speed(int index, int *fan_speed);
940Sstevel@tonic-gate static int read_vol_temp(ptree_rarg_t *parg, void *buf);
950Sstevel@tonic-gate static int read_vol_volts_status(ptree_rarg_t *parg, void *buf);
960Sstevel@tonic-gate static int read_vol_volts_shutdown(ptree_rarg_t *parg, void *buf);
970Sstevel@tonic-gate static int read_fan_speed(ptree_rarg_t *parg, void *buf);
980Sstevel@tonic-gate static int read_fan_status(ptree_rarg_t *parg, void *buf);
990Sstevel@tonic-gate static int lookup_led_status(int8_t state, const char **string);
1000Sstevel@tonic-gate static int read_led_status(ptree_rarg_t *parg, void *buf);
1010Sstevel@tonic-gate static void convert_node_name(char *ptr);
1020Sstevel@tonic-gate static int add_temp_sensors(int lom_fd, picl_nodehdl_t lominfh);
1030Sstevel@tonic-gate static int add_voltage_monitors(int lom_fd,
1040Sstevel@tonic-gate picl_nodehdl_t lominfh);
1050Sstevel@tonic-gate static int add_fan_nodes(int lom_fd, picl_nodehdl_t lominfh);
1060Sstevel@tonic-gate static int get_config_file(char *outfilename);
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate #pragma init(picllom_register)
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static picld_plugin_reg_t my_reg_info = {
1110Sstevel@tonic-gate PICLD_PLUGIN_VERSION_1,
1120Sstevel@tonic-gate PICLD_PLUGIN_NON_CRITICAL,
1130Sstevel@tonic-gate "SUNW_picllom",
1140Sstevel@tonic-gate picllom_init,
1150Sstevel@tonic-gate picllom_fini
1160Sstevel@tonic-gate };
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate static const char str_OK[] = "OK";
1190Sstevel@tonic-gate static const char str_FAIL[] = "FAIL";
1200Sstevel@tonic-gate static const char str_On[] = "on";
1210Sstevel@tonic-gate static const char str_Off[] = "off";
1220Sstevel@tonic-gate static const char str_Enabled[] = "Enabled";
1230Sstevel@tonic-gate static const char str_Disabled[] = "Disabled";
1240Sstevel@tonic-gate static char lom_device_path[PATH_MAX];
1250Sstevel@tonic-gate static tempr_t high_warnings[MAX_TEMPS];
1260Sstevel@tonic-gate static tempr_t high_shutdowns[MAX_TEMPS];
1270Sstevel@tonic-gate static picl_prophdl_t temp_handles[MAX_TEMPS];
1280Sstevel@tonic-gate static lom_fandata_t fandata;
1290Sstevel@tonic-gate static picl_prophdl_t fan_speed_handles[MAX_FANS];
1300Sstevel@tonic-gate static picl_prophdl_t fan_status_handles[MAX_FANS];
1310Sstevel@tonic-gate static lom_volts_t voltsdata;
1320Sstevel@tonic-gate static picl_prophdl_t volts_status_handles[MAX_VOLTS];
1330Sstevel@tonic-gate static picl_prophdl_t volts_shutdown_handles[MAX_VOLTS];
1340Sstevel@tonic-gate static int n_leds = 0;
1350Sstevel@tonic-gate static int max_state_size = 0;
1360Sstevel@tonic-gate static picl_prophdl_t *led_handles = NULL;
1370Sstevel@tonic-gate static char **led_labels = NULL;
1380Sstevel@tonic-gate static lom2_info_t info2data;
1390Sstevel@tonic-gate static struct {
1400Sstevel@tonic-gate int size;
1410Sstevel@tonic-gate char *str_colour;
1420Sstevel@tonic-gate } colour_lkup[1 + LOM_LED_COLOUR_AMBER];
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate static struct {
1450Sstevel@tonic-gate int8_t state;
1460Sstevel@tonic-gate char *str_ledstate;
1470Sstevel@tonic-gate } ledstate_lkup[] = {
1480Sstevel@tonic-gate { LOM_LED_OFF },
1490Sstevel@tonic-gate { LOM_LED_ON },
1500Sstevel@tonic-gate { LOM_LED_BLINKING },
1510Sstevel@tonic-gate };
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate static node_el_t *
create_node_el(picl_nodehdl_t nodeh)1540Sstevel@tonic-gate create_node_el(picl_nodehdl_t nodeh)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate node_el_t *ptr = malloc(sizeof (node_el_t));
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate if (ptr != NULL) {
1590Sstevel@tonic-gate ptr->nodeh = nodeh;
1600Sstevel@tonic-gate ptr->next = NULL;
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate return (ptr);
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate static void
delete_node_el(node_el_t * pel)1670Sstevel@tonic-gate delete_node_el(node_el_t *pel)
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate free(pel);
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate static node_list_t *
create_node_list()1730Sstevel@tonic-gate create_node_list()
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate node_list_t *ptr = malloc(sizeof (node_list_t));
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate if (ptr != NULL) {
1780Sstevel@tonic-gate ptr->head = NULL;
1790Sstevel@tonic-gate ptr->tail = NULL;
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate return (ptr);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate static void
delete_node_list_contents(node_list_t * pnl)1860Sstevel@tonic-gate delete_node_list_contents(node_list_t *pnl)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate node_el_t *pel;
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate if (pnl == NULL)
1910Sstevel@tonic-gate return;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate while ((pel = pnl->head) != NULL) {
1940Sstevel@tonic-gate pnl->head = pel->next;
1950Sstevel@tonic-gate delete_node_el(pel);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate pnl->tail = NULL;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate static void
delete_node_list(node_list_t * pnl)2020Sstevel@tonic-gate delete_node_list(node_list_t *pnl)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate delete_node_list_contents(pnl);
2050Sstevel@tonic-gate free(pnl);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate * Get a linking element and add handle to end of chain
2100Sstevel@tonic-gate */
2110Sstevel@tonic-gate static void
add_node_to_list(picl_nodehdl_t nodeh,node_list_t * listp)2120Sstevel@tonic-gate add_node_to_list(picl_nodehdl_t nodeh, node_list_t *listp)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate node_el_t *pel = create_node_el(nodeh);
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate if (pel != NULL) {
2170Sstevel@tonic-gate if (listp->tail == NULL)
2180Sstevel@tonic-gate listp->head = pel;
2190Sstevel@tonic-gate else
2200Sstevel@tonic-gate listp->tail->next = pel;
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate listp->tail = pel;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /*
2270Sstevel@tonic-gate * Get a list of nodes of the specified classname under nodeh.
2280Sstevel@tonic-gate * Once a node of the specified class is found, its children are not
2290Sstevel@tonic-gate * searched.
2300Sstevel@tonic-gate */
2310Sstevel@tonic-gate static void
get_node_list_by_class(picl_nodehdl_t nodeh,const char * classname,node_list_t * listp)2320Sstevel@tonic-gate get_node_list_by_class(picl_nodehdl_t nodeh, const char *classname,
2330Sstevel@tonic-gate node_list_t *listp)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate int err;
2360Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX+1];
2370Sstevel@tonic-gate picl_nodehdl_t chdh;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate /*
2400Sstevel@tonic-gate * go through the children
2410Sstevel@tonic-gate */
2420Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
2430Sstevel@tonic-gate sizeof (picl_nodehdl_t));
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate while (err == PICL_SUCCESS) {
2460Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME,
2470Sstevel@tonic-gate clname, strlen(classname) + 1);
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate if ((err == PICL_SUCCESS) && (strcmp(clname, classname) == 0))
2500Sstevel@tonic-gate add_node_to_list(chdh, listp);
2510Sstevel@tonic-gate else
2520Sstevel@tonic-gate get_node_list_by_class(chdh, classname, listp);
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
2550Sstevel@tonic-gate sizeof (picl_nodehdl_t));
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate static int
get_lom_node(picl_nodehdl_t * lominfh)2600Sstevel@tonic-gate get_lom_node(picl_nodehdl_t *lominfh)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate int err = PICL_SUCCESS;
2630Sstevel@tonic-gate node_list_t *listp;
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate listp = create_node_list();
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate if ((err = ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM,
2680Sstevel@tonic-gate lominfh)) != PICL_SUCCESS) {
2690Sstevel@tonic-gate syslog(LOG_ERR, EM_MISSING_NODE,
2700Sstevel@tonic-gate PICL_NODE_ROOT PICL_NODE_PLATFORM);
2710Sstevel@tonic-gate return (err); /* no /platform ! */
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate get_node_list_by_class(*lominfh, PICL_CLASS_SERVICE_PROCESSOR, listp);
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate if (listp->head == NULL) {
2770Sstevel@tonic-gate *lominfh = 0;
2780Sstevel@tonic-gate syslog(LOG_ERR, EM_MISSING_NODE, PICL_CLASS_SERVICE_PROCESSOR);
2790Sstevel@tonic-gate err = PICL_NODENOTFOUND;
2800Sstevel@tonic-gate } else {
2810Sstevel@tonic-gate *lominfh = listp->head->nodeh;
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate if (listp->head != listp->tail)
2840Sstevel@tonic-gate syslog(LOG_ERR, EM_LOM_DUPLICATE);
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate delete_node_list(listp);
2880Sstevel@tonic-gate return (err);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate static int
get_lom_device_path(picl_nodehdl_t * lominfh)2920Sstevel@tonic-gate get_lom_device_path(picl_nodehdl_t *lominfh)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate int err = PICL_SUCCESS;
2950Sstevel@tonic-gate char devfs_path[PATH_MAX];
2960Sstevel@tonic-gate char devices_path[PATH_MAX];
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate err = ptree_get_propval_by_name(*lominfh, PICL_PROP_DEVFS_PATH,
299*13093SRoger.Faulkner@Oracle.COM devfs_path, sizeof (devfs_path));
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate /* Build up the full device path and set the global */
3020Sstevel@tonic-gate strcpy(devices_path, "/devices");
3030Sstevel@tonic-gate strcat(devices_path, devfs_path);
3040Sstevel@tonic-gate strcat(devices_path, LOM_DEV_MINOR_NAME);
3050Sstevel@tonic-gate strcpy(lom_device_path, devices_path);
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate return (err);
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate * Look for a node of specified name and class
3160Sstevel@tonic-gate * Confine search to nodes one level below that of supplied handle
3170Sstevel@tonic-gate */
3180Sstevel@tonic-gate static int
get_node_by_name_and_class(picl_nodehdl_t srchnodeh,const char * nodename,const char * classname,picl_nodehdl_t * chdh)3190Sstevel@tonic-gate get_node_by_name_and_class(picl_nodehdl_t srchnodeh, const char *nodename,
3200Sstevel@tonic-gate const char *classname, picl_nodehdl_t *chdh)
3210Sstevel@tonic-gate {
3220Sstevel@tonic-gate int err;
3230Sstevel@tonic-gate char namebuf[PATH_MAX];
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate err = ptree_get_propval_by_name(srchnodeh, PICL_PROP_CHILD, chdh,
3260Sstevel@tonic-gate sizeof (picl_nodehdl_t));
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate while (err == PICL_SUCCESS) {
3290Sstevel@tonic-gate err = ptree_get_propval_by_name(*chdh, PICL_PROP_NAME, namebuf,
3300Sstevel@tonic-gate sizeof (namebuf));
3310Sstevel@tonic-gate if (err != PICL_SUCCESS)
3320Sstevel@tonic-gate break;
3330Sstevel@tonic-gate if (strcmp(namebuf, nodename) == 0) {
3340Sstevel@tonic-gate err = ptree_get_propval_by_name(*chdh,
3350Sstevel@tonic-gate PICL_PROP_CLASSNAME, namebuf, sizeof (namebuf));
3360Sstevel@tonic-gate if ((err == PICL_SUCCESS) &&
3370Sstevel@tonic-gate (strcmp(namebuf, classname) == 0))
3380Sstevel@tonic-gate return (PICL_SUCCESS);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate err = ptree_get_propval_by_name(*chdh, PICL_PROP_PEER, chdh,
3410Sstevel@tonic-gate sizeof (picl_nodehdl_t));
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate return (err);
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate /*
3480Sstevel@tonic-gate * Create and add the specified regular property
3490Sstevel@tonic-gate */
3500Sstevel@tonic-gate
3510Sstevel@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)3520Sstevel@tonic-gate add_regular_prop(picl_nodehdl_t nodeh, const char *name, int type, int access,
3530Sstevel@tonic-gate int size, const void *valbuf, picl_prophdl_t *prophp)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate int err;
3560Sstevel@tonic-gate ptree_propinfo_t propinfo;
3570Sstevel@tonic-gate picl_prophdl_t proph;
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
3600Sstevel@tonic-gate type, access, size, (char *)name, NULL, NULL);
3610Sstevel@tonic-gate if (err != PICL_SUCCESS)
3620Sstevel@tonic-gate return (err);
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, (void *)valbuf,
3650Sstevel@tonic-gate &proph);
3660Sstevel@tonic-gate if (err == PICL_SUCCESS && prophp)
3670Sstevel@tonic-gate *prophp = proph;
3680Sstevel@tonic-gate return (err);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate /*
3730Sstevel@tonic-gate * Create and add the specified volatile property
3740Sstevel@tonic-gate */
3750Sstevel@tonic-gate static int
add_volatile_prop(picl_nodehdl_t nodeh,char * name,int type,int access,int size,ptree_vol_rdfunc_t rdfunc,ptree_vol_wrfunc_t wrfunc,picl_prophdl_t * prophp)3760Sstevel@tonic-gate add_volatile_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
3770Sstevel@tonic-gate int size, ptree_vol_rdfunc_t rdfunc, ptree_vol_wrfunc_t wrfunc,
3780Sstevel@tonic-gate picl_prophdl_t *prophp)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate int err;
3810Sstevel@tonic-gate ptree_propinfo_t propinfo;
3820Sstevel@tonic-gate picl_prophdl_t proph;
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
3850Sstevel@tonic-gate type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc);
3860Sstevel@tonic-gate if (err != PICL_SUCCESS)
3870Sstevel@tonic-gate return (err);
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
3900Sstevel@tonic-gate if (err == PICL_SUCCESS && prophp)
3910Sstevel@tonic-gate *prophp = proph;
3920Sstevel@tonic-gate return (err);
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /*
3960Sstevel@tonic-gate * open LOM device to read
3970Sstevel@tonic-gate */
3980Sstevel@tonic-gate static int
open_lom_rd(int * lom_fd)3990Sstevel@tonic-gate open_lom_rd(int *lom_fd)
4000Sstevel@tonic-gate {
4010Sstevel@tonic-gate *lom_fd = open(lom_device_path, O_RDONLY);
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate if (*lom_fd < 0)
4040Sstevel@tonic-gate return (PICL_FAILURE);
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate return (PICL_SUCCESS);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * Function to open LOM and read temperature sensor values.
4110Sstevel@tonic-gate * The index to a specific sensor is supplied and that value returned.
4120Sstevel@tonic-gate */
4130Sstevel@tonic-gate static int
get_lom_temp(int index,tempr_t * temp_p)4140Sstevel@tonic-gate get_lom_temp(int index, tempr_t *temp_p)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate lom_temp_t lom_temp;
4170Sstevel@tonic-gate int lom_fd;
4180Sstevel@tonic-gate int err;
4190Sstevel@tonic-gate int res;
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate err = open_lom_rd(&lom_fd);
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate if (err == PICL_SUCCESS) {
4240Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCTEMP, &lom_temp);
4250Sstevel@tonic-gate (void) close(lom_fd);
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if (res == 0) {
4280Sstevel@tonic-gate *temp_p = lom_temp.temp[index];
4290Sstevel@tonic-gate } else {
4300Sstevel@tonic-gate err = PICL_FAILURE;
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate return (err);
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * Function to open LOM and read voltage monitor values.
4390Sstevel@tonic-gate * Called for each property, so only perform update if time has changed
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate static int
update_voltage_stats()4420Sstevel@tonic-gate update_voltage_stats()
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate static time_t then = 0;
4450Sstevel@tonic-gate int lom_fd;
4460Sstevel@tonic-gate int err;
4470Sstevel@tonic-gate int res;
4480Sstevel@tonic-gate time_t now = time(NULL);
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate if (now == then)
4510Sstevel@tonic-gate return (PICL_SUCCESS);
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate then = now;
4540Sstevel@tonic-gate err = open_lom_rd(&lom_fd);
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate if (err == PICL_SUCCESS) {
4570Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCVOLTS, &voltsdata);
4580Sstevel@tonic-gate (void) close(lom_fd);
4590Sstevel@tonic-gate if (res < 0) {
4600Sstevel@tonic-gate err = PICL_FAILURE;
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate return (err);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate * Function to open LOM and read voltage monitor values.
4690Sstevel@tonic-gate * The index to a specific voltage status is supplied and that value returned.
4700Sstevel@tonic-gate */
4710Sstevel@tonic-gate static int
get_lom_volts_status(int index,int * voltsStatus_p)4720Sstevel@tonic-gate get_lom_volts_status(int index, int *voltsStatus_p)
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate int res;
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate if ((res = update_voltage_stats()) != PICL_SUCCESS)
4770Sstevel@tonic-gate return (res);
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate *voltsStatus_p = voltsdata.status[index];
4800Sstevel@tonic-gate return (PICL_SUCCESS);
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate * Function to open LOM and read voltage monitor values.
4850Sstevel@tonic-gate * The index to a specific shutdown flag is supplied and that value returned.
4860Sstevel@tonic-gate */
4870Sstevel@tonic-gate static int
get_lom_volts_shutdown(int index,int * voltsShutdown_p)4880Sstevel@tonic-gate get_lom_volts_shutdown(int index, int *voltsShutdown_p)
4890Sstevel@tonic-gate {
4900Sstevel@tonic-gate int res;
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate if ((res = update_voltage_stats()) != PICL_SUCCESS)
4930Sstevel@tonic-gate return (res);
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate *voltsShutdown_p = voltsdata.shutdown_enabled[index];
4960Sstevel@tonic-gate return (PICL_SUCCESS);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate /*
5020Sstevel@tonic-gate * Function to open LOM and read fan values.
5030Sstevel@tonic-gate * Called for each property, so only perform update if time has changed
5040Sstevel@tonic-gate */
5050Sstevel@tonic-gate static int
update_fan_stats()5060Sstevel@tonic-gate update_fan_stats()
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate static time_t then = 0;
5090Sstevel@tonic-gate int lom_fd;
5100Sstevel@tonic-gate int err;
5110Sstevel@tonic-gate int res;
5120Sstevel@tonic-gate time_t now = time(NULL);
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate if (now == then)
5150Sstevel@tonic-gate return (PICL_SUCCESS);
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate then = now;
5180Sstevel@tonic-gate err = open_lom_rd(&lom_fd);
5190Sstevel@tonic-gate if (err == PICL_SUCCESS) {
5200Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCFANSTATE, &fandata);
5210Sstevel@tonic-gate (void) close(lom_fd);
5220Sstevel@tonic-gate if (res < 0) {
5230Sstevel@tonic-gate err = PICL_FAILURE;
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate return (err);
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate /*
5330Sstevel@tonic-gate * The index to a specific fan is supplied and its speed value returned.
5340Sstevel@tonic-gate */
5350Sstevel@tonic-gate static int
get_lom_fan_speed(int index,int * fan_speed)5360Sstevel@tonic-gate get_lom_fan_speed(int index, int *fan_speed)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate int res;
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate if ((res = update_fan_stats()) != PICL_SUCCESS)
5410Sstevel@tonic-gate return (res);
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate *fan_speed = fandata.speed[index];
5440Sstevel@tonic-gate return (PICL_SUCCESS);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate /*
5490Sstevel@tonic-gate * Read function for volatile "Temperature" property via LOM
5500Sstevel@tonic-gate */
5510Sstevel@tonic-gate static int
read_vol_temp(ptree_rarg_t * parg,void * buf)5520Sstevel@tonic-gate read_vol_temp(ptree_rarg_t *parg, void *buf)
5530Sstevel@tonic-gate {
5540Sstevel@tonic-gate tempr_t temp;
5550Sstevel@tonic-gate picl_prophdl_t proph;
5560Sstevel@tonic-gate int index;
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate /*
5590Sstevel@tonic-gate * get the sensor index from the displacement of the
5600Sstevel@tonic-gate * property handle and get its temperature.
5610Sstevel@tonic-gate */
5620Sstevel@tonic-gate proph = parg->proph;
5630Sstevel@tonic-gate for (index = 0; index < MAX_TEMPS; index++) {
5640Sstevel@tonic-gate if (temp_handles[index] == proph)
5650Sstevel@tonic-gate break;
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate if (index == MAX_TEMPS) {
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate * Handle not found. As this is a plugin, stale handles
5710Sstevel@tonic-gate * cannot occur, so just fail.
5720Sstevel@tonic-gate */
5730Sstevel@tonic-gate return (PICL_FAILURE);
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate if (get_lom_temp(index, &temp) != PICL_SUCCESS)
5770Sstevel@tonic-gate return (PICL_FAILURE);
5780Sstevel@tonic-gate (void) memcpy(buf, (caddr_t)&temp, sizeof (tempr_t));
5790Sstevel@tonic-gate return (PICL_SUCCESS);
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate /*
5830Sstevel@tonic-gate * Read function for volatile "VoltageStatus" property via LOM
5840Sstevel@tonic-gate */
5850Sstevel@tonic-gate static int
read_vol_volts_status(ptree_rarg_t * parg,void * buf)5860Sstevel@tonic-gate read_vol_volts_status(ptree_rarg_t *parg, void *buf)
5870Sstevel@tonic-gate {
5880Sstevel@tonic-gate int voltsStatus;
5890Sstevel@tonic-gate picl_prophdl_t proph;
5900Sstevel@tonic-gate int index;
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate /*
5930Sstevel@tonic-gate * get the voltage monitor index from the displacement of the
5940Sstevel@tonic-gate * status property handle and get its status.
5950Sstevel@tonic-gate */
5960Sstevel@tonic-gate proph = parg->proph;
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate for (index = 0; index < MAX_VOLTS; index++) {
5990Sstevel@tonic-gate if (volts_status_handles[index] == proph)
6000Sstevel@tonic-gate break;
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate if (index == MAX_VOLTS)
6040Sstevel@tonic-gate return (PICL_FAILURE);
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate if (get_lom_volts_status(index, &voltsStatus) != PICL_SUCCESS)
6070Sstevel@tonic-gate return (PICL_FAILURE);
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate (void) strlcpy(buf, (voltsStatus == 0) ? str_OK : str_FAIL,
6100Sstevel@tonic-gate sizeof (str_FAIL));
6110Sstevel@tonic-gate return (PICL_SUCCESS);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate /*
6150Sstevel@tonic-gate * Read function for volatile "VoltageShutdown" property via LOM
6160Sstevel@tonic-gate */
6170Sstevel@tonic-gate static int
read_vol_volts_shutdown(ptree_rarg_t * parg,void * buf)6180Sstevel@tonic-gate read_vol_volts_shutdown(ptree_rarg_t *parg, void *buf)
6190Sstevel@tonic-gate {
6200Sstevel@tonic-gate int voltsShutdown;
6210Sstevel@tonic-gate picl_prophdl_t proph;
6220Sstevel@tonic-gate int index;
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate /*
6250Sstevel@tonic-gate * get the voltage monitor index from the displacement of the
6260Sstevel@tonic-gate * shutdown property handle and get its value.
6270Sstevel@tonic-gate */
6280Sstevel@tonic-gate proph = parg->proph;
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate for (index = 0; index < MAX_VOLTS; index++) {
6310Sstevel@tonic-gate if (volts_shutdown_handles[index] == proph)
6320Sstevel@tonic-gate break;
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate if (index == MAX_VOLTS)
6360Sstevel@tonic-gate return (PICL_FAILURE);
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate if (get_lom_volts_shutdown(index, &voltsShutdown) != PICL_SUCCESS)
6390Sstevel@tonic-gate return (PICL_FAILURE);
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate (void) strlcpy(buf, (voltsShutdown == 0) ? str_Disabled : str_Enabled,
6420Sstevel@tonic-gate sizeof (str_Disabled));
6430Sstevel@tonic-gate return (PICL_SUCCESS);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate /*
6480Sstevel@tonic-gate * Read function for volatile fan speed property via LOM
6490Sstevel@tonic-gate */
6500Sstevel@tonic-gate static int
read_fan_speed(ptree_rarg_t * parg,void * buf)6510Sstevel@tonic-gate read_fan_speed(ptree_rarg_t *parg, void *buf)
6520Sstevel@tonic-gate {
6530Sstevel@tonic-gate int fan_speed;
6540Sstevel@tonic-gate picl_prophdl_t proph;
6550Sstevel@tonic-gate int index;
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate * get the relevant fan from the displacement of its property handle
6590Sstevel@tonic-gate */
6600Sstevel@tonic-gate proph = parg->proph;
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate for (index = 0; index < MAX_FANS; index++) {
6630Sstevel@tonic-gate if (fan_speed_handles[index] == proph)
6640Sstevel@tonic-gate break;
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate if (index == MAX_FANS)
6680Sstevel@tonic-gate return (PICL_FAILURE);
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate if (get_lom_fan_speed(index, &fan_speed) != PICL_SUCCESS)
6710Sstevel@tonic-gate return (PICL_FAILURE);
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate (void) memcpy(buf, (caddr_t)&fan_speed, sizeof (fan_speed));
6740Sstevel@tonic-gate return (PICL_SUCCESS);
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate /*
6780Sstevel@tonic-gate * look up function to convert led status into string
6790Sstevel@tonic-gate */
6800Sstevel@tonic-gate static int
lookup_led_status(int8_t state,const char ** string)6810Sstevel@tonic-gate lookup_led_status(int8_t state, const char **string)
6820Sstevel@tonic-gate {
6830Sstevel@tonic-gate int i;
6840Sstevel@tonic-gate int lim = sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0]);
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate for (i = 0; i < lim; i++) {
6870Sstevel@tonic-gate if (ledstate_lkup[i].state == state) {
6880Sstevel@tonic-gate *string = ledstate_lkup[i].str_ledstate;
6890Sstevel@tonic-gate return (PICL_SUCCESS);
6900Sstevel@tonic-gate }
6910Sstevel@tonic-gate }
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate *string = "";
6940Sstevel@tonic-gate switch (state) {
6950Sstevel@tonic-gate case LOM_LED_ACCESS_ERROR:
6960Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE);
6970Sstevel@tonic-gate case LOM_LED_NOT_IMPLEMENTED:
6980Sstevel@tonic-gate /*FALLTHROUGH*/
6990Sstevel@tonic-gate case LOM_LED_OUTOFRANGE:
7000Sstevel@tonic-gate /*FALLTHROUGH*/
7010Sstevel@tonic-gate default:
7020Sstevel@tonic-gate return (PICL_FAILURE);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate /*
7070Sstevel@tonic-gate * Read function for volatile led status property.
7080Sstevel@tonic-gate */
7090Sstevel@tonic-gate static int
read_led_status(ptree_rarg_t * parg,void * buf)7100Sstevel@tonic-gate read_led_status(ptree_rarg_t *parg, void *buf)
7110Sstevel@tonic-gate {
7120Sstevel@tonic-gate lom_led_state_t led_data;
7130Sstevel@tonic-gate picl_prophdl_t proph;
7140Sstevel@tonic-gate int index;
7150Sstevel@tonic-gate int lom_fd;
7160Sstevel@tonic-gate int res;
7170Sstevel@tonic-gate const char *string;
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate /*
7200Sstevel@tonic-gate * get the relevant led from the displacement of its property handle
7210Sstevel@tonic-gate */
7220Sstevel@tonic-gate proph = parg->proph;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate for (index = 0; index < n_leds; index++) {
7250Sstevel@tonic-gate if (led_handles[index] == proph)
7260Sstevel@tonic-gate break;
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate if (index == n_leds)
7300Sstevel@tonic-gate return (PICL_FAILURE);
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate res = open_lom_rd(&lom_fd);
7330Sstevel@tonic-gate if (res != PICL_SUCCESS)
7340Sstevel@tonic-gate return (res);
7350Sstevel@tonic-gate /*
7360Sstevel@tonic-gate * The interface for reading LED status doesn't promise to maintain
7370Sstevel@tonic-gate * a constant mapping between LED index number and LED identity
7380Sstevel@tonic-gate * (as defined by its label). On the other hand, PICL does promise
7390Sstevel@tonic-gate * that whilst a handle remains valid the object it represents will
7400Sstevel@tonic-gate * remain constant. To reconcile these positions, we maintain
7410Sstevel@tonic-gate * tables of labels and handles linked by index value. We search
7420Sstevel@tonic-gate * for the handle with which we are presented and then locate its
7430Sstevel@tonic-gate * label. Then we request LED entries from the LOM and compare their
7440Sstevel@tonic-gate * labels with the one we seek. As an optimisation, we try the original
7450Sstevel@tonic-gate * index value first and then revert to a full search.
7460Sstevel@tonic-gate */
7470Sstevel@tonic-gate (void) memset(&led_data, 0, sizeof (led_data));
7480Sstevel@tonic-gate led_data.index = index;
7490Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCLEDSTATE, &led_data);
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate if (res != 0 || led_data.state == LOM_LED_NOT_IMPLEMENTED ||
7520Sstevel@tonic-gate strcmp(led_data.label, led_labels[index]) != 0) {
7530Sstevel@tonic-gate /*
7540Sstevel@tonic-gate * full scan required (bet it doesn't work!)
7550Sstevel@tonic-gate * first re-establish the range to scan
7560Sstevel@tonic-gate */
7570Sstevel@tonic-gate int i;
7580Sstevel@tonic-gate int n;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate (void) memset(&led_data, 0, sizeof (led_data));
7610Sstevel@tonic-gate led_data.index = -1;
7620Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCLEDSTATE, &led_data);
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate if (res != 0) {
7650Sstevel@tonic-gate (void) close(lom_fd);
7660Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate if (led_data.state == LOM_LED_NOT_IMPLEMENTED ||
7700Sstevel@tonic-gate strcmp(led_data.label, led_labels[index]) != 0) {
7710Sstevel@tonic-gate n = led_data.index;
7720Sstevel@tonic-gate for (i = 0; i < n; i++) {
7730Sstevel@tonic-gate (void) memset(&led_data, 0, sizeof (led_data));
7740Sstevel@tonic-gate led_data.index = i;
7750Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCLEDSTATE, &led_data);
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate if (res == 0 &&
7780Sstevel@tonic-gate led_data.state != LOM_LED_NOT_IMPLEMENTED ||
7790Sstevel@tonic-gate strcmp(led_data.label, led_labels[index]) ==
7800Sstevel@tonic-gate 0) {
7810Sstevel@tonic-gate break;
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate if (i == n) {
7860Sstevel@tonic-gate (void) close(lom_fd);
7870Sstevel@tonic-gate return (PICL_PROPVALUNAVAILABLE);
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate
7920Sstevel@tonic-gate /*
7930Sstevel@tonic-gate * if we get here, then we found the right LED.
7940Sstevel@tonic-gate */
7950Sstevel@tonic-gate (void) close(lom_fd);
7960Sstevel@tonic-gate res = lookup_led_status(led_data.state, &string);
7970Sstevel@tonic-gate (void) strlcpy(buf, string, max_state_size);
7980Sstevel@tonic-gate return (res);
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate /*
8020Sstevel@tonic-gate * Read function for volatile fan status property.
8030Sstevel@tonic-gate * This is a synthesized property using speed and min speed properties
8040Sstevel@tonic-gate */
8050Sstevel@tonic-gate static int
read_fan_status(ptree_rarg_t * parg,void * buf)8060Sstevel@tonic-gate read_fan_status(ptree_rarg_t *parg, void *buf)
8070Sstevel@tonic-gate {
8080Sstevel@tonic-gate int fan_speed;
8090Sstevel@tonic-gate picl_prophdl_t proph;
8100Sstevel@tonic-gate int index;
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate /*
8130Sstevel@tonic-gate * get the relevant fan from the displacement of its property handle
8140Sstevel@tonic-gate */
8150Sstevel@tonic-gate proph = parg->proph;
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate for (index = 0; index < MAX_FANS; index++) {
8180Sstevel@tonic-gate if (fan_status_handles[index] == proph)
8190Sstevel@tonic-gate break;
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate if (index == MAX_FANS)
8230Sstevel@tonic-gate return (PICL_FAILURE);
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate if (get_lom_fan_speed(index, &fan_speed) != PICL_SUCCESS)
8260Sstevel@tonic-gate return (PICL_FAILURE);
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate (void) strlcpy(buf,
8290Sstevel@tonic-gate fan_speed < fandata.minspeed[index] ? str_FAIL : str_OK,
8300Sstevel@tonic-gate sizeof (str_FAIL));
8310Sstevel@tonic-gate return (PICL_SUCCESS);
8320Sstevel@tonic-gate }
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate /*
8370Sstevel@tonic-gate * change to lower case and convert any spaces into hyphens
8380Sstevel@tonic-gate */
8390Sstevel@tonic-gate static void
convert_node_name(char * ptr)8400Sstevel@tonic-gate convert_node_name(char *ptr)
8410Sstevel@tonic-gate {
8420Sstevel@tonic-gate char ch;
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate for (ch = *ptr; ch != '\0'; ch = *++ptr) {
8450Sstevel@tonic-gate if (isupper(ch)) {
8460Sstevel@tonic-gate *ptr = tolower(ch);
8470Sstevel@tonic-gate } else if (isspace(ch)) {
8480Sstevel@tonic-gate *ptr = '-';
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate static int
add_temp_sensors(int lom_fd,picl_nodehdl_t lominfh)8540Sstevel@tonic-gate add_temp_sensors(int lom_fd, picl_nodehdl_t lominfh)
8550Sstevel@tonic-gate {
8560Sstevel@tonic-gate lom_temp_t lom_temp;
8570Sstevel@tonic-gate int res;
8580Sstevel@tonic-gate int i;
8590Sstevel@tonic-gate int err = PICL_SUCCESS;
8600Sstevel@tonic-gate const char *cptr;
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCTEMP, &lom_temp);
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate if ((res == 0) && (lom_temp.num > 0)) {
8650Sstevel@tonic-gate /*
8660Sstevel@tonic-gate * for each temperature location add a sensor node
8670Sstevel@tonic-gate */
8680Sstevel@tonic-gate for (i = 0; i < lom_temp.num; i++) {
8690Sstevel@tonic-gate picl_nodehdl_t tempsensh;
8700Sstevel@tonic-gate picl_prophdl_t proph;
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate high_warnings[i] = lom_temp.warning[i];
8730Sstevel@tonic-gate high_shutdowns[i] = lom_temp.shutdown[i];
8740Sstevel@tonic-gate
8750Sstevel@tonic-gate convert_node_name(lom_temp.name[i]);
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate err = ptree_create_node(lom_temp.name[i],
8780Sstevel@tonic-gate PICL_CLASS_TEMPERATURE_SENSOR, &tempsensh);
8790Sstevel@tonic-gate if (err != PICL_SUCCESS)
8800Sstevel@tonic-gate break;
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate err = add_volatile_prop(tempsensh,
8830Sstevel@tonic-gate PICL_PROP_TEMPERATURE, PICL_PTYPE_INT, PICL_READ,
8840Sstevel@tonic-gate sizeof (tempr_t), read_vol_temp, NULL,
8850Sstevel@tonic-gate &temp_handles[i]);
8860Sstevel@tonic-gate if (err != PICL_SUCCESS)
8870Sstevel@tonic-gate break;
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate if (high_warnings[i] != 0) {
8900Sstevel@tonic-gate err = add_regular_prop(
8910Sstevel@tonic-gate tempsensh, PICL_PROP_HIGH_WARNING,
8920Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ,
8930Sstevel@tonic-gate sizeof (tempr_t), &high_warnings[i],
8940Sstevel@tonic-gate &proph);
8950Sstevel@tonic-gate if (err != PICL_SUCCESS)
8960Sstevel@tonic-gate break;
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate if (high_shutdowns[i] != 0) {
9000Sstevel@tonic-gate err = add_regular_prop(
9010Sstevel@tonic-gate tempsensh, PICL_PROP_HIGH_SHUTDOWN,
9020Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ,
9030Sstevel@tonic-gate sizeof (tempr_t), &high_shutdowns[i],
9040Sstevel@tonic-gate &proph);
9050Sstevel@tonic-gate if (err != PICL_SUCCESS)
9060Sstevel@tonic-gate break;
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate
9090Sstevel@tonic-gate /*
9100Sstevel@tonic-gate * for the benefit of prtdiag, add a label of
9110Sstevel@tonic-gate * either enclosure or die where appropriate
9120Sstevel@tonic-gate */
9130Sstevel@tonic-gate if ((strcasestr(lom_temp.name[i], CPU_ENCLOSURE) !=
9140Sstevel@tonic-gate NULL) ||
9150Sstevel@tonic-gate (strcasestr(lom_temp.name[i], CPU_AMBIENT) !=
9160Sstevel@tonic-gate NULL)) {
9170Sstevel@tonic-gate cptr = CPU_AMBIENT;
9180Sstevel@tonic-gate } else if ((cptr = strcasestr(lom_temp.name[i],
9190Sstevel@tonic-gate CPU_DIE)) != NULL) {
9200Sstevel@tonic-gate cptr = CPU_DIE;
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate if (cptr != NULL) {
9240Sstevel@tonic-gate err = add_regular_prop(
9250Sstevel@tonic-gate tempsensh, PICL_PROP_LABEL,
9260Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ,
9270Sstevel@tonic-gate strlen(cptr) + 1, cptr, &proph);
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9300Sstevel@tonic-gate break;
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate err = ptree_add_node(lominfh, tempsensh);
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate if (err != PICL_SUCCESS)
9370Sstevel@tonic-gate break;
9380Sstevel@tonic-gate }
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9410Sstevel@tonic-gate syslog(LOG_ERR, EM_LOMINFO_TREE_FAILED);
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate return (err);
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate static int
add_voltage_monitors(int lom_fd,picl_nodehdl_t lominfh)9490Sstevel@tonic-gate add_voltage_monitors(int lom_fd, picl_nodehdl_t lominfh)
9500Sstevel@tonic-gate {
9510Sstevel@tonic-gate int res;
9520Sstevel@tonic-gate int i;
9530Sstevel@tonic-gate int err = PICL_SUCCESS;
9540Sstevel@tonic-gate picl_prophdl_t proph;
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCVOLTS, &voltsdata);
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate if ((res == 0) && (voltsdata.num > 0)) {
9590Sstevel@tonic-gate /*
9600Sstevel@tonic-gate * for each voltage monitor add a monitor node
9610Sstevel@tonic-gate */
9620Sstevel@tonic-gate for (i = 0; i < voltsdata.num; i++) {
9630Sstevel@tonic-gate picl_nodehdl_t voltsmonh;
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate convert_node_name(voltsdata.name[i]);
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate err = ptree_create_node(voltsdata.name[i],
9680Sstevel@tonic-gate PICL_CLASS_VOLTAGE_INDICATOR, &voltsmonh);
9690Sstevel@tonic-gate if (err != PICL_SUCCESS)
9700Sstevel@tonic-gate break;
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate err = add_regular_prop(voltsmonh, PICL_PROP_LABEL,
9730Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ,
9740Sstevel@tonic-gate strlen(voltsdata.name[i]) + 1,
9750Sstevel@tonic-gate voltsdata.name[i], &proph);
9760Sstevel@tonic-gate if (err != PICL_SUCCESS)
9770Sstevel@tonic-gate break;
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate err = add_volatile_prop(voltsmonh, PICL_VOLTS_SHUTDOWN,
9800Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ,
9810Sstevel@tonic-gate sizeof (str_Disabled), read_vol_volts_shutdown,
9820Sstevel@tonic-gate NULL, &volts_shutdown_handles[i]);
9830Sstevel@tonic-gate if (err != PICL_SUCCESS)
9840Sstevel@tonic-gate break;
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate err = add_volatile_prop(voltsmonh, PICL_PROP_CONDITION,
9870Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ,
9880Sstevel@tonic-gate sizeof (str_FAIL), read_vol_volts_status, NULL,
9890Sstevel@tonic-gate &volts_status_handles[i]);
9900Sstevel@tonic-gate if (err != PICL_SUCCESS)
9910Sstevel@tonic-gate break;
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate err = ptree_add_node(lominfh, voltsmonh);
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate if (err != PICL_SUCCESS)
9960Sstevel@tonic-gate break;
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate
9990Sstevel@tonic-gate if (err != PICL_SUCCESS) {
10000Sstevel@tonic-gate syslog(LOG_ERR, EM_LOMINFO_TREE_FAILED);
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate return (err);
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate static void
add_led(const lom_led_state_t * led_state,picl_nodehdl_t lominfh)10080Sstevel@tonic-gate add_led(const lom_led_state_t *led_state, picl_nodehdl_t lominfh)
10090Sstevel@tonic-gate {
10100Sstevel@tonic-gate int err;
10110Sstevel@tonic-gate picl_nodehdl_t ledh;
10120Sstevel@tonic-gate picl_nodehdl_t proph;
10130Sstevel@tonic-gate
1014796Smathue if (((unsigned char)led_state->state == LOM_LED_STATE_NOT_PRESENT) ||
10150Sstevel@tonic-gate (led_state->label[0] == '\0')) {
10160Sstevel@tonic-gate return;
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate err = ptree_create_node(led_state->label, PICL_CLASS_LED, &ledh);
10200Sstevel@tonic-gate /*
10210Sstevel@tonic-gate * the led may exist already, e.g. Fault
10220Sstevel@tonic-gate */
10230Sstevel@tonic-gate if (err != PICL_SUCCESS)
10240Sstevel@tonic-gate return;
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate /*
10270Sstevel@tonic-gate * Unlike LEDs derived from other interfaces, these are not
10280Sstevel@tonic-gate * writable. Establish a read-only volatile property.
10290Sstevel@tonic-gate */
10300Sstevel@tonic-gate err = add_volatile_prop(ledh, PICL_PROP_STATE, PICL_PTYPE_CHARSTRING,
10310Sstevel@tonic-gate PICL_READ, max_state_size, read_led_status, NULL,
10320Sstevel@tonic-gate &led_handles[led_state->index]);
10330Sstevel@tonic-gate if (err != PICL_SUCCESS)
10340Sstevel@tonic-gate return;
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate /*
10370Sstevel@tonic-gate * if colour was defined for this LED, add a colour property
10380Sstevel@tonic-gate */
10390Sstevel@tonic-gate if ((led_state->colour != LOM_LED_COLOUR_NONE) &&
10400Sstevel@tonic-gate (led_state->colour != LOM_LED_COLOUR_ANY)) {
1041*13093SRoger.Faulkner@Oracle.COM err = add_regular_prop(ledh, PICL_PROP_COLOR,
1042*13093SRoger.Faulkner@Oracle.COM PICL_PTYPE_CHARSTRING, PICL_READ,
1043*13093SRoger.Faulkner@Oracle.COM colour_lkup[led_state->index].size,
1044*13093SRoger.Faulkner@Oracle.COM colour_lkup[led_state->index].str_colour, &proph);
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate if (err != PICL_SUCCESS)
10470Sstevel@tonic-gate return;
10480Sstevel@tonic-gate
10490Sstevel@tonic-gate err = add_regular_prop(ledh, PICL_PROP_LABEL,
10500Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(led_state->label) + 1,
10510Sstevel@tonic-gate led_state->label, &proph);
10520Sstevel@tonic-gate if (err != PICL_SUCCESS)
10530Sstevel@tonic-gate return;
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate err = ptree_add_node(lominfh, ledh);
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate if (err != PICL_SUCCESS) {
10580Sstevel@tonic-gate syslog(LOG_ERR, EM_LOMINFO_TREE_FAILED);
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate
10620Sstevel@tonic-gate static void
fixstate(uint8_t state,const char * string,int * max_len)10630Sstevel@tonic-gate fixstate(uint8_t state, const char *string, int *max_len)
10640Sstevel@tonic-gate {
10650Sstevel@tonic-gate int i;
10660Sstevel@tonic-gate int len;
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate for (i = 0; i < (sizeof (ledstate_lkup) / sizeof (ledstate_lkup[0]));
10690Sstevel@tonic-gate i++) {
10700Sstevel@tonic-gate if (ledstate_lkup[i].state == state) {
10710Sstevel@tonic-gate if (ledstate_lkup[i].str_ledstate != NULL)
10720Sstevel@tonic-gate free(ledstate_lkup[i].str_ledstate);
10730Sstevel@tonic-gate ledstate_lkup[i].str_ledstate = strdup(string);
10740Sstevel@tonic-gate len = strlen(string);
10750Sstevel@tonic-gate if (len >= *max_len)
10760Sstevel@tonic-gate *max_len = len + 1;
10770Sstevel@tonic-gate break;
10780Sstevel@tonic-gate }
10790Sstevel@tonic-gate }
10800Sstevel@tonic-gate }
10810Sstevel@tonic-gate
10820Sstevel@tonic-gate static void
add_led_nodes(int lom_fd,picl_nodehdl_t lominfh)10830Sstevel@tonic-gate add_led_nodes(int lom_fd, picl_nodehdl_t lominfh)
10840Sstevel@tonic-gate {
10850Sstevel@tonic-gate lom_led_state_t led_data;
10860Sstevel@tonic-gate picl_nodehdl_t ledh;
10870Sstevel@tonic-gate int res;
10880Sstevel@tonic-gate int i;
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /*
10910Sstevel@tonic-gate * If the led state enquiry ioctl is supported, an enquiry on
10920Sstevel@tonic-gate * index -1 will return the state of the highest supported index
10930Sstevel@tonic-gate * value.
10940Sstevel@tonic-gate */
10950Sstevel@tonic-gate (void) memset(&led_data, 0, sizeof (led_data));
10960Sstevel@tonic-gate led_data.index = -1;
10970Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCLEDSTATE, &led_data);
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate if (res != 0)
11000Sstevel@tonic-gate return;
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate if (led_labels != NULL) {
11030Sstevel@tonic-gate for (i = 0; i < n_leds; i++) {
11040Sstevel@tonic-gate if (led_labels[i] != NULL) {
11050Sstevel@tonic-gate free(led_labels[i]);
11060Sstevel@tonic-gate }
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate free(led_labels);
11100Sstevel@tonic-gate led_labels = NULL;
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate
11130Sstevel@tonic-gate if (led_handles != NULL) {
11140Sstevel@tonic-gate free(led_handles);
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate n_leds = 0;
11180Sstevel@tonic-gate led_handles = calloc(led_data.index + 1, sizeof (picl_nodehdl_t));
11190Sstevel@tonic-gate led_labels = calloc(led_data.index + 1, sizeof (char *));
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate if ((led_labels == NULL) || (led_handles == NULL)) {
11220Sstevel@tonic-gate if (led_labels != NULL)
11230Sstevel@tonic-gate free(led_labels);
11240Sstevel@tonic-gate if (led_handles != NULL)
11250Sstevel@tonic-gate free(led_handles);
11260Sstevel@tonic-gate led_labels = NULL;
11270Sstevel@tonic-gate led_handles = NULL;
11280Sstevel@tonic-gate syslog(LOG_ERR, EM_NO_LED_MEM);
11290Sstevel@tonic-gate return;
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate n_leds = led_data.index + 1;
11330Sstevel@tonic-gate
11340Sstevel@tonic-gate /*
11350Sstevel@tonic-gate * For each LED with a valid state, add a node
11360Sstevel@tonic-gate * and because of the ludicrous API, stache a copy of its label too
11370Sstevel@tonic-gate */
11380Sstevel@tonic-gate for (i = 0; i < n_leds; i++) {
11390Sstevel@tonic-gate (void) memset(&led_data, 0, sizeof (led_data));
11400Sstevel@tonic-gate led_data.index = i;
11410Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCLEDSTATE, &led_data);
11420Sstevel@tonic-gate
11430Sstevel@tonic-gate if (res != 0)
11440Sstevel@tonic-gate continue;
11450Sstevel@tonic-gate
11460Sstevel@tonic-gate if (led_data.state == LOM_LED_OUTOFRANGE ||
11470Sstevel@tonic-gate led_data.state == LOM_LED_NOT_IMPLEMENTED)
11480Sstevel@tonic-gate continue;
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate led_labels[i] = strdup(led_data.label);
11520Sstevel@tonic-gate convert_node_name(led_data.label);
11530Sstevel@tonic-gate
11540Sstevel@tonic-gate if (get_node_by_name_and_class(lominfh, led_data.label,
11550Sstevel@tonic-gate "led", &ledh) != PICL_SUCCESS) {
11560Sstevel@tonic-gate /*
11570Sstevel@tonic-gate * only add a new led node,
11580Sstevel@tonic-gate * if it's not already in place
11590Sstevel@tonic-gate */
11600Sstevel@tonic-gate add_led(&led_data, lominfh);
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate }
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate static int
add_fan_nodes(int lom_fd,picl_nodehdl_t lominfh)11660Sstevel@tonic-gate add_fan_nodes(int lom_fd, picl_nodehdl_t lominfh)
11670Sstevel@tonic-gate {
11680Sstevel@tonic-gate int res;
11690Sstevel@tonic-gate int i;
11700Sstevel@tonic-gate int err = PICL_SUCCESS;
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate res = ioctl(lom_fd, LOMIOCFANSTATE, &fandata);
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate if (res == 0) {
11750Sstevel@tonic-gate /*
11760Sstevel@tonic-gate * fan data available through lom, remove any placeholder
11770Sstevel@tonic-gate * fan-unit nodes, they will be superseded via lom.conf
11780Sstevel@tonic-gate */
11790Sstevel@tonic-gate char path[80];
11800Sstevel@tonic-gate int slot;
11810Sstevel@tonic-gate picl_nodehdl_t fan_unit_h;
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate for (slot = 0; slot < MAX_FANS; slot++) {
11840Sstevel@tonic-gate (void) snprintf(path, sizeof (path),
11850Sstevel@tonic-gate "/frutree/chassis/fan-slot?Slot=%d/fan-unit", slot);
11860Sstevel@tonic-gate if (ptree_get_node_by_path(path, &fan_unit_h) !=
11870Sstevel@tonic-gate PICL_SUCCESS)
11880Sstevel@tonic-gate continue;
11890Sstevel@tonic-gate if (ptree_delete_node(fan_unit_h) != PICL_SUCCESS)
11900Sstevel@tonic-gate continue;
11910Sstevel@tonic-gate (void) ptree_destroy_node(fan_unit_h);
11920Sstevel@tonic-gate }
11930Sstevel@tonic-gate /*
11940Sstevel@tonic-gate * see if fan names can be obtained
11950Sstevel@tonic-gate */
11960Sstevel@tonic-gate (void) memset(&info2data, 0, sizeof (info2data));
11970Sstevel@tonic-gate /*
11980Sstevel@tonic-gate * if LOMIOCINFO2 not supported, names area
11990Sstevel@tonic-gate * will remain empty
12000Sstevel@tonic-gate */
12010Sstevel@tonic-gate (void) ioctl(lom_fd, LOMIOCINFO2, &info2data);
12020Sstevel@tonic-gate
12030Sstevel@tonic-gate /*
12040Sstevel@tonic-gate * for each fan which is present, add a fan node
12050Sstevel@tonic-gate */
12060Sstevel@tonic-gate for (i = 0; i < MAX_FANS; i++) {
12070Sstevel@tonic-gate char fanname[80];
12080Sstevel@tonic-gate picl_nodehdl_t fanh;
12090Sstevel@tonic-gate picl_nodehdl_t proph;
12100Sstevel@tonic-gate
12110Sstevel@tonic-gate if (fandata.fitted[i] == 0)
12120Sstevel@tonic-gate continue;
12130Sstevel@tonic-gate
12140Sstevel@tonic-gate if (info2data.fan_names[i][0] == '\0') {
12150Sstevel@tonic-gate (void) snprintf(fanname, sizeof (fanname),
12160Sstevel@tonic-gate "fan%d", i + 1);
12170Sstevel@tonic-gate } else {
12180Sstevel@tonic-gate (void) strlcpy(fanname, info2data.fan_names[i],
12190Sstevel@tonic-gate sizeof (fanname));
12200Sstevel@tonic-gate }
12210Sstevel@tonic-gate convert_node_name(fanname);
12220Sstevel@tonic-gate err = ptree_create_node(fanname, PICL_CLASS_FAN, &fanh);
12230Sstevel@tonic-gate if (err != PICL_SUCCESS)
12240Sstevel@tonic-gate break;
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate err = add_volatile_prop(fanh, PICL_PROP_FAN_SPEED,
12270Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (int),
12280Sstevel@tonic-gate read_fan_speed, NULL, &fan_speed_handles[i]);
12290Sstevel@tonic-gate if (err != PICL_SUCCESS)
12300Sstevel@tonic-gate break;
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate err = add_regular_prop(fanh, PICL_PROP_LOW_WARNING,
12330Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (int),
12340Sstevel@tonic-gate &fandata.minspeed[i], &proph);
12350Sstevel@tonic-gate if (err != PICL_SUCCESS)
12360Sstevel@tonic-gate break;
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate err = add_regular_prop(fanh, PICL_PROP_FAN_SPEED_UNIT,
12390Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, sizeof ("%"),
12400Sstevel@tonic-gate "%", &proph);
12410Sstevel@tonic-gate if (err != PICL_SUCCESS)
12420Sstevel@tonic-gate break;
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate err = add_volatile_prop(fanh, PICL_PROP_CONDITION,
12450Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ,
12460Sstevel@tonic-gate sizeof (str_FAIL), read_fan_status, NULL,
12470Sstevel@tonic-gate &fan_status_handles[i]);
12480Sstevel@tonic-gate if (err != PICL_SUCCESS)
12490Sstevel@tonic-gate break;
12500Sstevel@tonic-gate
12510Sstevel@tonic-gate /*
12520Sstevel@tonic-gate * add a label for prtdiag
12530Sstevel@tonic-gate */
12540Sstevel@tonic-gate err = add_regular_prop(fanh, PICL_PROP_LABEL,
12550Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ,
12560Sstevel@tonic-gate strlen(fanname) + 1, fanname, &proph);
12570Sstevel@tonic-gate if (err != PICL_SUCCESS)
12580Sstevel@tonic-gate break;
12590Sstevel@tonic-gate
12600Sstevel@tonic-gate err = ptree_add_node(lominfh, fanh);
12610Sstevel@tonic-gate if (err != PICL_SUCCESS)
12620Sstevel@tonic-gate break;
12630Sstevel@tonic-gate }
12640Sstevel@tonic-gate
12650Sstevel@tonic-gate if (err != PICL_SUCCESS) {
12660Sstevel@tonic-gate syslog(LOG_ERR, EM_LOMINFO_TREE_FAILED);
12670Sstevel@tonic-gate }
12680Sstevel@tonic-gate }
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate return (err);
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate
12730Sstevel@tonic-gate static void
setup_strings()12740Sstevel@tonic-gate setup_strings()
12750Sstevel@tonic-gate {
12760Sstevel@tonic-gate /*
12770Sstevel@tonic-gate * initialise led colours lookup
12780Sstevel@tonic-gate */
12790Sstevel@tonic-gate int i;
12800Sstevel@tonic-gate int lim = sizeof (colour_lkup) / sizeof (colour_lkup[0]);
12810Sstevel@tonic-gate
12820Sstevel@tonic-gate for (i = 0; i < lim; i++) {
12830Sstevel@tonic-gate if (colour_lkup[i].str_colour != NULL)
12840Sstevel@tonic-gate free(colour_lkup[i].str_colour);
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate colour_lkup[LOM_LED_COLOUR_ANY].str_colour = strdup(gettext("any"));
12880Sstevel@tonic-gate colour_lkup[LOM_LED_COLOUR_WHITE].str_colour = strdup(gettext("white"));
12890Sstevel@tonic-gate colour_lkup[LOM_LED_COLOUR_BLUE].str_colour = strdup(gettext("blue"));
12900Sstevel@tonic-gate colour_lkup[LOM_LED_COLOUR_GREEN].str_colour = strdup(gettext("green"));
12910Sstevel@tonic-gate colour_lkup[LOM_LED_COLOUR_AMBER].str_colour = strdup(gettext("amber"));
12920Sstevel@tonic-gate
12930Sstevel@tonic-gate for (i = 0; i < lim; i++) {
12940Sstevel@tonic-gate if (colour_lkup[i].str_colour != NULL)
12950Sstevel@tonic-gate colour_lkup[i].size =
12960Sstevel@tonic-gate 1 + strlen(colour_lkup[i].str_colour);
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate /*
13000Sstevel@tonic-gate * initialise led state lookup strings
13010Sstevel@tonic-gate */
13020Sstevel@tonic-gate fixstate(LOM_LED_OFF, gettext("off"), &max_state_size);
13030Sstevel@tonic-gate fixstate(LOM_LED_ON, gettext("on"), &max_state_size);
13040Sstevel@tonic-gate fixstate(LOM_LED_BLINKING, gettext("blinking"), &max_state_size);
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate /*
13080Sstevel@tonic-gate * The size of outfilename must be PATH_MAX
13090Sstevel@tonic-gate */
13100Sstevel@tonic-gate static int
get_config_file(char * outfilename)13110Sstevel@tonic-gate get_config_file(char *outfilename)
13120Sstevel@tonic-gate {
13130Sstevel@tonic-gate char nmbuf[SYS_NMLN];
13140Sstevel@tonic-gate char pname[PATH_MAX];
13150Sstevel@tonic-gate
13160Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
13170Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
13180Sstevel@tonic-gate (void) strlcat(pname, LOM_CONFFILE_NAME, PATH_MAX);
13190Sstevel@tonic-gate if (access(pname, R_OK) == 0) {
13200Sstevel@tonic-gate (void) strlcpy(outfilename, pname, PATH_MAX);
13210Sstevel@tonic-gate return (0);
13220Sstevel@tonic-gate }
13230Sstevel@tonic-gate }
13240Sstevel@tonic-gate
13250Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
13260Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
13270Sstevel@tonic-gate (void) strlcat(pname, LOM_CONFFILE_NAME, PATH_MAX);
13280Sstevel@tonic-gate if (access(pname, R_OK) == 0) {
13290Sstevel@tonic-gate (void) strlcpy(outfilename, pname, PATH_MAX);
13300Sstevel@tonic-gate return (0);
13310Sstevel@tonic-gate }
13320Sstevel@tonic-gate }
13330Sstevel@tonic-gate
13340Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
13350Sstevel@tonic-gate LOM_CONFFILE_NAME);
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate if (access(pname, R_OK) == 0) {
13380Sstevel@tonic-gate (void) strlcpy(outfilename, pname, PATH_MAX);
13390Sstevel@tonic-gate return (0);
13400Sstevel@tonic-gate }
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate return (-1);
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate
13470Sstevel@tonic-gate /*
13480Sstevel@tonic-gate * executed as part of .init when the plugin is dlopen()ed
13490Sstevel@tonic-gate */
13500Sstevel@tonic-gate static void
picllom_register(void)13510Sstevel@tonic-gate picllom_register(void)
13520Sstevel@tonic-gate {
13530Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info);
13540Sstevel@tonic-gate }
13550Sstevel@tonic-gate
13560Sstevel@tonic-gate /*
13570Sstevel@tonic-gate * Init entry point of the plugin
13580Sstevel@tonic-gate * Creates the PICL nodes and properties in the physical and logical aspects.
13590Sstevel@tonic-gate */
13600Sstevel@tonic-gate static void
picllom_init(void)13610Sstevel@tonic-gate picllom_init(void)
13620Sstevel@tonic-gate {
13630Sstevel@tonic-gate picl_nodehdl_t rooth;
13640Sstevel@tonic-gate picl_nodehdl_t plfh;
13650Sstevel@tonic-gate picl_nodehdl_t lominfh;
13660Sstevel@tonic-gate int lom_fd;
13670Sstevel@tonic-gate char fullfilename[PATH_MAX];
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate /*
13700Sstevel@tonic-gate * Get platform node
13710Sstevel@tonic-gate */
13720Sstevel@tonic-gate if (ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM, &plfh)
13730Sstevel@tonic-gate != PICL_SUCCESS) {
13740Sstevel@tonic-gate syslog(LOG_ERR, EM_MISSING_NODE, PICL_NODE_PLATFORM);
13750Sstevel@tonic-gate syslog(LOG_ERR, EM_INIT_FAILED);
13760Sstevel@tonic-gate return;
13770Sstevel@tonic-gate }
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate /*
13800Sstevel@tonic-gate * Get lom node
13810Sstevel@tonic-gate */
13820Sstevel@tonic-gate if (get_lom_node(&lominfh) != PICL_SUCCESS) {
13830Sstevel@tonic-gate syslog(LOG_ERR, EM_LOM_NODE_MISSING);
13840Sstevel@tonic-gate syslog(LOG_ERR, EM_INIT_FAILED);
13850Sstevel@tonic-gate return;
13860Sstevel@tonic-gate }
13870Sstevel@tonic-gate
13880Sstevel@tonic-gate /*
13890Sstevel@tonic-gate * Retrive the device path to open
13900Sstevel@tonic-gate */
13910Sstevel@tonic-gate if (get_lom_device_path(&lominfh) < 0) {
13920Sstevel@tonic-gate syslog(LOG_ERR, EM_INIT_FAILED);
13930Sstevel@tonic-gate return;
13940Sstevel@tonic-gate }
13950Sstevel@tonic-gate
13960Sstevel@tonic-gate /*
13970Sstevel@tonic-gate * Open LOM device and interrogate for devices it monitors
13980Sstevel@tonic-gate */
13990Sstevel@tonic-gate if ((lom_fd = open(lom_device_path, O_RDONLY)) < 0) {
14000Sstevel@tonic-gate syslog(LOG_ERR, EM_SYS_ERR, lom_device_path, strerror(errno));
14010Sstevel@tonic-gate return;
14020Sstevel@tonic-gate }
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate setup_strings();
14050Sstevel@tonic-gate (void) add_temp_sensors(lom_fd, lominfh);
14060Sstevel@tonic-gate (void) add_voltage_monitors(lom_fd, lominfh);
14070Sstevel@tonic-gate (void) add_fan_nodes(lom_fd, lominfh);
14080Sstevel@tonic-gate add_led_nodes(lom_fd, lominfh);
14090Sstevel@tonic-gate
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate if (get_config_file(fullfilename) < 0) {
14120Sstevel@tonic-gate (void) close(lom_fd);
14130Sstevel@tonic-gate syslog(LOG_ERR, EM_NO_CONFIG);
14140Sstevel@tonic-gate return;
14150Sstevel@tonic-gate }
14160Sstevel@tonic-gate
14170Sstevel@tonic-gate if (ptree_get_root(&rooth) != PICL_SUCCESS) {
14180Sstevel@tonic-gate (void) close(lom_fd);
14190Sstevel@tonic-gate return;
14200Sstevel@tonic-gate }
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate if (picld_pluginutil_parse_config_file(rooth, fullfilename) !=
14230Sstevel@tonic-gate PICL_SUCCESS)
14240Sstevel@tonic-gate syslog(LOG_ERR, EM_INIT_FAILED);
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate (void) close(lom_fd);
14270Sstevel@tonic-gate }
14280Sstevel@tonic-gate
14290Sstevel@tonic-gate /*
14300Sstevel@tonic-gate * fini entry point of the plugin
14310Sstevel@tonic-gate */
14320Sstevel@tonic-gate static void
picllom_fini(void)14330Sstevel@tonic-gate picllom_fini(void)
14340Sstevel@tonic-gate {
14350Sstevel@tonic-gate }
1436