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.
28 * This plugin creates PICL nodes and properties for objects handled through
29 * the enhanced LOMV system-processor interface.
31 * All the nodes which may be accessible through the system-processor are
32 * included below the service-processor node in the /platform tree.
33 * This plugin interrogates the system-processor to determine which of
34 * those nodes are actually available. Properties are added to such nodes and
35 * in the case of volatile properties like temperature, a call-back function
36 * is established for on-demand access to the current value.
37 * LEDs for which the system-processor provides write access are associated
38 * with read/write volatile properties.
41 * Depends on PICL devtree plugin.
54 #include <libnvpair.h>
58 #include <sys/types.h>
60 #include <sys/obpdefs.h>
61 #include <sys/envmon.h>
62 #include <sys/systeminfo.h>
66 #include <picld_pluginutil.h>
67 #include <libdevinfo.h>
68 #include "piclenvmon.h"
70 static void piclenvmon_register(void);
71 static void piclenvmon_init(void);
72 static void piclenvmon_fini(void);
73 static node_el_t
*create_node_el(picl_nodehdl_t nodeh
);
74 static void delete_node_el(node_el_t
*pel
);
75 static node_list_t
*create_node_list();
76 static void delete_node_list(node_list_t
*pnl
);
77 static void add_node_to_list(picl_nodehdl_t nodeh
, node_list_t
*listp
);
78 static void get_node_list_by_class(picl_nodehdl_t nodeh
,
79 const char *classname
, node_list_t
*listp
);
80 static int get_envmon_limits(int envmon_fd
, envmon_sysinfo_t
*limits_p
);
81 static void create_arrays();
82 static int get_envmon_node(picl_nodehdl_t
*envmoninfh
);
83 static char *create_envmon_pathname(picl_nodehdl_t envmoninfh
);
84 static int get_child_by_name(picl_nodehdl_t nodeh
, const char *name
,
85 picl_nodehdl_t
*childh
);
86 static int add_regular_prop(picl_nodehdl_t nodeh
, const char *name
,
87 int type
, int access
, int size
, const void *valbuf
, picl_prophdl_t
*prophp
);
88 static int add_volatile_prop(picl_nodehdl_t nodeh
, const char *name
,
89 int type
, int access
, int size
, ptree_vol_rdfunc_t rdfunc
,
90 ptree_vol_wrfunc_t wrfunc
, picl_prophdl_t
*prophp
);
91 static int get_sensor_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
92 envmon_thresholds_t
*lows
, envmon_thresholds_t
*highs
, int16_t *value
);
93 static int get_indicator_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
95 static int get_fan_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
96 envmon_thresholds_t
*lows
, uint16_t *speed
, char *units
);
97 static int get_led_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
98 int8_t *state
, int8_t *colour
);
99 static int get_keyswitch_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
100 envmon_keysw_pos_t
*key_state
);
101 static void convert_node_name(char *ptr
);
102 static void convert_label_name(char *ptr
);
103 static int add_value_prop(picl_nodehdl_t node_hdl
, const char *prop_name
,
104 int fru_type
, int16_t value
);
105 static int find_picl_handle(picl_prophdl_t proph
);
106 static int lookup_led_status(int8_t state
, const char **string
);
107 static int lookup_key_posn(envmon_keysw_pos_t pos
, const char **string
);
108 static int get_config_file(char *filename
);
109 static int read_vol_data(ptree_rarg_t
*r_arg
, void *buf
);
110 static int write_led_data(ptree_warg_t
*w_arg
, const void *buf
);
111 static int add_env_nodes(int envmon_fd
, uint8_t fru_type
,
112 picl_nodehdl_t envmonh
);
113 static void fixstate(uint8_t state
, const char *string
, int *max_len
);
114 static void fixkeyposn(envmon_keysw_pos_t keyposn
, const char *string
,
116 static void setup_strings();
117 static void free_vol_prop(picl_prophdl_t proph
);
118 static void envmon_evhandler(const char *ename
, const void *earg
,
119 size_t size
, void *cookie
);
120 static int get_serial_num(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
121 envmon_chassis_t
*chassis
);
123 #pragma init(piclenvmon_register)
125 static picld_plugin_reg_t my_reg_info
= {
126 PICLD_PLUGIN_VERSION_1
,
127 PICLD_PLUGIN_NON_CRITICAL
,
133 static const char str_On
[] = "on";
134 static const char str_Off
[] = "off";
135 static const char str_Blinking
[] = "blinking";
136 static const char str_Flashing
[] = "flashing";
137 static const char str_SC
[] = "SC";
138 static char *envmon_device_name
= NULL
;
139 static envmon_sysinfo_t env_limits
;
140 static handle_array_t handle_arr
;
144 } colour_lkup
[1 + ENVMON_LED_CLR_RED
];
149 } ledstate_lkup
[] = {
152 { ENVMON_LED_BLINKING
},
153 { ENVMON_LED_FLASHING
}
157 envmon_keysw_pos_t pos
;
160 { ENVMON_KEYSW_POS_UNKNOWN
},
161 { ENVMON_KEYSW_POS_NORMAL
},
162 { ENVMON_KEYSW_POS_DIAG
},
163 { ENVMON_KEYSW_POS_LOCKED
},
164 { ENVMON_KEYSW_POS_OFF
}
168 * fru-type to ioctl cmd lookup
181 ENVMONIOCCHASSISSERIALNUM
185 * fru-type to PICL CLASS
187 const char *fru_to_class
[] = {
188 PICL_CLASS_VOLTAGE_SENSOR
,
189 PICL_CLASS_VOLTAGE_INDICATOR
,
190 PICL_CLASS_CURRENT_SENSOR
,
191 PICL_CLASS_CURRENT_INDICATOR
,
192 PICL_CLASS_TEMPERATURE_SENSOR
,
193 PICL_CLASS_TEMPERATURE_INDICATOR
,
197 PICL_CLASS_KEYSWITCH
,
198 PICL_CLASS_CHASSIS_SERIAL_NUM
202 * fru-type to PICL PROPERTY for volatile data
204 const char *fru_to_prop
[] = {
209 PICL_PROP_TEMPERATURE
,
212 PICL_PROP_FAN_SPEED_UNIT
,
215 PICL_PROP_SERIAL_NUMBER
219 * fru-type to PICL PTYPE
221 int fru_to_ptype
[] = {
223 PICL_PTYPE_CHARSTRING
,
225 PICL_PTYPE_CHARSTRING
,
227 PICL_PTYPE_CHARSTRING
,
228 PICL_PTYPE_UNSIGNED_INT
,
229 PICL_PTYPE_CHARSTRING
,
230 PICL_PTYPE_CHARSTRING
,
231 PICL_PTYPE_CHARSTRING
,
232 PICL_PTYPE_CHARSTRING
238 static char *cond_okay
;
239 static char *cond_failed
;
242 * fru-type to size of volatile property
243 * the -1's are replaced by the max size of a condition string
245 int fru_to_size
[] = {
246 4, -1, 4, -1, 2, -1, 2, -1, -1, -1, -1
250 create_node_el(picl_nodehdl_t nodeh
)
252 node_el_t
*ptr
= malloc(sizeof (node_el_t
));
263 delete_node_el(node_el_t
*pel
)
271 node_list_t
*ptr
= malloc(sizeof (node_list_t
));
282 delete_node_list(node_list_t
*pnl
)
289 while ((pel
= pnl
->head
) != NULL
) {
290 pnl
->head
= pel
->next
;
295 * normally pnl->tail would be to NULL next,
296 * but as it is about to be freed, this step can be skipped.
302 * Get a linking element and add handle to end of chain
305 add_node_to_list(picl_nodehdl_t nodeh
, node_list_t
*listp
)
307 node_el_t
*pel
= create_node_el(nodeh
);
310 if (listp
->tail
== NULL
)
313 listp
->tail
->next
= pel
;
320 * Get a list of nodes of the specified classname under nodeh.
321 * Once a node of the specified class is found, its children are not
325 get_node_list_by_class(picl_nodehdl_t nodeh
, const char *classname
,
329 char clname
[PICL_CLASSNAMELEN_MAX
+1];
333 * go through the children
335 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_CHILD
, &chdh
,
336 sizeof (picl_nodehdl_t
));
338 while (err
== PICL_SUCCESS
) {
339 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_CLASSNAME
,
340 clname
, strlen(classname
) + 1);
342 if ((err
== PICL_SUCCESS
) && (strcmp(clname
, classname
) == 0))
343 add_node_to_list(chdh
, listp
);
345 get_node_list_by_class(chdh
, classname
, listp
);
347 err
= ptree_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
348 sizeof (picl_nodehdl_t
));
353 get_envmon_limits(int envmon_fd
, envmon_sysinfo_t
*limits_p
)
355 return (ioctl(envmon_fd
, ENVMONIOCSYSINFO
, limits_p
));
359 re_create_arrays(int envmon_fd
)
361 envmon_sysinfo_t new_limits
;
365 envmon_handle_t
*envhandles
;
366 picl_prophdl_t
*piclprhdls
;
368 res
= get_envmon_limits(envmon_fd
, &new_limits
);
372 maxnum
= new_limits
.maxVoltSens
+ new_limits
.maxVoltInd
+
373 new_limits
.maxAmpSens
+ new_limits
.maxAmpInd
+
374 new_limits
.maxTempSens
+ new_limits
.maxTempInd
+
375 new_limits
.maxFanSens
+ new_limits
.maxFanInd
+
376 new_limits
.maxLED
+ N_KEY_SWITCHES
;
378 if (maxnum
!= handle_arr
.maxnum
) {
380 * space requirements have changed
382 fru_types
= calloc(maxnum
, sizeof (uchar_t
));
383 envhandles
= calloc(maxnum
, sizeof (envmon_handle_t
));
384 piclprhdls
= calloc(maxnum
, sizeof (picl_prophdl_t
));
385 if ((fru_types
== NULL
) || (envhandles
== NULL
) ||
386 (piclprhdls
== NULL
)) {
392 free(handle_arr
.fru_types
);
393 handle_arr
.fru_types
= fru_types
;
394 free(handle_arr
.envhandles
);
395 handle_arr
.envhandles
= envhandles
;
396 free(handle_arr
.piclprhdls
);
397 handle_arr
.piclprhdls
= piclprhdls
;
399 (void) memset(handle_arr
.fru_types
, 0,
400 maxnum
* sizeof (uchar_t
));
401 (void) memset(handle_arr
.envhandles
, 0,
402 maxnum
* sizeof (envmon_handle_t
));
403 (void) memset(handle_arr
.piclprhdls
, 0,
404 maxnum
* sizeof (picl_prophdl_t
));
408 handle_arr
.maxnum
= maxnum
;
409 env_limits
= new_limits
;
416 int maxnum
= env_limits
.maxVoltSens
+ env_limits
.maxVoltInd
+
417 env_limits
.maxAmpSens
+ env_limits
.maxAmpInd
+
418 env_limits
.maxTempSens
+ env_limits
.maxTempInd
+
419 env_limits
.maxFanSens
+ env_limits
.maxFanInd
+
420 env_limits
.maxLED
+ N_KEY_SWITCHES
;
421 handle_arr
.maxnum
= maxnum
;
423 handle_arr
.fru_types
= calloc(maxnum
, sizeof (uchar_t
));
424 handle_arr
.envhandles
= calloc(maxnum
, sizeof (envmon_handle_t
));
425 handle_arr
.piclprhdls
= calloc(maxnum
, sizeof (picl_prophdl_t
));
429 get_envmon_node(picl_nodehdl_t
*envmoninfh
)
431 int err
= PICL_SUCCESS
;
434 listp
= create_node_list();
436 if ((err
= ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM
,
437 envmoninfh
)) != PICL_SUCCESS
) {
438 syslog(LOG_ERR
, EM_MISSING_NODE
,
439 PICL_NODE_ROOT PICL_NODE_PLATFORM
);
440 return (err
); /* no /platform ! */
443 get_node_list_by_class(*envmoninfh
, PICL_CLASS_SERVICE_PROCESSOR
,
446 if (listp
->head
== NULL
) {
448 syslog(LOG_ERR
, EM_MISSING_NODE
, PICL_CLASS_SERVICE_PROCESSOR
);
449 err
= PICL_NODENOTFOUND
;
451 *envmoninfh
= listp
->head
->nodeh
;
454 delete_node_list(listp
);
459 create_envmon_pathname(picl_nodehdl_t envmoninfh
)
462 char namebuf
[PATH_MAX
];
468 /* prefix devfs-path name with /devices */
469 (void) strlcpy(namebuf
, "/devices", PATH_MAX
);
472 * append devfs-path property
474 len
= strlen(namebuf
);
475 if (ptree_get_propval_by_name(envmoninfh
, PICL_PROP_DEVFS_PATH
,
476 namebuf
+ len
, sizeof (namebuf
) - len
) != PICL_SUCCESS
) {
477 syslog(LOG_ERR
, EM_SC_NODE_INCOMPLETE
);
481 /* locate final component of name */
482 ptr
= strrchr(namebuf
, '/');
485 *ptr
= '\0'; /* terminate at end of directory path */
486 len
= strlen(ptr
+ 1); /* length of terminal name */
487 dirp
= opendir(namebuf
);
489 syslog(LOG_ERR
, EM_SC_NODE_MISSING
);
492 *ptr
++ = '/'; /* restore '/' and advance to final name */
494 while ((dp
= readdir(dirp
)) != NULL
) {
496 * look for a name which starts with the string at *ptr
498 if (strlen(dp
->d_name
) < len
)
499 continue; /* skip short names */
500 if (strncmp(dp
->d_name
, ptr
, len
) == 0) {
502 * Got a match, restore full pathname and stat the
503 * entry. Reject if not a char device
505 (void) strlcpy(ptr
, dp
->d_name
,
506 sizeof (namebuf
) - (ptr
- namebuf
));
507 if (stat(namebuf
, &statbuf
) < 0)
508 continue; /* reject if can't stat it */
509 if (!S_ISCHR(statbuf
.st_mode
))
510 continue; /* not a character device */
514 (void) closedir(dirp
);
515 return (strdup(namebuf
));
518 syslog(LOG_ERR
, EM_SC_NODE_MISSING
);
519 (void) closedir(dirp
);
524 * look for named node as child of supplied handle
527 get_child_by_name(picl_nodehdl_t nodeh
, const char *name
,
528 picl_nodehdl_t
*childh
)
531 char node_name
[ENVMON_MAXNAMELEN
];
533 if (strlen(name
) >= ENVMON_MAXNAMELEN
)
534 return (PICL_NODENOTFOUND
);
535 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_CHILD
, childh
,
537 while (err
== PICL_SUCCESS
) {
538 err
= ptree_get_propval_by_name(*childh
, PICL_PROP_NAME
,
539 node_name
, sizeof (node_name
));
540 if ((err
== PICL_SUCCESS
) &&
541 (strncmp(name
, node_name
, ENVMON_MAXNAMELEN
) == 0))
542 return (PICL_SUCCESS
);
543 err
= ptree_get_propval_by_name(*childh
, PICL_PROP_PEER
,
544 childh
, sizeof (*childh
));
550 * Create and add the specified regular property
553 add_regular_prop(picl_nodehdl_t nodeh
, const char *name
, int type
, int access
,
554 int size
, const void *valbuf
, picl_prophdl_t
*prophp
)
557 ptree_propinfo_t propinfo
;
558 picl_prophdl_t proph
;
560 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
561 type
, access
, size
, (char *)name
, NULL
, NULL
);
562 if (err
!= PICL_SUCCESS
)
565 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, (void *)valbuf
,
567 if (err
== PICL_SUCCESS
&& prophp
)
574 * Create and add the specified volatile property
577 add_volatile_prop(picl_nodehdl_t nodeh
, const char *name
, int type
, int access
,
578 int size
, ptree_vol_rdfunc_t rdfunc
, ptree_vol_wrfunc_t wrfunc
,
579 picl_prophdl_t
*prophp
)
582 ptree_propinfo_t propinfo
;
583 picl_prophdl_t proph
;
585 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
586 type
, (access
|PICL_VOLATILE
), size
, (char *)name
, rdfunc
, wrfunc
);
587 if (err
!= PICL_SUCCESS
)
590 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, &proph
);
591 if (err
== PICL_SUCCESS
&& prophp
)
597 * There are 5 different structures used for reading environmental data
598 * from the service-processor. A different function is used for each one.
599 * Some functions cover several ioctls, so the desired ioctl is part of
600 * the interface. In each case the id parameter is read/write, the
601 * returned value being the next id for this fru type.
605 * Function to read sensor data.
608 get_sensor_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
609 envmon_thresholds_t
*lows
, envmon_thresholds_t
*highs
, int16_t *value
)
612 envmon_sensor_t data
;
614 (void) memset(&data
, 0, sizeof (data
));
616 res
= ioctl(envmon_fd
, cmd
, &data
);
618 return (PICL_NOTREADABLE
);
623 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
624 return (PICL_INVALIDHANDLE
);
627 * it is assumed that threshold data will be available,
628 * even though the current sensor value may be inaccessible
631 *lows
= data
.lowthresholds
;
633 *highs
= data
.highthresholds
;
635 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
637 *value
= ENVMON_VAL_UNAVAILABLE
;
638 return (PICL_PROPVALUNAVAILABLE
);
642 return (PICL_SUCCESS
);
646 * Function to read indicator data.
649 get_indicator_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
653 envmon_indicator_t data
;
656 res
= ioctl(envmon_fd
, cmd
, &data
);
658 return (PICL_NOTREADABLE
);
660 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
661 return (PICL_INVALIDHANDLE
);
662 if (condition
!= NULL
)
663 *condition
= data
.condition
;
664 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
665 return (PICL_PROPVALUNAVAILABLE
);
667 return (PICL_SUCCESS
);
671 * Function to read fan data.
674 get_fan_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
675 envmon_thresholds_t
*lows
, uint16_t *speed
, char *units
)
681 res
= ioctl(envmon_fd
, cmd
, &data
);
683 return (PICL_NOTREADABLE
);
685 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
686 return (PICL_INVALIDHANDLE
);
688 *lows
= data
.lowthresholds
;
690 (void) strlcpy(units
, data
.units
, sizeof (data
.units
));
692 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
694 *speed
= ENVMON_VAL_UNAVAILABLE
;
695 return (PICL_PROPVALUNAVAILABLE
);
699 return (PICL_SUCCESS
);
703 * Function to read LED data.
706 get_led_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
707 int8_t *state
, int8_t *colour
)
710 envmon_led_info_t data
;
713 res
= ioctl(envmon_fd
, cmd
, &data
);
715 return (PICL_NOTREADABLE
);
717 if ((data
.sensor_status
& ENVMON_NOT_PRESENT
) != 0)
718 return (PICL_INVALIDHANDLE
);
720 *colour
= data
.led_color
;
721 if ((data
.sensor_status
& ENVMON_INACCESSIBLE
) != 0) {
722 return (PICL_PROPVALUNAVAILABLE
);
725 *state
= data
.led_state
;
726 return (PICL_SUCCESS
);
730 * Function to read key-switch position
731 * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails)
734 get_keyswitch_data(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
735 envmon_keysw_pos_t
*key_state
)
739 if (id
->name
[0] == '\0') {
740 (void) strlcpy(id
->name
, KEYSWITCH_NAME
, sizeof (id
->name
));
741 return (PICL_INVALIDHANDLE
);
742 } else if (strncmp(id
->name
, KEYSWITCH_NAME
, sizeof (id
->name
)) != 0) {
744 return (PICL_INVALIDHANDLE
);
746 res
= ioctl(envmon_fd
, cmd
, key_state
);
750 return (PICL_INVALIDHANDLE
);
751 return (PICL_SUCCESS
);
756 * Function to read the chassis serial number
757 * Returns PICL_INVALIDHANDLE if ioctl not supported (or fails)
760 get_serial_num(int envmon_fd
, envmon_handle_t
*id
, int cmd
,
761 envmon_chassis_t
*chassis
)
765 if (id
->name
[0] == '\0') {
766 (void) strlcpy(id
->name
, CHASSIS_SERIAL_NUMBER
,
768 return (PICL_INVALIDHANDLE
);
769 } else if (strncmp(id
->name
, CHASSIS_SERIAL_NUMBER
, sizeof (id
->name
))
772 return (PICL_INVALIDHANDLE
);
774 res
= ioctl(envmon_fd
, cmd
, chassis
);
778 return (PICL_INVALIDHANDLE
);
779 return (PICL_SUCCESS
);
784 * change to lower case and convert any spaces into hyphens,
785 * and any dots or colons symbols into underscores
788 convert_node_name(char *ptr
)
792 for (ch
= *ptr
; ch
!= '\0'; ch
= *++ptr
) {
795 } else if (isspace(ch
)) {
797 } else if ((ch
== '.') || (ch
== ':')) {
804 * strip to the last '.' separator and keep the rest
805 * change ':' to '/' within the last component
808 convert_label_name(char *name
)
813 cptr
= strrchr(name
, '.');
818 cptr
++; /* skip the '.' */
827 } while (ch
!= '\0');
831 * add a value property
834 add_value_prop(picl_nodehdl_t node_hdl
, const char *prop_name
, int fru_type
,
843 if (fru_to_ptype
[fru_type
] == PICL_PTYPE_FLOAT
)
844 val_buf
.u_f
= (float)((float)value
/ (float)1000.0);
846 val_buf
.u_i16
= value
;
848 err
= add_regular_prop(node_hdl
, prop_name
, fru_to_ptype
[fru_type
],
849 PICL_READ
, fru_to_size
[fru_type
], &val_buf
, NULL
);
854 find_picl_handle(picl_prophdl_t proph
)
858 for (index
= 0; index
< handle_arr
.num
; index
++) {
859 if (handle_arr
.piclprhdls
[index
] == proph
)
867 * look up function to convert led status into string
870 lookup_led_status(int8_t state
, const char **string
)
873 int lim
= sizeof (ledstate_lkup
) / sizeof (ledstate_lkup
[0]);
875 for (i
= 0; i
< lim
; i
++) {
876 if (ledstate_lkup
[i
].state
== state
) {
877 *string
= ledstate_lkup
[i
].str_ledstate
;
878 return (PICL_SUCCESS
);
883 return (PICL_PROPVALUNAVAILABLE
);
887 lookup_key_posn(envmon_keysw_pos_t pos
, const char **string
)
890 int lim
= sizeof (keyposn_lkup
) / sizeof (keyposn_lkup
[0]);
892 for (i
= 0; i
< lim
; i
++) {
893 if (keyposn_lkup
[i
].pos
== pos
) {
894 *string
= keyposn_lkup
[i
].str_keyposn
;
895 return (PICL_SUCCESS
);
900 return (PICL_PROPVALUNAVAILABLE
);
904 * function to read volatile data associated with a PICL property handle
907 read_vol_data(ptree_rarg_t
*r_arg
, void *buf
)
909 picl_prophdl_t proph
;
915 envmon_keysw_pos_t key_posn
;
916 envmon_chassis_t chassis
;
923 proph
= r_arg
->proph
;
924 index
= find_picl_handle(proph
);
926 return (PICL_INVALIDHANDLE
);
927 fru_type
= handle_arr
.fru_types
[index
];
928 id
= handle_arr
.envhandles
[index
];
929 cmd
= fru_to_cmd
[fru_type
];
930 envmon_fd
= open(envmon_device_name
, O_RDONLY
);
932 return (PICL_NOTREADABLE
);
935 * read environmental data according to type
938 case ENVMON_VOLT_SENS
:
940 case ENVMON_AMP_SENS
:
942 case ENVMON_TEMP_SENS
:
943 err
= get_sensor_data(envmon_fd
, &id
, cmd
, NULL
, NULL
,
946 case ENVMON_VOLT_IND
:
950 case ENVMON_TEMP_IND
:
953 err
= get_indicator_data(envmon_fd
, &id
, cmd
, &sensor_data
);
955 case ENVMON_FAN_SENS
:
956 err
= get_fan_data(envmon_fd
, &id
, cmd
, NULL
,
957 (uint16_t *)&sensor_data
, NULL
);
960 err
= get_led_data(envmon_fd
, &id
, cmd
, &led_state
, NULL
);
962 case ENVMON_KEY_SWITCH
:
963 err
= get_keyswitch_data(envmon_fd
, &id
, cmd
, &key_posn
);
966 err
= get_serial_num(envmon_fd
, &id
, cmd
, &chassis
);
973 (void) close(envmon_fd
);
974 if (err
!= PICL_SUCCESS
) {
976 * PICL_INVALIDHANDLE is used internally, but it upsets
977 * prtpicl; change it to PICL_PROPVALUNAVAILABLE
979 if (err
== PICL_INVALIDHANDLE
)
980 err
= PICL_PROPVALUNAVAILABLE
;
985 * convert data and copy out
988 case ENVMON_VOLT_SENS
:
990 case ENVMON_AMP_SENS
:
991 float_data
= (float)((float)sensor_data
/ (float)1000.0);
992 (void) memcpy(buf
, &float_data
, sizeof (float_data
));
995 case ENVMON_TEMP_SENS
:
997 case ENVMON_FAN_SENS
:
998 (void) memcpy(buf
, &sensor_data
, sizeof (sensor_data
));
1001 case ENVMON_VOLT_IND
:
1003 case ENVMON_AMP_IND
:
1005 case ENVMON_TEMP_IND
:
1007 case ENVMON_FAN_IND
:
1008 (void) strlcpy(buf
, sensor_data
== 0 ? cond_okay
: cond_failed
,
1009 fru_to_size
[fru_type
]);
1012 case ENVMON_LED_IND
:
1013 err
= lookup_led_status(led_state
, &cptr
);
1014 if (err
!= PICL_SUCCESS
)
1016 (void) strlcpy(buf
, cptr
, fru_to_size
[fru_type
]);
1019 case ENVMON_KEY_SWITCH
:
1020 err
= lookup_key_posn(key_posn
, &cptr
);
1021 if (err
!= PICL_SUCCESS
)
1023 (void) strlcpy(buf
, cptr
, fru_to_size
[fru_type
]);
1025 case ENVMON_CHASSIS
:
1026 (void) memcpy(buf
, chassis
.serial_number
,
1027 sizeof (chassis
.serial_number
));
1031 return (PICL_FAILURE
);
1034 return (PICL_SUCCESS
);
1038 write_led_data(ptree_warg_t
*w_arg
, const void *buf
)
1040 picl_prophdl_t proph
;
1045 envmon_led_ctl_t led_ctl
;
1047 proph
= w_arg
->proph
;
1048 index
= find_picl_handle(proph
);
1050 return (PICL_INVALIDHANDLE
);
1051 fru_type
= handle_arr
.fru_types
[index
];
1052 if (fru_type
!= ENVMON_LED_IND
)
1053 return (PICL_INVALIDARG
);
1054 if (w_arg
->cred
.dc_euid
!= SUPER_USER
)
1055 return (PICL_PERMDENIED
);
1057 /* see if the requested state is recognized */
1058 if (strcasecmp(str_Off
, buf
) == 0)
1059 led_ctl
.led_state
= ENVMON_LED_OFF
;
1060 else if (strcasecmp(str_On
, buf
) == 0)
1061 led_ctl
.led_state
= ENVMON_LED_ON
;
1062 else if (strcasecmp(str_Blinking
, buf
) == 0)
1063 led_ctl
.led_state
= ENVMON_LED_BLINKING
;
1064 else if (strcasecmp(str_Flashing
, buf
) == 0)
1065 led_ctl
.led_state
= ENVMON_LED_FLASHING
;
1067 return (PICL_INVALIDARG
);
1069 envmon_fd
= open(envmon_device_name
, O_RDWR
);
1071 return (PICL_FAILURE
);
1072 led_ctl
.id
= handle_arr
.envhandles
[index
];
1073 err
= ioctl(envmon_fd
, ENVMONIOCSETLED
, &led_ctl
);
1074 (void) close(envmon_fd
);
1076 return (PICL_FAILURE
);
1077 return (PICL_SUCCESS
);
1081 * if colour information is not supplied by the service processor,
1082 * try to determine led colour from the handle name.
1085 fix_led_colour(int8_t *colour_p
, const char *id
)
1087 const char *cptr
= strrchr(id
, '.');
1089 if ((*colour_p
< ENVMON_LED_CLR_NONE
) ||
1090 (*colour_p
> ENVMON_LED_CLR_RED
))
1091 syslog(LOG_ERR
, EM_INVALID_COLOR
, *colour_p
, id
);
1093 *colour_p
= ENVMON_LED_CLR_NONE
;
1097 cptr
++; /* step over '.' */
1099 if (strcmp(cptr
, LED_ACT
) == 0)
1100 *colour_p
= ENVMON_LED_CLR_GREEN
;
1101 else if (strcmp(cptr
, LED_SERVICE
) == 0)
1102 *colour_p
= ENVMON_LED_CLR_AMBER
;
1103 else if (strcmp(cptr
, LED_LOCATE
) == 0)
1104 *colour_p
= ENVMON_LED_CLR_WHITE
;
1105 else if (strcmp(cptr
, LED_OK2RM
) == 0)
1106 *colour_p
= ENVMON_LED_CLR_BLUE
;
1108 *colour_p
= ENVMON_LED_CLR_NONE
;
1112 * Add nodes for environmental devices of type fru_type
1113 * below the supplied node.
1116 add_env_nodes(int envmon_fd
, uint8_t fru_type
, picl_nodehdl_t envmonh
)
1119 envmon_thresholds_t lows
;
1120 envmon_thresholds_t highs
;
1121 char units
[ENVMON_MAXNAMELEN
];
1122 char platform_tree_name
[ENVMON_MAXNAMELEN
];
1123 char label_name
[ENVMON_MAXNAMELEN
];
1124 int16_t sensor_data
;
1127 envmon_keysw_pos_t key_state
;
1128 envmon_chassis_t chassis_num
;
1131 int index
= handle_arr
.num
;
1132 picl_nodehdl_t node_hdl
;
1135 * catch table is full at start
1137 if (index
>= handle_arr
.maxnum
)
1138 return (PICL_FAILURE
);
1140 cmd
= fru_to_cmd
[fru_type
];
1144 lows
.warning
= lows
.shutdown
= lows
.poweroff
=
1145 ENVMON_VAL_UNAVAILABLE
;
1146 highs
.warning
= highs
.shutdown
= highs
.poweroff
=
1147 ENVMON_VAL_UNAVAILABLE
;
1148 handle_arr
.fru_types
[index
] = fru_type
;
1149 /* must store id before reading data as it is then updated */
1150 handle_arr
.envhandles
[index
] = id
;
1152 * read environmental data according to type
1155 case ENVMON_VOLT_SENS
:
1157 case ENVMON_AMP_SENS
:
1159 case ENVMON_TEMP_SENS
:
1160 err
= get_sensor_data(envmon_fd
, &id
, cmd
, &lows
,
1161 &highs
, &sensor_data
);
1163 case ENVMON_VOLT_IND
:
1165 case ENVMON_AMP_IND
:
1167 case ENVMON_TEMP_IND
:
1169 case ENVMON_FAN_IND
:
1170 err
= get_indicator_data(envmon_fd
, &id
, cmd
,
1173 case ENVMON_FAN_SENS
:
1174 err
= get_fan_data(envmon_fd
, &id
, cmd
, &lows
,
1175 (uint16_t *)&sensor_data
, units
);
1177 case ENVMON_LED_IND
:
1178 err
= get_led_data(envmon_fd
, &id
, cmd
, &led_state
,
1181 case ENVMON_KEY_SWITCH
:
1182 err
= get_keyswitch_data(envmon_fd
, &id
, cmd
,
1185 case ENVMON_CHASSIS
:
1186 err
= get_serial_num(envmon_fd
, &id
, cmd
,
1190 return (PICL_FAILURE
);
1193 if (err
== PICL_INVALIDHANDLE
)
1195 if ((err
!= PICL_SUCCESS
) && (err
!= PICL_PROPVALUNAVAILABLE
)) {
1196 syslog(LOG_ERR
, EM_NODE_ACCESS
, id
, fru_type
, err
);
1201 * successfully read environmental data, add to PICL
1203 (void) strlcpy(platform_tree_name
,
1204 handle_arr
.envhandles
[index
].name
,
1205 sizeof (platform_tree_name
));
1207 (void) strlcpy(label_name
, platform_tree_name
,
1209 convert_label_name(label_name
);
1210 convert_node_name(platform_tree_name
);
1212 * does this node already exist?
1214 err
= get_child_by_name(envmonh
, platform_tree_name
, &node_hdl
);
1215 if (err
== PICL_SUCCESS
) {
1217 * skip over existing node
1221 err
= ptree_create_node(platform_tree_name
,
1222 fru_to_class
[fru_type
], &node_hdl
);
1223 if (err
!= PICL_SUCCESS
) {
1226 err
= add_volatile_prop(node_hdl
, fru_to_prop
[fru_type
],
1227 fru_to_ptype
[fru_type
],
1228 PICL_READ
| (fru_type
== ENVMON_LED_IND
? PICL_WRITE
: 0),
1229 fru_to_size
[fru_type
], read_vol_data
,
1230 fru_type
== ENVMON_LED_IND
? write_led_data
: NULL
,
1231 &handle_arr
.piclprhdls
[index
]);
1232 if (err
!= PICL_SUCCESS
) {
1237 * if any thresholds are defined add a property
1239 if (lows
.warning
!= ENVMON_VAL_UNAVAILABLE
) {
1240 err
= add_value_prop(node_hdl
, PICL_PROP_LOW_WARNING
,
1241 fru_type
, lows
.warning
);
1242 if (err
!= PICL_SUCCESS
) {
1246 if (lows
.shutdown
!= ENVMON_VAL_UNAVAILABLE
) {
1247 err
= add_value_prop(node_hdl
, PICL_PROP_LOW_SHUTDOWN
,
1248 fru_type
, lows
.shutdown
);
1249 if (err
!= PICL_SUCCESS
) {
1253 if (lows
.poweroff
!= ENVMON_VAL_UNAVAILABLE
) {
1254 err
= add_value_prop(node_hdl
, PICL_PROP_LOW_POWER_OFF
,
1255 fru_type
, lows
.poweroff
);
1256 if (err
!= PICL_SUCCESS
) {
1260 if (highs
.warning
!= ENVMON_VAL_UNAVAILABLE
) {
1261 err
= add_value_prop(node_hdl
, PICL_PROP_HIGH_WARNING
,
1262 fru_type
, highs
.warning
);
1263 if (err
!= PICL_SUCCESS
) {
1267 if (highs
.shutdown
!= ENVMON_VAL_UNAVAILABLE
) {
1268 err
= add_value_prop(node_hdl
, PICL_PROP_HIGH_SHUTDOWN
,
1269 fru_type
, highs
.shutdown
);
1270 if (err
!= PICL_SUCCESS
) {
1274 if (highs
.poweroff
!= ENVMON_VAL_UNAVAILABLE
) {
1275 err
= add_value_prop(node_hdl
, PICL_PROP_HIGH_POWER_OFF
,
1276 fru_type
, highs
.poweroff
);
1277 if (err
!= PICL_SUCCESS
) {
1283 * if device is a fan sensor, add a speedunit property
1285 if (fru_type
== ENVMON_FAN_SENS
) {
1286 err
= add_regular_prop(node_hdl
,
1287 PICL_PROP_FAN_SPEED_UNIT
, PICL_PTYPE_CHARSTRING
,
1288 PICL_READ
, 1 + strlen(units
), units
, NULL
);
1289 if (err
!= PICL_SUCCESS
) {
1294 * If device is a LED indicator and returns a colour,
1295 * add a colour property.
1297 if (fru_type
== ENVMON_LED_IND
) {
1298 if (colour
< 0 || colour
== ENVMON_LED_CLR_ANY
||
1299 colour
> ENVMON_LED_CLR_RED
)
1300 fix_led_colour(&colour
,
1301 handle_arr
.envhandles
[index
].name
);
1302 if (colour
!= ENVMON_LED_CLR_NONE
) {
1303 err
= add_regular_prop(node_hdl
,
1304 PICL_PROP_COLOR
, PICL_PTYPE_CHARSTRING
,
1305 PICL_READ
, colour_lkup
[colour
].size
,
1306 colour_lkup
[colour
].str_colour
, NULL
);
1307 if (err
!= PICL_SUCCESS
) {
1313 * add a label property unless it's a keyswitch or the
1314 * chassis serial number. keyswitch and chassis serial
1315 * number are labelled from a config file because the
1316 * ALOM interface doesn't supply a name for it)
1318 if ((fru_type
!= ENVMON_KEY_SWITCH
) &&
1319 (fru_type
!= ENVMON_CHASSIS
)) {
1320 err
= add_regular_prop(node_hdl
, PICL_PROP_LABEL
,
1321 PICL_PTYPE_CHARSTRING
, PICL_READ
,
1322 1 + strlen(label_name
), label_name
, NULL
);
1324 if (err
!= PICL_SUCCESS
) {
1329 * all properties added to this node, add the node below
1330 * the supplied anchor point
1332 err
= ptree_add_node(envmonh
, node_hdl
);
1334 if (err
!= PICL_SUCCESS
) {
1339 * that node went in OK, advance index
1343 } while ((id
.name
[0] != '\0') && (index
< handle_arr
.maxnum
));
1345 handle_arr
.num
= index
;
1350 fixstate(uint8_t state
, const char *string
, int *max_len
)
1355 for (i
= 0; i
< (sizeof (ledstate_lkup
) / sizeof (ledstate_lkup
[0]));
1357 if (ledstate_lkup
[i
].state
== state
) {
1358 free(ledstate_lkup
[i
].str_ledstate
);
1359 ledstate_lkup
[i
].str_ledstate
= strdup(string
);
1360 len
= strlen(string
);
1361 if (len
>= *max_len
)
1369 fixkeyposn(envmon_keysw_pos_t keyposn
, const char *string
, int *max_len
)
1374 for (i
= 0; i
< (sizeof (keyposn_lkup
) / sizeof (keyposn_lkup
[0]));
1376 if (keyposn_lkup
[i
].pos
== keyposn
) {
1377 free(keyposn_lkup
[i
].str_keyposn
);
1378 keyposn_lkup
[i
].str_keyposn
= strdup(string
);
1379 len
= strlen(string
);
1380 if (len
>= *max_len
)
1392 int lim
= sizeof (colour_lkup
) / sizeof (colour_lkup
[0]);
1395 * initialise led colours lookup
1397 for (i
= 0; i
< lim
; i
++) {
1398 free(colour_lkup
[i
].str_colour
);
1401 colour_lkup
[ENVMON_LED_CLR_ANY
].str_colour
= strdup(gettext("any"));
1402 colour_lkup
[ENVMON_LED_CLR_WHITE
].str_colour
=
1403 strdup(gettext("white"));
1404 colour_lkup
[ENVMON_LED_CLR_BLUE
].str_colour
= strdup(gettext("blue"));
1405 colour_lkup
[ENVMON_LED_CLR_GREEN
].str_colour
=
1406 strdup(gettext("green"));
1407 colour_lkup
[ENVMON_LED_CLR_AMBER
].str_colour
=
1408 strdup(gettext("amber"));
1409 colour_lkup
[ENVMON_LED_CLR_RED
].str_colour
=
1410 strdup(gettext("red"));
1412 for (i
= 0; i
< lim
; i
++) {
1413 if (colour_lkup
[i
].str_colour
!= NULL
)
1414 colour_lkup
[i
].size
=
1415 1 + strlen(colour_lkup
[i
].str_colour
);
1419 * initialise condition strings and note longest
1422 cond_okay
= strdup(gettext("okay"));
1423 if (strlen(cond_okay
) >= string_size
)
1424 string_size
= 1 + strlen(cond_okay
);
1425 cond_failed
= strdup(gettext("failed"));
1426 if (strlen(cond_failed
) >= string_size
)
1427 string_size
= 1 + strlen(cond_failed
);
1429 for (i
= 0; i
< sizeof (fru_to_size
) / sizeof (fru_to_size
[0]); i
++)
1430 if (fru_to_size
[i
] == -1)
1431 fru_to_size
[i
] = string_size
;
1434 * initialise led state lookup strings
1437 fixstate(ENVMON_LED_OFF
, gettext("off"), &string_size
);
1438 fixstate(ENVMON_LED_ON
, gettext("on"), &string_size
);
1439 fixstate(ENVMON_LED_BLINKING
, gettext("blinking"), &string_size
);
1440 fixstate(ENVMON_LED_FLASHING
, gettext("flashing"), &string_size
);
1441 fru_to_size
[ENVMON_LED_IND
] = string_size
;
1444 * initialise key position lookup strings
1447 fixkeyposn(ENVMON_KEYSW_POS_UNKNOWN
, gettext("UNKNOWN"), &string_size
);
1448 fixkeyposn(ENVMON_KEYSW_POS_NORMAL
, gettext("NORMAL"), &string_size
);
1449 fixkeyposn(ENVMON_KEYSW_POS_DIAG
, gettext("DIAG"), &string_size
);
1450 fixkeyposn(ENVMON_KEYSW_POS_LOCKED
, gettext("LOCKED"), &string_size
);
1451 fixkeyposn(ENVMON_KEYSW_POS_OFF
, gettext("STBY"), &string_size
);
1452 fru_to_size
[ENVMON_KEY_SWITCH
] = string_size
;
1455 * initialise chassis serial number string
1457 fru_to_size
[ENVMON_CHASSIS
] = ENVMON_MAXNAMELEN
;
1461 * The size of outfilename must be PATH_MAX
1464 get_config_file(char *filename
)
1466 char nmbuf
[SYS_NMLN
];
1467 char pname
[PATH_MAX
];
1469 if (sysinfo(SI_PLATFORM
, nmbuf
, sizeof (nmbuf
)) != -1) {
1470 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
1471 (void) strlcat(pname
, ENVMON_CONFFILE_NAME
, PATH_MAX
);
1472 if (access(pname
, R_OK
) == 0) {
1473 (void) strlcpy(filename
, pname
, PATH_MAX
);
1478 if (sysinfo(SI_MACHINE
, nmbuf
, sizeof (nmbuf
)) != -1) {
1479 (void) snprintf(pname
, PATH_MAX
, PICLD_PLAT_PLUGIN_DIRF
, nmbuf
);
1480 (void) strlcat(pname
, ENVMON_CONFFILE_NAME
, PATH_MAX
);
1481 if (access(pname
, R_OK
) == 0) {
1482 (void) strlcpy(filename
, pname
, PATH_MAX
);
1487 (void) snprintf(pname
, PATH_MAX
, "%s/%s",
1488 PICLD_COMMON_PLUGIN_DIR
, ENVMON_CONFFILE_NAME
);
1490 if (access(pname
, R_OK
) == 0) {
1491 (void) strlcpy(filename
, pname
, PATH_MAX
);
1499 free_vol_prop(picl_prophdl_t proph
)
1503 index
= find_picl_handle(proph
);
1506 if (index
!= handle_arr
.num
) {
1507 /* relocate last entry into hole just created */
1508 handle_arr
.fru_types
[index
] =
1509 handle_arr
.fru_types
[handle_arr
.num
];
1510 handle_arr
.envhandles
[index
] =
1511 handle_arr
.envhandles
[handle_arr
.num
];
1512 handle_arr
.piclprhdls
[index
] =
1513 handle_arr
.piclprhdls
[handle_arr
.num
];
1519 * handle PICL FRU ADDED and FRU REMOVED events
1523 envmon_evhandler(const char *ename
, const void *earg
, size_t size
,
1526 char path
[MAXPATHLEN
];
1527 picl_nodehdl_t locnodeh
;
1529 picl_nodehdl_t childh
;
1530 picl_nodehdl_t nodeh
;
1531 picl_prophdl_t tableh
;
1532 picl_prophdl_t tblh
;
1533 picl_prophdl_t proph
;
1534 ptree_propinfo_t pi
;
1536 if (strcmp(ename
, PICL_FRU_ADDED
) == 0) {
1537 retval
= nvlist_lookup_uint64((nvlist_t
*)earg
,
1538 PICLEVENTARG_PARENTHANDLE
, &locnodeh
);
1541 syslog(LOG_ERR
, EM_EV_MISSING_ARG
,
1542 PICLEVENTARG_PARENTHANDLE
);
1545 retval
= ptree_get_propval_by_name(locnodeh
, PICL_PROP_NAME
,
1546 path
, sizeof (path
));
1547 if (retval
== PICL_SUCCESS
) {
1549 * Open envmon device and interrogate
1553 picl_nodehdl_t envmoninfh
;
1555 if (get_envmon_node(&envmoninfh
) != PICL_SUCCESS
) {
1556 syslog(LOG_ERR
, EM_SC_NODE_MISSING
);
1560 if ((envmon_fd
= open(envmon_device_name
, O_RDONLY
)) <
1562 syslog(LOG_ERR
, EM_SYS_ERR
, envmon_device_name
,
1567 if (strcmp(str_SC
, path
) == 0) {
1569 * SC state change - re-assess platform tree
1571 if (re_create_arrays(envmon_fd
) != 0) {
1573 * out of memory - make no changes
1578 * dropped memory of volatile prop handles
1579 * so drop the nodes also, then rebuild for
1580 * the newly loaded SC
1582 retval
= ptree_get_propval_by_name(envmoninfh
,
1583 PICL_PROP_PARENT
, &nodeh
, sizeof (nodeh
));
1584 if (retval
!= PICL_SUCCESS
) {
1585 (void) close(envmon_fd
);
1588 retval
= ptree_get_propval_by_name(envmoninfh
,
1589 PICL_PROP_NAME
, path
, sizeof (path
));
1590 if (retval
!= PICL_SUCCESS
) {
1591 (void) close(envmon_fd
);
1595 retval
= ptree_delete_node(envmoninfh
);
1596 if (retval
== PICL_SUCCESS
)
1597 (void) ptree_destroy_node(envmoninfh
);
1598 retval
= ptree_create_node(path
,
1599 PICL_CLASS_SERVICE_PROCESSOR
, &envmoninfh
);
1600 if (retval
!= PICL_SUCCESS
) {
1601 (void) close(envmon_fd
);
1604 retval
= ptree_add_node(nodeh
, envmoninfh
);
1605 if (retval
!= PICL_SUCCESS
) {
1606 (void) close(envmon_fd
);
1611 for (fru_type
= 0; fru_type
< ENVMONTYPES
;
1613 (void) add_env_nodes(envmon_fd
, fru_type
,
1617 (void) close(envmon_fd
);
1619 } else if (strcmp(ename
, PICL_FRU_REMOVED
) == 0) {
1620 retval
= nvlist_lookup_uint64((nvlist_t
*)earg
,
1621 PICLEVENTARG_FRUHANDLE
, &childh
);
1624 syslog(LOG_ERR
, EM_EV_MISSING_ARG
,
1625 PICLEVENTARG_FRUHANDLE
);
1628 retval
= ptree_get_propval_by_name(childh
, PICL_PROP_NAME
,
1629 path
, sizeof (path
));
1630 if (retval
== PICL_SUCCESS
) {
1631 retval
= ptree_get_prop_by_name(childh
,
1632 PICL_PROP_DEVICES
, &tableh
);
1634 if (retval
!= PICL_SUCCESS
) {
1635 /* no Devices table, nothing to do */
1640 * follow all reference properties in the second
1641 * column of the table and delete the referenced node
1643 retval
= ptree_get_propval(tableh
, &tblh
,
1645 if (retval
!= PICL_SUCCESS
) {
1647 * can't get value of table property
1651 /* get first col, first row */
1652 retval
= ptree_get_next_by_col(tblh
, &tblh
);
1653 if (retval
!= PICL_SUCCESS
) {
1660 * starting at next col, get every entry in the column
1662 for (retval
= ptree_get_next_by_row(tblh
, &tblh
);
1663 retval
== PICL_SUCCESS
;
1664 retval
= ptree_get_next_by_col(tblh
, &tblh
)) {
1666 * should be a ref prop in our hands,
1667 * get the target node handle
1669 retval
= ptree_get_propval(tblh
, &nodeh
,
1671 if (retval
!= PICL_SUCCESS
) {
1675 * got the referenced node, has it got a
1676 * volatile property to clean up?
1678 retval
= ptree_get_first_prop(nodeh
, &proph
);
1679 while (retval
== PICL_SUCCESS
) {
1680 retval
= ptree_get_propinfo(proph
, &pi
);
1681 if ((retval
== PICL_SUCCESS
) &&
1682 (pi
.piclinfo
.accessmode
&
1684 free_vol_prop(proph
);
1685 retval
= ptree_get_next_prop(proph
,
1689 * all volatile properties gone, remove node
1691 retval
= ptree_delete_node(nodeh
);
1692 if (retval
== PICL_SUCCESS
)
1693 (void) ptree_destroy_node(nodeh
);
1700 * executed as part of .init when the plugin is dlopen()ed
1703 piclenvmon_register(void)
1705 (void) picld_plugin_register(&my_reg_info
);
1709 * Init entry point of the plugin
1710 * Creates the PICL nodes and properties in the physical and logical aspects.
1713 piclenvmon_init(void)
1715 picl_nodehdl_t rooth
;
1716 picl_nodehdl_t plfh
;
1717 picl_nodehdl_t envmoninfh
;
1721 char pathname
[PATH_MAX
];
1724 * locate and parse config file
1726 if (get_config_file(pathname
) < 0)
1729 if ((ptree_get_root(&rooth
) != PICL_SUCCESS
) ||
1730 (picld_pluginutil_parse_config_file(rooth
, pathname
) !=
1732 syslog(LOG_ERR
, EM_INIT_FAILED
);
1738 if (ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM
, &plfh
)
1740 syslog(LOG_ERR
, EM_MISSING_NODE
, PICL_NODE_PLATFORM
);
1741 syslog(LOG_ERR
, EM_INIT_FAILED
);
1746 * Get service-processor node
1748 if (get_envmon_node(&envmoninfh
) != PICL_SUCCESS
)
1752 * We may have been restarted, make sure we don't leak
1754 if (envmon_device_name
!= NULL
) {
1755 free(envmon_device_name
);
1758 if ((envmon_device_name
= create_envmon_pathname(envmoninfh
)) == NULL
)
1762 * Open envmon device and interrogate for devices it monitors
1764 if ((envmon_fd
= open(envmon_device_name
, O_RDONLY
)) < 0) {
1765 syslog(LOG_ERR
, EM_SYS_ERR
, envmon_device_name
,
1770 if (get_envmon_limits(envmon_fd
, &env_limits
) < 0)
1774 * A set of arrays are used whose bounds are determined by the
1775 * response to get_envmon_limits. Establish these arrays now.
1780 for (fru_type
= 0; fru_type
< ENVMONTYPES
; fru_type
++) {
1781 (void) add_env_nodes(envmon_fd
, fru_type
, envmoninfh
);
1784 (void) close(envmon_fd
);
1786 res
= ptree_register_handler(PICL_FRU_ADDED
, envmon_evhandler
, NULL
);
1787 if (res
!= PICL_SUCCESS
) {
1788 syslog(LOG_ERR
, EM_EVREG_FAILED
, res
);
1790 res
= ptree_register_handler(PICL_FRU_REMOVED
, envmon_evhandler
, NULL
);
1791 if (res
!= PICL_SUCCESS
) {
1792 syslog(LOG_ERR
, EM_EVREG_FAILED
, res
);
1797 * fini entry point of the plugin
1800 piclenvmon_fini(void)
1802 if (envmon_device_name
!= NULL
) {
1803 free(envmon_device_name
);
1804 envmon_device_name
= NULL
;
1806 (void) ptree_unregister_handler(PICL_FRU_ADDED
,
1807 envmon_evhandler
, NULL
);
1808 (void) ptree_unregister_handler(PICL_FRU_REMOVED
,
1809 envmon_evhandler
, NULL
);