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 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This plugin-in creates the FRU Hierarchy for the
31 * SUNW,Netra-T12 platform and manages the environmental sensors
46 #include <libnvpair.h>
47 #include <sys/param.h>
49 #include <config_admin.h>
50 #include <sys/sbd_ioctl.h>
51 #include <sys/sgfrutree.h>
52 #include <sys/sgenv.h>
53 #include <sys/ioccom.h>
55 #include <sys/sysevent/dr.h>
57 #include <sys/obpdefs.h>
58 #include "libdevice.h"
64 * Plugin registration entry points
66 static void piclfrutree_register(void);
67 static void piclfrutree_init(void);
68 static void piclfrutree_fini(void);
69 #pragma init(piclfrutree_register)
71 static picld_plugin_reg_t my_reg_info
= {
72 PICLD_PLUGIN_VERSION_1
,
73 PICLD_PLUGIN_CRITICAL
,
74 "SUNW_Netra-T12_frutree",
82 #define DEV_OPEN_FAIL gettext("piclfrutree_init: open of %s failed: %s")
83 #define ADD_NODES_FAIL gettext("piclfrutree_init: add_all_nodes failed: %d")
84 #define GET_ROOT_FAIL gettext("piclfrutree_init: ptree_get_root failed")
85 #define ADD_FRUTREE_FAIL gettext("piclfrutree_init: add frutree failed")
86 #define INVALID_PICL_CLASS gettext("add_subtree: invalid picl class 0x%x")
87 #define ADD_NODE_FAIL gettext("ptree_create_and_add_node %s failed: %d")
88 #define GET_NEXT_BY_ROW_FAIL gettext("ptree_get_next_by_row %s failed: %d")
89 #define PROPINFO_FAIL gettext("ptree_init_propinfo %s failed: %d")
90 #define GET_PROPVAL_FAIL gettext("ptree_get_propval failed: %d")
91 #define DELETE_PROP_FAIL gettext("ptree_delete_prop failed: %d")
92 #define DELETE_NODE_FAIL gettext("ptree_delete_node failed: %d")
93 #define ADD_PROP_FAIL gettext("ptree_create_and_add_prop %s failed: %d")
94 #define SGFRU_IOCTL_FAIL gettext("sgfru ioctl 0x%x handle 0x%llx failed: %s")
95 #define LED_IOCTL_FAIL gettext("led ioctl failed: %s")
96 #define MALLOC_FAIL gettext("piclfrutree: malloc failed")
97 #define NO_SC_FAIL gettext("piclfrutree: cannot find sc node")
98 #define NO_NODE_FAIL gettext("piclfrutree: cannot find node %s: %d")
99 #define KSTAT_FAIL gettext("piclfrutree: failure accessing kstats")
100 #define ADD_TBL_ENTRY_FAIL gettext("piclfrutree: cannot add entry to table")
101 #define PROP_LOOKUP_FAIL gettext("piclfrutree: cannot find %s property: %d")
102 #define EM_DI_INIT_FAIL gettext("frutree: di_init failed: %s")
103 #define EM_THREAD_CREATE_FAILED gettext("frutree: pthread_create failed: %s")
104 #define EM_MUTEX_FAIL gettext("frutree: pthread_mutex_lock returned: %s")
105 #define EM_POLL_FAIL gettext("frutree: poll() failed: %s")
106 #define DEVCTL_DEVICE_ACQUIRE_FAILED \
107 gettext("frutree: devctl_device_acquire() failed: %s")
110 * PICL property values
112 #define PICL_PROPVAL_TRUE "true"
113 #define PICL_PROPVAL_SYSTEM "system"
114 #define PICL_PROPVAL_ON "ON"
115 #define PICL_PROPVAL_OFF "OFF"
116 #define PICL_PROPVAL_BLINKING "BLINKING"
117 #define PICL_PROPVAL_FLASHING "FLASHING"
118 #define PICL_PROPVAL_CHASSIS "chassis"
119 #define PICL_PROPVAL_AMBIENT "Ambient"
120 #define PICL_PROPVAL_DIE "Die"
121 #define PICL_PROPVAL_GREEN "green"
122 #define PICL_PROPVAL_AMBER "amber"
123 #define PICL_PROPVAL_OKAY "okay"
124 #define PICL_PROPVAL_FAILED "failed"
125 #define PICL_PROPVAL_WARNING "warning"
126 #define PICL_PROPVAL_DISABLED "disabled"
127 #define PICL_PROPVAL_UNKNOWN "unknown"
128 #define PICL_PROPVAL_SELF_REGULATING "self-regulating"
129 #define PICL_PROPVAL_PER_CENT "%"
130 #define PICL_PROP_BANK_STATUS "bank-status"
133 * PICL property names
135 #define PICL_PROP_LOW_WARNING_THRESHOLD "LowWarningThreshold"
140 #define MAX_LINE_SIZE 1024
142 #define MAX_SPEED_UNIT_LEN 20
143 #define MAX_OPERATIONAL_STATUS_LEN 10
144 #define MAX_CONDITION_LEN 10
145 #define MAX_LABEL_LEN 256
146 #define MAX_STATE_LEN 10
147 #define MAX_STATE_SIZE 32
148 #define LED_PSEUDO_DEV "/devices/pseudo/lw8@0:lw8"
149 #define SC_DEV "/platform/ssm@0,0/pci@18,700000/bootbus-controller@4"
150 #define SC_DEV_PCIX "/platform/ssm@0,0/pci@18,700000/pci@4/bootbus-controller@3"
151 #define CPU_DEV "/platform/ssm@0,0/SUNW,UltraSPARC-III@%x,0"
152 #define CPU_DEV2 "/platform/ssm@0,0/SUNW,UltraSPARC-III+@%x,0"
153 #define CPU_DEV3C0 "/platform/ssm@0,0/cmp@%x,0/cpu@0"
154 #define CPU_DEV3C1 "/platform/ssm@0,0/cmp@%x,0/cpu@1"
155 #define MEMORY_DEV "/platform/ssm@0,0/memory-controller@%x,400000"
156 #define IO_DEV "/platform/ssm@0,0/pci@%s"
157 #define DISK0_BASE_PATH "/ssm@0,0/pci@18,600000/scsi@2/sd@0,0"
158 #define DISK0_DEV "/platform" DISK0_BASE_PATH
159 #define DISK1_BASE_PATH "/ssm@0,0/pci@18,600000/scsi@2/sd@1,0"
160 #define DISK1_DEV "/platform" DISK1_BASE_PATH
161 #define DISK0_BASE_PATH_PCIX "/ssm@0,0/pci@18,700000/scsi@2/sd@0,0"
162 #define DISK0_DEV_PCIX "/platform" DISK0_BASE_PATH_PCIX
163 #define DISK1_BASE_PATH_PCIX "/ssm@0,0/pci@18,700000/scsi@2/sd@1,0"
164 #define DISK1_DEV_PCIX "/platform" DISK1_BASE_PATH_PCIX
165 #define TAPE_DEV "/platform/ssm@0,0/pci@18,600000/scsi@2/st@5,0"
166 #define TAPE_DEV_PCIX "/platform/ssm@0,0/pci@18,700000/scsi@2/st@5,0"
167 #define DVD_DEV "/platform/ssm@0,0/pci@18,700000/ide@3/sd@0,0"
168 #define DVD_DEV_PCIX "/platform/ssm@0,0/pci@18,700000/pci@4/ide@2/sd@0,0"
169 #define CHASSIS_PATH "/frutree/chassis"
170 #define CHASSIS_LOC_PATH "/frutree/chassis/%s"
171 #define PROC_LOC_PATH "/frutree/chassis/SB%d/SB%d/P%d"
172 #define PROC_FRU_PATH "/frutree/chassis/SB%d/SB%d/P%d/P%d"
174 * Calculate safari address to put in CPU_DEV/MEMORY_DEV string based on
175 * SBx/Py fru path name
177 #define SB_P_TO_SAFARI_ADDR(sbname, pname) \
178 ((pname[1] - '0') + (4 * (sbname[2] - '0')))
179 #define SAFARI_ADDR_TO_SB(value) (value >> 2)
180 #define SAFARI_ADDR_TO_P(value) (value & 3)
181 #define AP_ID_PREAMBLE "ssm0:N0."
182 #define AP_ID_PREAMBLE_LEN 8
183 #define LABEL_PREAMBLE "N0/"
184 #define LABEL_PREAMBLE_LEN 3
186 * work out type of fru based on name
188 #define IS_ECACHE_NODE(name) (name[0] == 'E')
189 #define IS_DIMM_NODE(name) (name[0] == 'D' && name[1] != 'V')
190 #define IS_PROC_NODE(name) (name[0] == 'P' && name[1] != 'S')
191 #define IS_PSU_NODE(name) (name[0] == 'P' && name[1] == 'S')
192 #define IS_SB_NODE(name) (name[0] == 'S' && name[1] == 'B')
193 #define IS_IB_NODE(name) (name[0] == 'I')
194 #define IS_FT_NODE(name) (name[0] == 'F' && name[1] == 'T')
195 #define IS_FAN_NODE(name) (name[0] == 'F' && name[1] != 'T')
196 #define IS_RP_NODE(name) (name[0] == 'R')
198 * rename sgfru driver's node_t to sgfrunode_t to avoid confusion
200 #define sgfrunode_t node_t
205 #define REMOK_LED "ok_to_remove"
206 #define FAULT_LED "fault"
207 #define POWER_LED "power"
210 * 'struct lw8_disk' contains the per-disk metadata needed to
211 * manage the current state of one of the internal disks.
213 * 'lw8_disks[]' is an array that contains the metadata
216 * The d_fruname field of 'struct lw8_disk' is static.
217 * d_plat_path and d_devices_path are aliases for device-paths
218 * to the disk. They are logically static, as they are computed
219 * when the disk_leds_thread() thread does its initialization.
221 * d_state is the most interesting field, as it changes
222 * dynamically, based on whether the associated disk
223 * is currently Configured or Unconfigured (by DR). d_state
224 * is an optimization that minimizes per-disk actions such
225 * as setting of LEDs and updating the FRU Tree.
227 * A disk starts in a d_state of DISK_STATE_NOT_INIT
228 * and moves to DISK_STATE_READY when the disk is
229 * Configured (by DR) and it moves to DISK_STATE_NOT_READY
230 * when it is Unconfigured (by DR).
239 char *d_fruname
; /* FRU name */
240 char *d_plat_path
; /* /platform */
241 char *d_devices_path
; /* /devices */
242 disk_state_t d_state
;
246 static struct lw8_disk lw8_disks
[N_DISKS
] = {
247 {"DISK0", NULL
, NULL
, DISK_STATE_NOT_INIT
},
248 {"DISK1", NULL
, NULL
, DISK_STATE_NOT_INIT
} };
250 /* Duration of inactivity within disk_leds_thread() */
251 #define THR_POLL_PERIOD 5000 /* milliseconds */
253 static volatile boolean_t disk_leds_thread_ack
= B_FALSE
;
254 static pthread_t ledsthr_tid
;
255 static pthread_attr_t ledsthr_attr
;
256 static boolean_t ledsthr_created
= B_FALSE
;
257 static uint_t ledsthr_poll_period
=
259 static boolean_t g_mutex_init
= B_FALSE
;
260 static pthread_cond_t g_cv
;
261 static pthread_cond_t g_cv_ack
;
262 static pthread_mutex_t g_mutex
;
263 static volatile boolean_t g_wait_now
= B_FALSE
;
265 static void disk_leds_init(void);
266 static void disk_leds_fini(void);
267 static void *disk_leds_thread(void *args
);
270 * Tables to convert sgenv information
272 static char *hpu_type_table
[] = { "", "SSC", "SB", "RP", "FT",
274 static char *hpu_fru_type_table
[] = { "", "SSC", "CPU", "RP", "FT",
276 static char *hpu_part_table
[] = { "", "sbbc", "sdc",
277 "ar", "cbh", "dx", "cheetah", "1.5vdc", "3.3vdc",
278 "5vdc", "12vdc", "output", "current", "board", "sc-app",
279 "schizo", "fan", "input"};
280 static char *hpu_sensor_table
[] = { "", "", "current",
281 "temp", "cooling", "1.5vdc", "1.8vdc", "3.3vdc", "5vdc",
282 "12vdc", "48vdc", NULL
, "2.4vdc"};
283 static char *hpu_sensor_class_table
[] = { "", "", PICL_CLASS_CURRENT_SENSOR
,
284 PICL_CLASS_TEMPERATURE_SENSOR
, PICL_CLASS_FAN
,
285 PICL_CLASS_VOLTAGE_SENSOR
, PICL_CLASS_VOLTAGE_SENSOR
,
286 PICL_CLASS_VOLTAGE_SENSOR
, PICL_CLASS_VOLTAGE_SENSOR
,
287 PICL_CLASS_VOLTAGE_SENSOR
, PICL_CLASS_VOLTAGE_INDICATOR
,
288 NULL
, PICL_CLASS_VOLTAGE_SENSOR
};
289 static char *hpu_sensor_prop_table
[] = { "", "", PICL_PROP_CURRENT
,
290 PICL_PROP_TEMPERATURE
, PICL_PROP_FAN_SPEED
, PICL_PROP_VOLTAGE
,
291 PICL_PROP_VOLTAGE
, PICL_PROP_VOLTAGE
, PICL_PROP_VOLTAGE
,
292 PICL_PROP_VOLTAGE
, PICL_PROP_CONDITION
, NULL
, PICL_PROP_VOLTAGE
};
293 static char *hpu_condition_table
[] = {"unknown", "okay", "failing",
294 "failed", "unusable"};
297 * variables set up in init
299 static picl_nodehdl_t frutreeh
;
300 static picl_nodehdl_t sch
= NULL
;
301 static int init_complete
;
302 static int pcix_io
= 0;
307 static int add_all_nodes(void);
308 static int remove_subtree(picl_nodehdl_t parh
);
309 static int add_subtree(picl_nodehdl_t parh
, fru_hdl_t fruparent
);
310 static int add_picl_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
311 picl_nodehdl_t
*childp
);
312 static int add_chassis_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
313 picl_nodehdl_t
*childp
);
314 static int add_fru_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
315 picl_nodehdl_t
*childp
);
316 static int add_location_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
317 picl_nodehdl_t
*childp
);
318 static int add_led_nodes(picl_nodehdl_t nodeh
, char *name
, int position
,
319 picl_prophdl_t tblhdl
);
320 static int add_env_nodes(picl_nodehdl_t nodeh
, char *nodename
,
321 picl_prophdl_t tblhdl
);
322 static int add_intermediate_nodes(picl_nodehdl_t
*nodep
, char *labelp
,
323 picl_prophdl_t
*tblhdlp
, char *slot_name
, char *fru_name
);
324 static int add_intermediate_location(picl_nodehdl_t
*nodep
, char *labelp
,
326 static int add_pci_location(picl_nodehdl_t childh
, char *parent_addr
,
327 char bus_addr
, char *slot_name
);
328 static picl_nodehdl_t
find_child_by_name(picl_nodehdl_t parh
, char *name
);
329 static int create_dimm_references(picl_nodehdl_t parh
, int dimm_id
,
330 picl_nodehdl_t nodeh
, picl_prophdl_t tblhdl
);
331 static int create_cpu_references(char *pname
, picl_nodehdl_t nodeh
,
332 picl_prophdl_t tblhdl
);
333 static void post_frudr_event(char *ename
, picl_nodehdl_t parenth
,
334 picl_nodehdl_t fruh
);
335 static int remove_references(picl_prophdl_t refprop
, char *class);
336 static int remove_picl_node(picl_nodehdl_t nodeh
);
337 static sgfrunode_t
*get_node_children(fru_hdl_t fruparent
, int *num_childrenp
);
338 static int add_prop_ull(picl_nodehdl_t nodeh
, uint64_t handle
, char *name
);
339 static int add_prop_void(picl_nodehdl_t nodeh
, char *name
);
340 static int add_prop_ref(picl_nodehdl_t nodeh
, picl_nodehdl_t value
, char *name
);
341 static int add_prop_int(picl_nodehdl_t nodeh
, int value
, char *name
);
342 static int add_prop_float(picl_nodehdl_t nodeh
, float value
, char *name
);
343 static int add_prop_charstring(picl_nodehdl_t nodeh
, char *value
, char *name
);
344 static void frudr_evhandler(const char *ename
, const void *earg
,
345 size_t size
, void *cookie
);
346 static void frumemcfg_evhandler(const char *ename
, const void *earg
,
347 size_t size
, void *cookie
);
348 static int add_sensor_prop(picl_nodehdl_t nodeh
, char *class);
349 static int add_sensor_node(picl_nodehdl_t fruhdl
, picl_nodehdl_t lochdl
,
350 char *nodename
, char *class, char *prop_class
,
351 picl_prophdl_t tblhdl
, picl_nodehdl_t
*sensorhdlp
);
352 static int create_table(picl_nodehdl_t fruhdl
, picl_prophdl_t
*tblhdlp
,
354 static int create_table_entry(picl_prophdl_t tblhdl
,
355 picl_nodehdl_t refhdl
, char *class);
356 static int get_sensor_data(ptree_rarg_t
*arg
, void *result
);
357 static int get_led(char *name
, char *ptr
, char *result
);
358 static int get_led_data(ptree_rarg_t
*arg
, void *result
);
359 static int set_led_data(ptree_warg_t
*arg
, const void *value
);
360 static int get_cpu_status(ptree_rarg_t
*arg
, void *result
);
361 static int add_board_status(picl_nodehdl_t nodeh
, char *nodename
);
362 static int get_board_status(ptree_rarg_t
*arg
, void *result
);
363 static int get_op_status(ptree_rarg_t
*arg
, void *result
);
365 #define sprintf_buf2(buf, a1, a2) (void) snprintf(buf, sizeof (buf), a1, a2)
366 #define sprintf_buf3(buf, a1, a2, a3) \
367 (void) snprintf(buf, sizeof (buf), a1, a2, a3)
368 #define sprintf_buf4(buf, a1, a2, a3, a4) \
369 (void) snprintf(buf, sizeof (buf), a1, a2, a3, a4)
370 #define sprintf_buf5(buf, a1, a2, a3, a4, a5) \
371 (void) snprintf(buf, sizeof (buf), a1, a2, a3, a4, a5)
373 * This function is executed as part of .init when the plugin is
377 piclfrutree_register(void)
379 (void) picld_plugin_register(&my_reg_info
);
383 * This function is the init entry point of the plugin.
384 * It initializes the /frutree tree
387 piclfrutree_init(void)
391 (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE
,
392 frudr_evhandler
, NULL
);
393 (void) ptree_register_handler(PICLEVENT_MC_ADDED
,
394 frumemcfg_evhandler
, NULL
);
395 (void) ptree_register_handler(PICLEVENT_MC_REMOVED
,
396 frumemcfg_evhandler
, NULL
);
399 err
= add_all_nodes();
402 if (err
!= PICL_SUCCESS
) {
403 syslog(LOG_ERR
, ADD_NODES_FAIL
, err
);
409 * This function is the fini entry point of the plugin.
412 piclfrutree_fini(void)
414 (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE
,
415 frudr_evhandler
, NULL
);
416 (void) ptree_unregister_handler(PICLEVENT_MC_ADDED
,
417 frumemcfg_evhandler
, NULL
);
418 (void) ptree_unregister_handler(PICLEVENT_MC_REMOVED
,
419 frumemcfg_evhandler
, NULL
);
420 (void) remove_subtree(frutreeh
);
425 * called from piclfrutree_init() to initialise picl frutree
431 picl_nodehdl_t rooth
;
433 /* Get the root node of the PICL tree */
434 err
= ptree_get_root(&rooth
);
435 if (err
!= PICL_SUCCESS
) {
436 syslog(LOG_ERR
, GET_ROOT_FAIL
);
440 /* find sc node so we can create sensor nodes under it */
442 err
= ptree_get_node_by_path(SC_DEV
, &sch
);
443 if (err
!= PICL_SUCCESS
) {
446 * There is a XMITS/PCI-X IO Board assembly implements
447 * a different path for the the bootbus controller.
449 err
= ptree_get_node_by_path(SC_DEV_PCIX
, &sch
);
450 if (err
== PICL_SUCCESS
)
454 if (err
!= PICL_SUCCESS
) {
455 syslog(LOG_ERR
, NO_SC_FAIL
);
459 /* Create and add the root node of the FRU subtree */
460 err
= ptree_create_and_add_node(rooth
, PICL_NODE_FRUTREE
,
461 PICL_CLASS_PICL
, &frutreeh
);
462 if (err
!= PICL_SUCCESS
) {
463 syslog(LOG_ERR
, ADD_FRUTREE_FAIL
);
467 /* Recursively query the SC and add frutree nodes */
468 return (add_subtree(frutreeh
, ROOTPARENT
));
472 * Recursive routine to add picl nodes to the frutree. Called from
473 * add_all_nodes() for the whole frutree at initialisation, and from
474 * frudr_evhandler() for portions of the frutree on DR insert events
477 add_subtree(picl_nodehdl_t parh
, fru_hdl_t handle
)
481 sgfrunode_t
*cp
, *fruchildren
= NULL
;
482 picl_nodehdl_t childh
;
484 /* find children of the parent node */
485 fruchildren
= get_node_children(handle
, &num_children
);
486 if (fruchildren
== NULL
)
487 return (PICL_FAILURE
);
489 /* for each child, add a new picl node */
490 for (i
= 0, cp
= fruchildren
; i
< num_children
; i
++, cp
++) {
492 * Add the appropriate PICL class
495 err
= add_picl_node(parh
, cp
, &childh
);
496 if (err
== PICL_NOTNODE
)
498 if (err
!= PICL_SUCCESS
) {
504 * Recursively call this function based on has_children hint
506 if (childh
&& cp
->has_children
) {
507 err
= add_subtree(childh
, cp
->handle
);
508 if (err
!= PICL_SUCCESS
) {
515 return (PICL_SUCCESS
);
519 * Recursive routine to remove picl nodes to the frutree. Called from
520 * piclfrutree_fini() for the whole frutree at termination, and from
521 * frudr_completion_handler() for portions of the frutree on DR remove events
524 remove_subtree(picl_nodehdl_t parh
)
529 if (ptree_get_propval_by_name(parh
, PICL_PROP_CHILD
, &chdh
,
530 sizeof (picl_nodehdl_t
)) == PICL_SUCCESS
) {
531 if (remove_subtree(chdh
) != PICL_SUCCESS
)
532 return (PICL_FAILURE
);
534 return (remove_picl_node(parh
));
541 * Add fru and location nodes with SC_handle property
542 * (aka, container handle, for frus).
543 * Return picl_nodehdl of created node in *childp.
546 add_picl_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
547 picl_nodehdl_t
*childp
)
549 switch (sgfrunode
->class) {
550 case PSEUDO_FRU_CLASS
:
551 return (add_chassis_node(parh
, sgfrunode
, childp
));
554 return (add_fru_node(parh
, sgfrunode
, childp
));
557 return (add_location_node(parh
, sgfrunode
, childp
));
560 syslog(LOG_ERR
, INVALID_PICL_CLASS
, sgfrunode
->class);
561 return (PICL_NOTNODE
);
566 * create chassis node
569 add_chassis_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
570 picl_nodehdl_t
*childp
)
573 uint64_t handle
= (uint64_t)sgfrunode
->handle
;
574 picl_prophdl_t tblhdl
;
575 picl_nodehdl_t nodeh
;
576 picl_nodehdl_t devhdl
;
577 picl_nodehdl_t childh
;
579 err
= ptree_create_and_add_node(parh
, PICL_PROPVAL_CHASSIS
,
580 PICL_CLASS_FRU
, &childh
);
581 if (err
!= PICL_SUCCESS
) {
582 syslog(LOG_ERR
, ADD_NODE_FAIL
, PICL_PROPVAL_CHASSIS
, err
);
585 err
= add_prop_ull(childh
, handle
, PICL_PROP_SC_HANDLE
);
586 if (err
!= PICL_SUCCESS
)
590 * add devices table to chassis node (may need references
593 err
= create_table(childh
, &tblhdl
, PICL_PROP_DEVICES
);
594 if (err
!= PICL_SUCCESS
)
597 err
= add_led_nodes(childh
, "chassis", LOM_LED_POSITION_FRU
, tblhdl
);
598 if (err
!= PICL_SUCCESS
)
602 err
= ptree_get_node_by_path(DISK0_DEV_PCIX
, &devhdl
);
604 err
= ptree_get_node_by_path(DISK0_DEV
, &devhdl
);
607 if (err
!= PICL_SUCCESS
) {
608 err
= add_intermediate_location(&nodeh
, "DISK0", "disk-slot");
610 err
= add_intermediate_nodes(&nodeh
, "DISK0", &tblhdl
,
612 if (err
!= PICL_SUCCESS
)
614 err
= add_prop_ref(devhdl
, nodeh
, PICL_REFPROP_FRU_PARENT
);
615 if (err
!= PICL_SUCCESS
)
617 err
= create_table_entry(tblhdl
, devhdl
, PICL_CLASS_BLOCK
);
619 if (err
!= PICL_SUCCESS
)
623 err
= ptree_get_node_by_path(DISK1_DEV_PCIX
, &devhdl
);
625 err
= ptree_get_node_by_path(DISK1_DEV
, &devhdl
);
628 if (err
!= PICL_SUCCESS
) {
629 err
= add_intermediate_location(&nodeh
, "DISK1", "disk-slot");
631 err
= add_intermediate_nodes(&nodeh
, "DISK1", &tblhdl
,
633 if (err
!= PICL_SUCCESS
)
635 err
= add_prop_ref(devhdl
, nodeh
, PICL_REFPROP_FRU_PARENT
);
636 if (err
!= PICL_SUCCESS
)
638 err
= create_table_entry(tblhdl
, devhdl
, PICL_CLASS_BLOCK
);
640 if (err
!= PICL_SUCCESS
)
644 err
= ptree_get_node_by_path(TAPE_DEV_PCIX
, &devhdl
);
646 err
= ptree_get_node_by_path(TAPE_DEV
, &devhdl
);
649 if (err
!= PICL_SUCCESS
) {
650 err
= add_intermediate_location(&nodeh
, "TAPE", "tape-slot");
652 err
= add_intermediate_nodes(&nodeh
, "TAPE", &tblhdl
,
654 if (err
!= PICL_SUCCESS
)
656 err
= add_prop_ref(devhdl
, nodeh
, PICL_REFPROP_FRU_PARENT
);
657 if (err
!= PICL_SUCCESS
)
659 err
= create_table_entry(tblhdl
, devhdl
, PICL_CLASS_TAPE
);
661 if (err
!= PICL_SUCCESS
)
665 err
= ptree_get_node_by_path(DVD_DEV_PCIX
, &devhdl
);
667 err
= ptree_get_node_by_path(DVD_DEV
, &devhdl
);
670 if (err
!= PICL_SUCCESS
) {
671 err
= add_intermediate_location(&nodeh
, "DVD", "dvd-slot");
673 err
= add_intermediate_nodes(&nodeh
, "DVD", &tblhdl
,
675 if (err
!= PICL_SUCCESS
)
677 err
= add_prop_ref(devhdl
, nodeh
, PICL_REFPROP_FRU_PARENT
);
678 if (err
!= PICL_SUCCESS
)
680 err
= create_table_entry(tblhdl
, devhdl
, PICL_CLASS_CDROM
);
682 if (err
!= PICL_SUCCESS
)
687 * The XMITS/PCI-X IO Assembly is layed out a bit differently.
689 err
= add_pci_location(childh
, "19,600000", '1', "PCI0");
690 if (err
!= PICL_SUCCESS
)
692 err
= add_pci_location(childh
, "19,600000", '2', "PCI1");
693 if (err
!= PICL_SUCCESS
)
695 err
= add_pci_location(childh
, "19,700000", '1', "PCI2");
696 if (err
!= PICL_SUCCESS
)
698 err
= add_pci_location(childh
, "19,700000", '2', "PCI3");
699 if (err
!= PICL_SUCCESS
)
701 err
= add_pci_location(childh
, "18,600000", '1', "PCI4");
702 if (err
!= PICL_SUCCESS
)
704 err
= add_pci_location(childh
, "18,600000", '2', "PCI5");
705 if (err
!= PICL_SUCCESS
)
708 err
= add_pci_location(childh
, "18,700000", '1', "PCI0");
709 if (err
!= PICL_SUCCESS
)
711 err
= add_pci_location(childh
, "18,700000", '2', "PCI1");
712 if (err
!= PICL_SUCCESS
)
714 err
= add_pci_location(childh
, "19,700000", '1', "PCI2");
715 if (err
!= PICL_SUCCESS
)
717 err
= add_pci_location(childh
, "19,700000", '2', "PCI3");
718 if (err
!= PICL_SUCCESS
)
720 err
= add_pci_location(childh
, "19,700000", '3', "PCI4");
721 if (err
!= PICL_SUCCESS
)
723 err
= add_pci_location(childh
, "18,600000", '1', "PCI5");
724 if (err
!= PICL_SUCCESS
)
728 return (PICL_SUCCESS
);
732 * create fru node, based on sgfru node "sgfrunode" under parent parh. Return
733 * picl_nodehdl of created node in *childp.
736 add_fru_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
737 picl_nodehdl_t
*childp
)
740 picl_prophdl_t tblhdl
;
741 picl_nodehdl_t childh
;
742 uint64_t handle
= (uint64_t)sgfrunode
->handle
;
743 char *nodename
= sgfrunode
->nodename
;
746 * if sgfrunode already there, then just carry on own the tree
748 childh
= find_child_by_name(parh
, nodename
);
749 if (childh
!= NULL
) {
751 * for frus other than dimms and ecaches, update environmental
752 * sensors and board status if necessary
754 if (IS_ECACHE_NODE(nodename
)) {
756 return (PICL_SUCCESS
);
758 if (IS_DIMM_NODE(nodename
)) {
760 * for dimms we just want status
762 err
= add_board_status(childh
, nodename
);
763 if (err
!= PICL_SUCCESS
)
766 return (PICL_SUCCESS
);
768 err
= add_board_status(childh
, nodename
);
769 if (err
!= PICL_SUCCESS
)
771 err
= ptree_get_propval_by_name(childh
, PICL_PROP_DEVICES
,
772 &tblhdl
, sizeof (tblhdl
));
773 if (err
!= PICL_SUCCESS
)
775 err
= add_env_nodes(childh
, nodename
, tblhdl
);
776 if (err
!= PICL_SUCCESS
)
779 return (PICL_SUCCESS
);
783 * create requested fru node
785 err
= ptree_create_and_add_node(parh
, nodename
, PICL_CLASS_FRU
,
787 if (err
!= PICL_SUCCESS
) {
788 syslog(LOG_ERR
, ADD_NODE_FAIL
, nodename
, err
);
793 * if sgfru has sent us a valid handle, then there is fruid information.
794 * create the SC_handle, and FRUDateAvailable properties for FRUID.
796 if (handle
!= -1ULL) {
797 err
= add_prop_ull(childh
, handle
, PICL_PROP_SC_HANDLE
);
798 if (err
!= PICL_SUCCESS
)
800 err
= add_prop_void(childh
, PICL_PROP_FRUDATA_AVAIL
);
801 if (err
!= PICL_SUCCESS
)
806 * post fru added event to fru data plugin if this was due to
807 * a dr event - ie post-initialisation
810 post_frudr_event(PICL_FRU_ADDED
, parh
, NULL
);
813 * Create empty Devices table - we'll add lines to it as we go along
815 err
= create_table(childh
, &tblhdl
, PICL_PROP_DEVICES
);
816 if (err
!= PICL_SUCCESS
)
820 * Ecache nodes don't have sensors - just set up FRUType
822 if (IS_ECACHE_NODE(nodename
)) {
823 err
= add_prop_charstring(childh
, "EEPROM", PICL_PROP_FRU_TYPE
);
824 if (err
!= PICL_SUCCESS
)
827 return (PICL_SUCCESS
);
831 * Dimm nodes don't have sensors - just set up FRUType and
832 * also reference properties to memory module nodes and OpStatus
834 if (IS_DIMM_NODE(nodename
)) {
835 err
= add_prop_charstring(childh
, "DIMM", PICL_PROP_FRU_TYPE
);
836 if (err
!= PICL_SUCCESS
)
838 err
= create_dimm_references(parh
, nodename
[1] - '0',
840 if (err
!= PICL_SUCCESS
)
842 err
= add_board_status(childh
, nodename
);
843 if (err
!= PICL_SUCCESS
)
846 return (PICL_SUCCESS
);
850 * not a Dimm or Ecache node - set up environmental info,
851 * board status and led info
853 err
= add_env_nodes(childh
, nodename
, tblhdl
);
854 if (err
!= PICL_SUCCESS
)
857 err
= add_board_status(childh
, nodename
);
858 if (err
!= PICL_SUCCESS
)
861 err
= add_led_nodes(childh
, nodename
, LOM_LED_POSITION_FRU
, tblhdl
);
862 if (err
!= PICL_SUCCESS
)
866 return (PICL_SUCCESS
);
870 * create location node, based on sgfru node "sgfrunode" under parent parh.
871 * Return picl_nodehdl of created node in *childp.
874 add_location_node(picl_nodehdl_t parh
, sgfrunode_t
*sgfrunode
,
875 picl_nodehdl_t
*childp
)
878 uint64_t handle
= (uint64_t)sgfrunode
->handle
;
880 char label
[MAX_LABEL_LEN
];
882 picl_prophdl_t tblhdl
;
883 picl_nodehdl_t childh
;
886 * strip "N0/" off the label if present (hang-over from wildcat)
888 if (strncmp(sgfrunode
->location_label
, LABEL_PREAMBLE
,
889 LABEL_PREAMBLE_LEN
) == 0)
890 (void) strlcpy(label
, &sgfrunode
->location_label
[
891 LABEL_PREAMBLE_LEN
], sizeof (label
));
893 (void) strlcpy(label
, &sgfrunode
->location_label
[0],
897 * some of the locations returned by sgfru are actually of the form
898 * XX/YY/ZZ - we need to create multiple levels in the picl tree for
902 while ((ptr
= strchr(labelp
, '/')) != NULL
) {
904 * null end of this section of label
909 * add intermediate nodes - parh will point to the created node
911 if (IS_PROC_NODE(labelp
)) {
912 err
= add_intermediate_nodes(&parh
, labelp
, &tblhdl
,
915 err
= add_intermediate_nodes(&parh
, labelp
, &tblhdl
,
918 if (err
!= PICL_SUCCESS
)
921 * if processor node, then create links to associated cpu node
922 * and OpStatus property
924 if (IS_PROC_NODE(labelp
)) {
925 err
= create_cpu_references(labelp
, parh
, tblhdl
);
926 if (err
!= PICL_SUCCESS
)
928 err
= add_board_status(parh
, labelp
);
929 if (err
!= PICL_SUCCESS
)
941 * if node already there, then just carry on down the tree
943 childh
= find_child_by_name(parh
, labelp
);
944 if (childh
!= NULL
) {
946 return (PICL_SUCCESS
);
950 * now just have the final level of the node left. First create it.
952 err
= ptree_create_and_add_node(parh
, labelp
, PICL_CLASS_LOCATION
,
954 if (err
!= PICL_SUCCESS
) {
955 syslog(LOG_ERR
, ADD_NODE_FAIL
, labelp
, err
);
960 * if sgfru has sent us a valid handle, then there is fruid information.
961 * create the SC_handle property for FRUID.
963 if (handle
!= -1ULL) {
964 err
= add_prop_ull(childh
, handle
, PICL_PROP_SC_HANDLE
);
965 if (err
!= PICL_SUCCESS
)
969 /* create label property for location class */
970 err
= add_prop_charstring(childh
, labelp
, PICL_PROP_LABEL
);
971 if (err
!= PICL_SUCCESS
)
974 /* create SlotType property where appropriate */
975 if (IS_ECACHE_NODE(sgfrunode
->nodename
)) {
976 err
= add_prop_charstring(childh
,
977 "ecache", PICL_PROP_SLOT_TYPE
);
979 * For Ecache, don't need to add environmental info
984 } else if (IS_DIMM_NODE(sgfrunode
->nodename
)) {
985 err
= add_prop_charstring(childh
, "memory-module",
986 PICL_PROP_SLOT_TYPE
);
988 * For Dimm, don't need to add environmental info
993 } else if (IS_SB_NODE(sgfrunode
->nodename
)) {
994 err
= add_prop_charstring(childh
, "system-board",
995 PICL_PROP_SLOT_TYPE
);
996 } else if (IS_PSU_NODE(sgfrunode
->nodename
)) {
997 err
= add_prop_charstring(childh
, "power-supply",
998 PICL_PROP_SLOT_TYPE
);
999 } else if (IS_FT_NODE(sgfrunode
->nodename
)) {
1000 err
= add_prop_charstring(childh
, "fan-tray",
1001 PICL_PROP_SLOT_TYPE
);
1003 if (err
!= PICL_SUCCESS
)
1007 * add devices table to location node (may need
1008 * references to led devices)
1010 err
= create_table(childh
, &tblhdl
, PICL_PROP_DEVICES
);
1011 if (err
!= PICL_SUCCESS
)
1014 err
= add_led_nodes(childh
, labelp
, LOM_LED_POSITION_LOCATION
, tblhdl
);
1015 if (err
!= PICL_SUCCESS
)
1018 return (PICL_SUCCESS
);
1022 * remove an individual picl node - called from remove_subtree()
1023 * also removes any sensor nodes pointed at by Devices table
1026 remove_picl_node(picl_nodehdl_t nodeh
)
1029 picl_prophdl_t tblhdl
;
1030 picl_prophdl_t nextprop
;
1031 picl_prophdl_t refprop
;
1032 char class[PICL_CLASSNAMELEN_MAX
];
1035 * first scan Devices table so we can find any sensor nodes
1036 * we need to delete as well
1038 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_DEVICES
,
1039 &tblhdl
, sizeof (tblhdl
));
1042 * If Devices table present, then read first column.
1043 * Devices table may be empty so don't treat this as an error
1045 if (err
== PICL_SUCCESS
&&
1046 ptree_get_next_by_row(tblhdl
, &nextprop
) == PICL_SUCCESS
) {
1047 /* find second column */
1048 err
= ptree_get_next_by_row(nextprop
, &nextprop
);
1049 if (err
!= PICL_SUCCESS
) {
1050 syslog(LOG_ERR
, GET_NEXT_BY_ROW_FAIL
,
1051 PICL_PROP_DEVICES
, err
);
1056 * walk down second column (ref ptr)
1057 * deleting the referenced nodes
1059 while (err
== PICL_SUCCESS
) {
1060 err
= ptree_get_propval(nextprop
, &refprop
,
1062 if (err
!= PICL_SUCCESS
) {
1063 syslog(LOG_ERR
, GET_PROPVAL_FAIL
, err
);
1068 * don't delete memory-module nodes
1069 * or cpu nodes (they weren't created
1072 err
= ptree_get_propval_by_name(refprop
,
1073 PICL_PROP_CLASSNAME
, class, sizeof (class));
1074 if (err
== PICL_STALEHANDLE
) {
1076 * if another plugin has already deleted the
1077 * node for us then that is ok
1079 err
= ptree_get_next_by_col(nextprop
,
1083 if (err
!= PICL_SUCCESS
) {
1084 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
,
1085 PICL_PROP_CLASSNAME
, err
);
1088 if (strcmp(class, PICL_CLASS_MEMORY_MODULE
) == 0 ||
1089 strcmp(class, PICL_CLASS_CPU
) == 0) {
1091 * but - do need to remove _fru_parent
1092 * property and Environment table (for cpu)
1094 err
= remove_references(refprop
, class);
1095 if (err
!= PICL_SUCCESS
)
1099 * sensor node - need to delete it
1101 err
= ptree_delete_node(refprop
);
1102 if (err
!= PICL_SUCCESS
) {
1103 syslog(LOG_ERR
, DELETE_PROP_FAIL
, err
);
1106 (void) ptree_destroy_node(refprop
);
1108 err
= ptree_get_next_by_col(nextprop
, &nextprop
);
1113 * now we can remove the frutree node
1115 err
= ptree_delete_node(nodeh
);
1116 if (err
!= PICL_SUCCESS
) {
1117 syslog(LOG_ERR
, DELETE_PROP_FAIL
, err
);
1120 (void) ptree_destroy_node(nodeh
);
1121 return (PICL_SUCCESS
);
1125 add_child_pci_references(picl_nodehdl_t nodeh
, picl_prophdl_t tblhdl
,
1126 picl_nodehdl_t devnodeh
)
1128 int err
= PICL_SUCCESS
;
1129 picl_nodehdl_t childnodeh
;
1130 char class[PICL_CLASSNAMELEN_MAX
];
1132 if (ptree_get_propval_by_name(devnodeh
, PICL_PROP_CHILD
, &childnodeh
,
1133 sizeof (childnodeh
)) != PICL_SUCCESS
) {
1134 return (PICL_SUCCESS
);
1137 err
= ptree_get_propval_by_name(childnodeh
,
1138 PICL_PROP_CLASSNAME
, class, sizeof (class));
1139 if (err
!= PICL_SUCCESS
)
1141 err
= add_prop_ref(childnodeh
, nodeh
, PICL_REFPROP_FRU_PARENT
);
1142 if (err
!= PICL_SUCCESS
)
1144 err
= create_table_entry(tblhdl
, childnodeh
, class);
1145 if (err
!= PICL_SUCCESS
)
1147 err
= add_child_pci_references(nodeh
, tblhdl
, childnodeh
);
1148 if (err
!= PICL_SUCCESS
)
1150 err
= ptree_get_propval_by_name(childnodeh
,
1151 PICL_PROP_PEER
, &childnodeh
, sizeof (picl_nodehdl_t
));
1152 if (err
!= PICL_SUCCESS
) {
1161 add_pci_location(picl_nodehdl_t childh
, char *parent_addr
, char bus_addr
,
1166 picl_nodehdl_t nodeh
;
1167 picl_nodehdl_t devnodeh
;
1168 picl_nodehdl_t devhdl
;
1169 char addr
[MAXPATHLEN
];
1170 char parent_path
[MAXPATHLEN
];
1171 picl_prophdl_t tblhdl
;
1172 char class[PICL_CLASSNAMELEN_MAX
];
1175 * search for any device nodes whose BUS_ADDR or UNIT_ADDRESS
1176 * are appropriate for this pci slot
1178 sprintf_buf2(parent_path
, IO_DEV
, parent_addr
);
1179 if (ptree_get_node_by_path(parent_path
, &devhdl
) == PICL_SUCCESS
&&
1180 ptree_get_propval_by_name(devhdl
, PICL_PROP_CHILD
, &devnodeh
,
1181 sizeof (devnodeh
)) == PICL_SUCCESS
) {
1183 err
= ptree_get_propval_by_name(devnodeh
,
1184 PICL_PROP_BUS_ADDR
, addr
, sizeof (addr
));
1185 if (err
== PICL_SUCCESS
&& addr
[0] == bus_addr
&&
1186 (addr
[1] == ',' || addr
[1] == '\0')) {
1190 err
= ptree_get_propval_by_name(devnodeh
,
1191 PICL_PROP_UNIT_ADDRESS
, addr
, sizeof (addr
));
1192 if (err
== PICL_SUCCESS
&& addr
[0] == bus_addr
&&
1193 (addr
[1] == ',' || addr
[1] == '\0')) {
1197 err
= ptree_get_propval_by_name(devnodeh
,
1198 PICL_PROP_PEER
, &devnodeh
, sizeof (picl_nodehdl_t
));
1199 if (err
!= PICL_SUCCESS
)
1206 * no devnodes for this slot. Create location node but
1207 * no fru node (empty slot)
1209 return (add_intermediate_location(&nodeh
, slot_name
, "pci"));
1213 * we've got the first devnode for this slot. Create the fru node
1214 * then walk along other nodes looking for further devnodes
1216 err
= add_intermediate_nodes(&nodeh
, slot_name
, &tblhdl
, "pci", NULL
);
1217 if (err
!= PICL_SUCCESS
)
1221 if (((err
= ptree_get_propval_by_name(devnodeh
,
1222 PICL_PROP_BUS_ADDR
, addr
, sizeof (addr
))) ==
1223 PICL_SUCCESS
&& addr
[0] == bus_addr
&&
1224 (addr
[1] == ',' || addr
[1] == '\0')) ||
1225 ((err
= ptree_get_propval_by_name(devnodeh
,
1226 PICL_PROP_UNIT_ADDRESS
, addr
, sizeof (addr
))) ==
1227 PICL_SUCCESS
&& addr
[0] == bus_addr
&&
1228 (addr
[1] == ',' || addr
[1] == '\0'))) {
1229 err
= ptree_get_propval_by_name(devnodeh
,
1230 PICL_PROP_CLASSNAME
, class, sizeof (class));
1231 if (err
!= PICL_SUCCESS
)
1233 err
= add_prop_ref(devnodeh
, nodeh
,
1234 PICL_REFPROP_FRU_PARENT
);
1235 if (err
!= PICL_SUCCESS
)
1237 err
= create_table_entry(tblhdl
, devnodeh
, class);
1238 if (err
!= PICL_SUCCESS
)
1240 err
= add_child_pci_references(nodeh
, tblhdl
, devnodeh
);
1241 if (err
!= PICL_SUCCESS
)
1244 err
= ptree_get_propval_by_name(devnodeh
,
1245 PICL_PROP_PEER
, &devnodeh
, sizeof (picl_nodehdl_t
));
1246 if (err
!= PICL_SUCCESS
) {
1255 * add intermediate location into frutree (ie a location that we know
1256 * exists but sgfru doesn't)
1259 add_intermediate_location(picl_nodehdl_t
*nodep
, char *labelp
, char *slot_name
)
1262 picl_nodehdl_t intermediate
;
1263 picl_prophdl_t tblhdl
;
1264 char parent_name
[PICL_PROPNAMELEN_MAX
];
1266 err
= ptree_create_and_add_node(*nodep
, labelp
, PICL_CLASS_LOCATION
,
1268 if (err
!= PICL_SUCCESS
) {
1269 syslog(LOG_ERR
, ADD_NODE_FAIL
, labelp
, err
);
1274 * create label property for location class
1276 err
= add_prop_charstring(intermediate
, labelp
, PICL_PROP_LABEL
);
1277 if (err
!= PICL_SUCCESS
)
1281 * add devices table to location node (may need references to led
1284 err
= create_table(intermediate
, &tblhdl
, PICL_PROP_DEVICES
);
1285 if (err
!= PICL_SUCCESS
)
1289 * scapp knows FANs 0 and 1 on IB as FAN8 and FAN9
1291 err
= ptree_get_propval_by_name(*nodep
, PICL_PROP_NAME
, parent_name
,
1292 sizeof (parent_name
));
1293 if (err
!= PICL_SUCCESS
)
1295 if (strcmp(labelp
, "FAN0") == 0 && strcmp(parent_name
, "IB6") == 0)
1296 err
= add_led_nodes(intermediate
, "FAN8",
1297 LOM_LED_POSITION_LOCATION
, tblhdl
);
1298 else if (strcmp(labelp
, "FAN1") == 0 && strcmp(parent_name
, "IB6") == 0)
1299 err
= add_led_nodes(intermediate
, "FAN9",
1300 LOM_LED_POSITION_LOCATION
, tblhdl
);
1302 err
= add_led_nodes(intermediate
, labelp
,
1303 LOM_LED_POSITION_LOCATION
, tblhdl
);
1304 if (err
!= PICL_SUCCESS
)
1308 err
= add_prop_charstring(intermediate
, slot_name
,
1309 PICL_PROP_SLOT_TYPE
);
1310 if (err
!= PICL_SUCCESS
)
1313 *nodep
= intermediate
;
1314 return (PICL_SUCCESS
);
1318 * adds an intermediate location/fru pair into frutree
1321 add_intermediate_nodes(picl_nodehdl_t
*nodep
, char *labelp
,
1322 picl_prophdl_t
*tblhdlp
, char *slot_name
, char *fru_name
)
1325 picl_nodehdl_t intermediate
;
1326 picl_nodehdl_t intermediate2
;
1329 * create intermediate location node (unless it has already been
1332 intermediate
= find_child_by_name(*nodep
, labelp
);
1333 if (intermediate
== NULL
) {
1334 intermediate
= *nodep
;
1335 err
= add_intermediate_location(&intermediate
, labelp
,
1337 if (err
!= PICL_SUCCESS
) {
1343 * create intermediate fru node (unless it has already been
1346 intermediate2
= find_child_by_name(intermediate
, labelp
);
1347 if (intermediate2
== NULL
) {
1349 * need to create intermediate fru node node
1351 err
= ptree_create_and_add_node(intermediate
, labelp
,
1352 PICL_CLASS_FRU
, &intermediate2
);
1353 if (err
!= PICL_SUCCESS
) {
1354 syslog(LOG_ERR
, ADD_NODE_FAIL
, labelp
, err
);
1359 * Create empty Devices table
1361 err
= create_table(intermediate2
, tblhdlp
, PICL_PROP_DEVICES
);
1362 if (err
!= PICL_SUCCESS
)
1366 err
= add_prop_charstring(intermediate2
, fru_name
,
1367 PICL_PROP_FRU_TYPE
);
1368 if (err
!= PICL_SUCCESS
)
1372 err
= ptree_get_propval_by_name(intermediate2
,
1373 PICL_PROP_DEVICES
, tblhdlp
, sizeof (*tblhdlp
));
1374 if (err
!= PICL_SUCCESS
)
1377 *nodep
= intermediate2
;
1378 return (PICL_SUCCESS
);
1382 * need to remove _fru_parent property and Environment table (for cpu)
1385 remove_references(picl_prophdl_t refprop
, char *class)
1387 picl_prophdl_t platprop
;
1390 err
= ptree_get_prop_by_name(refprop
, PICL_REFPROP_FRU_PARENT
,
1392 if (err
!= PICL_SUCCESS
) {
1393 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1396 err
= ptree_delete_prop(platprop
);
1397 if (err
!= PICL_SUCCESS
) {
1398 syslog(LOG_ERR
, DELETE_PROP_FAIL
, err
);
1401 (void) ptree_destroy_prop(platprop
);
1402 if (strcmp(class, PICL_CLASS_CPU
) == 0) {
1403 err
= ptree_get_prop_by_name(refprop
, PICL_PROP_ENV
, &platprop
);
1404 if (err
!= PICL_SUCCESS
) {
1406 * multi-core cpu is setup with only one cpu having
1407 * env table so ignore PICL_PROPNOTFOUND error.
1409 if (err
== PICL_PROPNOTFOUND
) {
1410 return (PICL_SUCCESS
);
1412 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_ENV
, err
);
1415 err
= ptree_delete_prop(platprop
);
1416 if (err
!= PICL_SUCCESS
) {
1417 syslog(LOG_ERR
, DELETE_PROP_FAIL
, err
);
1420 (void) ptree_destroy_prop(platprop
);
1422 return (PICL_SUCCESS
);
1426 * subroutine for various functions. Finds immediate child of parh with
1427 * requested name if present. Otherwise returns NULL.
1429 static picl_nodehdl_t
1430 find_child_by_name(picl_nodehdl_t parh
, char *name
)
1432 picl_nodehdl_t nodeh
;
1434 char nodename
[PICL_PROPNAMELEN_MAX
];
1436 err
= ptree_get_propval_by_name(parh
, PICL_PROP_CHILD
,
1437 &nodeh
, sizeof (picl_nodehdl_t
));
1438 if (err
!= PICL_SUCCESS
)
1441 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_NAME
, nodename
,
1443 if (err
!= PICL_SUCCESS
)
1445 if (strcmp(name
, nodename
) == 0) {
1448 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_PEER
,
1449 &nodeh
, sizeof (picl_nodehdl_t
));
1450 if (err
!= PICL_SUCCESS
)
1456 create_dimm_references(picl_nodehdl_t parh
, int dimm_id
,
1457 picl_nodehdl_t nodeh
, picl_prophdl_t tblhdl
)
1460 picl_nodehdl_t memctlhdl
= NULL
;
1461 picl_nodehdl_t memgrphdl
;
1462 picl_nodehdl_t memhdl
;
1463 char name
[MAXPATHLEN
];
1464 char sbname
[PICL_PROPNAMELEN_MAX
];
1465 char pname
[PICL_PROPNAMELEN_MAX
];
1466 char bname
[PICL_PROPNAMELEN_MAX
];
1467 picl_nodehdl_t parentfruh
;
1468 picl_nodehdl_t parentloch
;
1472 * create reference properties for memory nodes
1473 * - first find names of ancestor frus - ie "SBx/Py/Bz"
1475 err
= ptree_get_propval_by_name(parh
, PICL_PROP_PARENT
, &parentfruh
,
1476 sizeof (picl_nodehdl_t
));
1477 if (err
!= PICL_SUCCESS
) {
1478 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1481 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_NAME
,
1482 bname
, sizeof (bname
));
1483 if (err
!= PICL_SUCCESS
) {
1484 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_NAME
, err
);
1487 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_PARENT
,
1488 &parentloch
, sizeof (picl_nodehdl_t
));
1489 if (err
!= PICL_SUCCESS
) {
1490 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1493 err
= ptree_get_propval_by_name(parentloch
, PICL_PROP_PARENT
,
1494 &parentfruh
, sizeof (picl_nodehdl_t
));
1495 if (err
!= PICL_SUCCESS
) {
1496 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1499 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_NAME
,
1500 pname
, sizeof (pname
));
1501 if (err
!= PICL_SUCCESS
) {
1502 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_NAME
, err
);
1506 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_PARENT
,
1507 &parentloch
, sizeof (picl_nodehdl_t
));
1508 if (err
!= PICL_SUCCESS
) {
1509 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1512 err
= ptree_get_propval_by_name(parentloch
, PICL_PROP_PARENT
,
1513 &parentfruh
, sizeof (picl_nodehdl_t
));
1514 if (err
!= PICL_SUCCESS
) {
1515 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1518 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_NAME
, sbname
,
1520 if (err
!= PICL_SUCCESS
) {
1521 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_NAME
, err
);
1526 * ok - we've now got name of system board node in sbname and
1527 * name of processor node in pname.
1528 * Now find corresponding memory-controller node if present
1530 sprintf_buf2(name
, MEMORY_DEV
, SB_P_TO_SAFARI_ADDR(sbname
, pname
));
1531 err
= ptree_get_node_by_path(name
, &memctlhdl
);
1532 if (err
!= PICL_SUCCESS
)
1533 return (PICL_SUCCESS
);
1536 * now find corresponding memory-module-group node if present
1538 err
= ptree_get_propval_by_name(memctlhdl
, PICL_PROP_CHILD
, &memgrphdl
,
1539 sizeof (picl_nodehdl_t
));
1540 if (err
!= PICL_SUCCESS
)
1541 return (PICL_SUCCESS
);
1544 * check if this is the right bank - if not move on to sibling
1546 err
= ptree_get_propval_by_name(memgrphdl
, PICL_PROP_ID
,
1548 if (err
!= PICL_SUCCESS
)
1549 return (PICL_SUCCESS
);
1550 if (bname
[1] != id
+ '0') {
1551 err
= ptree_get_propval_by_name(memgrphdl
, PICL_PROP_PEER
,
1552 &memgrphdl
, sizeof (picl_nodehdl_t
));
1553 if (err
!= PICL_SUCCESS
)
1554 return (PICL_SUCCESS
);
1555 err
= ptree_get_propval_by_name(memgrphdl
, PICL_PROP_ID
,
1557 if (err
!= PICL_SUCCESS
)
1558 return (PICL_SUCCESS
);
1559 if (bname
[1] != id
+ '0')
1560 return (PICL_SUCCESS
);
1564 * now find corresponding memory-module node if present
1566 err
= ptree_get_propval_by_name(memgrphdl
, PICL_PROP_CHILD
, &memhdl
,
1567 sizeof (picl_nodehdl_t
));
1568 if (err
!= PICL_SUCCESS
)
1569 return (PICL_SUCCESS
);
1572 * for each DIMM set up links with matching memory-module node
1575 err
= ptree_get_propval_by_name(memhdl
, PICL_PROP_ID
,
1577 if (err
== PICL_SUCCESS
&& dimm_id
== id
) {
1578 err
= add_prop_ref(memhdl
, nodeh
,
1579 PICL_REFPROP_FRU_PARENT
);
1580 if (err
!= PICL_SUCCESS
)
1582 err
= create_table_entry(tblhdl
, memhdl
,
1583 PICL_CLASS_MEMORY_MODULE
);
1584 if (err
!= PICL_SUCCESS
)
1587 err
= ptree_get_propval_by_name(memhdl
, PICL_PROP_PEER
,
1588 &memhdl
, sizeof (picl_nodehdl_t
));
1589 if (err
!= PICL_SUCCESS
)
1592 return (PICL_SUCCESS
);
1596 create_cpu_references(char *pname
, picl_nodehdl_t nodeh
, picl_prophdl_t tblhdl
)
1599 picl_nodehdl_t sensorhdl
;
1600 picl_nodehdl_t parentloch
;
1601 picl_nodehdl_t parentfruh
;
1602 picl_nodehdl_t cpuhdl
;
1603 picl_nodehdl_t cpuhdl1
;
1604 picl_prophdl_t envtblhdl
;
1605 picl_prophdl_t prophdl
;
1606 char name
[MAXPATHLEN
];
1607 char sbname
[PICL_PROPNAMELEN_MAX
];
1609 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_PARENT
,
1610 &parentloch
, sizeof (picl_nodehdl_t
));
1611 if (err
!= PICL_SUCCESS
) {
1612 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1615 err
= ptree_get_propval_by_name(parentloch
, PICL_PROP_PARENT
,
1616 &parentfruh
, sizeof (picl_nodehdl_t
));
1617 if (err
!= PICL_SUCCESS
) {
1618 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
1621 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_NAME
, sbname
,
1623 if (err
!= PICL_SUCCESS
) {
1624 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_NAME
, err
);
1629 * Find corresponding cpu node if present. Note, this code will
1630 * attempt to find a corresponding cpu node, by searching for devices
1631 * of the types /platform/ssm@0,0/SUNW,UltraSPARC-III+@%x,0,
1632 * /platform/ssm@0,0/SUNW,UltraSPARC-III@%x,0 or
1633 * /platform/ssm@0,0/cmp@%x,0/cpu@0 or 1. If we can not find
1634 * any such device, we return PICL_SUCCESS such that we
1635 * continue the construction of the remaining part of the
1636 * tree. We first check for UltraSPARC-III. If we do not
1637 * find such a device we check for UltraSPARC-III+. If
1638 * we are unsuccesful again we try one of the jaguar cores
1639 * /platform/ssm@0,0/cmp@%x,0/cpu@. If we do not find the
1640 * first one, there's no point in continuing and we just
1641 * return PICL_SUCCESS. Similarly if we find one core
1642 * but not the other, something must be wrong, so we
1643 * again just return PICL_SUCCESS without creating any
1646 sprintf_buf2(name
, CPU_DEV
, SB_P_TO_SAFARI_ADDR(sbname
, pname
));
1648 err
= ptree_get_node_by_path(name
, &cpuhdl
);
1650 if (err
!= PICL_SUCCESS
) {
1651 sprintf_buf2(name
, CPU_DEV2
,
1652 SB_P_TO_SAFARI_ADDR(sbname
, pname
));
1653 err
= ptree_get_node_by_path(name
, &cpuhdl
);
1654 if (err
!= PICL_SUCCESS
) {
1655 /* check for jaguar cores */
1656 sprintf_buf2(name
, CPU_DEV3C1
,
1657 SB_P_TO_SAFARI_ADDR(sbname
, pname
));
1658 err
= ptree_get_node_by_path(name
, &cpuhdl1
);
1659 if (err
!= PICL_SUCCESS
)
1660 return (PICL_SUCCESS
);
1661 /* add fru parent reference for the second core */
1662 err
= ptree_get_prop_by_name(cpuhdl1
,
1663 PICL_REFPROP_FRU_PARENT
, &prophdl
);
1664 if (err
!= PICL_SUCCESS
) {
1665 err
= add_prop_ref(cpuhdl1
, nodeh
,
1666 PICL_REFPROP_FRU_PARENT
);
1667 if (err
!= PICL_SUCCESS
)
1669 err
= create_table_entry(tblhdl
, cpuhdl1
,
1671 if (err
!= PICL_SUCCESS
)
1674 sprintf_buf2(name
, CPU_DEV3C0
,
1675 SB_P_TO_SAFARI_ADDR(sbname
, pname
));
1676 err
= ptree_get_node_by_path(name
, &cpuhdl
);
1677 if (err
!= PICL_SUCCESS
)
1678 return (PICL_SUCCESS
);
1684 * now create reference properties
1686 err
= ptree_get_prop_by_name(cpuhdl
, PICL_REFPROP_FRU_PARENT
, &prophdl
);
1687 if (err
!= PICL_SUCCESS
) {
1688 err
= add_prop_ref(cpuhdl
, nodeh
, PICL_REFPROP_FRU_PARENT
);
1689 if (err
!= PICL_SUCCESS
)
1691 err
= create_table_entry(tblhdl
, cpuhdl
, PICL_CLASS_CPU
);
1692 if (err
!= PICL_SUCCESS
)
1697 * create Environment table on cpu node - with Die and Ambient
1698 * temperature sensors if present. If already there, delete and start
1701 err
= ptree_get_prop_by_name(cpuhdl
, PICL_PROP_ENV
, &prophdl
);
1702 if (err
== PICL_SUCCESS
) {
1703 err
= ptree_delete_prop(prophdl
);
1704 if (err
!= PICL_SUCCESS
)
1706 (void) ptree_destroy_prop(prophdl
);
1708 err
= create_table(cpuhdl
, &envtblhdl
, PICL_PROP_ENV
);
1709 if (err
!= PICL_SUCCESS
)
1713 sprintf_buf4(name
, "%s/%s_t_cheetah%d@0", SC_DEV_PCIX
, sbname
,
1716 sprintf_buf4(name
, "%s/%s_t_cheetah%d@0", SC_DEV
, sbname
,
1719 err
= ptree_get_node_by_path(name
, &sensorhdl
);
1720 if (err
== PICL_SUCCESS
) {
1721 err
= create_table_entry(envtblhdl
, sensorhdl
,
1722 PICL_CLASS_TEMPERATURE_SENSOR
);
1723 if (err
!= PICL_SUCCESS
)
1728 sprintf_buf4(name
, "%s/%s_t_ambient%d@0", SC_DEV_PCIX
, sbname
,
1731 sprintf_buf4(name
, "%s/%s_t_ambient%d@0", SC_DEV
, sbname
,
1734 err
= ptree_get_node_by_path(name
, &sensorhdl
);
1735 if (err
== PICL_SUCCESS
) {
1736 return (create_table_entry(envtblhdl
, sensorhdl
,
1737 PICL_CLASS_TEMPERATURE_SENSOR
));
1739 return (PICL_SUCCESS
);
1743 * subroutine of add_subtree - get a list of children of a parent node
1745 static sgfrunode_t
*
1746 get_node_children(fru_hdl_t fruparent
, int *num_childrenp
)
1748 int max_children
, i
;
1749 sgfrunode_t
*fruchildren
= NULL
;
1750 child_info_t child_info
;
1754 * Open the sgfru pseudo dev
1756 if ((frufd
= open(FRU_PSEUDO_DEV
, O_RDWR
, 0)) == -1) {
1757 syslog(LOG_ERR
, DEV_OPEN_FAIL
, FRU_PSEUDO_DEV
, strerror(errno
));
1760 for (i
= 1; i
<= MAX_TRIES
; i
++) {
1761 max_children
= i
* MAX_NODE_CHILDREN
;
1762 if ((fruchildren
= calloc(max_children
,
1763 sizeof (sgfrunode_t
))) == NULL
) {
1764 (void) close(frufd
);
1765 syslog(LOG_ERR
, MALLOC_FAIL
);
1768 child_info
.fru_hdl
= fruparent
;
1769 child_info
.fru_cnt
= max_children
;
1770 child_info
.frus
= (void *)fruchildren
;
1771 if (ioctl(frufd
, SGFRU_GETCHILDLIST
, &child_info
) == 0) {
1773 * got them - return success
1775 (void) close(frufd
);
1776 *num_childrenp
= child_info
.fru_cnt
;
1777 return (fruchildren
);
1782 * if ENOMEM, need to calloc more space - so go round loop again
1785 if (errno
!= ENOMEM
) {
1786 (void) close(frufd
);
1787 syslog(LOG_ERR
, SGFRU_IOCTL_FAIL
, SGFRU_GETCHILDLIST
,
1788 fruparent
, strerror(errno
));
1792 (void) close(frufd
);
1793 syslog(LOG_ERR
, MALLOC_FAIL
);
1797 /* Creates an unsigned longlong property for a given PICL node */
1799 add_prop_ull(picl_nodehdl_t nodeh
, uint64_t handle
, char *name
)
1801 picl_prophdl_t proph
;
1802 ptree_propinfo_t propinfo
;
1805 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
1806 PICL_PTYPE_UNSIGNED_INT
, PICL_READ
, sizeof (unsigned long long),
1807 PICL_PROP_SC_HANDLE
, NULL
, NULL
);
1808 if (err
!= PICL_SUCCESS
) {
1809 syslog(LOG_ERR
, PROPINFO_FAIL
, name
, err
);
1812 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &handle
, &proph
);
1813 if (err
!= PICL_SUCCESS
) {
1814 syslog(LOG_ERR
, ADD_PROP_FAIL
, name
, err
);
1817 return (PICL_SUCCESS
);
1820 /* Creates a void property for a given PICL node */
1822 add_prop_void(picl_nodehdl_t nodeh
, char *name
)
1824 picl_prophdl_t proph
;
1825 ptree_propinfo_t propinfo
;
1828 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
1829 PICL_PTYPE_VOID
, PICL_READ
, 0, PICL_PROP_FRUDATA_AVAIL
, NULL
, NULL
);
1830 if (err
!= PICL_SUCCESS
) {
1831 syslog(LOG_ERR
, PROPINFO_FAIL
, name
, err
);
1834 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, &proph
);
1835 if (err
!= PICL_SUCCESS
) {
1836 syslog(LOG_ERR
, ADD_PROP_FAIL
, name
, err
);
1839 return (PICL_SUCCESS
);
1842 /* Creates a reference property for a given PICL node */
1844 add_prop_ref(picl_nodehdl_t nodeh
, picl_nodehdl_t value
, char *name
)
1846 picl_prophdl_t proph
;
1847 ptree_propinfo_t propinfo
;
1850 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
1851 PICL_PTYPE_REFERENCE
, PICL_READ
, sizeof (picl_nodehdl_t
), name
,
1853 if (err
!= PICL_SUCCESS
) {
1854 syslog(LOG_ERR
, PROPINFO_FAIL
, name
, err
);
1857 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &value
, &proph
);
1858 if (err
!= PICL_SUCCESS
) {
1859 syslog(LOG_ERR
, ADD_PROP_FAIL
, name
, err
);
1862 return (PICL_SUCCESS
);
1865 /* Creates an integer property for a given PICL node */
1867 add_prop_int(picl_nodehdl_t nodeh
, int value
, char *name
)
1869 picl_prophdl_t proph
;
1870 ptree_propinfo_t propinfo
;
1873 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
1874 PICL_PTYPE_INT
, PICL_READ
, sizeof (int), name
, NULL
, NULL
);
1875 if (err
!= PICL_SUCCESS
) {
1876 syslog(LOG_ERR
, PROPINFO_FAIL
, name
, err
);
1879 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &value
, &proph
);
1880 if (err
!= PICL_SUCCESS
) {
1881 syslog(LOG_ERR
, ADD_PROP_FAIL
, name
, err
);
1884 return (PICL_SUCCESS
);
1887 /* Creates an integer property for a given PICL node */
1889 add_prop_float(picl_nodehdl_t nodeh
, float value
, char *name
)
1891 picl_prophdl_t proph
;
1892 ptree_propinfo_t propinfo
;
1895 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
1896 PICL_PTYPE_FLOAT
, PICL_READ
, sizeof (float), name
, NULL
, NULL
);
1897 if (err
!= PICL_SUCCESS
) {
1898 syslog(LOG_ERR
, PROPINFO_FAIL
, name
, err
);
1901 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &value
, &proph
);
1902 if (err
!= PICL_SUCCESS
) {
1903 syslog(LOG_ERR
, ADD_PROP_FAIL
, name
, err
);
1906 return (PICL_SUCCESS
);
1909 /* Creates a charstring property for a given PICL node */
1911 add_prop_charstring(picl_nodehdl_t nodeh
, char *value
, char *name
)
1913 picl_prophdl_t proph
;
1914 ptree_propinfo_t propinfo
;
1917 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
1918 PICL_PTYPE_CHARSTRING
, PICL_READ
, strlen(value
) + 1,
1920 if (err
!= PICL_SUCCESS
) {
1921 syslog(LOG_ERR
, PROPINFO_FAIL
, name
, err
);
1924 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, value
, &proph
);
1925 if (err
!= PICL_SUCCESS
) {
1926 syslog(LOG_ERR
, ADD_PROP_FAIL
, name
, err
);
1929 return (PICL_SUCCESS
);
1932 /* create an entry in the specified table */
1934 create_table_entry(picl_prophdl_t tblhdl
, picl_nodehdl_t refhdl
, char *class)
1937 ptree_propinfo_t prop
;
1938 picl_prophdl_t prophdl
[2];
1940 /* first column is class */
1941 prop
.version
= PTREE_PROPINFO_VERSION
;
1942 prop
.piclinfo
.type
= PICL_PTYPE_CHARSTRING
;
1943 prop
.piclinfo
.accessmode
= PICL_READ
;
1944 prop
.piclinfo
.size
= PICL_CLASSNAMELEN_MAX
;
1947 (void) strlcpy(prop
.piclinfo
.name
, PICL_PROP_CLASS
,
1948 sizeof (prop
.piclinfo
.name
));
1949 err
= ptree_create_prop(&prop
, class, &prophdl
[0]);
1950 if (err
!= PICL_SUCCESS
) {
1951 syslog(LOG_ERR
, ADD_TBL_ENTRY_FAIL
, err
);
1955 /* second column is refernce property */
1956 prop
.version
= PTREE_PROPINFO_VERSION
;
1957 prop
.piclinfo
.type
= PICL_PTYPE_REFERENCE
;
1958 prop
.piclinfo
.accessmode
= PICL_READ
;
1959 prop
.piclinfo
.size
= sizeof (picl_nodehdl_t
);
1962 sprintf_buf2(prop
.piclinfo
.name
, "_%s_", class);
1963 err
= ptree_create_prop(&prop
, &refhdl
, &prophdl
[1]);
1964 if (err
!= PICL_SUCCESS
) {
1965 syslog(LOG_ERR
, ADD_TBL_ENTRY_FAIL
, err
);
1969 /* add row to table */
1970 err
= ptree_add_row_to_table(tblhdl
, 2, prophdl
);
1971 if (err
!= PICL_SUCCESS
)
1972 syslog(LOG_ERR
, ADD_TBL_ENTRY_FAIL
, err
);
1976 /* create an empty table property */
1978 create_table(picl_nodehdl_t fruhdl
, picl_prophdl_t
*tblhdlp
, char *tbl_name
)
1981 ptree_propinfo_t prop
;
1982 picl_prophdl_t tblprophdl
;
1984 err
= ptree_create_table(tblhdlp
);
1985 if (err
!= PICL_SUCCESS
) {
1986 syslog(LOG_ERR
, ADD_PROP_FAIL
, tbl_name
, err
);
1989 prop
.version
= PTREE_PROPINFO_VERSION
;
1990 prop
.piclinfo
.type
= PICL_PTYPE_TABLE
;
1991 prop
.piclinfo
.accessmode
= PICL_READ
;
1992 prop
.piclinfo
.size
= sizeof (picl_prophdl_t
);
1995 (void) strlcpy(prop
.piclinfo
.name
, tbl_name
,
1996 sizeof (prop
.piclinfo
.name
));
1997 err
= ptree_create_and_add_prop(fruhdl
, &prop
, tblhdlp
, &tblprophdl
);
1998 if (err
!= PICL_SUCCESS
)
1999 syslog(LOG_ERR
, ADD_PROP_FAIL
, tbl_name
, err
);
2004 frudr_add_subtree(picl_nodehdl_t parh
)
2007 if (ptree_get_propval_by_name(parh
, PICL_PROP_SC_HANDLE
,
2008 &sgfruhdl
, sizeof (sgfruhdl
)) != PICL_SUCCESS
) {
2011 (void) add_subtree(parh
, sgfruhdl
);
2014 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
2017 frudr_completion_handler(char *ename
, void *earg
, size_t size
)
2019 picl_nodehdl_t fruh
;
2020 picl_nodehdl_t parh
;
2022 if (strcmp(ename
, PICL_FRU_REMOVED
) == 0) {
2024 * now frudata has been notified that the node is to be
2025 * removed, we can actually remove it
2028 (void) nvlist_lookup_uint64(earg
,
2029 PICLEVENTARG_FRUHANDLE
, &fruh
);
2031 (void) remove_subtree(fruh
);
2034 * Now repopulate the frutree with current data.
2037 (void) nvlist_lookup_uint64(earg
,
2038 PICLEVENTARG_PARENTHANDLE
, &parh
);
2040 frudr_add_subtree(parh
);
2050 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
2053 post_frudr_event(char *ename
, picl_nodehdl_t parenth
, picl_nodehdl_t fruh
)
2058 ev_name
= strdup(ename
);
2059 if (ev_name
== NULL
)
2061 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME_TYPE
, NULL
)) {
2065 if (parenth
!= 0L &&
2066 nvlist_add_uint64(nvl
, PICLEVENTARG_PARENTHANDLE
, parenth
)) {
2072 nvlist_add_uint64(nvl
, PICLEVENTARG_FRUHANDLE
, fruh
)) {
2077 if (ptree_post_event(ev_name
, nvl
, sizeof (nvl
),
2078 frudr_completion_handler
) != 0) {
2085 * updates the picl node 'loc' with the new fru handle (PICL_PROP_SC_HANDLE)
2086 * (helper function for frudr_evhandler, when a stale fru handle is
2090 update_fru_hdl(picl_nodehdl_t loc
, fru_hdl_t newsgfruhdl
)
2092 picl_prophdl_t schproph
;
2095 err
= ptree_get_prop_by_name(loc
, PICL_PROP_SC_HANDLE
, &schproph
);
2096 if (err
== PICL_SUCCESS
) {
2097 if (ptree_delete_prop(schproph
) == PICL_SUCCESS
) {
2098 (void) ptree_destroy_prop(schproph
);
2101 (void) add_prop_ull(loc
, (uint64_t)newsgfruhdl
, PICL_PROP_SC_HANDLE
);
2105 * Get the fru handle of loc by iterating through the parent's children.
2106 * Sets fruhdl and returns PICL_SUCCESS unless an error is encountered.
2109 get_fruhdl_from_parent(picl_nodehdl_t loc
, fru_hdl_t
*fruhdl
)
2111 picl_nodehdl_t parlocnodeh
;
2112 fru_hdl_t parsgfruhdl
;
2114 sgfrunode_t
*fruchildren
;
2115 char nodename
[PICL_PROPNAMELEN_MAX
];
2120 err
= ptree_get_propval_by_name(loc
, PICL_PROP_NAME
, (void *)nodename
,
2121 PICL_PROPNAMELEN_MAX
);
2122 if (err
!= PICL_SUCCESS
)
2124 err
= ptree_get_propval_by_name(loc
, PICL_PROP_PARENT
, &parlocnodeh
,
2125 sizeof (picl_nodehdl_t
));
2126 if (err
!= PICL_SUCCESS
)
2128 if ((err
= ptree_get_propval_by_name(parlocnodeh
, PICL_PROP_SC_HANDLE
,
2129 &parsgfruhdl
, sizeof (parsgfruhdl
))) != PICL_SUCCESS
)
2131 /* find children of the parent node */
2132 fruchildren
= get_node_children(parsgfruhdl
, &num_children
);
2133 if (fruchildren
== NULL
)
2134 return (PICL_FAILURE
);
2135 for (i
= 0, cp
= fruchildren
; i
< num_children
; i
++, cp
++) {
2136 /* find the child we're interested in */
2137 if (strcmp(cp
->nodename
, nodename
) == 0) {
2138 *fruhdl
= cp
->handle
;
2140 return (PICL_SUCCESS
);
2144 return (PICL_FAILURE
);
2148 * handle EC_DR picl events
2152 frudr_evhandler(const char *ename
, const void *earg
, size_t size
, void *cookie
)
2158 char path
[MAXPATHLEN
];
2159 picl_nodehdl_t fruh
;
2160 picl_nodehdl_t locnodeh
;
2162 fru_hdl_t sgfruhdl_from_parent
;
2164 if (strcmp(ename
, PICLEVENT_DR_AP_STATE_CHANGE
) != 0)
2167 if (nvlist_unpack((char *)earg
, size
, &nvlp
, NULL
))
2170 if (nvlist_lookup_string(nvlp
, PICLEVENTARG_DATA_TYPE
, &dtype
)) {
2175 if (strcmp(dtype
, PICLEVENTARG_PICLEVENT_DATA
) != 0) {
2180 if (nvlist_lookup_string(nvlp
, PICLEVENTARG_AP_ID
, &ap_id
)) {
2185 if (nvlist_lookup_string(nvlp
, PICLEVENTARG_HINT
, &hint
)) {
2190 if (strncmp(ap_id
, AP_ID_PREAMBLE
, AP_ID_PREAMBLE_LEN
) != 0) {
2196 * OK - so this is an EC_DR event - let's handle it.
2198 sprintf_buf2(path
, CHASSIS_LOC_PATH
, &ap_id
[AP_ID_PREAMBLE_LEN
]);
2201 * special case - SSC arrival means that SSC has been reset - we
2202 * need to flush the cached sgfru handles
2204 if (strcmp(&ap_id
[AP_ID_PREAMBLE_LEN
], "SSC1") == 0) {
2205 picl_nodehdl_t chdh
;
2206 picl_nodehdl_t peerh
;
2207 picl_nodehdl_t parh
;
2209 char label
[MAX_LABEL_LEN
];
2211 sgfrunode_t
*sgfruchassisp
= NULL
;
2213 picl_prophdl_t schproph
;
2215 /* find existing chassis node */
2216 if (ptree_get_node_by_path(CHASSIS_PATH
, &parh
) !=
2222 /* find new chassis sgfru node */
2223 sgfruchassisp
= get_node_children(ROOTPARENT
, &num_children
);
2224 if (sgfruchassisp
== NULL
|| num_children
!= 1) {
2229 /* update chassis SC_HANDLE property */
2230 err
= ptree_get_prop_by_name(parh
, PICL_PROP_SC_HANDLE
,
2232 if (err
!= PICL_SUCCESS
) {
2236 err
= ptree_delete_prop(schproph
);
2237 if (err
!= PICL_SUCCESS
) {
2241 (void) ptree_destroy_prop(schproph
);
2242 err
= add_prop_ull(parh
, sgfruchassisp
->handle
,
2243 PICL_PROP_SC_HANDLE
);
2244 if (err
!= PICL_SUCCESS
) {
2250 * remove all subtrees except DISK, TAPE, DVD and PCI subtrees
2252 if (ptree_get_propval_by_name(parh
, PICL_PROP_CHILD
, &chdh
,
2253 sizeof (picl_nodehdl_t
)) == PICL_SUCCESS
) {
2255 if (ptree_get_propval_by_name(chdh
,
2256 PICL_PROP_PEER
, &peerh
,
2257 sizeof (picl_nodehdl_t
)) != PICL_SUCCESS
)
2261 err
= ptree_get_propval_by_name(chdh
,
2262 PICL_PROP_LABEL
, label
, sizeof (label
));
2263 if (err
== PICL_SUCCESS
) {
2264 if (strncmp(label
, "DISK",
2265 strlen("DISK")) != 0 &&
2266 strncmp(label
, "TAPE",
2267 strlen("TAPE")) != 0 &&
2268 strncmp(label
, "PCI",
2269 strlen("PCI")) != 0 &&
2270 strncmp(label
, "DVD",
2271 strlen("DVD")) != 0) {
2272 (void) remove_subtree(chdh
);
2281 /* add new subtrees */
2282 (void) add_subtree(parh
, sgfruchassisp
->handle
);
2283 free(sgfruchassisp
);
2289 if (ptree_get_node_by_path(path
, &locnodeh
) != PICL_SUCCESS
) {
2293 if (ptree_get_propval_by_name(locnodeh
, PICL_PROP_SC_HANDLE
,
2294 &sgfruhdl
, sizeof (sgfruhdl
)) != PICL_SUCCESS
) {
2300 * now either add or delete the fru node as appropriate. If no
2301 * hint, treat as insert - add_subtree will update the tree if
2304 if (strcmp(hint
, DR_HINT_REMOVE
) == 0) {
2305 if (ptree_get_propval_by_name(locnodeh
, PICL_PROP_CHILD
,
2306 &fruh
, sizeof (picl_nodehdl_t
)) != PICL_PROPNOTFOUND
) {
2308 * fru was there - but has gone away
2310 post_frudr_event(PICL_FRU_REMOVED
, locnodeh
, fruh
);
2314 * fru has been inserted (or may need to update)
2316 * sgfruhdl may be stale due to hotplugging. We check this
2317 * by getting the fru_hdl_t from the parent's children
2318 * and compare it to the cached value in sgfruhdl. If we
2319 * have a stale handle, we update the cached value and
2320 * use it in the call to add_subtree.
2322 if (get_fruhdl_from_parent(locnodeh
, &sgfruhdl_from_parent
) ==
2324 if (sgfruhdl
!= sgfruhdl_from_parent
) {
2325 update_fru_hdl(locnodeh
, sgfruhdl_from_parent
);
2326 sgfruhdl
= sgfruhdl_from_parent
;
2330 (void) add_subtree(locnodeh
, sgfruhdl
);
2336 * handle memcfg picl events - need to update reference properties
2340 frumemcfg_evhandler(const char *ename
, const void *earg
, size_t size
,
2343 picl_nodehdl_t nodeh
;
2344 picl_nodehdl_t lochdl
;
2345 picl_nodehdl_t fruhdl
;
2346 picl_nodehdl_t memgrphdl
;
2347 picl_nodehdl_t memhdl
;
2348 picl_prophdl_t tblhdl
;
2349 picl_prophdl_t tblproph
;
2351 char addr
[MAXPATHLEN
];
2352 char bname
[PICL_PROPNAMELEN_MAX
];
2353 picl_nodehdl_t banklochdl
;
2354 picl_nodehdl_t bankfruhdl
;
2355 char label
[MAX_LABEL_LEN
];
2360 char buf
[MAX_LINE_SIZE
];
2362 if (strcmp(ename
, PICLEVENT_MC_ADDED
) != 0 &&
2363 strcmp(ename
, PICLEVENT_MC_REMOVED
) != 0)
2367 * find corresponding frutree dimm nodes
2369 if (nvlist_unpack((char *)earg
, size
, &nvlp
, NULL
))
2371 if (nvlist_lookup_uint64(nvlp
, PICLEVENTARG_NODEHANDLE
, &nodeh
)) {
2376 err
= ptree_get_propval_by_name(nodeh
, PICL_PROP_UNIT_ADDRESS
, addr
,
2378 if (err
!= PICL_SUCCESS
)
2380 ptr
= strchr(addr
, ',');
2384 value
= strtol(addr
, NULL
, 16);
2385 sprintf_buf5(buf
, PROC_FRU_PATH
, SAFARI_ADDR_TO_SB(value
),
2386 SAFARI_ADDR_TO_SB(value
), SAFARI_ADDR_TO_P(value
),
2387 SAFARI_ADDR_TO_P(value
));
2388 err
= ptree_get_node_by_path(buf
, &fruhdl
);
2389 if (err
!= PICL_SUCCESS
)
2391 err
= ptree_get_propval_by_name(fruhdl
, PICL_PROP_CHILD
,
2392 &banklochdl
, sizeof (banklochdl
));
2393 if (err
!= PICL_SUCCESS
)
2397 * walk through the DIMM locations
2400 err
= ptree_get_propval_by_name(banklochdl
, PICL_PROP_CHILD
,
2401 &bankfruhdl
, sizeof (bankfruhdl
));
2402 if (err
!= PICL_SUCCESS
)
2404 err
= ptree_get_propval_by_name(bankfruhdl
, PICL_PROP_CHILD
,
2405 &lochdl
, sizeof (lochdl
));
2406 if (err
!= PICL_SUCCESS
)
2409 err
= ptree_get_propval_by_name(lochdl
, PICL_PROP_CHILD
,
2410 &fruhdl
, sizeof (fruhdl
));
2411 if (err
!= PICL_SUCCESS
)
2415 * this is a frutree dimm node corresponding to the
2416 * memory controller that has been added/deleted
2417 * - so create/delete reference properties
2419 if (strcmp(ename
, PICLEVENT_MC_ADDED
) == 0) {
2423 err
= ptree_get_propval_by_name(fruhdl
,
2424 PICL_PROP_DEVICES
, &tblhdl
,
2426 if (err
!= PICL_SUCCESS
)
2428 err
= ptree_get_propval_by_name(lochdl
,
2429 PICL_PROP_LABEL
, label
, sizeof (label
));
2430 if (err
!= PICL_SUCCESS
)
2433 err
= ptree_get_propval_by_name(bankfruhdl
,
2434 PICL_PROP_NAME
, bname
, sizeof (bname
));
2435 if (err
!= PICL_SUCCESS
)
2439 * find memory group node
2441 err
= ptree_get_propval_by_name(nodeh
,
2442 PICL_PROP_CHILD
, &memgrphdl
,
2443 sizeof (memgrphdl
));
2444 if (err
!= PICL_SUCCESS
)
2448 * check if this is the right bank - if not
2449 * move on to sibling
2451 err
= ptree_get_propval_by_name(memgrphdl
,
2452 PICL_PROP_ID
, &id
, sizeof (id
));
2453 if (err
!= PICL_SUCCESS
)
2455 if (bname
[1] != id
+ '0') {
2457 ptree_get_propval_by_name(memgrphdl
,
2458 PICL_PROP_PEER
, &memgrphdl
,
2459 sizeof (memgrphdl
));
2460 if (err
!= PICL_SUCCESS
)
2463 ptree_get_propval_by_name(memgrphdl
,
2464 PICL_PROP_ID
, &id
, sizeof (id
));
2465 if (err
!= PICL_SUCCESS
)
2467 if (bname
[1] != id
+ '0')
2472 * got the right bank - now create appropriate
2475 err
= ptree_get_propval_by_name(memgrphdl
,
2476 PICL_PROP_CHILD
, &memhdl
,
2478 if (err
!= PICL_SUCCESS
)
2481 err
= ptree_get_propval_by_name(memhdl
,
2482 PICL_PROP_ID
, &id
, sizeof (id
));
2483 if (err
!= PICL_SUCCESS
)
2485 if (label
[1] == ('0' + id
)) {
2486 err
= add_prop_ref(memhdl
,
2488 PICL_REFPROP_FRU_PARENT
);
2489 if (err
!= PICL_SUCCESS
)
2491 err
= create_table_entry(tblhdl
,
2493 PICL_CLASS_MEMORY_MODULE
);
2494 if (err
!= PICL_SUCCESS
)
2497 err
= ptree_get_propval_by_name(memhdl
,
2499 &memhdl
, sizeof (memhdl
));
2500 if (err
== PICL_PROPNOTFOUND
)
2502 if (err
!= PICL_SUCCESS
)
2505 } else if (strcmp(ename
, PICLEVENT_MC_REMOVED
) == 0) {
2507 * XXX - no mechanism for deleting row - so
2508 * delete whole tabel and start again
2510 err
= ptree_get_prop_by_name(fruhdl
,
2511 PICL_PROP_DEVICES
, &tblproph
);
2512 if (err
== PICL_SUCCESS
) {
2513 err
= ptree_delete_prop(tblproph
);
2514 if (err
!= PICL_SUCCESS
)
2516 (void) ptree_destroy_prop(tblproph
);
2518 err
= create_table(fruhdl
, &tblhdl
,
2520 if (err
!= PICL_SUCCESS
)
2524 err
= ptree_get_propval_by_name(lochdl
,
2525 PICL_PROP_PEER
, &lochdl
, sizeof (lochdl
));
2526 if (err
== PICL_PROPNOTFOUND
)
2528 if (err
!= PICL_SUCCESS
)
2532 err
= ptree_get_propval_by_name(banklochdl
,
2533 PICL_PROP_PEER
, &banklochdl
, sizeof (banklochdl
));
2534 if (err
== PICL_PROPNOTFOUND
)
2536 if (err
!= PICL_SUCCESS
)
2540 * We don't get an event to say that cpu nodes have been added/
2541 * deleted (in fact as things stand they are never deleted). However
2542 * we know that all cpus must be configured before the MC_ADDED event
2543 * we are handling here. So if the cpu links haven't been set up yet
2544 * then we do it now.
2546 if (strcmp(ename
, PICLEVENT_MC_ADDED
) == 0) {
2547 sprintf_buf4(buf
, PROC_LOC_PATH
, SAFARI_ADDR_TO_SB(value
),
2548 SAFARI_ADDR_TO_SB(value
), SAFARI_ADDR_TO_P(value
));
2549 err
= ptree_get_node_by_path(buf
, &lochdl
);
2550 if (err
!= PICL_SUCCESS
)
2552 sprintf_buf5(buf
, PROC_FRU_PATH
, SAFARI_ADDR_TO_SB(value
),
2553 SAFARI_ADDR_TO_SB(value
), SAFARI_ADDR_TO_P(value
),
2554 SAFARI_ADDR_TO_P(value
));
2555 err
= ptree_get_node_by_path(buf
, &fruhdl
);
2556 if (err
!= PICL_SUCCESS
)
2558 sprintf_buf2(buf
, "P%d", SAFARI_ADDR_TO_P(value
));
2559 err
= ptree_get_propval_by_name(fruhdl
,
2560 PICL_PROP_DEVICES
, &tblhdl
, sizeof (tblhdl
));
2561 if (err
!= PICL_SUCCESS
)
2563 (void) create_cpu_references(buf
, fruhdl
, tblhdl
);
2568 * subroutine for add_env_nodes(), and add_led_node(). Adds a sensor
2569 * node under the sc node in the platform tree, of name "nodename" and
2570 * class "class". Also add UnitAddress property (always 0 as the nodenames
2571 * are unique anyway). Add reference property back to parent fru/location node
2572 * in frutree and a Devices table entry pointing to this node from the
2573 * parent fru/location node in frutree.
2576 add_sensor_node(picl_nodehdl_t fruhdl
, picl_nodehdl_t lochdl
, char *nodename
,
2577 char *class, char *prop_class
, picl_prophdl_t tblhdl
,
2578 picl_nodehdl_t
*sensorhdlp
)
2582 err
= ptree_create_and_add_node(sch
, nodename
, class, sensorhdlp
);
2583 if (err
!= PICL_SUCCESS
) {
2584 syslog(LOG_ERR
, ADD_NODE_FAIL
, nodename
, err
);
2588 err
= create_table_entry(tblhdl
, *sensorhdlp
, class);
2589 if (err
!= PICL_SUCCESS
)
2592 err
= add_sensor_prop(*sensorhdlp
, prop_class
);
2593 if (err
!= PICL_SUCCESS
)
2596 err
= add_prop_charstring(*sensorhdlp
, "0", PICL_PROP_UNIT_ADDRESS
);
2597 if (err
!= PICL_SUCCESS
)
2600 if (fruhdl
!= NULL
) {
2601 err
= add_prop_ref(*sensorhdlp
, fruhdl
,
2602 PICL_REFPROP_FRU_PARENT
);
2604 err
= add_prop_ref(*sensorhdlp
, lochdl
,
2605 PICL_REFPROP_LOC_PARENT
);
2611 * subroutine for add_sensor_node()/add_env_nodes(). Used for adding dynamic
2615 add_sensor_prop(picl_nodehdl_t nodeh
, char *class)
2617 ptree_propinfo_t propinfo
;
2620 if (strcmp(class, PICL_PROP_TEMPERATURE
) == 0) {
2621 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
2622 PICL_PTYPE_INT
, PICL_READ
+ PICL_VOLATILE
,
2623 sizeof (int), class, get_sensor_data
, NULL
);
2624 } else if (strcmp(class, PICL_PROP_FAN_SPEED
) == 0) {
2625 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
2626 PICL_PTYPE_INT
, PICL_READ
+ PICL_VOLATILE
,
2627 sizeof (int), class, get_sensor_data
, NULL
);
2628 } else if (strcmp(class, PICL_PROP_FAN_SPEED_UNIT
) == 0) {
2629 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
2630 PICL_PTYPE_CHARSTRING
, PICL_READ
+ PICL_VOLATILE
,
2631 MAX_SPEED_UNIT_LEN
, class, get_sensor_data
, NULL
);
2632 } else if (strcmp(class, PICL_PROP_CONDITION
) == 0) {
2633 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
2634 PICL_PTYPE_CHARSTRING
, PICL_READ
+ PICL_VOLATILE
,
2635 MAX_CONDITION_LEN
, class, get_sensor_data
, NULL
);
2636 } else if (strcmp(class, PICL_PROP_STATE
) == 0) {
2637 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
2638 PICL_PTYPE_CHARSTRING
, PICL_READ
+ PICL_WRITE
+
2639 PICL_VOLATILE
, MAX_STATE_LEN
, class, get_led_data
,
2642 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
2643 PICL_PTYPE_FLOAT
, PICL_READ
+ PICL_VOLATILE
,
2644 sizeof (float), class, get_sensor_data
, NULL
);
2646 if (err
!= PICL_SUCCESS
) {
2647 syslog(LOG_ERR
, PROPINFO_FAIL
, class, err
);
2651 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, NULL
);
2652 if (err
!= PICL_SUCCESS
) {
2653 syslog(LOG_ERR
, ADD_PROP_FAIL
, class, err
);
2656 return (PICL_SUCCESS
);
2660 * Get requested kstat
2663 open_kstat(char *name
, void **ptr
, kstat_ctl_t
**kcp
)
2667 *kcp
= kstat_open();
2669 syslog(LOG_ERR
, KSTAT_FAIL
);
2670 return (PICL_FAILURE
);
2672 info_ksp
= kstat_lookup(*kcp
, NULL
, -1, name
);
2673 if (info_ksp
== NULL
) {
2675 syslog(LOG_ERR
, KSTAT_FAIL
);
2676 return (PICL_FAILURE
);
2678 if (kstat_read(*kcp
, info_ksp
, NULL
) == -1) {
2680 syslog(LOG_ERR
, KSTAT_FAIL
);
2681 return (PICL_FAILURE
);
2684 return (PICL_SUCCESS
);
2688 * dimm status - uses bank-status property on memory-controller node
2692 get_dimm_status(ptree_rarg_t
*arg
, void *result
)
2696 picl_prophdl_t tblhdl
;
2697 picl_prophdl_t nextprop
;
2698 picl_prophdl_t refprop
;
2699 picl_prophdl_t mmgprop
;
2700 picl_prophdl_t mcprop
;
2701 picl_prophdl_t bankprop
;
2702 char nodename
[PICL_PROPNAMELEN_MAX
];
2703 char class[PICL_CLASSNAMELEN_MAX
];
2704 char bankname
[PICL_PROPNAMELEN_MAX
];
2705 char state
[MAX_STATE_SIZE
];
2708 * find the name of this node
2710 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_NAME
, nodename
,
2712 if (err
!= PICL_SUCCESS
) {
2713 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_NAME
, err
);
2718 * find the name of grandparent (dimm bank) node
2720 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_PARENT
, &bankprop
,
2721 sizeof (picl_nodehdl_t
));
2722 if (err
!= PICL_SUCCESS
) {
2723 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
2726 err
= ptree_get_propval_by_name(bankprop
, PICL_PROP_PARENT
, &bankprop
,
2727 sizeof (picl_nodehdl_t
));
2728 if (err
!= PICL_SUCCESS
) {
2729 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
2732 err
= ptree_get_propval_by_name(bankprop
, PICL_PROP_NAME
, bankname
,
2734 if (err
!= PICL_SUCCESS
) {
2735 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_NAME
, err
);
2740 * lookup memory-module node in Devices table
2742 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_DEVICES
, &tblhdl
,
2744 if (err
!= PICL_SUCCESS
) {
2745 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_DEVICES
, err
);
2748 err
= ptree_get_next_by_row(tblhdl
, &nextprop
);
2749 if (err
!= PICL_SUCCESS
) {
2751 * if Devices table empty then dimm is unconfigured
2753 (void) strlcpy(result
, PICL_PROPVAL_DISABLED
,
2754 MAX_OPERATIONAL_STATUS_LEN
);
2755 return (PICL_SUCCESS
);
2757 err
= ptree_get_next_by_row(nextprop
, &nextprop
);
2758 if (err
!= PICL_SUCCESS
) {
2759 syslog(LOG_ERR
, GET_NEXT_BY_ROW_FAIL
, PICL_PROP_DEVICES
, err
);
2764 * walk down second column (ref ptr)
2766 while (err
== PICL_SUCCESS
) {
2767 err
= ptree_get_propval(nextprop
, &refprop
, sizeof (refprop
));
2768 if (err
!= PICL_SUCCESS
) {
2769 syslog(LOG_ERR
, GET_PROPVAL_FAIL
, err
);
2770 return (PICL_PROPVALUNAVAILABLE
);
2772 err
= ptree_get_propval_by_name(refprop
, PICL_PROP_CLASSNAME
,
2773 class, sizeof (class));
2774 if (err
== PICL_SUCCESS
&& strcmp(class,
2775 PICL_CLASS_MEMORY_MODULE
) == 0)
2777 if (err
!= PICL_SUCCESS
&& err
!= PICL_STALEHANDLE
) {
2778 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_CLASSNAME
,
2782 err
= ptree_get_next_by_col(nextprop
, &nextprop
);
2783 if (err
!= PICL_SUCCESS
) {
2785 * if no memory-module in Devices table
2786 * then dimm is unconfigured
2788 (void) strlcpy(result
, PICL_PROPVAL_DISABLED
,
2789 MAX_OPERATIONAL_STATUS_LEN
);
2790 return (PICL_SUCCESS
);
2795 * we've finally found the associated memory-module
2796 * node. Now need to find the bank-status property on
2797 * its parent memory-controller.
2799 err
= ptree_get_propval_by_name(refprop
, PICL_PROP_PARENT
,
2800 &mmgprop
, sizeof (picl_nodehdl_t
));
2801 if (err
!= PICL_SUCCESS
) {
2802 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
2805 err
= ptree_get_propval_by_name(mmgprop
, PICL_PROP_PARENT
, &mcprop
,
2806 sizeof (picl_nodehdl_t
));
2807 if (err
!= PICL_SUCCESS
) {
2808 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_PARENT
, err
);
2811 err
= ptree_get_propval_by_name(mcprop
, PICL_PROP_BANK_STATUS
, &tblhdl
,
2813 if (err
!= PICL_SUCCESS
) {
2814 (void) strlcpy(result
, PICL_PROPVAL_UNKNOWN
,
2815 MAX_OPERATIONAL_STATUS_LEN
);
2816 return (PICL_SUCCESS
);
2820 * bank-status is a table. Need to find the entry corresponding
2823 err
= ptree_get_next_by_row(tblhdl
, &nextprop
);
2824 if (err
!= PICL_SUCCESS
) {
2825 (void) strlcpy(result
, PICL_PROPVAL_UNKNOWN
,
2826 MAX_OPERATIONAL_STATUS_LEN
);
2827 return (PICL_SUCCESS
);
2829 for (i
= 0; i
< 4; i
++) {
2830 err
= ptree_get_propval(nextprop
, &state
, sizeof (state
));
2831 if (err
!= PICL_SUCCESS
) {
2832 (void) strlcpy(result
, PICL_PROPVAL_UNKNOWN
,
2833 MAX_OPERATIONAL_STATUS_LEN
);
2836 if ((i
& 1) == (bankname
[1] - '0')) {
2837 if (strcmp(state
, "pass") == 0) {
2838 (void) strlcpy(result
, PICL_PROPVAL_OKAY
,
2839 MAX_OPERATIONAL_STATUS_LEN
);
2840 } else if (strcmp(state
, "fail") == 0) {
2841 (void) strlcpy(result
, PICL_PROPVAL_FAILED
,
2842 MAX_OPERATIONAL_STATUS_LEN
);
2844 (void) strlcpy(result
, state
,
2845 MAX_OPERATIONAL_STATUS_LEN
);
2849 err
= ptree_get_next_by_col(nextprop
, &nextprop
);
2850 if (err
!= PICL_SUCCESS
) {
2851 (void) strlcpy(result
, PICL_PROPVAL_OKAY
,
2852 MAX_OPERATIONAL_STATUS_LEN
);
2856 return (PICL_SUCCESS
);
2860 * cpu status - uses State property on cpu node
2864 get_cpu_status(ptree_rarg_t
*arg
, void *result
)
2867 picl_prophdl_t tblhdl
;
2868 picl_prophdl_t nextprop
;
2869 picl_prophdl_t refprop
;
2870 char class[PICL_CLASSNAMELEN_MAX
];
2871 char state
[MAX_STATE_SIZE
];
2874 * lookup cpu node in Devices table
2876 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_DEVICES
, &tblhdl
,
2878 if (err
!= PICL_SUCCESS
) {
2879 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_DEVICES
, err
);
2882 err
= ptree_get_next_by_row(tblhdl
, &nextprop
);
2883 if (err
!= PICL_SUCCESS
) {
2885 * if Devices table empty then cpu is unconfigured
2887 (void) strlcpy(result
, PICL_PROPVAL_DISABLED
,
2888 MAX_OPERATIONAL_STATUS_LEN
);
2889 return (PICL_SUCCESS
);
2891 err
= ptree_get_next_by_row(nextprop
, &nextprop
);
2892 if (err
!= PICL_SUCCESS
) {
2893 syslog(LOG_ERR
, GET_NEXT_BY_ROW_FAIL
, PICL_PROP_DEVICES
, err
);
2898 * walk down second column (ref ptr)
2900 while (err
== PICL_SUCCESS
) {
2901 err
= ptree_get_propval(nextprop
, &refprop
, sizeof (refprop
));
2902 if (err
!= PICL_SUCCESS
) {
2903 syslog(LOG_ERR
, GET_PROPVAL_FAIL
, err
);
2906 err
= ptree_get_propval_by_name(refprop
, PICL_PROP_CLASSNAME
,
2907 class, sizeof (class));
2908 if (err
== PICL_SUCCESS
&& strcmp(class, PICL_CLASS_CPU
) == 0)
2910 if (err
!= PICL_SUCCESS
&& err
!= PICL_STALEHANDLE
) {
2911 syslog(LOG_ERR
, PROP_LOOKUP_FAIL
, PICL_PROP_CLASSNAME
,
2915 err
= ptree_get_next_by_col(nextprop
, &nextprop
);
2916 if (err
!= PICL_SUCCESS
) {
2918 * if no cpu in Devices table
2919 * then cpu is unconfigured
2921 (void) strlcpy(result
, PICL_PROPVAL_DISABLED
,
2922 MAX_OPERATIONAL_STATUS_LEN
);
2923 return (PICL_SUCCESS
);
2928 * we've finally found the associated cpu node. Now need to find its
2929 * status property if present (if not assume OK)
2931 err
= ptree_get_propval_by_name(refprop
, OBP_STATUS
,
2932 state
, sizeof (state
));
2933 if (err
== PICL_SUCCESS
) {
2934 if (strcmp(state
, "fail") == 0)
2935 (void) strlcpy(result
, PICL_PROPVAL_FAILED
,
2936 MAX_OPERATIONAL_STATUS_LEN
);
2938 (void) strlcpy(result
, state
,
2939 MAX_OPERATIONAL_STATUS_LEN
);
2940 return (PICL_SUCCESS
);
2943 (void) strlcpy(result
, PICL_PROPVAL_OKAY
, MAX_OPERATIONAL_STATUS_LEN
);
2944 return (PICL_SUCCESS
);
2948 * system/io board condition - uses sgenv driver kstats
2952 get_board_status(ptree_rarg_t
*arg
, void *result
)
2954 int err
= PICL_SUCCESS
;
2956 sg_board_info_t
*brd
;
2957 char name
[PICL_PROPNAMELEN_MAX
];
2958 char buf
[PICL_PROPNAMELEN_MAX
];
2960 kstat_t
*board_info_ksp
;
2962 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_NAME
, name
,
2964 if (err
!= PICL_SUCCESS
) {
2968 err
= open_kstat(SG_BOARD_STATUS_KSTAT_NAME
, (void **)&board_info_ksp
,
2970 if (err
!= PICL_SUCCESS
) {
2974 brd
= board_info_ksp
->ks_data
;
2975 for (i
= 0; i
< SGENV_NUM_BOARD_READINGS(board_info_ksp
); i
++, brd
++) {
2977 * check this kstat matches the name of the node
2979 if (SG_BOARD_IS_CPU_TYPE(brd
->board_num
)) {
2980 sprintf_buf3(buf
, "%s%d",
2981 SG_HPU_TYPE_CPU_BOARD_ID
, brd
->board_num
);
2983 sprintf_buf3(buf
, "%s%d",
2984 SG_HPU_TYPE_PCI_IO_BOARD_ID
, brd
->board_num
);
2986 if (strncmp(buf
, name
, strlen(buf
)) != 0)
2990 * ok - got the right kstat - get it's value
2991 * note that values 0-4 are defined in sbdp_mbox.h
2993 if (brd
->condition
>= 0 && brd
->condition
< 5)
2994 (void) strlcpy(result
,
2995 hpu_condition_table
[brd
->condition
],
2996 MAX_OPERATIONAL_STATUS_LEN
);
2998 return (PICL_SUCCESS
);
3001 return (PICL_PROPVALUNAVAILABLE
);
3005 get_op_status(ptree_rarg_t
*arg
, void *result
)
3007 int err
= PICL_SUCCESS
;
3008 char name
[PICL_PROPNAMELEN_MAX
];
3009 char value
[MAX_STATE_LEN
];
3010 char parent_name
[PICL_PROPNAMELEN_MAX
];
3011 picl_nodehdl_t loch
;
3012 picl_nodehdl_t parentfruh
;
3014 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_NAME
, name
,
3016 if (err
!= PICL_SUCCESS
) {
3021 * handle dimms, cpus and system boards specially
3023 if (IS_PROC_NODE(name
)) {
3024 return (get_cpu_status(arg
, result
));
3025 } else if (IS_DIMM_NODE(name
)) {
3026 return (get_dimm_status(arg
, result
));
3027 } else if (IS_SB_NODE(name
) || IS_IB_NODE(name
)) {
3028 return (get_board_status(arg
, result
));
3032 * otherwise OperationalStatus is derived from the fault led state
3036 * scapp knows FANs 0 and 1 on IB as FAN8 and FAN9
3038 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_PARENT
, &loch
,
3040 if (err
!= PICL_SUCCESS
)
3041 return (PICL_PROPVALUNAVAILABLE
);
3042 err
= ptree_get_propval_by_name(loch
, PICL_PROP_PARENT
, &parentfruh
,
3043 sizeof (parentfruh
));
3044 if (err
!= PICL_SUCCESS
)
3045 return (PICL_PROPVALUNAVAILABLE
);
3046 err
= ptree_get_propval_by_name(parentfruh
, PICL_PROP_NAME
, parent_name
,
3047 sizeof (parent_name
));
3048 if (err
!= PICL_SUCCESS
)
3049 return (PICL_PROPVALUNAVAILABLE
);
3050 if (strcmp(name
, "FAN0") == 0 && strcmp(parent_name
, "IB6") == 0) {
3051 if (get_led("FAN8", FAULT_LED
, value
) != PICL_SUCCESS
) {
3052 return (PICL_PROPVALUNAVAILABLE
);
3054 } else if (strcmp(name
, "FAN1") == 0 && strcmp(parent_name
,
3056 if (get_led("FAN9", FAULT_LED
, value
) != PICL_SUCCESS
) {
3057 return (PICL_PROPVALUNAVAILABLE
);
3060 if (get_led(name
, FAULT_LED
, value
) != PICL_SUCCESS
) {
3061 return (PICL_PROPVALUNAVAILABLE
);
3064 if (strcmp(value
, PICL_PROPVAL_ON
) == 0)
3065 (void) strlcpy(result
, PICL_PROPVAL_FAILED
,
3066 MAX_OPERATIONAL_STATUS_LEN
);
3068 (void) strlcpy(result
, PICL_PROPVAL_OKAY
,
3069 MAX_OPERATIONAL_STATUS_LEN
);
3070 return (PICL_SUCCESS
);
3074 add_board_status(picl_nodehdl_t nodeh
, char *nodename
)
3076 ptree_propinfo_t propinfo
;
3078 picl_prophdl_t prophdl
;
3081 * check if OperationalStatus property already created for this fru
3083 err
= ptree_get_prop_by_name(nodeh
, PICL_PROP_OPERATIONAL_STATUS
,
3085 if (err
== PICL_SUCCESS
)
3086 return (PICL_SUCCESS
);
3089 * put operational status on dimms, cpus, SBs, IBs, PSUs, FTs, Fans, RPs
3091 if (IS_DIMM_NODE(nodename
) || IS_PROC_NODE(nodename
) ||
3092 IS_SB_NODE(nodename
) || IS_IB_NODE(nodename
) ||
3093 IS_PSU_NODE(nodename
) || IS_FT_NODE(nodename
) ||
3094 IS_FAN_NODE(nodename
) || IS_RP_NODE(nodename
)) {
3095 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
3096 PICL_PTYPE_CHARSTRING
, PICL_READ
+ PICL_VOLATILE
,
3097 MAX_OPERATIONAL_STATUS_LEN
, PICL_PROP_OPERATIONAL_STATUS
,
3098 get_op_status
, NULL
);
3099 if (err
!= PICL_SUCCESS
) {
3100 syslog(LOG_ERR
, PROPINFO_FAIL
,
3101 PICL_PROP_OPERATIONAL_STATUS
, err
);
3104 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, NULL
);
3105 if (err
!= PICL_SUCCESS
) {
3106 syslog(LOG_ERR
, ADD_PROP_FAIL
,
3107 PICL_PROP_OPERATIONAL_STATUS
, err
);
3111 return (PICL_SUCCESS
);
3115 * environmental information handling - uses sgenv driver kstats
3119 add_env_nodes(picl_nodehdl_t nodeh
, char *nodename
, picl_prophdl_t tblhdl
)
3121 int err
= PICL_SUCCESS
;
3124 picl_prophdl_t tblhdl2
;
3125 picl_prophdl_t frutype
;
3126 char fruname
[PICL_PROPNAMELEN_MAX
];
3127 char buf
[PICL_PROPNAMELEN_MAX
];
3128 char id
[PICL_PROPNAMELEN_MAX
];
3130 picl_nodehdl_t childh
;
3131 picl_nodehdl_t sensorhdl
;
3133 kstat_t
*env_info_ksp
;
3135 err
= open_kstat(SG_ENV_INFO_KSTAT_NAME
, (void **)&env_info_ksp
, &kc
);
3136 if (err
!= PICL_SUCCESS
) {
3140 env
= env_info_ksp
->ks_data
;
3141 for (i
= 0; i
< SGENV_NUM_ENV_READINGS(env_info_ksp
); i
++, env
++) {
3143 * check values from kstat entry are within valid range
3145 if (env
->sd_id
.id
.sensor_type
< SG_SENSOR_TYPE_CURRENT
)
3147 if (env
->sd_id
.id
.sensor_type
== SG_SENSOR_TYPE_ENVDB
)
3149 if (env
->sd_id
.id
.sensor_type
> SG_SENSOR_TYPE_2_5_VDC
)
3151 if ((env
->sd_id
.id
.hpu_type
>> 8) >=
3152 (SG_HPU_TYPE_SUN_FIRE_3800_CENTERPLANE
>> 8))
3154 if (env
->sd_id
.id
.sensor_part
> SG_SENSOR_PART_INPUT
)
3158 * does this kstat entry belong to this fru?
3159 * Note sc reports RPS as 10 and 12 via env messages
3160 * but by 0 and 2 via fru messages, so correct here
3162 if ((env
->sd_id
.id
.hpu_type
>> 8) ==
3163 (SG_HPU_TYPE_REPEATER_BOARD
>> 8)) {
3164 sprintf_buf3(fruname
, "%s%d",
3165 hpu_type_table
[env
->sd_id
.id
.hpu_type
>> 8],
3166 env
->sd_id
.id
.hpu_slot
- 10);
3168 sprintf_buf3(fruname
, "%s%d",
3169 hpu_type_table
[env
->sd_id
.id
.hpu_type
>> 8],
3170 env
->sd_id
.id
.hpu_slot
);
3172 if (strcmp(nodename
, fruname
) != 0)
3176 * set up FRUType. Note we only want to do this once per fru
3178 err
= ptree_get_prop_by_name(nodeh
, PICL_PROP_FRU_TYPE
,
3180 if (err
!= PICL_SUCCESS
) {
3181 err
= add_prop_charstring(nodeh
,
3182 hpu_fru_type_table
[env
->sd_id
.id
.hpu_type
>> 8],
3183 PICL_PROP_FRU_TYPE
);
3184 if (err
!= PICL_SUCCESS
)
3189 * create the sensor node with a sensible name
3191 switch (env
->sd_id
.id
.sensor_type
) {
3192 case SG_SENSOR_TYPE_TEMPERATURE
:
3193 if (env
->sd_id
.id
.sensor_part
== SG_SENSOR_PART_BOARD
) {
3194 sprintf_buf2(id
, "t_ambient%d",
3195 env
->sd_id
.id
.sensor_typenum
);
3197 sprintf_buf3(id
, "t_%s%d",
3198 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3199 env
->sd_id
.id
.sensor_partnum
);
3202 case SG_SENSOR_TYPE_CURRENT
:
3203 sprintf_buf3(id
, "i_%s%d",
3204 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3205 env
->sd_id
.id
.sensor_partnum
);
3207 case SG_SENSOR_TYPE_COOLING
:
3208 sprintf_buf3(id
, "ft_%s%d",
3209 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3210 env
->sd_id
.id
.sensor_partnum
);
3212 default: /* voltage */
3213 if (env
->sd_id
.id
.sensor_part
== SG_SENSOR_PART_BOARD
) {
3214 sprintf_buf3(id
, "v_%s%d",
3215 hpu_sensor_table
[env
->sd_id
.id
.sensor_type
],
3216 env
->sd_id
.id
.sensor_typenum
);
3218 sprintf_buf3(id
, "v_%s%d",
3219 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3220 env
->sd_id
.id
.sensor_partnum
);
3226 * check if sensor node has already been created
3228 sprintf_buf3(buf
, "%s_%s", nodename
, id
);
3229 if (find_child_by_name(sch
, buf
) != NULL
)
3232 if (env
->sd_id
.id
.sensor_type
== SG_SENSOR_TYPE_COOLING
) {
3234 * create individual fan_unit nodes
3237 sprintf_buf2(fruname
, "FAN%d",
3238 env
->sd_id
.id
.sensor_partnum
);
3239 err
= add_intermediate_nodes(&childh
, fruname
,
3240 &tblhdl2
, "fan-unit", "FAN");
3241 if (err
!= PICL_SUCCESS
)
3243 err
= add_board_status(childh
, fruname
);
3244 if (err
!= PICL_SUCCESS
)
3246 } else if (env
->sd_id
.id
.sensor_part
==
3247 SG_SENSOR_PART_CHEETAH
||
3248 ((env
->sd_id
.id
.hpu_type
>> 8) ==
3249 (SG_HPU_TYPE_CPU_BOARD
>> 8) &&
3250 (env
->sd_id
.id
.sensor_type
== SG_SENSOR_TYPE_TEMPERATURE
) &&
3251 (env
->sd_id
.id
.sensor_part
== SG_SENSOR_PART_BOARD
))) {
3253 * put sensors under individual processor nodes
3256 if (env
->sd_id
.id
.sensor_part
== SG_SENSOR_PART_BOARD
)
3257 sprintf_buf2(fruname
, "P%d",
3258 env
->sd_id
.id
.sensor_typenum
);
3260 sprintf_buf2(fruname
, "P%d",
3261 env
->sd_id
.id
.sensor_partnum
);
3262 err
= add_intermediate_nodes(&childh
, fruname
,
3263 &tblhdl2
, "cpu", "PROC");
3264 if (err
!= PICL_SUCCESS
)
3270 err
= add_sensor_node(childh
, NULL
, buf
,
3271 hpu_sensor_class_table
[env
->sd_id
.id
.sensor_type
],
3272 hpu_sensor_prop_table
[env
->sd_id
.id
.sensor_type
],
3273 tblhdl2
, &sensorhdl
);
3274 if (err
!= PICL_SUCCESS
)
3278 * add additional properties
3280 switch (env
->sd_id
.id
.sensor_type
) {
3281 case SG_SENSOR_TYPE_COOLING
:
3282 err
= add_prop_charstring(sensorhdl
, id
,
3284 if (err
!= PICL_SUCCESS
)
3287 * add threshold at 75% of full speed
3289 err
= add_prop_int(sensorhdl
, 75,
3290 PICL_PROP_LOW_WARNING_THRESHOLD
);
3291 if (err
!= PICL_SUCCESS
)
3293 err
= add_sensor_prop(sensorhdl
,
3294 PICL_PROP_FAN_SPEED_UNIT
);
3295 if (err
!= PICL_SUCCESS
)
3298 case SG_SENSOR_TYPE_TEMPERATURE
:
3299 if ((env
->sd_id
.id
.hpu_type
>> 8 ==
3300 (SG_HPU_TYPE_CPU_BOARD
>> 8)) &&
3301 (env
->sd_id
.id
.sensor_part
==
3302 SG_SENSOR_PART_BOARD
)) {
3303 err
= add_prop_charstring(sensorhdl
,
3304 PICL_PROPVAL_AMBIENT
, PICL_PROP_LABEL
);
3305 if (err
!= PICL_SUCCESS
)
3307 } else if (env
->sd_id
.id
.sensor_part
==
3308 SG_SENSOR_PART_CHEETAH
) {
3309 err
= add_prop_charstring(sensorhdl
,
3310 PICL_PROPVAL_DIE
, PICL_PROP_LABEL
);
3311 if (err
!= PICL_SUCCESS
)
3314 err
= add_prop_charstring(sensorhdl
, id
,
3316 if (err
!= PICL_SUCCESS
)
3319 err
= add_prop_int(sensorhdl
, env
->sd_lo_warn
/
3320 SG_TEMPERATURE_SCALE
, PICL_PROP_LOW_WARNING
);
3321 if (err
!= PICL_SUCCESS
)
3323 err
= add_prop_int(sensorhdl
, env
->sd_lo
/
3324 SG_TEMPERATURE_SCALE
, PICL_PROP_LOW_SHUTDOWN
);
3325 if (err
!= PICL_SUCCESS
)
3327 err
= add_prop_int(sensorhdl
, env
->sd_hi_warn
/
3328 SG_TEMPERATURE_SCALE
, PICL_PROP_HIGH_WARNING
);
3329 if (err
!= PICL_SUCCESS
)
3331 err
= add_prop_int(sensorhdl
, env
->sd_hi
/
3332 SG_TEMPERATURE_SCALE
, PICL_PROP_HIGH_SHUTDOWN
);
3333 if (err
!= PICL_SUCCESS
)
3336 case SG_SENSOR_TYPE_1_5_VDC
:
3337 scale
= SG_1_5_VDC_SCALE
;
3339 case SG_SENSOR_TYPE_1_8_VDC
:
3340 scale
= SG_1_8_VDC_SCALE
;
3342 case SG_SENSOR_TYPE_2_5_VDC
:
3343 scale
= SG_2_5_VDC_SCALE
;
3345 case SG_SENSOR_TYPE_3_3_VDC
:
3346 scale
= SG_3_3_VDC_SCALE
;
3348 case SG_SENSOR_TYPE_5_VDC
:
3349 scale
= SG_5_VDC_SCALE
;
3351 case SG_SENSOR_TYPE_12_VDC
:
3352 scale
= SG_12_VDC_SCALE
;
3354 case SG_SENSOR_TYPE_48_VDC
:
3356 * The 48VDC sensor is just an indicator - doesn't
3357 * give reading or thresholds
3359 err
= add_prop_charstring(sensorhdl
, id
,
3361 if (err
!= PICL_SUCCESS
)
3364 case SG_SENSOR_TYPE_CURRENT
:
3365 scale
= SG_CURRENT_SCALE
;
3368 err
= add_prop_charstring(sensorhdl
, id
, PICL_PROP_LABEL
);
3369 if (err
!= PICL_SUCCESS
)
3371 err
= add_prop_float(sensorhdl
, (float)env
->sd_lo_warn
/ scale
,
3372 PICL_PROP_LOW_WARNING
);
3373 if (err
!= PICL_SUCCESS
)
3375 err
= add_prop_float(sensorhdl
, (float)env
->sd_lo
/ scale
,
3376 PICL_PROP_LOW_SHUTDOWN
);
3377 if (err
!= PICL_SUCCESS
)
3379 err
= add_prop_float(sensorhdl
, (float)env
->sd_hi_warn
/ scale
,
3380 PICL_PROP_HIGH_WARNING
);
3381 if (err
!= PICL_SUCCESS
)
3383 err
= add_prop_float(sensorhdl
, (float)env
->sd_hi
/ scale
,
3384 PICL_PROP_HIGH_SHUTDOWN
);
3385 if (err
!= PICL_SUCCESS
)
3394 get_sensor_data(ptree_rarg_t
*arg
, void *result
)
3396 int err
; /* return code */
3398 char name
[PICL_PROPNAMELEN_MAX
];
3399 ptree_propinfo_t propinfo
;
3402 char buf
[PICL_PROPNAMELEN_MAX
];
3403 char buf1
[PICL_PROPNAMELEN_MAX
];
3404 kstat_t
*env_info_ksp
;
3406 err
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_NAME
, name
,
3408 if (err
!= PICL_SUCCESS
)
3410 err
= ptree_get_propinfo(arg
->proph
, &propinfo
);
3411 if (err
!= PICL_SUCCESS
)
3414 err
= open_kstat(SG_ENV_INFO_KSTAT_NAME
, (void **)&env_info_ksp
, &kc
);
3415 if (err
!= PICL_SUCCESS
) {
3419 env
= env_info_ksp
->ks_data
;
3420 for (i
= 0; i
< SGENV_NUM_ENV_READINGS(env_info_ksp
); i
++, env
++) {
3422 * check kstat values are within range
3424 if (SG_INFO_VALUESTATUS(env
->sd_infostamp
) != SG_INFO_VALUE_OK
)
3426 if (env
->sd_id
.id
.sensor_type
< SG_SENSOR_TYPE_CURRENT
)
3428 if (env
->sd_id
.id
.sensor_type
== SG_SENSOR_TYPE_ENVDB
)
3430 if (env
->sd_id
.id
.sensor_type
> SG_SENSOR_TYPE_2_5_VDC
)
3432 if ((env
->sd_id
.id
.hpu_type
>> 8) >=
3433 (SG_HPU_TYPE_SUN_FIRE_3800_CENTERPLANE
>> 8))
3435 if (env
->sd_id
.id
.sensor_part
> SG_SENSOR_PART_INPUT
)
3439 * check this kstat matches the name of the node
3440 * note sc reports RPS as 10 and 12 via env messages
3441 * but by 0 and 2 via fru messages, so correct here
3443 if ((env
->sd_id
.id
.hpu_type
>> 8) ==
3444 (SG_HPU_TYPE_REPEATER_BOARD
>> 8))
3445 sprintf_buf3(buf
, "%s%d",
3446 hpu_type_table
[env
->sd_id
.id
.hpu_type
>> 8],
3447 env
->sd_id
.id
.hpu_slot
- 10);
3449 sprintf_buf3(buf
, "%s%d",
3450 hpu_type_table
[env
->sd_id
.id
.hpu_type
>> 8],
3451 env
->sd_id
.id
.hpu_slot
);
3452 switch (env
->sd_id
.id
.sensor_type
) {
3453 case SG_SENSOR_TYPE_TEMPERATURE
:
3454 if (env
->sd_id
.id
.sensor_part
== SG_SENSOR_PART_BOARD
) {
3455 sprintf_buf3(buf1
, "%s_t_ambient%d",
3456 buf
, env
->sd_id
.id
.sensor_typenum
);
3458 sprintf_buf4(buf1
, "%s_t_%s%d", buf
,
3459 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3460 env
->sd_id
.id
.sensor_partnum
);
3463 case SG_SENSOR_TYPE_CURRENT
:
3464 sprintf_buf4(buf1
, "%s_i_%s%d", buf
,
3465 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3466 env
->sd_id
.id
.sensor_partnum
);
3468 case SG_SENSOR_TYPE_COOLING
:
3469 sprintf_buf4(buf1
, "%s_ft_%s%d", buf
,
3470 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3471 env
->sd_id
.id
.sensor_partnum
);
3473 default: /* voltage */
3474 if (env
->sd_id
.id
.sensor_part
== SG_SENSOR_PART_BOARD
) {
3475 sprintf_buf4(buf1
, "%s_v_%s%d", buf
,
3476 hpu_sensor_table
[env
->sd_id
.id
.sensor_type
],
3477 env
->sd_id
.id
.sensor_typenum
);
3479 sprintf_buf4(buf1
, "%s_v_%s%d", buf
,
3480 hpu_part_table
[env
->sd_id
.id
.sensor_part
],
3481 env
->sd_id
.id
.sensor_partnum
);
3485 if (strcmp(buf1
, name
) != 0)
3489 * ok - this is the kstat we want - update
3490 * Condition, or sensor reading as requested
3492 if (strcmp(propinfo
.piclinfo
.name
, PICL_PROP_CONDITION
) == 0) {
3493 switch (SG_GET_SENSOR_STATUS(env
->sd_status
)) {
3494 case SG_SENSOR_STATUS_OK
:
3495 (void) strlcpy(result
, PICL_PROPVAL_OKAY
,
3498 case SG_SENSOR_STATUS_LO_WARN
:
3499 case SG_SENSOR_STATUS_HI_WARN
:
3500 (void) strlcpy(result
, PICL_PROPVAL_WARNING
,
3503 case SG_SENSOR_STATUS_LO_DANGER
:
3504 case SG_SENSOR_STATUS_HI_DANGER
:
3505 (void) strlcpy(result
, PICL_PROPVAL_FAILED
,
3510 return (PICL_PROPVALUNAVAILABLE
);
3513 return (PICL_SUCCESS
);
3515 switch (env
->sd_id
.id
.sensor_type
) {
3516 case SG_SENSOR_TYPE_TEMPERATURE
:
3517 *(int *)result
= env
->sd_value
/ SG_TEMPERATURE_SCALE
;
3519 case SG_SENSOR_TYPE_1_5_VDC
:
3521 (float)env
->sd_value
/ (float)SG_1_5_VDC_SCALE
;
3523 case SG_SENSOR_TYPE_1_8_VDC
:
3525 (float)env
->sd_value
/ (float)SG_1_8_VDC_SCALE
;
3527 case SG_SENSOR_TYPE_2_5_VDC
:
3529 (float)env
->sd_value
/ (float)SG_2_5_VDC_SCALE
;
3531 case SG_SENSOR_TYPE_3_3_VDC
:
3533 (float)env
->sd_value
/ (float)SG_3_3_VDC_SCALE
;
3535 case SG_SENSOR_TYPE_5_VDC
:
3537 (float)env
->sd_value
/ (float)SG_5_VDC_SCALE
;
3539 case SG_SENSOR_TYPE_12_VDC
:
3541 (float)env
->sd_value
/ (float)SG_12_VDC_SCALE
;
3543 case SG_SENSOR_TYPE_CURRENT
:
3545 (float)env
->sd_value
/ (float)SG_CURRENT_SCALE
;
3547 case SG_SENSOR_TYPE_COOLING
:
3548 if (strcmp(propinfo
.piclinfo
.name
,
3549 PICL_PROP_FAN_SPEED_UNIT
) == 0) {
3550 if (SG_GET_SENSOR_STATUS(env
->sd_status
) ==
3551 SG_SENSOR_STATUS_FAN_LOW
) {
3552 (void) strlcpy(result
,
3553 PICL_PROPVAL_SELF_REGULATING
,
3554 MAX_SPEED_UNIT_LEN
);
3556 (void) strlcpy(result
,
3557 PICL_PROPVAL_PER_CENT
,
3558 MAX_SPEED_UNIT_LEN
);
3561 switch (SG_GET_SENSOR_STATUS(env
->sd_status
)) {
3562 case SG_SENSOR_STATUS_FAN_HIGH
:
3563 *(int *)result
= 100;
3565 case SG_SENSOR_STATUS_FAN_FAIL
:
3566 case SG_SENSOR_STATUS_FAN_OFF
:
3570 case SG_SENSOR_STATUS_FAN_LOW
:
3572 return (PICL_PROPVALUNAVAILABLE
);
3578 return (PICL_PROPVALUNAVAILABLE
);
3581 return (PICL_SUCCESS
);
3584 return (PICL_PROPVALUNAVAILABLE
);
3588 * led information handling - uses lw8 driver
3592 add_led_nodes(picl_nodehdl_t nodeh
, char *name
, int position
,
3593 picl_prophdl_t tblhdl
)
3597 lom_get_led_t lom_get_led
;
3598 picl_nodehdl_t sensorhdl
;
3599 char buf
[PICL_PROPNAMELEN_MAX
];
3602 * Open the lw8 pseudo dev to get the led information
3604 if ((ledfd
= open(LED_PSEUDO_DEV
, O_RDWR
, 0)) == -1) {
3605 syslog(LOG_ERR
, DEV_OPEN_FAIL
, LED_PSEUDO_DEV
, strerror(errno
));
3606 return (PICL_SUCCESS
);
3608 bzero(&lom_get_led
, sizeof (lom_get_led
));
3609 (void) strlcpy(lom_get_led
.location
, name
,
3610 sizeof (lom_get_led
.location
));
3611 if (ioctl(ledfd
, LOMIOCGETLED
, &lom_get_led
) == -1) {
3612 (void) close(ledfd
);
3613 syslog(LOG_ERR
, LED_IOCTL_FAIL
, strerror(errno
));
3614 return (PICL_FAILURE
);
3616 while (lom_get_led
.next_id
[0] != '\0') {
3617 (void) strlcpy(lom_get_led
.id
, lom_get_led
.next_id
,
3618 sizeof (lom_get_led
.id
));
3619 lom_get_led
.next_id
[0] = '\0';
3620 lom_get_led
.position
= LOM_LED_POSITION_FRU
;
3621 if (ioctl(ledfd
, LOMIOCGETLED
, &lom_get_led
) == -1) {
3622 (void) close(ledfd
);
3623 syslog(LOG_ERR
, LED_IOCTL_FAIL
, strerror(errno
));
3624 return (PICL_FAILURE
);
3626 sprintf_buf3(buf
, "%s_%s", name
, lom_get_led
.id
);
3627 if (position
!= lom_get_led
.position
)
3629 if (position
== LOM_LED_POSITION_LOCATION
) {
3630 err
= add_sensor_node(NULL
, nodeh
, buf
, PICL_CLASS_LED
,
3631 PICL_PROP_STATE
, tblhdl
, &sensorhdl
);
3633 err
= add_sensor_node(nodeh
, NULL
, buf
, PICL_CLASS_LED
,
3634 PICL_PROP_STATE
, tblhdl
, &sensorhdl
);
3636 if (err
!= PICL_SUCCESS
) {
3637 (void) close(ledfd
);
3640 if (strcmp(name
, "chassis") == 0 && strcmp(lom_get_led
.id
,
3642 err
= add_prop_charstring(sensorhdl
, PICL_PROPVAL_TRUE
,
3643 PICL_PROP_IS_LOCATOR
);
3644 if (err
!= PICL_SUCCESS
) {
3645 (void) close(ledfd
);
3648 err
= add_prop_charstring(sensorhdl
,
3649 PICL_PROPVAL_SYSTEM
, PICL_PROP_LOCATOR_NAME
);
3650 if (err
!= PICL_SUCCESS
) {
3651 (void) close(ledfd
);
3655 err
= add_prop_charstring(sensorhdl
, lom_get_led
.id
,
3657 if (err
!= PICL_SUCCESS
) {
3658 (void) close(ledfd
);
3661 err
= add_prop_charstring(sensorhdl
, lom_get_led
.color
,
3663 if (err
!= PICL_SUCCESS
) {
3664 (void) close(ledfd
);
3668 (void) close(ledfd
);
3669 return (PICL_SUCCESS
);
3673 get_led(char *name
, char *ptr
, char *result
)
3676 lom_get_led_t lom_get_led
;
3679 * Open the lw8 pseudo dev to get the led information
3681 if ((ledfd
= open(LED_PSEUDO_DEV
, O_RDWR
, 0)) == -1) {
3682 syslog(LOG_ERR
, DEV_OPEN_FAIL
, LED_PSEUDO_DEV
, strerror(errno
));
3683 return (PICL_FAILURE
);
3685 bzero(&lom_get_led
, sizeof (lom_get_led
));
3686 (void) strlcpy(lom_get_led
.location
, name
,
3687 sizeof (lom_get_led
.location
));
3688 (void) strlcpy(lom_get_led
.id
, ptr
, sizeof (lom_get_led
.id
));
3689 if (ioctl(ledfd
, LOMIOCGETLED
, &lom_get_led
) == -1) {
3690 (void) close(ledfd
);
3691 syslog(LOG_ERR
, LED_IOCTL_FAIL
, strerror(errno
));
3692 return (PICL_PROPVALUNAVAILABLE
);
3694 if (lom_get_led
.status
== LOM_LED_STATUS_ON
)
3695 (void) strlcpy(result
, PICL_PROPVAL_ON
, MAX_STATE_LEN
);
3696 else if (lom_get_led
.status
== LOM_LED_STATUS_FLASHING
)
3697 (void) strlcpy(result
, PICL_PROPVAL_FLASHING
, MAX_STATE_LEN
);
3698 else if (lom_get_led
.status
== LOM_LED_STATUS_BLINKING
)
3699 (void) strlcpy(result
, PICL_PROPVAL_BLINKING
, MAX_STATE_LEN
);
3701 (void) strlcpy(result
, PICL_PROPVAL_OFF
, MAX_STATE_LEN
);
3702 (void) close(ledfd
);
3703 return (PICL_SUCCESS
);
3707 get_led_data(ptree_rarg_t
*arg
, void *result
)
3709 int rc
; /* return code */
3710 char name
[PICL_PROPNAMELEN_MAX
];
3713 rc
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_NAME
, name
,
3715 if (rc
!= PICL_SUCCESS
)
3718 ptr
= strchr(name
, '_');
3719 *ptr
++ = '\0'; /* now name is fru name, ptr is led name */
3720 return (get_led(name
, ptr
, (char *)result
));
3724 set_led(char *name
, char *ptr
, char *value
)
3727 lom_set_led_t lom_set_led
;
3730 * Open the lw8 pseudo dev to set the led information
3732 if ((ledfd
= open(LED_PSEUDO_DEV
, O_RDWR
, 0)) == -1) {
3733 syslog(LOG_ERR
, DEV_OPEN_FAIL
, LED_PSEUDO_DEV
, strerror(errno
));
3734 return (PICL_FAILURE
);
3736 bzero(&lom_set_led
, sizeof (lom_set_led
));
3737 (void) strlcpy(lom_set_led
.location
, name
,
3738 sizeof (lom_set_led
.location
));
3739 (void) strlcpy(lom_set_led
.id
, ptr
, sizeof (lom_set_led
.id
));
3740 if (strcmp(value
, PICL_PROPVAL_ON
) == 0) {
3741 lom_set_led
.status
= LOM_LED_STATUS_ON
;
3742 } else if (strcmp(value
, PICL_PROPVAL_FLASHING
) == 0) {
3743 lom_set_led
.status
= LOM_LED_STATUS_FLASHING
;
3744 } else if (strcmp(value
, PICL_PROPVAL_BLINKING
) == 0) {
3745 lom_set_led
.status
= LOM_LED_STATUS_BLINKING
;
3747 lom_set_led
.status
= LOM_LED_STATUS_OFF
;
3749 if (ioctl(ledfd
, LOMIOCSETLED
, &lom_set_led
) == -1) {
3750 (void) close(ledfd
);
3751 syslog(LOG_ERR
, LED_IOCTL_FAIL
, strerror(errno
));
3752 return (PICL_PROPVALUNAVAILABLE
);
3754 (void) close(ledfd
);
3755 return (PICL_SUCCESS
);
3759 set_led_data(ptree_warg_t
*arg
, const void *value
)
3761 int rc
; /* return code */
3762 char name
[PICL_PROPNAMELEN_MAX
];
3765 rc
= ptree_get_propval_by_name(arg
->nodeh
, PICL_PROP_NAME
, name
,
3767 if (rc
!= PICL_SUCCESS
)
3770 ptr
= strchr(name
, '_');
3771 *ptr
++ = '\0'; /* now name is fru name, ptr is led name */
3772 return (set_led(name
, ptr
, (char *)value
));
3776 disk_leds_init(void)
3780 if (!g_mutex_init
) {
3781 if ((pthread_cond_init(&g_cv
, NULL
) == 0) &&
3782 (pthread_cond_init(&g_cv_ack
, NULL
) == 0) &&
3783 (pthread_mutex_init(&g_mutex
, NULL
) == 0)) {
3784 g_mutex_init
= B_TRUE
;
3790 if (ledsthr_created
) {
3792 * this is a restart, wake up sleeping threads
3794 err
= pthread_mutex_lock(&g_mutex
);
3796 syslog(LOG_ERR
, EM_MUTEX_FAIL
, strerror(err
));
3799 g_wait_now
= B_FALSE
;
3800 (void) pthread_cond_broadcast(&g_cv
);
3801 (void) pthread_mutex_unlock(&g_mutex
);
3803 if ((pthread_attr_init(&ledsthr_attr
) != 0) ||
3804 (pthread_attr_setscope(&ledsthr_attr
,
3805 PTHREAD_SCOPE_SYSTEM
) != 0))
3807 if ((err
= pthread_create(&ledsthr_tid
, &ledsthr_attr
,
3808 disk_leds_thread
, NULL
)) != 0) {
3809 syslog(LOG_ERR
, EM_THREAD_CREATE_FAILED
, strerror(err
));
3812 ledsthr_created
= B_TRUE
;
3814 for (i
= 0; i
< N_DISKS
; i
++) {
3815 (void) set_led(lw8_disks
[i
].d_fruname
, FAULT_LED
,
3821 disk_leds_fini(void)
3826 * tell led thread to pause
3828 if (!ledsthr_created
)
3830 err
= pthread_mutex_lock(&g_mutex
);
3832 syslog(LOG_ERR
, EM_MUTEX_FAIL
, strerror(err
));
3835 g_wait_now
= B_TRUE
;
3836 disk_leds_thread_ack
= B_FALSE
;
3837 (void) pthread_cond_broadcast(&g_cv
);
3840 * and wait for the led thread to acknowledge
3842 while (!disk_leds_thread_ack
) {
3843 (void) pthread_cond_wait(&g_cv_ack
, &g_mutex
);
3845 (void) pthread_mutex_unlock(&g_mutex
);
3849 update_disk_node(struct lw8_disk
*diskp
)
3851 picl_nodehdl_t slotndh
;
3852 picl_nodehdl_t diskndh
;
3853 picl_nodehdl_t devhdl
;
3854 picl_prophdl_t tblhdl
;
3856 char path
[MAXPATHLEN
];
3857 char *fruname
= diskp
->d_fruname
;
3859 sprintf_buf2(path
, CHASSIS_LOC_PATH
, fruname
);
3860 if (ptree_get_node_by_path(path
, &slotndh
) != PICL_SUCCESS
) {
3863 diskndh
= find_child_by_name(slotndh
, fruname
);
3864 err
= ptree_get_node_by_path(diskp
->d_plat_path
, &devhdl
);
3865 if (err
== PICL_SUCCESS
) {
3866 if (diskndh
!= NULL
)
3868 err
= ptree_create_and_add_node(slotndh
, fruname
,
3869 PICL_CLASS_FRU
, &diskndh
);
3870 if (err
!= PICL_SUCCESS
) {
3871 syslog(LOG_ERR
, ADD_NODE_FAIL
, fruname
, err
);
3874 err
= create_table(diskndh
, &tblhdl
, PICL_PROP_DEVICES
);
3875 if (err
!= PICL_SUCCESS
)
3877 err
= create_table_entry(tblhdl
, devhdl
, PICL_CLASS_BLOCK
);
3878 if (err
!= PICL_SUCCESS
)
3880 err
= add_prop_ref(devhdl
, diskndh
, PICL_REFPROP_FRU_PARENT
);
3881 if (err
!= PICL_SUCCESS
)
3884 if (diskndh
== NULL
)
3886 err
= ptree_delete_node(diskndh
);
3887 if (err
!= PICL_SUCCESS
)
3889 (void) ptree_destroy_node(diskndh
);
3894 * Implement a state machine in order to:
3896 * o enable/disable disk LEDs
3897 * o add/delete the disk's node in the FRU tree
3899 * The machine changes state based on the current, in-memory
3900 * state of the disk (eg, the d_state field of 'struct lw8_disk')
3901 * and libdevice's current view of whether the disk is
3902 * Configured or Unconfigured.
3904 * If the new state is the same as the previous state, then
3905 * no side effects occur. Otherwise, the LEDs for the
3906 * disk are set and the disk's associated node in the
3907 * FRU Tree is added or deleted.
3910 set_disk_leds(struct lw8_disk
*disk
)
3913 uint_t cur_state
= 0;
3915 dhdl
= devctl_device_acquire(disk
->d_devices_path
, 0);
3918 syslog(LOG_ERR
, DEVCTL_DEVICE_ACQUIRE_FAILED
,
3922 devctl_device_getstate(dhdl
, &cur_state
);
3923 devctl_release(dhdl
);
3925 if ((cur_state
& DEVICE_OFFLINE
) != 0) {
3926 switch (disk
->d_state
) {
3929 * State machine should never get here.
3930 * When NDEBUG is defined, control will
3931 * fall through and force d_state to
3932 * match the semantics of "DEVICE_OFFLINE".
3933 * During development, NDEBUG can be undefined,
3934 * and this will fire an assertion.
3939 case DISK_STATE_NOT_INIT
:
3940 case DISK_STATE_READY
:
3941 disk
->d_state
= DISK_STATE_NOT_READY
;
3943 (void) set_led(disk
->d_fruname
, POWER_LED
,
3945 (void) set_led(disk
->d_fruname
, REMOK_LED
,
3948 update_disk_node(disk
);
3951 case DISK_STATE_NOT_READY
:
3954 } else if ((cur_state
& DEVICE_ONLINE
) != 0) {
3955 switch (disk
->d_state
) {
3958 * State machine should never get here.
3959 * When NDEBUG is defined, control will
3960 * fall through and force d_state to
3961 * match the semantics of "DEVICE_ONLINE".
3962 * During development, NDEBUG can be undefined,
3963 * and this will fire an assertion.
3968 case DISK_STATE_NOT_INIT
:
3969 case DISK_STATE_NOT_READY
:
3970 disk
->d_state
= DISK_STATE_READY
;
3972 (void) set_led(disk
->d_fruname
, REMOK_LED
,
3974 (void) set_led(disk
->d_fruname
, POWER_LED
,
3977 update_disk_node(disk
);
3980 case DISK_STATE_READY
:
3987 * NOTE: this implementation of disk_leds_thread is based on the version in
3988 * plugins/sun4u/mpxu/frudr/piclfrudr.c (with V440 raid support removed). Some
3989 * day the source code layout and build environment should support common code
3990 * used by platform specific plugins, in which case LW8 support could be added
3991 * to the mpxu version (which would be moved to a common directory).
3995 disk_leds_thread(void *args
)
3999 int n_disks
= N_DISKS
;
4001 static char *lw8_pci_devs
[] = {
4006 static char *lw8_pcix_devs
[] = {
4007 DISK0_BASE_PATH_PCIX
,
4008 DISK1_BASE_PATH_PCIX
4011 static char **lw8_devs
;
4014 lw8_devs
= lw8_pcix_devs
;
4016 lw8_devs
= lw8_pci_devs
;
4020 * create aliases for disk names
4022 for (i
= 0; i
< n_disks
; i
++) {
4023 char buffer
[MAXPATHLEN
];
4025 (void) snprintf(buffer
, sizeof (buffer
), "/devices%s",
4027 lw8_disks
[i
].d_devices_path
= strdup(buffer
);
4029 (void) snprintf(buffer
, sizeof (buffer
), "/platform%s",
4031 lw8_disks
[i
].d_plat_path
= strdup(buffer
);
4035 for (i
= 0; i
< n_disks
; i
++) {
4036 set_disk_leds(&lw8_disks
[i
]);
4040 * wait a bit until we check again
4042 err
= poll(NULL
, 0, ledsthr_poll_period
);
4045 syslog(LOG_ERR
, EM_POLL_FAIL
, strerror(err
));
4048 err
= pthread_mutex_lock(&g_mutex
);
4050 syslog(LOG_ERR
, EM_MUTEX_FAIL
, strerror(err
));
4053 if (g_wait_now
!= B_FALSE
) {
4054 /* notify _fini routine that we've paused */
4055 disk_leds_thread_ack
= B_TRUE
;
4056 (void) pthread_cond_signal(&g_cv_ack
);
4057 /* and go to sleep in case we get restarted */
4058 while (g_wait_now
!= B_FALSE
)
4059 (void) pthread_cond_wait(&g_cv
, &g_mutex
);
4061 (void) pthread_mutex_unlock(&g_mutex
);
4063 return ((void *)err
);