4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This plugin creates PICL nodes and properties for objects handled through
31 * the enhanced LOMV system-processor interface.
33 * All the nodes which may be accessible through the system-processor are
34 * included below the service-processor node in the /platform tree.
35 * This plugin interrogates the system-processor to determine which of
36 * those nodes are actually available. Properties are added to such nodes and
37 * in the case of volatile properties like temperature, a call-back function
38 * is established for on-demand access to the current value.
39 * LEDs for which the system-processor provides write access are associated
40 * with read/write volatile properties.
43 * Depends on PICL devtree plugin.
56 #include <libnvpair.h>
60 #include <sys/types.h>
62 #include <sys/obpdefs.h>
63 #include <sys/envmon.h>
64 #include <sys/systeminfo.h>
68 #include <picld_pluginutil.h>
69 #include <libdevinfo.h>
70 #include "piclenvmon.h"
72 static void piclenvmon_register(void);
73 static void piclenvmon_init(void);
74 static void piclenvmon_fini(void);
75 static node_el_t
*create_node_el(picl_nodehdl_t nodeh
);
76 static void delete_node_el(node_el_t
*pel
);
77 static node_list_t
*create_node_list();
78 static void delete_node_list(node_list_t
*pnl
);
79 static void add_node_to_list(picl_nodehdl_t nodeh
, node_list_t
*listp
);
80 static void get_node_list_by_class(picl_nodehdl_t nodeh
,
81 const char *classname
, node_list_t
*listp
);
82 static int get_envmon_limits(int envmon_fd
, envmon_sysinfo_t
*limits_p
);
83 static void create_arrays();
84 static int get_envmon_node(picl_nodehdl_t
*envmoninfh
);
85 static char *create_envmon_pathname(picl_nodehdl_t envmoninfh
);
86 static int get_child_by_name(picl_nodehdl_t nodeh
, const char *name
,
87 picl_nodehdl_t
*childh
);
88 static int add_regular_prop(picl_nodehdl_t nodeh
, const char *name
,
89 int type
, int access
, int size
, const void *valbuf
, picl_prophdl_t
*prophp
);
90 static int add_volatile_prop(picl_nodehdl_t nodeh
, const char *name
,
91 int type
, int access
, int size
, ptree_vol_rdfunc_t rdfunc
,
92 ptree_vol_wrfunc_t wrfunc
, picl_prophdl_t
*prophp
);
93 static int get_sensor_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
94 envmon_thresholds_t
*lows
, envmon_thresholds_t
*highs
, int16_t *value
);
95 static int get_indicator_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
97 static int get_fan_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
98 envmon_thresholds_t
*lows
, uint16_t *speed
, char *units
);
99 static int get_led_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
100 int8_t *state
, int8_t *colour
);
101 static int get_keyswitch_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
102 envmon_keysw_pos_t
*key_state
);
103 static void convert_node_name(char *ptr
);
104 static void convert_label_name(char *ptr
);
105 static int add_value_prop(picl_nodehdl_t node_hdl
, const char *prop_name
,
106 int fru_type
, int16_t value
);
107 static int find_picl_handle(picl_prophdl_t proph
);
108 static int lookup_led_status(int8_t state
, const char **string
);
109 static int lookup_key_posn(envmon_keysw_pos_t pos
, const char **string
);
110 static int get_config_file(char *filename
);
111 static int read_vol_data(ptree_rarg_t
*r_arg
, void *buf
);
112 static int write_led_data(ptree_warg_t
*w_arg
, const void *buf
);
113 static int add_env_nodes(int envmon_fd
, uint8_t fru_type
,
114 picl_nodehdl_t envmonh
);
115 static void fixstate(uint8_t state
, const char *string
, int *max_len
);
116 static void fixkeyposn(envmon_keysw_pos_t keyposn
, const char *string
,
118 static void setup_strings();
119 static void free_vol_prop(picl_prophdl_t proph
);
120 static void envmon_evhandler(const char *ename
, const void *earg
,
121 size_t size
, void *cookie
);
122 static int get_serial_num(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
123 envmon_chassis_t
*chassis
);
125 #pragma init(piclenvmon_register)
127 static picld_plugin_reg_t my_reg_info
= {
128 PICLD_PLUGIN_VERSION_1
,
129 PICLD_PLUGIN_NON_CRITICAL
,
135 static const char str_On
[] = "on";
136 static const char str_Off
[] = "off";
137 static const char str_Blinking
[] = "blinking";
138 static const char str_Flashing
[] = "flashing";
139 static const char str_SC
[] = "SC";
140 static char *envmon_device_name
= NULL
;
141 static envmon_sysinfo_t env_limits
;
142 static handle_array_t handle_arr
;
146 } colour_lkup
[1 + ENVMON_LED_CLR_RED
];
151 } ledstate_lkup
[] = {
154 { ENVMON_LED_BLINKING
},
155 { ENVMON_LED_FLASHING
}
159 envmon_keysw_pos_t pos
;
162 { ENVMON_KEYSW_POS_UNKNOWN
},
163 { ENVMON_KEYSW_POS_NORMAL
},
164 { ENVMON_KEYSW_POS_DIAG
},
165 { ENVMON_KEYSW_POS_LOCKED
},
166 { ENVMON_KEYSW_POS_OFF
}
170 * fru-type to ioctl cmd lookup
183 ENVMONIOCCHASSISSERIALNUM
187 * fru-type to PICL CLASS
189 const char *fru_to_class
[] = {
190 PICL_CLASS_VOLTAGE_SENSOR
,
191 PICL_CLASS_VOLTAGE_INDICATOR
,
192 PICL_CLASS_CURRENT_SENSOR
,
193 PICL_CLASS_CURRENT_INDICATOR
,
194 PICL_CLASS_TEMPERATURE_SENSOR
,
195 PICL_CLASS_TEMPERATURE_INDICATOR
,
199 PICL_CLASS_KEYSWITCH
,
200 PICL_CLASS_CHASSIS_SERIAL_NUM
204 * fru-type to PICL PROPERTY for volatile data
206 const char *fru_to_prop
[] = {
211 PICL_PROP_TEMPERATURE
,
214 PICL_PROP_FAN_SPEED_UNIT
,
217 PICL_PROP_SERIAL_NUMBER
221 * fru-type to PICL PTYPE
223 int fru_to_ptype
[] = {
225 PICL_PTYPE_CHARSTRING
,
227 PICL_PTYPE_CHARSTRING
,
229 PICL_PTYPE_CHARSTRING
,
230 PICL_PTYPE_UNSIGNED_INT
,
231 PICL_PTYPE_CHARSTRING
,
232 PICL_PTYPE_CHARSTRING
,
233 PICL_PTYPE_CHARSTRING
,
234 PICL_PTYPE_CHARSTRING
240 static char *cond_okay
;
241 static char *cond_failed
;
244 * fru-type to size of volatile property
245 * the -1's are replaced by the max size of a condition string
247 int fru_to_size
[] = {
248 4, -1, 4, -1, 2, -1, 2, -1, -1, -1, -1
252 create_node_el(picl_nodehdl_t nodeh
)
254 node_el_t
*ptr
= malloc(sizeof (node_el_t
));
265 delete_node_el(node_el_t
*pel
)
273 node_list_t
*ptr
= malloc(sizeof (node_list_t
));
284 delete_node_list(node_list_t
*pnl
)
291 while ((pel
= pnl
->head
) != NULL
) {
292 pnl
->head
= pel
->next
;
297 * normally pnl->tail would be to NULL next,
298 * but as it is about to be freed, this step can be skipped.
304 * Get a linking element and add handle to end of chain
307 add_node_to_list(picl_nodehdl_t nodeh
, node_list_t
*listp
)
309 node_el_t
*pel
= create_node_el(nodeh
);
312 if (listp
->tail
== NULL
)
315 listp
->tail
->next
= pel
;
322 * Get a list of nodes of the specified classname under nodeh.
323 * Once a node of the specified class is found, its children are not
327 get_node_list_by_class(picl_nodehdl_t nodeh
, const char *classname
,
331 char clname
[PICL_CLASSNAMELEN_MAX
+1];
335 * go through the children
337 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_CHILD
, &chdh
,
338 sizeof (picl_nodehdl_t
));
340 while (err
== PICL_SUCCESS
) {
341 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_CLASSNAME
,
342 clname
, strlen(classname
) + 1);
344 if ((err
== PICL_SUCCESS
) && (strcmp(clname
, classname
) == 0))
345 add_node_to_list(chdh
, listp
);
347 get_node_list_by_class(chdh
, classname
, listp
);
349 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
350 sizeof (picl_nodehdl_t
));
355 get_envmon_limits(int envmon_fd
, envmon_sysinfo_t
*limits_p
)
357 return (ioctl(envmon_fd
, ENVMONIOCSYSINFO
, limits_p
));
361 re_create_arrays(int envmon_fd
)
363 envmon_sysinfo_t new_limits
;
367 envmon_handle_t
*envhandles
;
368 picl_prophdl_t
*piclprhdls
;
370 res
= get_envmon_limits(envmon_fd
, &new_limits
);
374 maxnum
= new_limits
.maxVoltSens
+ new_limits
.maxVoltInd
+
375 new_limits
.maxAmpSens
+ new_limits
.maxAmpInd
+
376 new_limits
.maxTempSens
+ new_limits
.maxTempInd
+
377 new_limits
.maxFanSens
+ new_limits
.maxFanInd
+
378 new_limits
.maxLED
+ N_KEY_SWITCHES
;
380 if (maxnum
!= handle_arr
.maxnum
) {
382 * space requirements have changed
384 fru_types
= calloc(maxnum
, sizeof (uchar_t
));
385 envhandles
= calloc(maxnum
, sizeof (envmon_handle_t
));
386 piclprhdls
= calloc(maxnum
, sizeof (picl_prophdl_t
));
387 if ((fru_types
== NULL
) || (envhandles
== NULL
) ||
388 (piclprhdls
== NULL
)) {
394 free(handle_arr
.fru_types
);
395 handle_arr
.fru_types
= fru_types
;
396 free(handle_arr
.envhandles
);
397 handle_arr
.envhandles
= envhandles
;
398 free(handle_arr
.piclprhdls
);
399 handle_arr
.piclprhdls
= piclprhdls
;
401 (void) memset(handle_arr
.fru_types
, 0,
402 maxnum
* sizeof (uchar_t
));
403 (void) memset(handle_arr
.envhandles
, 0,
404 maxnum
* sizeof (envmon_handle_t
));
405 (void) memset(handle_arr
.piclprhdls
, 0,
406 maxnum
* sizeof (picl_prophdl_t
));
410 handle_arr
.maxnum
= maxnum
;
411 env_limits
= new_limits
;
418 int maxnum
= env_limits
.maxVoltSens
+ env_limits
.maxVoltInd
+
419 env_limits
.maxAmpSens
+ env_limits
.maxAmpInd
+
420 env_limits
.maxTempSens
+ env_limits
.maxTempInd
+
421 env_limits
.maxFanSens
+ env_limits
.maxFanInd
+
422 env_limits
.maxLED
+ N_KEY_SWITCHES
;
423 handle_arr
.maxnum
= maxnum
;
425 handle_arr
.fru_types
= calloc(maxnum
, sizeof (uchar_t
));
426 handle_arr
.envhandles
= calloc(maxnum
, sizeof (envmon_handle_t
));
427 handle_arr
.piclprhdls
= calloc(maxnum
, sizeof (picl_prophdl_t
));
431 get_envmon_node(picl_nodehdl_t
*envmoninfh
)
433 int err
= PICL_SUCCESS
;
436 listp
= create_node_list();
438 if ((err
= ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM
,
439 envmoninfh
)) != PICL_SUCCESS
) {
440 syslog(LOG_ERR
, EM_MISSING_NODE
,
441 PICL_NODE_ROOT PICL_NODE_PLATFORM
);
442 return (err
); /* no /platform ! */
445 get_node_list_by_class(*envmoninfh
, PICL_CLASS_SERVICE_PROCESSOR
,
448 if (listp
->head
== NULL
) {
450 syslog(LOG_ERR
, EM_MISSING_NODE
, PICL_CLASS_SERVICE_PROCESSOR
);
451 err
= PICL_NODENOTFOUND
;
453 *envmoninfh
= listp
->head
->nodeh
;
456 delete_node_list(listp
);
461 create_envmon_pathname(picl_nodehdl_t envmoninfh
)
464 char namebuf
[PATH_MAX
];
470 /* prefix devfs-path name with /devices */
471 (void) strlcpy(namebuf
, "/devices", PATH_MAX
);
474 * append devfs-path property
476 len
= strlen(namebuf
);
477 if (ptree_get_propval_by_name(envmoninfh
, PICL_PROP_DEVFS_PATH
,
478 namebuf
+ len
, sizeof (namebuf
) - len
) != PICL_SUCCESS
) {
479 syslog(LOG_ERR
, EM_SC_NODE_INCOMPLETE
);
483 /* locate final component of name */
484 ptr
= strrchr(namebuf
, '/');
487 *ptr
= '\0'; /* terminate at end of directory path */
488 len
= strlen(ptr
+ 1); /* length of terminal name */
489 dirp
= opendir(namebuf
);
491 syslog(LOG_ERR
, EM_SC_NODE_MISSING
);
494 *ptr
++ = '/'; /* restore '/' and advance to final name */
496 while ((dp
= readdir(dirp
)) != NULL
) {
498 * look for a name which starts with the string at *ptr
500 if (strlen(dp
->d_name
) < len
)
501 continue; /* skip short names */
502 if (strncmp(dp
->d_name
, ptr
, len
) == 0) {
504 * Got a match, restore full pathname and stat the
505 * entry. Reject if not a char device
507 (void) strlcpy(ptr
, dp
->d_name
,
508 sizeof (namebuf
) - (ptr
- namebuf
));
509 if (stat(namebuf
, &statbuf
) < 0)
510 continue; /* reject if can't stat it */
511 if (!S_ISCHR(statbuf
.st_mode
))
512 continue; /* not a character device */
516 (void) closedir(dirp
);
517 return (strdup(namebuf
));
520 syslog(LOG_ERR
, EM_SC_NODE_MISSING
);
521 (void) closedir(dirp
);
526 * look for named node as child of supplied handle
529 get_child_by_name(picl_nodehdl_t nodeh
, const char *name
,
530 picl_nodehdl_t
*childh
)
533 char node_name
[ENVMON_MAXNAMELEN
];
535 if (strlen(name
) >= ENVMON_MAXNAMELEN
)
536 return (PICL_NODENOTFOUND
);
537 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_CHILD
, childh
,
539 while (err
== PICL_SUCCESS
) {
540 err
= ptree_get_propval_by_name(*childh
, PICL_PROP_NAME
,
541 node_name
, sizeof (node_name
));
542 if ((err
== PICL_SUCCESS
) &&
543 (strncmp(name
, node_name
, ENVMON_MAXNAMELEN
) == 0))
544 return (PICL_SUCCESS
);
545 err
= ptree_get_propval_by_name(*childh
, PICL_PROP_PEER
,
546 childh
, sizeof (*childh
));
552 * Create and add the specified regular property
555 add_regular_prop(picl_nodehdl_t nodeh
, const char *name
, int type
, int access
,
556 int size
, const void *valbuf
, picl_prophdl_t
*prophp
)
559 ptree_propinfo_t propinfo
;
560 picl_prophdl_t proph
;
562 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
563 type
, access
, size
, (char *)name
, NULL
, NULL
);
564 if (err
!= PICL_SUCCESS
)
567 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, (void *)valbuf
,
569 if (err
== PICL_SUCCESS
&& prophp
)
576 * Create and add the specified volatile property
579 add_volatile_prop(picl_nodehdl_t nodeh
, const char *name
, int type
, int access
,
580 int size
, ptree_vol_rdfunc_t rdfunc
, ptree_vol_wrfunc_t wrfunc
,
581 picl_prophdl_t
*prophp
)
584 ptree_propinfo_t propinfo
;
585 picl_prophdl_t proph
;
587 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
588 type
, (access
|PICL_VOLATILE
), size
, (char *)name
, rdfunc
, wrfunc
);
589 if (err
!= PICL_SUCCESS
)
592 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, &proph
);
593 if (err
== PICL_SUCCESS
&& prophp
)
599 * There are 5 different structures used for reading environmental data
600 * from the service-processor. A different function is used for each one.
601 * Some functions cover several ioctls, so the desired ioctl is part of
602 * the interface. In each case the id parameter is read/write, the
603 * returned value being the next id for this fru type.
607 * Function to read sensor data.
610 get_sensor_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
611 envmon_thresholds_t
*lows
, envmon_thresholds_t
*highs
, int16_t *value
)
614 envmon_sensor_t data
;
616 (void) memset(&data
, 0, sizeof (data
));
618 res
= ioctl(envmon_fd
, cmd
, &data
);
620 return (PICL_NOTREADABLE
);
625 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
626 return (PICL_INVALIDHANDLE
);
629 * it is assumed that threshold data will be available,
630 * even though the current sensor value may be inaccessible
633 *lows
= data
.lowthresholds
;
635 *highs
= data
.highthresholds
;
637 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
639 *value
= ENVMON_VAL_UNAVAILABLE
;
640 return (PICL_PROPVALUNAVAILABLE
);
644 return (PICL_SUCCESS
);
648 * Function to read indicator data.
651 get_indicator_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
655 envmon_indicator_t data
;
658 res
= ioctl(envmon_fd
, cmd
, &data
);
660 return (PICL_NOTREADABLE
);
662 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
663 return (PICL_INVALIDHANDLE
);
664 if (condition
!= NULL
)
665 *condition
= data
.condition
;
666 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
667 return (PICL_PROPVALUNAVAILABLE
);
669 return (PICL_SUCCESS
);
673 * Function to read fan data.
676 get_fan_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
677 envmon_thresholds_t
*lows
, uint16_t *speed
, char *units
)
683 res
= ioctl(envmon_fd
, cmd
, &data
);
685 return (PICL_NOTREADABLE
);
687 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
688 return (PICL_INVALIDHANDLE
);
690 *lows
= data
.lowthresholds
;
692 (void) strlcpy(units
, data
.units
, sizeof (data
.units
));
694 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
696 *speed
= ENVMON_VAL_UNAVAILABLE
;
697 return (PICL_PROPVALUNAVAILABLE
);
701 return (PICL_SUCCESS
);
705 * Function to read LED data.
708 get_led_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
709 int8_t *state
, int8_t *colour
)
712 envmon_led_info_t data
;
715 res
= ioctl(envmon_fd
, cmd
, &data
);
717 return (PICL_NOTREADABLE
);
719 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
720 return (PICL_INVALIDHANDLE
);
722 *colour
= data
.led_color
;
723 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
724 return (PICL_PROPVALUNAVAILABLE
);
727 *state
= data
.led_state
;
728 return (PICL_SUCCESS
);
732 * Function to read key-switch position
733 * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails)
736 get_keyswitch_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
737 envmon_keysw_pos_t
*key_state
)
741 if (id
->name
[0] == '\0') {
742 (void) strlcpy(id
->name
, KEYSWITCH_NAME
, sizeof (id
->name
));
743 return (PICL_INVALIDHANDLE
);
744 } else if (strncmp(id
->name
, KEYSWITCH_NAME
, sizeof (id
->name
)) != 0) {
746 return (PICL_INVALIDHANDLE
);
748 res
= ioctl(envmon_fd
, cmd
, key_state
);
752 return (PICL_INVALIDHANDLE
);
753 return (PICL_SUCCESS
);
758 * Function to read the chassis serial number
759 * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails)
762 get_serial_num(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
763 envmon_chassis_t
*chassis
)
767 if (id
->name
[0] == '\0') {
768 (void) strlcpy(id
->name
, CHASSIS_SERIAL_NUMBER
,
770 return (PICL_INVALIDHANDLE
);
771 } else if (strncmp(id
->name
, CHASSIS_SERIAL_NUMBER
, sizeof (id
->name
))
774 return (PICL_INVALIDHANDLE
);
776 res
= ioctl(envmon_fd
, cmd
, chassis
);
780 return (PICL_INVALIDHANDLE
);
781 return (PICL_SUCCESS
);
786 * change to lower case and convert any spaces into hyphens,
787 * and any dots or colons symbols into underscores
790 convert_node_name(char *ptr
)
794 for (ch
= *ptr
; ch
!= '\0'; ch
= *++ptr
) {
797 } else if (isspace(ch
)) {
799 } else if ((ch
== '.') || (ch
== ':')) {
806 * strip to the last '.' separator and keep the rest
807 * change ':' to '/' within the last component
810 convert_label_name(char *name
)
815 cptr
= strrchr(name
, '.');
820 cptr
++; /* skip the '.' */
829 } while (ch
!= '\0');
833 * add a value property
836 add_value_prop(picl_nodehdl_t node_hdl
, const char *prop_name
, int fru_type
,
845 if (fru_to_ptype
[fru_type
] == PICL_PTYPE_FLOAT
)
846 val_buf
.u_f
= (float)((float)value
/ (float)1000.0);
848 val_buf
.u_i16
= value
;
850 err
= add_regular_prop(node_hdl
, prop_name
, fru_to_ptype
[fru_type
],
851 PICL_READ
, fru_to_size
[fru_type
], &val_buf
, NULL
);
856 find_picl_handle(picl_prophdl_t proph
)
860 for (index
= 0; index
< handle_arr
.num
; index
++) {
861 if (handle_arr
.piclprhdls
[index
] == proph
)
869 * look up function to convert led status into string
872 lookup_led_status(int8_t state
, const char **string
)
875 int lim
= sizeof (ledstate_lkup
) / sizeof (ledstate_lkup
[0]);
877 for (i
= 0; i
< lim
; i
++) {
878 if (ledstate_lkup
[i
].state
== state
) {
879 *string
= ledstate_lkup
[i
].str_ledstate
;
880 return (PICL_SUCCESS
);
885 return (PICL_PROPVALUNAVAILABLE
);
889 lookup_key_posn(envmon_keysw_pos_t pos
, const char **string
)
892 int lim
= sizeof (keyposn_lkup
) / sizeof (keyposn_lkup
[0]);
894 for (i
= 0; i
< lim
; i
++) {
895 if (keyposn_lkup
[i
].pos
== pos
) {
896 *string
= keyposn_lkup
[i
].str_keyposn
;
897 return (PICL_SUCCESS
);
902 return (PICL_PROPVALUNAVAILABLE
);
906 * function to read volatile data associated with a PICL property handle
909 read_vol_data(ptree_rarg_t
*r_arg
, void *buf
)
911 picl_prophdl_t proph
;
917 envmon_keysw_pos_t key_posn
;
918 envmon_chassis_t chassis
;
925 proph
= r_arg
->proph
;
926 index
= find_picl_handle(proph
);
928 return (PICL_INVALIDHANDLE
);
929 fru_type
= handle_arr
.fru_types
[index
];
930 id
= handle_arr
.envhandles
[index
];
931 cmd
= fru_to_cmd
[fru_type
];
932 envmon_fd
= open(envmon_device_name
, O_RDONLY
);
934 return (PICL_NOTREADABLE
);
937 * read environmental data according to type
940 case ENVMON_VOLT_SENS
:
942 case ENVMON_AMP_SENS
:
944 case ENVMON_TEMP_SENS
:
945 err
= get_sensor_data(envmon_fd
, &id
, cmd
, NULL
, NULL
,
948 case ENVMON_VOLT_IND
:
952 case ENVMON_TEMP_IND
:
955 err
= get_indicator_data(envmon_fd
, &id
, cmd
, &sensor_data
);
957 case ENVMON_FAN_SENS
:
958 err
= get_fan_data(envmon_fd
, &id
, cmd
, NULL
,
959 (uint16_t *)&sensor_data
, NULL
);
962 err
= get_led_data(envmon_fd
, &id
, cmd
, &led_state
, NULL
);
964 case ENVMON_KEY_SWITCH
:
965 err
= get_keyswitch_data(envmon_fd
, &id
, cmd
, &key_posn
);
968 err
= get_serial_num(envmon_fd
, &id
, cmd
, &chassis
);
975 (void) close(envmon_fd
);
976 if (err
!= PICL_SUCCESS
) {
978 * PICL_INVALIDHANDLE is used internally, but it upsets
979 * prtpicl; change it to PICL_PROPVALUNAVAILABLE
981 if (err
== PICL_INVALIDHANDLE
)
982 err
= PICL_PROPVALUNAVAILABLE
;
987 * convert data and copy out
990 case ENVMON_VOLT_SENS
:
992 case ENVMON_AMP_SENS
:
993 float_data
= (float)((float)sensor_data
/ (float)1000.0);
994 (void) memcpy(buf
, &float_data
, sizeof (float_data
));
997 case ENVMON_TEMP_SENS
:
999 case ENVMON_FAN_SENS
:
1000 (void) memcpy(buf
, &sensor_data
, sizeof (sensor_data
));
1003 case ENVMON_VOLT_IND
:
1005 case ENVMON_AMP_IND
:
1007 case ENVMON_TEMP_IND
:
1009 case ENVMON_FAN_IND
:
1010 (void) strlcpy(buf
, sensor_data
== 0 ? cond_okay
: cond_failed
,
1011 fru_to_size
[fru_type
]);
1014 case ENVMON_LED_IND
:
1015 err
= lookup_led_status(led_state
, &cptr
);
1016 if (err
!= PICL_SUCCESS
)
1018 (void) strlcpy(buf
, cptr
, fru_to_size
[fru_type
]);
1021 case ENVMON_KEY_SWITCH
:
1022 err
= lookup_key_posn(key_posn
, &cptr
);
1023 if (err
!= PICL_SUCCESS
)
1025 (void) strlcpy(buf
, cptr
, fru_to_size
[fru_type
]);
1027 case ENVMON_CHASSIS
:
1028 (void) memcpy(buf
, chassis
.serial_number
,
1029 sizeof (chassis
.serial_number
));
1033 return (PICL_FAILURE
);
1036 return (PICL_SUCCESS
);
1040 write_led_data(ptree_warg_t
*w_arg
, const void *buf
)
1042 picl_prophdl_t proph
;
1047 envmon_led_ctl_t led_ctl
;
1049 proph
= w_arg
->proph
;
1050 index
= find_picl_handle(proph
);
1052 return (PICL_INVALIDHANDLE
);
1053 fru_type
= handle_arr
.fru_types
[index
];
1054 if (fru_type
!= ENVMON_LED_IND
)
1055 return (PICL_INVALIDARG
);
1056 if (w_arg
->cred
.dc_euid
!= SUPER_USER
)
1057 return (PICL_PERMDENIED
);
1059 /* see if the requested state is recognized */
1060 if (strcasecmp(str_Off
, buf
) == 0)
1061 led_ctl
.led_state
= ENVMON_LED_OFF
;
1062 else if (strcasecmp(str_On
, buf
) == 0)
1063 led_ctl
.led_state
= ENVMON_LED_ON
;
1064 else if (strcasecmp(str_Blinking
, buf
) == 0)
1065 led_ctl
.led_state
= ENVMON_LED_BLINKING
;
1066 else if (strcasecmp(str_Flashing
, buf
) == 0)
1067 led_ctl
.led_state
= ENVMON_LED_FLASHING
;
1069 return (PICL_INVALIDARG
);
1071 envmon_fd
= open(envmon_device_name
, O_RDWR
);
1073 return (PICL_FAILURE
);
1074 led_ctl
.id
= handle_arr
.envhandles
[index
];
1075 err
= ioctl(envmon_fd
, ENVMONIOCSETLED
, &led_ctl
);
1076 (void) close(envmon_fd
);
1078 return (PICL_FAILURE
);
1079 return (PICL_SUCCESS
);
1083 * if colour information is not supplied by the service processor,
1084 * try to determine led colour from the handle name.
1087 fix_led_colour(int8_t *colour_p
, const char *id
)
1089 const char *cptr
= strrchr(id
, '.');
1091 if ((*colour_p
< ENVMON_LED_CLR_NONE
) ||
1092 (*colour_p
> ENVMON_LED_CLR_RED
))
1093 syslog(LOG_ERR
, EM_INVALID_COLOR
, *colour_p
, id
);
1095 *colour_p
= ENVMON_LED_CLR_NONE
;
1099 cptr
++; /* step over '.' */
1101 if (strcmp(cptr
, LED_ACT
) == 0)
1102 *colour_p
= ENVMON_LED_CLR_GREEN
;
1103 else if (strcmp(cptr
, LED_SERVICE
) == 0)
1104 *colour_p
= ENVMON_LED_CLR_AMBER
;
1105 else if (strcmp(cptr
, LED_LOCATE
) == 0)
1106 *colour_p
= ENVMON_LED_CLR_WHITE
;
1107 else if (strcmp(cptr
, LED_OK2RM
) == 0)
1108 *colour_p
= ENVMON_LED_CLR_BLUE
;
1110 *colour_p
= ENVMON_LED_CLR_NONE
;
1114 * Add nodes for environmental devices of type fru_type
1115 * below the supplied node.
1118 add_env_nodes(int envmon_fd
, uint8_t fru_type
, picl_nodehdl_t envmonh
)
1121 envmon_thresholds_t lows
;
1122 envmon_thresholds_t highs
;
1123 char units
[ENVMON_MAXNAMELEN
];
1124 char platform_tree_name
[ENVMON_MAXNAMELEN
];
1125 char label_name
[ENVMON_MAXNAMELEN
];
1126 int16_t sensor_data
;
1129 envmon_keysw_pos_t key_state
;
1130 envmon_chassis_t chassis_num
;
1133 int index
= handle_arr
.num
;
1134 picl_nodehdl_t node_hdl
;
1137 * catch table is full at start
1139 if (index
>= handle_arr
.maxnum
)
1140 return (PICL_FAILURE
);
1142 cmd
= fru_to_cmd
[fru_type
];
1146 lows
.warning
= lows
.shutdown
= lows
.poweroff
=
1147 ENVMON_VAL_UNAVAILABLE
;
1148 highs
.warning
= highs
.shutdown
= highs
.poweroff
=
1149 ENVMON_VAL_UNAVAILABLE
;
1150 handle_arr
.fru_types
[index
] = fru_type
;
1151 /* must store id before reading data as it is then updated */
1152 handle_arr
.envhandles
[index
] = id
;
1154 * read environmental data according to type
1157 case ENVMON_VOLT_SENS
:
1159 case ENVMON_AMP_SENS
:
1161 case ENVMON_TEMP_SENS
:
1162 err
= get_sensor_data(envmon_fd
, &id
, cmd
, &lows
,
1163 &highs
, &sensor_data
);
1165 case ENVMON_VOLT_IND
:
1167 case ENVMON_AMP_IND
:
1169 case ENVMON_TEMP_IND
:
1171 case ENVMON_FAN_IND
:
1172 err
= get_indicator_data(envmon_fd
, &id
, cmd
,
1175 case ENVMON_FAN_SENS
:
1176 err
= get_fan_data(envmon_fd
, &id
, cmd
, &lows
,
1177 (uint16_t *)&sensor_data
, units
);
1179 case ENVMON_LED_IND
:
1180 err
= get_led_data(envmon_fd
, &id
, cmd
, &led_state
,
1183 case ENVMON_KEY_SWITCH
:
1184 err
= get_keyswitch_data(envmon_fd
, &id
, cmd
,
1187 case ENVMON_CHASSIS
:
1188 err
= get_serial_num(envmon_fd
, &id
, cmd
,
1192 return (PICL_FAILURE
);
1195 if (err
== PICL_INVALIDHANDLE
)
1197 if ((err
!= PICL_SUCCESS
) && (err
!= PICL_PROPVALUNAVAILABLE
)) {
1198 syslog(LOG_ERR
, EM_NODE_ACCESS
, id
, fru_type
, err
);
1203 * successfully read environmental data, add to PICL
1205 (void) strlcpy(platform_tree_name
,
1206 handle_arr
.envhandles
[index
].name
,
1207 sizeof (platform_tree_name
));
1209 (void) strlcpy(label_name
, platform_tree_name
,
1211 convert_label_name(label_name
);
1212 convert_node_name(platform_tree_name
);
1214 * does this node already exist?
1216 err
= get_child_by_name(envmonh
, platform_tree_name
, &node_hdl
);
1217 if (err
== PICL_SUCCESS
) {
1219 * skip over existing node
1223 err
= ptree_create_node(platform_tree_name
,
1224 fru_to_class
[fru_type
], &node_hdl
);
1225 if (err
!= PICL_SUCCESS
) {
1228 err
= add_volatile_prop(node_hdl
, fru_to_prop
[fru_type
],
1229 fru_to_ptype
[fru_type
],
1230 PICL_READ
| (fru_type
== ENVMON_LED_IND
? PICL_WRITE
: 0),
1231 fru_to_size
[fru_type
], read_vol_data
,
1232 fru_type
== ENVMON_LED_IND
? write_led_data
: NULL
,
1233 &handle_arr
.piclprhdls
[index
]);
1234 if (err
!= PICL_SUCCESS
) {
1239 * if any thresholds are defined add a property
1241 if (lows
.warning
!= ENVMON_VAL_UNAVAILABLE
) {
1242 err
= add_value_prop(node_hdl
, PICL_PROP_LOW_WARNING
,
1243 fru_type
, lows
.warning
);
1244 if (err
!= PICL_SUCCESS
) {
1248 if (lows
.shutdown
!= ENVMON_VAL_UNAVAILABLE
) {
1249 err
= add_value_prop(node_hdl
, PICL_PROP_LOW_SHUTDOWN
,
1250 fru_type
, lows
.shutdown
);
1251 if (err
!= PICL_SUCCESS
) {
1255 if (lows
.poweroff
!= ENVMON_VAL_UNAVAILABLE
) {
1256 err
= add_value_prop(node_hdl
, PICL_PROP_LOW_POWER_OFF
,
1257 fru_type
, lows
.poweroff
);
1258 if (err
!= PICL_SUCCESS
) {
1262 if (highs
.warning
!= ENVMON_VAL_UNAVAILABLE
) {
1263 err
= add_value_prop(node_hdl
, PICL_PROP_HIGH_WARNING
,
1264 fru_type
, highs
.warning
);
1265 if (err
!= PICL_SUCCESS
) {
1269 if (highs
.shutdown
!= ENVMON_VAL_UNAVAILABLE
) {
1270 err
= add_value_prop(node_hdl
, PICL_PROP_HIGH_SHUTDOWN
,
1271 fru_type
, highs
.shutdown
);
1272 if (err
!= PICL_SUCCESS
) {
1276 if (highs
.poweroff
!= ENVMON_VAL_UNAVAILABLE
) {
1277 err
= add_value_prop(node_hdl
, PICL_PROP_HIGH_POWER_OFF
,
1278 fru_type
, highs
.poweroff
);
1279 if (err
!= PICL_SUCCESS
) {
1285 * if device is a fan sensor, add a speedunit property
1287 if (fru_type
== ENVMON_FAN_SENS
) {
1288 err
= add_regular_prop(node_hdl
,
1289 PICL_PROP_FAN_SPEED_UNIT
, PICL_PTYPE_CHARSTRING
,
1290 PICL_READ
, 1 + strlen(units
), units
, NULL
);
1291 if (err
!= PICL_SUCCESS
) {
1296 * If device is a LED indicator and returns a colour,
1297 * add a colour property.
1299 if (fru_type
== ENVMON_LED_IND
) {
1300 if (colour
< 0 || colour
== ENVMON_LED_CLR_ANY
||
1301 colour
> ENVMON_LED_CLR_RED
)
1302 fix_led_colour(&colour
,
1303 handle_arr
.envhandles
[index
].name
);
1304 if (colour
!= ENVMON_LED_CLR_NONE
) {
1305 err
= add_regular_prop(node_hdl
,
1306 PICL_PROP_COLOR
, PICL_PTYPE_CHARSTRING
,
1307 PICL_READ
, colour_lkup
[colour
].size
,
1308 colour_lkup
[colour
].str_colour
, NULL
);
1309 if (err
!= PICL_SUCCESS
) {
1315 * add a label property unless it's a keyswitch or the
1316 * chassis serial number. keyswitch and chassis serial
1317 * number are labelled from a config file because the
1318 * ALOM interface doesn't supply a name for it)
1320 if ((fru_type
!= ENVMON_KEY_SWITCH
) &&
1321 (fru_type
!= ENVMON_CHASSIS
)) {
1322 err
= add_regular_prop(node_hdl
, PICL_PROP_LABEL
,
1323 PICL_PTYPE_CHARSTRING
, PICL_READ
,
1324 1 + strlen(label_name
), label_name
, NULL
);
1326 if (err
!= PICL_SUCCESS
) {
1331 * all properties added to this node, add the node below
1332 * the supplied anchor point
1334 err
= ptree_add_node(envmonh
, node_hdl
);
1336 if (err
!= PICL_SUCCESS
) {
1341 * that node went in OK, advance index
1345 } while ((id
.name
[0] != '\0') && (index
< handle_arr
.maxnum
));
1347 handle_arr
.num
= index
;
1352 fixstate(uint8_t state
, const char *string
, int *max_len
)
1357 for (i
= 0; i
< (sizeof (ledstate_lkup
) / sizeof (ledstate_lkup
[0]));
1359 if (ledstate_lkup
[i
].state
== state
) {
1360 if (ledstate_lkup
[i
].str_ledstate
!= NULL
)
1361 free(ledstate_lkup
[i
].str_ledstate
);
1362 ledstate_lkup
[i
].str_ledstate
= strdup(string
);
1363 len
= strlen(string
);
1364 if (len
>= *max_len
)
1372 fixkeyposn(envmon_keysw_pos_t keyposn
, const char *string
, int *max_len
)
1377 for (i
= 0; i
< (sizeof (keyposn_lkup
) / sizeof (keyposn_lkup
[0]));
1379 if (keyposn_lkup
[i
].pos
== keyposn
) {
1380 if (keyposn_lkup
[i
].str_keyposn
!= NULL
)
1381 free(keyposn_lkup
[i
].str_keyposn
);
1382 keyposn_lkup
[i
].str_keyposn
= strdup(string
);
1383 len
= strlen(string
);
1384 if (len
>= *max_len
)
1396 int lim
= sizeof (colour_lkup
) / sizeof (colour_lkup
[0]);
1399 * initialise led colours lookup
1401 for (i
= 0; i
< lim
; i
++) {
1402 if (colour_lkup
[i
].str_colour
!= NULL
)
1403 free(colour_lkup
[i
].str_colour
);
1406 colour_lkup
[ENVMON_LED_CLR_ANY
].str_colour
= strdup(gettext("any"));
1407 colour_lkup
[ENVMON_LED_CLR_WHITE
].str_colour
=
1408 strdup(gettext("white"));
1409 colour_lkup
[ENVMON_LED_CLR_BLUE
].str_colour
= strdup(gettext("blue"));
1410 colour_lkup
[ENVMON_LED_CLR_GREEN
].str_colour
=
1411 strdup(gettext("green"));
1412 colour_lkup
[ENVMON_LED_CLR_AMBER
].str_colour
=
1413 strdup(gettext("amber"));
1414 colour_lkup
[ENVMON_LED_CLR_RED
].str_colour
=
1415 strdup(gettext("red"));
1417 for (i
= 0; i
< lim
; i
++) {
1418 if (colour_lkup
[i
].str_colour
!= NULL
)
1419 colour_lkup
[i
].size
=
1420 1 + strlen(colour_lkup
[i
].str_colour
);
1424 * initialise condition strings and note longest
1427 cond_okay
= strdup(gettext("okay"));
1428 if (strlen(cond_okay
) >= string_size
)
1429 string_size
= 1 + strlen(cond_okay
);
1430 cond_failed
= strdup(gettext("failed"));
1431 if (strlen(cond_failed
) >= string_size
)
1432 string_size
= 1 + strlen(cond_failed
);
1434 for (i
= 0; i
< sizeof (fru_to_size
) / sizeof (fru_to_size
[0]); i
++)
1435 if (fru_to_size
[i
] == -1)
1436 fru_to_size
[i
] = string_size
;
1439 * initialise led state lookup strings
1442 fixstate(ENVMON_LED_OFF
, gettext("off"), &string_size
);
1443 fixstate(ENVMON_LED_ON
, gettext("on"), &string_size
);
1444 fixstate(ENVMON_LED_BLINKING
, gettext("blinking"), &string_size
);
1445 fixstate(ENVMON_LED_FLASHING
, gettext("flashing"), &string_size
);
1446 fru_to_size
[ENVMON_LED_IND
] = string_size
;
1449 * initialise key position lookup strings
1452 fixkeyposn(ENVMON_KEYSW_POS_UNKNOWN
, gettext("UNKNOWN"), &string_size
);
1453 fixkeyposn(ENVMON_KEYSW_POS_NORMAL
, gettext("NORMAL"), &string_size
);
1454 fixkeyposn(ENVMON_KEYSW_POS_DIAG
, gettext("DIAG"), &string_size
);
1455 fixkeyposn(ENVMON_KEYSW_POS_LOCKED
, gettext("LOCKED"), &string_size
);
1456 fixkeyposn(ENVMON_KEYSW_POS_OFF
, gettext("STBY"), &string_size
);
1457 fru_to_size
[ENVMON_KEY_SWITCH
] = string_size
;
1460 * initialise chassis serial number string
1462 fru_to_size
[ENVMON_CHASSIS
] = ENVMON_MAXNAMELEN
;
1466 * The size of outfilename must be PATH_MAX
1469 get_config_file(char *filename
)
1471 char nmbuf
[SYS_NMLN
];
1472 char pname
[PATH_MAX
];
1474 if (sysinfo(SI_PLATFORM
, nmbuf
, sizeof (nmbuf
)) != -1) {
1475 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
1476 (void) strlcat(pname
, ENVMON_CONFFILE_NAME
, PATH_MAX
);
1477 if (access(pname
, R_OK
) == 0) {
1478 (void) strlcpy(filename
, pname
, PATH_MAX
);
1483 if (sysinfo(SI_MACHINE
, nmbuf
, sizeof (nmbuf
)) != -1) {
1484 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
1485 (void) strlcat(pname
, ENVMON_CONFFILE_NAME
, PATH_MAX
);
1486 if (access(pname
, R_OK
) == 0) {
1487 (void) strlcpy(filename
, pname
, PATH_MAX
);
1492 (void) snprintf(pname
, PATH_MAX
, "%s/%s",
1493 PICLD_COMMON_PLUGIN_DIR
, ENVMON_CONFFILE_NAME
);
1495 if (access(pname
, R_OK
) == 0) {
1496 (void) strlcpy(filename
, pname
, PATH_MAX
);
1504 free_vol_prop(picl_prophdl_t proph
)
1508 index
= find_picl_handle(proph
);
1511 if (index
!= handle_arr
.num
) {
1512 /* relocate last entry into hole just created */
1513 handle_arr
.fru_types
[index
] =
1514 handle_arr
.fru_types
[handle_arr
.num
];
1515 handle_arr
.envhandles
[index
] =
1516 handle_arr
.envhandles
[handle_arr
.num
];
1517 handle_arr
.piclprhdls
[index
] =
1518 handle_arr
.piclprhdls
[handle_arr
.num
];
1524 * handle PICL FRU ADDED and FRU REMOVED events
1528 envmon_evhandler(const char *ename
, const void *earg
, size_t size
,
1531 char path
[MAXPATHLEN
];
1532 picl_nodehdl_t locnodeh
;
1534 picl_nodehdl_t childh
;
1535 picl_nodehdl_t nodeh
;
1536 picl_prophdl_t tableh
;
1537 picl_prophdl_t tblh
;
1538 picl_prophdl_t proph
;
1539 ptree_propinfo_t pi
;
1541 if (strcmp(ename
, PICL_FRU_ADDED
) == 0) {
1542 retval
= nvlist_lookup_uint64((nvlist_t
*)earg
,
1543 PICLEVENTARG_PARENTHANDLE
, &locnodeh
);
1546 syslog(LOG_ERR
, EM_EV_MISSING_ARG
,
1547 PICLEVENTARG_PARENTHANDLE
);
1550 retval
= ptree_get_propval_by_name(locnodeh
, PICL_PROP_NAME
,
1551 path
, sizeof (path
));
1552 if (retval
== PICL_SUCCESS
) {
1554 * Open envmon device and interrogate
1558 picl_nodehdl_t envmoninfh
;
1560 if (get_envmon_node(&envmoninfh
) != PICL_SUCCESS
) {
1561 syslog(LOG_ERR
, EM_SC_NODE_MISSING
);
1565 if ((envmon_fd
= open(envmon_device_name
, O_RDONLY
)) <
1567 syslog(LOG_ERR
, EM_SYS_ERR
, envmon_device_name
,
1572 if (strcmp(str_SC
, path
) == 0) {
1574 * SC state change - re-assess platform tree
1576 if (re_create_arrays(envmon_fd
) != 0) {
1578 * out of memory - make no changes
1583 * dropped memory of volatile prop handles
1584 * so drop the nodes also, then rebuild for
1585 * the newly loaded SC
1587 retval
= ptree_get_propval_by_name(envmoninfh
,
1588 PICL_PROP_PARENT
, &nodeh
, sizeof (nodeh
));
1589 if (retval
!= PICL_SUCCESS
) {
1590 (void) close(envmon_fd
);
1593 retval
= ptree_get_propval_by_name(envmoninfh
,
1594 PICL_PROP_NAME
, path
, sizeof (path
));
1595 if (retval
!= PICL_SUCCESS
) {
1596 (void) close(envmon_fd
);
1600 retval
= ptree_delete_node(envmoninfh
);
1601 if (retval
== PICL_SUCCESS
)
1602 (void) ptree_destroy_node(envmoninfh
);
1603 retval
= ptree_create_node(path
,
1604 PICL_CLASS_SERVICE_PROCESSOR
, &envmoninfh
);
1605 if (retval
!= PICL_SUCCESS
) {
1606 (void) close(envmon_fd
);
1609 retval
= ptree_add_node(nodeh
, envmoninfh
);
1610 if (retval
!= PICL_SUCCESS
) {
1611 (void) close(envmon_fd
);
1616 for (fru_type
= 0; fru_type
< ENVMONTYPES
;
1618 (void) add_env_nodes(envmon_fd
, fru_type
,
1622 (void) close(envmon_fd
);
1624 } else if (strcmp(ename
, PICL_FRU_REMOVED
) == 0) {
1625 retval
= nvlist_lookup_uint64((nvlist_t
*)earg
,
1626 PICLEVENTARG_FRUHANDLE
, &childh
);
1629 syslog(LOG_ERR
, EM_EV_MISSING_ARG
,
1630 PICLEVENTARG_FRUHANDLE
);
1633 retval
= ptree_get_propval_by_name(childh
, PICL_PROP_NAME
,
1634 path
, sizeof (path
));
1635 if (retval
== PICL_SUCCESS
) {
1636 retval
= ptree_get_prop_by_name(childh
,
1637 PICL_PROP_DEVICES
, &tableh
);
1639 if (retval
!= PICL_SUCCESS
) {
1640 /* no Devices table, nothing to do */
1645 * follow all reference properties in the second
1646 * column of the table and delete the referenced node
1648 retval
= ptree_get_propval(tableh
, &tblh
,
1650 if (retval
!= PICL_SUCCESS
) {
1652 * can't get value of table property
1656 /* get first col, first row */
1657 retval
= ptree_get_next_by_col(tblh
, &tblh
);
1658 if (retval
!= PICL_SUCCESS
) {
1665 * starting at next col, get every entry in the column
1667 for (retval
= ptree_get_next_by_row(tblh
, &tblh
);
1668 retval
== PICL_SUCCESS
;
1669 retval
= ptree_get_next_by_col(tblh
, &tblh
)) {
1671 * should be a ref prop in our hands,
1672 * get the target node handle
1674 retval
= ptree_get_propval(tblh
, &nodeh
,
1676 if (retval
!= PICL_SUCCESS
) {
1680 * got the referenced node, has it got a
1681 * volatile property to clean up?
1683 retval
= ptree_get_first_prop(nodeh
, &proph
);
1684 while (retval
== PICL_SUCCESS
) {
1685 retval
= ptree_get_propinfo(proph
, &pi
);
1686 if ((retval
== PICL_SUCCESS
) &&
1687 (pi
.piclinfo
.accessmode
&
1689 free_vol_prop(proph
);
1690 retval
= ptree_get_next_prop(proph
,
1694 * all volatile properties gone, remove node
1696 retval
= ptree_delete_node(nodeh
);
1697 if (retval
== PICL_SUCCESS
)
1698 (void) ptree_destroy_node(nodeh
);
1705 * executed as part of .init when the plugin is dlopen()ed
1708 piclenvmon_register(void)
1710 (void) picld_plugin_register(&my_reg_info
);
1714 * Init entry point of the plugin
1715 * Creates the PICL nodes and properties in the physical and logical aspects.
1718 piclenvmon_init(void)
1720 picl_nodehdl_t rooth
;
1721 picl_nodehdl_t plfh
;
1722 picl_nodehdl_t envmoninfh
;
1726 char pathname
[PATH_MAX
];
1729 * locate and parse config file
1731 if (get_config_file(pathname
) < 0)
1734 if ((ptree_get_root(&rooth
) != PICL_SUCCESS
) ||
1735 (picld_pluginutil_parse_config_file(rooth
, pathname
) !=
1737 syslog(LOG_ERR
, EM_INIT_FAILED
);
1743 if (ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM
, &plfh
)
1745 syslog(LOG_ERR
, EM_MISSING_NODE
, PICL_NODE_PLATFORM
);
1746 syslog(LOG_ERR
, EM_INIT_FAILED
);
1751 * Get service-processor node
1753 if (get_envmon_node(&envmoninfh
) != PICL_SUCCESS
)
1757 * We may have been restarted, make sure we don't leak
1759 if (envmon_device_name
!= NULL
) {
1760 free(envmon_device_name
);
1763 if ((envmon_device_name
= create_envmon_pathname(envmoninfh
)) == NULL
)
1767 * Open envmon device and interrogate for devices it monitors
1769 if ((envmon_fd
= open(envmon_device_name
, O_RDONLY
)) < 0) {
1770 syslog(LOG_ERR
, EM_SYS_ERR
, envmon_device_name
,
1775 if (get_envmon_limits(envmon_fd
, &env_limits
) < 0)
1779 * A set of arrays are used whose bounds are determined by the
1780 * response to get_envmon_limits. Establish these arrays now.
1785 for (fru_type
= 0; fru_type
< ENVMONTYPES
; fru_type
++) {
1786 (void) add_env_nodes(envmon_fd
, fru_type
, envmoninfh
);
1789 (void) close(envmon_fd
);
1791 res
= ptree_register_handler(PICL_FRU_ADDED
, envmon_evhandler
, NULL
);
1792 if (res
!= PICL_SUCCESS
) {
1793 syslog(LOG_ERR
, EM_EVREG_FAILED
, res
);
1795 res
= ptree_register_handler(PICL_FRU_REMOVED
, envmon_evhandler
, NULL
);
1796 if (res
!= PICL_SUCCESS
) {
1797 syslog(LOG_ERR
, EM_EVREG_FAILED
, res
);
1802 * fini entry point of the plugin
1805 piclenvmon_fini(void)
1807 if (envmon_device_name
!= NULL
) {
1808 free(envmon_device_name
);
1809 envmon_device_name
= NULL
;
1811 (void) ptree_unregister_handler(PICL_FRU_ADDED
,
1812 envmon_evhandler
, NULL
);
1813 (void) ptree_unregister_handler(PICL_FRU_REMOVED
,
1814 envmon_evhandler
, NULL
);