xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/daktari/psvcpolicy/psvcpolicy.c (revision 0dee7919e2f2a6479d16b370af93747b9416b242)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Daktari platform platform specific environment monitoring policies
31  */
32 #include	<poll.h>
33 #include	<syslog.h>
34 #include	<unistd.h>
35 #include	<stdio.h>
36 #include	<stdlib.h>
37 #include	<errno.h>
38 #include	<fcntl.h>
39 #include	<strings.h>
40 #include	<libintl.h>
41 #include	<sys/types.h>
42 #include	<sys/param.h>
43 #include	<config_admin.h>
44 #include	<libdevice.h>
45 #include	<picl.h>
46 #include	<picltree.h>
47 #include	<psvc_objects.h>
48 #include	<sys/i2c/clients/i2c_client.h>
49 #include	<sys/daktari.h>
50 #include	<sys/hpc3130_events.h>
51 #include	<assert.h>
52 
53 /*LINTLIBRARY*/
54 
55 /* resides in libcfgadm */
56 extern cfga_err_t config_change_state(cfga_cmd_t, int, char *const *,
57 	const char *, struct cfga_confirm *, struct cfga_msg *, char **,
58 	cfga_flags_t);
59 /* Local Routine */
60 static int32_t update_gen_fault_led(psvc_opaque_t, char *);
61 static void shutdown_routine(void);
62 static int32_t update_thresholds(psvc_opaque_t hdlp, char *id, int offset);
63 
64 
65 #ifdef DEBUG
66 
67 static int dak_policy_debug = 0;
68 
69 #define	D1SYS_ERR(ARGS) if (dak_policy_debug & 0x1) syslog ARGS;
70 #define	D2SYS_ERR(ARGS) if (dak_policy_debug & 0x2) syslog ARGS;
71 
72 #else
73 
74 #define	D1SYS_ERR(ARGS)
75 #define	D2SYS_ERR(ARGS)
76 
77 #endif
78 
79 #define	I2C_PATH	"/devices/pci@9,700000/ebus@1/i2c@1,30"
80 #define	I2C_NODE	I2C_PATH ":devctl"
81 #define	PCF8574		I2C_PATH "/ioexp@0,%x:pcf8574"
82 #define	PCF8591		I2C_PATH "/adio@0,%x:port_0"
83 #define	FRU		I2C_PATH "/fru@0,%x:fru"
84 #define	HPC3130_DEV	I2C_PATH "/hotplug-controller@0,%2x:port_%1x"
85 #define	GEN_FAULT_LED	"FSP_GEN_FAULT_LED"
86 #define	EMPTY_STRING	"EMPTY"
87 #define	DEVICE_FAILURE_MSG	gettext("WARNING: Device %s failure detected")
88 #define	DEVICE_INSERTED_MSG	gettext("Device %s inserted")
89 #define	DEVICE_REMOVED_MSG	gettext("Device %s removed")
90 #define	PS_UNPLUGGED_MSG	gettext("Device %s unplugged")
91 #define	PS_PLUGGED_MSG		gettext("Device %s Plugged in")
92 #define	DEVICE_OK_MSG		gettext("Device %s OK")
93 #define	SET_LED_FAILED_MSG		\
94 	gettext("Failed to set LED state, id = %s, errno = %d\n")
95 #define	GET_PRESENCE_FAILED_MSG		\
96 	gettext("Failed to get presence attribute, id = %s, errno = %d\n")
97 #define	GET_SENSOR_FAILED_MSG		\
98 	gettext("Failed to get sensor value, id = %s, errno = %d\n")
99 #define	ADD_PS_MSG			\
100 gettext("WARNING: Only 1 Power Supply in system. ADD a 2nd Power Supply.\n")
101 #define	REMOVE_LOAD_MSG			\
102 	gettext("WARNING: Power Supply at 95%% current. Remove some load.\n")
103 #define	PS_OVER_CURRENT_MSG		\
104 	gettext("WARNING: Power Supply overcurrent detected\n")
105 #define	DEVICE_UNKNOWN_MSG	gettext("Unknown device %s instance %d\n")
106 #define	DEVICE_HANDLE_FAIL_MSG		\
107 	gettext("Failed to get device handle for %s, errno = %d\n")
108 #define	DEVTREE_NODE_CREATE_FAILED	\
109 	gettext("psvc PICL plugin: Failed to create node for %s, errno = %d")
110 #define	DEVTREE_NODE_DELETE_FAILED	\
111 	gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d")
112 #define	DISK_FAULT_MSG		gettext("%s: Error Reported\n")
113 #define	DISK_OK_MSG		gettext("%s: Error Cleared\n")
114 #define	SET_FANSPEED_FAILED_MSG		\
115 	gettext("Failed to set fan speed, id = %s, errno = %d\n")
116 #define	GET_ATTR_FRU_FAILED_MSG	gettext("Failed psvc_get_attr for FRU info\n")
117 #define	NO_FRU_INFO_MSG			\
118 	gettext("No FRU Information for %s using default module card\n")
119 
120 #define	DAKTARI_MAX_PS	3
121 #define	DAK_MAX_PS_I_SENSORS 4
122 #define	DAK_MAX_DISKS	12
123 #define	DAK_MAX_CPU_MOD	4
124 #define	DAK_MAX_FAULT_SENSORS 3
125 #define	DAK_MAX_FANS 10
126 
127 static int co_ps = 0;
128 static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\"";
129 
130 typedef struct i2c_hp {
131 	int32_t		addr[2];
132 	char		name[256];
133 	char		compatible[256];
134 } i2c_hp_t;
135 
136 typedef struct seg_desc {
137 	int32_t segdesc;
138 	int16_t segoffset;
139 	int16_t seglength;
140 } seg_desc_t;
141 
142 static int32_t threshold_names[] = {
143 	PSVC_HW_LO_SHUT_ATTR,
144 	PSVC_LO_SHUT_ATTR,
145 	PSVC_LO_WARN_ATTR,
146 	PSVC_NOT_USED,			/* LOW MODE which is not used */
147 	PSVC_OPTIMAL_TEMP_ATTR,
148 	PSVC_HI_WARN_ATTR,
149 	PSVC_HI_SHUT_ATTR,
150 	PSVC_HW_HI_SHUT_ATTR
151 };
152 
153 int32_t
154 psvc_MB_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset)
155 {
156 	int IO_offset = 0xd;
157 	int32_t err;
158 
159 	err = update_thresholds(hdlp, id, IO_offset);
160 
161 	return (err);
162 }
163 
164 int32_t
165 psvc_IO_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset)
166 {
167 	int IO_offset = 0x8;
168 	int32_t err;
169 
170 	err = update_thresholds(hdlp, id, IO_offset);
171 
172 	return (err);
173 }
174 
175 int32_t
176 psvc_DBP_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset)
177 {
178 	int IO_offset = 0x7;
179 	int32_t err;
180 
181 	err = update_thresholds(hdlp, id, IO_offset);
182 
183 	return (err);
184 }
185 
186 /*
187  * used to determine if a change of state occured. valid when states
188  * are strings.
189  */
190 static int8_t
191 change_of_state_str(char *state1, char *check1, char *state2, char *check2)
192 {
193 	int change = 0;
194 
195 	if ((strcmp(state1, check1) == 0) && (strcmp(state2, check2) != 0))
196 		change = 1;
197 	if ((strcmp(state1, check1) != 0) && (strcmp(state2, check2) == 0))
198 		change = 1;
199 
200 	return (change);
201 }
202 
203 /*
204  * Update thresholds tries to read the temperature thresholds from the FRU
205  * SEEproms and then updates the thresholds in the object by overriding the
206  * hardcoded thresholds.  For Daktari it is an Error if the FRU does not
207  * contain the segment that had the temperature thresholds.
208  */
209 static int32_t
210 update_thresholds(psvc_opaque_t hdlp, char *id, int offset)
211 {
212 	int32_t status = PSVC_SUCCESS;
213 	fru_info_t fru_data;
214 	char *fru, seg_name[2];
215 	int8_t seg_count, temp_array[8];
216 	int32_t match_count, i, j, seg_desc_start = 0x1806, temp_address;
217 	int32_t seg_found, temp;
218 	boolean_t present;
219 	seg_desc_t segment;
220 
221 	status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present);
222 	if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT))
223 		return (status);
224 
225 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count,
226 	    PSVC_FRU);
227 	if (status == PSVC_FAILURE)
228 		return (status);
229 
230 	for (i = 0; i < match_count; i++) {
231 		seg_found = 0;
232 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
233 		    &fru, PSVC_FRU, i);
234 		if (status != PSVC_SUCCESS)
235 			return (status);
236 
237 		fru_data.buf_start = 0x1805;
238 		fru_data.buf = (char *)&seg_count;
239 		fru_data.read_size = 1;
240 
241 		status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
242 		    &fru_data);
243 		if (status != PSVC_SUCCESS) {
244 			return (status);
245 		}
246 		for (j = 0; (j < seg_count) && (!seg_found); j++) {
247 			fru_data.buf_start = seg_desc_start;
248 			fru_data.buf = seg_name;
249 			fru_data.read_size = 2;
250 
251 			status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
252 			    &fru_data);
253 
254 			seg_desc_start = seg_desc_start + 2;
255 			fru_data.buf_start = seg_desc_start;
256 			fru_data.buf = (char *)&segment;
257 			fru_data.read_size = sizeof (seg_desc_t);
258 
259 			status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
260 			    &fru_data);
261 			if (status != PSVC_SUCCESS) {
262 				syslog(LOG_ERR,
263 				    "Failed psvc_get_attr for FRU info\n");
264 				return (status);
265 			}
266 			seg_desc_start = seg_desc_start + sizeof (seg_desc_t);
267 			if (memcmp(seg_name, "SC", 2) == 0)
268 				seg_found = 1;
269 		}
270 		if (seg_found) {
271 			temp_address = segment.segoffset + offset;
272 			fru_data.buf_start = temp_address;
273 			fru_data.buf = (char *)&temp_array;
274 			fru_data.read_size = sizeof (temp_array);
275 			status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
276 			    &fru_data);
277 			if (status != PSVC_SUCCESS) {
278 				syslog(LOG_ERR,
279 				    "Failed psvc_get_attr for FRU info\n");
280 				return (status);
281 			} else {
282 				for (j = 0; j < sizeof (temp_array); j++) {
283 					if (threshold_names[j] ==
284 					    PSVC_NOT_USED)
285 						continue;
286 					temp = temp_array[j];
287 					status = psvc_set_attr(hdlp, id,
288 					    threshold_names[j], &temp);
289 					if (status != PSVC_SUCCESS) {
290 						return (status);
291 					}
292 				}
293 			}
294 		} else {
295 			syslog(LOG_ERR, "No FRU Information for %s"
296 			    " using default temperatures\n", id);
297 		}
298 	}
299 	return (status);
300 }
301 
302 int32_t
303 psvc_fan_init_speed_0(psvc_opaque_t hdlp, char *id)
304 {
305 	int32_t status = PSVC_SUCCESS;
306 	boolean_t present;
307 	char *control_id;
308 	int32_t init_speed = 0;
309 
310 	status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present);
311 	if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT))
312 		return (status);
313 
314 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &control_id,
315 		PSVC_FAN_DRIVE_CONTROL, 0);
316 	if (status != PSVC_SUCCESS)
317 		return (status);
318 
319 	status = psvc_set_attr(hdlp, control_id, PSVC_CONTROL_VALUE_ATTR,
320 	    &init_speed);
321 	if (status == PSVC_FAILURE) {
322 		syslog(LOG_ERR, SET_FANSPEED_FAILED_MSG, control_id, errno);
323 		return (status);
324 	}
325 
326 	return (status);
327 }
328 
329 int32_t
330 psvc_update_setpoint_0(psvc_opaque_t hdlp, char *id)
331 {
332 	int32_t status = PSVC_SUCCESS;
333 	char *temp_sensor;
334 	int32_t match_count, i, temp;
335 	int16_t lowest_temp = 500;
336 	boolean_t present;
337 
338 	status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present);
339 	if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT))
340 		return (status);
341 
342 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count,
343 	    PSVC_DEV_TEMP_SENSOR);
344 	if (status == PSVC_FAILURE)
345 		return (status);
346 
347 	for (i = 0; i < match_count; i++) {
348 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
349 		    &temp_sensor, PSVC_DEV_TEMP_SENSOR, i);
350 		if (status != PSVC_SUCCESS)
351 			return (status);
352 		status = psvc_get_attr(hdlp, temp_sensor,
353 		    PSVC_OPTIMAL_TEMP_ATTR, &temp);
354 		if (status != PSVC_SUCCESS) {
355 			syslog(LOG_ERR, "Failed to get Optimal temp for %s\n",
356 			    temp_sensor);
357 			return (status);
358 		}
359 		if (temp < lowest_temp)
360 			lowest_temp = temp;
361 	}
362 	status = psvc_set_attr(hdlp, id, PSVC_SETPOINT_ATTR, &lowest_temp);
363 	if (status == PSVC_FAILURE) {
364 		syslog(LOG_ERR, "Failed to change setpoint for %s\n", id);
365 		return (status);
366 	}
367 	return (status);
368 }
369 
370 int32_t
371 psvc_remove_missing_nodes_0(psvc_opaque_t hdlp, char *id)
372 {
373 	int32_t status = PSVC_SUCCESS;
374 	char state[32];
375 	char *physical_dev;
376 	int32_t i, device_count;
377 	char parent_path[256];
378 	picl_nodehdl_t child_node;
379 	boolean_t present;
380 
381 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR,
382 	    &device_count, PSVC_PHYSICAL_DEVICE);
383 	if (status == PSVC_FAILURE)
384 		return (status);
385 
386 	for (i = 0; i < device_count; i++) {
387 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
388 		    &physical_dev, PSVC_PHYSICAL_DEVICE, i);
389 		if (status != PSVC_SUCCESS)
390 			return (status);
391 		if (strncmp(physical_dev, "LTC1427", 7) == 0)
392 			continue;
393 		status = psvc_get_attr(hdlp, physical_dev,
394 		    PSVC_PROBE_RESULT_ATTR, state);
395 		if (status != PSVC_SUCCESS)
396 			continue;
397 		status = psvc_get_attr(hdlp, physical_dev, PSVC_PRESENCE_ATTR,
398 		    &present);
399 		if (status == PSVC_FAILURE) {
400 			syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, physical_dev,
401 			    errno);
402 			return (status);
403 		}
404 
405 		if ((strcmp(state, PSVC_ERROR) == 0) &&
406 		    (present == PSVC_PRESENT)) {
407 			/* convert name to node, and parent path */
408 			psvcplugin_lookup(physical_dev, parent_path,
409 			    &child_node);
410 			/* Device removed */
411 			ptree_delete_node(child_node);
412 		}
413 	}
414 	return (status);
415 }
416 
417 int32_t
418 psvc_check_ps_hotplug_status_0(psvc_opaque_t hdlp, char *id)
419 {
420 	char		fail_valid_switch_id[PICL_PROPNAMELEN_MAX];
421 	int32_t		status = PSVC_SUCCESS;
422 	char		valid_switch_state[32];
423 	char		state[32], fault[32];
424 	int32_t		led_count, j;
425 	char		*led_id;
426 	char		led_state[32];
427 	boolean_t	present;
428 	static int8_t	hotplug_failed_count = 0;
429 	int8_t		retry;
430 
431 	status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present);
432 	if (status == PSVC_FAILURE) {
433 		syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, id, errno);
434 		return (status);
435 	}
436 
437 	if (present == PSVC_ABSENT) {
438 		errno = ENODEV;
439 		return (PSVC_FAILURE);
440 	}
441 
442 	snprintf(fail_valid_switch_id, sizeof (fail_valid_switch_id), "%s%s",
443 	    id, "_SENSOR_VALID_SWITCH");
444 
445 	retry = 0;
446 	do {
447 		if (retry)
448 			sleep(1);
449 		status = psvc_get_attr(hdlp, fail_valid_switch_id,
450 		    PSVC_STATE_ATTR, valid_switch_state);
451 		if (status == PSVC_FAILURE) {
452 			if (hotplug_failed_count == 0) {
453 				/*
454 				 * First time the get_attr call failed
455 				 * set count so that if we fail again
456 				 * we will know
457 				 */
458 				hotplug_failed_count = 1;
459 				/*
460 				 * We probably failed because the power
461 				 * supply was just insterted or removed
462 				 * before the get_attr call. We then
463 				 * return from this policy successfully
464 				 * knowing it will be run again shortly
465 				 * with the right PS state.
466 				 */
467 				return (PSVC_SUCCESS);
468 			} else {
469 				/*
470 				 * We have failed before and so this
471 				 * we will consider a hardware problem
472 				 * and it should be reported
473 				 */
474 				syslog(LOG_ERR,
475 				    "Failed getting %s State: ",
476 				    "ps_hotplug_status_0\n",
477 				    fail_valid_switch_id);
478 				return (status);
479 			}
480 		}
481 		/*
482 		 * Because we have successfully gotten a value from
483 		 * the i2c device on the PS we will set the
484 		 * failed_count to 0
485 		 */
486 		hotplug_failed_count = 0;
487 
488 		status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state);
489 		if (status == PSVC_FAILURE)
490 			return (status);
491 		retry++;
492 		/*
493 		 * check to see if we need to retry. the conditions are:
494 		 *
495 		 * valid_switch_state	state			retry
496 		 * --------------------------------------------------
497 		 *	PSVC_OFF	!PSVC_HOTPLUGGED	yes
498 		 *	PSVC_ON		PSVC_HOTPLUGGED		yes
499 		 *	PSVC_OFF	PSVC_HOTPLUGGED		no
500 		 *	PSVC_ON		!PSVC_HOTPLUGGED	no
501 		 */
502 	} while ((retry < PSVC_NUM_OF_RETRIES) &&
503 	    change_of_state_str(valid_switch_state, PSVC_OFF,
504 	    state, PSVC_HOTPLUGGED));
505 
506 	if ((strcmp(valid_switch_state, PSVC_OFF) == 0) &&
507 		(strcmp(state, PSVC_HOTPLUGGED) != 0)) {
508 		strcpy(state, PSVC_HOTPLUGGED);
509 		strcpy(fault, PSVC_NO_FAULT);
510 		strcpy(led_state, PSVC_LED_OFF);
511 		status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR,
512 			state);
513 		if (status == PSVC_FAILURE)
514 			return (status);
515 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR,
516 			&led_count, PSVC_DEV_FAULT_LED);
517 		if (status == PSVC_FAILURE)
518 			return (status);
519 
520 		for (j = 0; j < led_count; j++) {
521 
522 			status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
523 				&led_id, PSVC_DEV_FAULT_LED, j);
524 			if (status != PSVC_SUCCESS)
525 				return (status);
526 
527 			status = psvc_set_attr(hdlp, led_id,
528 				PSVC_LED_STATE_ATTR, led_state);
529 			if (status != PSVC_SUCCESS) {
530 				syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id,
531 				    errno);
532 				return (status);
533 			}
534 
535 		}
536 		syslog(LOG_ERR, PS_UNPLUGGED_MSG, id);
537 		return (status);
538 	}
539 
540 	if ((strcmp(valid_switch_state, PSVC_ON) == 0) &&
541 		(strcmp(state, PSVC_HOTPLUGGED) == 0)) {
542 		strcpy(state, PSVC_OK);
543 		strcpy(fault, PSVC_NO_FAULT);
544 		status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state);
545 		if (status == PSVC_FAILURE)
546 			return (status);
547 		syslog(LOG_ERR, PS_PLUGGED_MSG, id);
548 	}
549 
550 	return (status);
551 }
552 
553 int32_t
554 psvc_ps_overcurrent_check_policy_0(psvc_opaque_t hdlp, char *system)
555 {
556 	int32_t status = PSVC_SUCCESS;
557 	boolean_t present;
558 	static char *sensor_id[DAKTARI_MAX_PS][DAK_MAX_PS_I_SENSORS];
559 	static char *power_supply_id[DAKTARI_MAX_PS] = {{NULL}};
560 	int32_t i, j;
561 	int32_t amps, oc_flag = 0, ps_present = 0;
562 	static int32_t hi_warn[DAKTARI_MAX_PS][DAK_MAX_PS_I_SENSORS];
563 	char state[32];
564 	static int8_t overcurrent_failed_check = 0;
565 	static int8_t threshold_counter = 0;
566 
567 	if (power_supply_id[0] == NULL) {
568 		for (i = 0; i < DAKTARI_MAX_PS; i++) {
569 			status = psvc_get_attr(hdlp, system,
570 			    PSVC_ASSOC_ID_ATTR, &(power_supply_id[i]),
571 			    PSVC_PS, i);
572 			if (status != PSVC_SUCCESS)
573 				return (status);
574 			for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) {
575 				status = psvc_get_attr(hdlp,
576 				    power_supply_id[i], PSVC_ASSOC_ID_ATTR,
577 				    &(sensor_id[i][j]), PSVC_PS_I_SENSOR, j);
578 				if (status != PSVC_SUCCESS)
579 					return (status);
580 				status = psvc_get_attr(hdlp, sensor_id[i][j],
581 				    PSVC_HI_WARN_ATTR, &(hi_warn[i][j]));
582 				if (status != PSVC_SUCCESS)
583 					return (status);
584 			}
585 		}
586 	}
587 
588 	for (i = 0; i < DAKTARI_MAX_PS; i++) {
589 		status = psvc_get_attr(hdlp, power_supply_id[i],
590 			PSVC_PRESENCE_ATTR, &present);
591 		if (status == PSVC_FAILURE) {
592 			syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG,
593 				power_supply_id[i], errno);
594 			return (status);
595 		}
596 
597 		if (present == PSVC_ABSENT) {
598 			continue;
599 		}
600 
601 		status = psvc_check_ps_hotplug_status_0(hdlp,
602 		    power_supply_id[i]);
603 		if (status == PSVC_FAILURE)
604 			return (status);
605 
606 		status = psvc_get_attr(hdlp, power_supply_id[i],
607 		    PSVC_STATE_ATTR, state);
608 		if (status == PSVC_FAILURE)
609 			return (status);
610 
611 		if (strcmp(state, PSVC_HOTPLUGGED) == 0) {
612 			continue;
613 		} else {
614 			ps_present++;
615 		}
616 
617 		for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) {
618 			status = psvc_get_attr(hdlp, sensor_id[i][j],
619 				PSVC_SENSOR_VALUE_ATTR, &amps);
620 			if (status != PSVC_SUCCESS) {
621 				if (overcurrent_failed_check == 0) {
622 					/*
623 					 * First time the get_attr call
624 					 * failed  set count so that if we
625 					 * fail again we will know
626 					 */
627 					overcurrent_failed_check = 1;
628 					/*
629 					 * We probably failed because the power
630 					 * supply was just insterted or removed
631 					 * before the get_attr call. We then
632 					 * return from this policy successfully
633 					 * knowing it will be run again shortly
634 					 * with the right PS state.
635 					 */
636 					return (PSVC_SUCCESS);
637 				} else {
638 					/*
639 					 * We have failed before and so this we
640 					 * will consider a hardware problem and
641 					 * it should be reported.
642 					 */
643 					syslog(LOG_ERR,
644 					    "Failed getting %s sensor value",
645 					    sensor_id[i][j]);
646 					return (status);
647 				}
648 			}
649 			/*
650 			 * Because we have successfully gotten a value from the
651 			 * i2c device on the PS we will set the failed_count
652 			 * to 0.
653 			 */
654 			overcurrent_failed_check = 0;
655 
656 			if (amps >= hi_warn[i][j]) {
657 				oc_flag = 1;
658 			}
659 		}
660 	}
661 
662 	if (oc_flag) {
663 		/*
664 		 * Because we observed an overcurrent
665 		 * condition, we increment threshold_counter.
666 		 * Once threshold_counter reaches the value
667 		 * of PSVC_THRESHOLD_COUNTER we log the event.
668 		 */
669 		threshold_counter++;
670 		if (threshold_counter == PSVC_THRESHOLD_COUNTER) {
671 			threshold_counter = 0;
672 			if (ps_present == 1) {
673 				syslog(LOG_ERR, PS_OVER_CURRENT_MSG);
674 				syslog(LOG_ERR, ADD_PS_MSG);
675 			} else {
676 				syslog(LOG_ERR, PS_OVER_CURRENT_MSG);
677 				syslog(LOG_ERR, REMOVE_LOAD_MSG);
678 			}
679 		}
680 	} else {
681 		threshold_counter = 0;
682 	}
683 
684 	return (PSVC_SUCCESS);
685 }
686 
687 int32_t
688 psvc_ps_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *system)
689 {
690 	static char *ps_id[DAKTARI_MAX_PS] = {{NULL}};
691 	static char *sensor_id[DAKTARI_MAX_PS][DAK_MAX_FAULT_SENSORS];
692 	char *led_id = "FSP_POWER_FAULT_LED";
693 	int i, j;
694 	char state[32], fault[32], previous_state[32], past_state[32];
695 	char led_state[32];
696 	char bad_sensors[DAK_MAX_FAULT_SENSORS][256];
697 	int32_t status = PSVC_SUCCESS;
698 	boolean_t present;
699 	int fail_state;
700 	static int8_t device_fail_failed_check = 0;
701 	int8_t retry, should_retry;
702 
703 	if (ps_id[0] == NULL) {
704 		for (i = 0; i < DAKTARI_MAX_PS; i++) {
705 			status = psvc_get_attr(hdlp, system,
706 			    PSVC_ASSOC_ID_ATTR, &(ps_id[i]), PSVC_PS, i);
707 			if (status != PSVC_SUCCESS)
708 				return (status);
709 			for (j = 0; j < DAK_MAX_FAULT_SENSORS; j++) {
710 				status = psvc_get_attr(hdlp, ps_id[i],
711 				    PSVC_ASSOC_ID_ATTR, &(sensor_id[i][j]),
712 				    PSVC_DEV_FAULT_SENSOR, j);
713 				if (status != PSVC_SUCCESS)
714 					return (status);
715 			}
716 		}
717 	}
718 
719 	for (i = 0; i < DAKTARI_MAX_PS; i++) {
720 		fail_state = 0;
721 		status = psvc_get_attr(hdlp, ps_id[i], PSVC_PRESENCE_ATTR,
722 		    &present);
723 		if (status == PSVC_FAILURE)
724 			return (status);
725 
726 		if (present == PSVC_ABSENT) {
727 			errno = ENODEV;
728 			return (PSVC_FAILURE);
729 		}
730 
731 		status = psvc_check_ps_hotplug_status_0(hdlp, ps_id[i]);
732 		if (status == PSVC_FAILURE)
733 			return (status);
734 
735 		status = psvc_get_attr(hdlp, ps_id[i], PSVC_STATE_ATTR,
736 		    past_state);
737 		if (status == PSVC_FAILURE)
738 			return (status);
739 
740 		if (strcmp(past_state, PSVC_HOTPLUGGED) == 0) {
741 			return (PICL_SUCCESS);
742 		}
743 
744 		retry = 0;
745 		do {
746 			if (retry)
747 				sleep(1);
748 			fail_state = 0;
749 			should_retry = 0;
750 			for (j = 0; j < DAK_MAX_FAULT_SENSORS; ++j) {
751 				status = psvc_get_attr(hdlp, sensor_id[i][j],
752 				    PSVC_SWITCH_STATE_ATTR, state);
753 				if (status != PSVC_SUCCESS) {
754 					if (device_fail_failed_check == 0) {
755 						/*
756 						 * First time the get_attr call
757 						 * failed  set count so that
758 						 * if we fail again we will know
759 						 */
760 						device_fail_failed_check = 1;
761 						/*
762 						 * We probably failed because
763 						 * the power supply was just
764 						 * insterted or removed before
765 						 * the get_attr call. We then
766 						 * return from this policy
767 						 * successfully knowing it will
768 						 * be run again shortly
769 						 * with the right PS state.
770 						 */
771 						return (PSVC_SUCCESS);
772 					} else {
773 						/*
774 						 * We have failed before and
775 						 * so this we will consider a
776 						 * hardware problem and
777 						 * it should be reported.
778 						 */
779 						syslog(LOG_ERR, "Failed in "
780 						    "getting sensor state for "
781 						    "%s\n", sensor_id[i][j]);
782 
783 						return (status);
784 					}
785 				}
786 
787 				/*
788 				 * Because we have successfully gotten
789 				 * a value from the i2c device on the
790 				 * PS we will set the failed_count to 0.
791 				 */
792 				device_fail_failed_check = 0;
793 
794 				/*
795 				 * If we find that the sensor is on we
796 				 * fill in the name of the sensor in
797 				 * the bad_sensor array. If the sensor
798 				 * is off we use EMPTY_STRING as a check
799 				 * later on as to when NOT to print out
800 				 * what is in bad_sensor[].
801 				 */
802 				if (strcmp(state, PSVC_SWITCH_ON) == 0) {
803 					fail_state++;
804 					strlcpy(bad_sensors[j], sensor_id[i][j],
805 					    sizeof (bad_sensors[j]));
806 				} else {
807 					strcpy(bad_sensors[j], EMPTY_STRING);
808 				}
809 			}
810 			retry++;
811 			/*
812 			 * check to see if we need to retry. the conditions are:
813 			 *
814 			 * fail_state		past_state		retry
815 			 * --------------------------------------------------
816 			 *	+		PSVC_OK			yes
817 			 *	0		PSVC_ERROR		yes
818 			 *	+		PSVC_ERROR		no
819 			 *	0		PSVC_OK			no
820 			 */
821 			if ((fail_state > 0) &&
822 			    (strcmp(past_state, PSVC_OK) == 0)) {
823 				should_retry = 1;
824 			} else if ((fail_state == 0) &&
825 			    (strcmp(past_state, PSVC_ERROR) == 0)) {
826 				should_retry = 1;
827 			}
828 		} while ((retry < PSVC_NUM_OF_RETRIES) && should_retry);
829 
830 		if (fail_state != 0) {
831 			strcpy(state, PSVC_ERROR);
832 			strcpy(fault, PSVC_GEN_FAULT);
833 		} else {
834 			strcpy(state, PSVC_OK);
835 			strcpy(fault, PSVC_NO_FAULT);
836 		}
837 
838 		status = psvc_set_attr(hdlp, ps_id[i], PSVC_STATE_ATTR, state);
839 		if (status != PSVC_SUCCESS)
840 			return (status);
841 
842 		status = psvc_set_attr(hdlp, ps_id[i], PSVC_FAULTID_ATTR,
843 		    fault);
844 		if (status != PSVC_SUCCESS)
845 			return (status);
846 
847 		status = psvc_get_attr(hdlp, ps_id[i], PSVC_PREV_STATE_ATTR,
848 		    previous_state);
849 		if (status != PSVC_SUCCESS)
850 			return (status);
851 
852 		if (strcmp(state, previous_state) != 0) {
853 			char dev_label[32];
854 
855 			psvc_get_attr(hdlp, ps_id[i], PSVC_LABEL_ATTR,
856 			    dev_label);
857 
858 			if (strcmp(state, PSVC_ERROR) == 0) {
859 				syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label);
860 				for (j = 0; j < DAK_MAX_FAULT_SENSORS; ++j) {
861 					if (strcmp(bad_sensors[j],
862 						EMPTY_STRING) != 0)
863 						syslog(LOG_ERR, "%s\n",
864 						    bad_sensors[j]);
865 				}
866 				strcpy(led_state, PSVC_LED_ON);
867 			} else {
868 				syslog(LOG_ERR, DEVICE_OK_MSG, dev_label);
869 				strcpy(led_state, PSVC_LED_OFF);
870 			}
871 
872 			status = psvc_set_attr(hdlp, led_id,
873 			    PSVC_LED_STATE_ATTR, led_state);
874 			if (status != PSVC_SUCCESS) {
875 				syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id,
876 				    errno);
877 				return (status);
878 			}
879 		}
880 	}
881 
882 	return (PSVC_SUCCESS);
883 }
884 
885 int32_t
886 psvc_ps_check_and_disable_dr_policy_0(psvc_opaque_t hdlp, char *id)
887 {
888 	char		state[32];
889 	static char	*name[DAKTARI_MAX_PS] = {{NULL}};
890 	int		ps_cnt = 0;
891 	int		i, j;
892 	int		dr_conf;
893 	int		fd, rv;
894 	boolean_t	present;
895 	char		dev_path[sizeof (HPC3130_DEV)+8];
896 	unsigned char	controller_names[HPC3130_CONTROLLERS] =
897 		{ 0xe2, 0xe6, 0xe8, 0xec };
898 
899 	if (name[0] == NULL) {
900 		for (i = 0; i < DAKTARI_MAX_PS; i++) {
901 			rv = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
902 			    &(name[i]), PSVC_PS, i);
903 			if (rv != PSVC_SUCCESS)
904 				return (rv);
905 		}
906 	}
907 
908 	/*
909 	 * Go through the power supplies to make sure they're present
910 	 * and OK.
911 	 */
912 	ps_cnt = DAKTARI_MAX_PS;
913 	for (i = 0; i < DAKTARI_MAX_PS; i++) {
914 		rv = psvc_get_attr(hdlp, name[i], PSVC_PRESENCE_ATTR,
915 		    &present);
916 		if (rv != PSVC_SUCCESS)
917 			return (rv);
918 
919 		if (present != PSVC_PRESENT) {
920 			ps_cnt--;
921 			continue;
922 		} else {
923 			rv = psvc_get_attr(hdlp, name[i], PSVC_STATE_ATTR,
924 				state);
925 			if (rv != PSVC_SUCCESS)
926 				return (rv);
927 
928 			if (strcmp(state, PSVC_OK))
929 				ps_cnt--;
930 		}
931 	}
932 
933 	/*
934 	 * No change in DR configuration is needed if the new power supply
935 	 * count equals the current count.
936 	 */
937 	if (ps_cnt == co_ps)
938 		return (PSVC_SUCCESS);
939 
940 	/*
941 	 * Disable DR when hotplugged down to 1 power supply; enable DR when
942 	 * hotplugged up from 1 supply.
943 	 */
944 	assert(ps_cnt);
945 	if ((co_ps == 0 || co_ps > 1) && ps_cnt != 1) {
946 		co_ps = ps_cnt;
947 		return (PSVC_SUCCESS);
948 	}
949 	dr_conf = (ps_cnt == 1 ? HPC3130_DR_DISABLE : HPC3130_DR_ENABLE);
950 	co_ps = ps_cnt;
951 
952 	for (i = 0; i < HPC3130_CONTROLLERS; i++) {
953 		for (j = 0; j < HPC3130_SLOTS; j++) {
954 			(void) snprintf(dev_path, sizeof (dev_path),
955 			    HPC3130_DEV, controller_names[i], j);
956 			fd = open(dev_path, O_RDWR);
957 			if (fd == -1)
958 				return (PSVC_FAILURE);
959 
960 			rv = ioctl(fd, HPC3130_CONF_DR, &dr_conf);
961 			close(fd);
962 			if (rv == -1)
963 				return (PSVC_FAILURE);
964 		}
965 	}
966 
967 	return (PSVC_SUCCESS);
968 }
969 
970 int32_t
971 psvc_fan_blast_shutoff_policy_0(psvc_opaque_t hdlp, char *id)
972 {
973 	char		switch_status[32];
974 	int32_t		status = PSVC_SUCCESS;
975 
976 	status = psvc_get_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, switch_status);
977 	if (status != PSVC_SUCCESS)
978 		return (status);
979 	status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR,
980 		PSVC_SWITCH_OFF);
981 	if (status != PSVC_SUCCESS)
982 		return (status);
983 	status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR,
984 		PSVC_SWITCH_ON);
985 	if (status != PSVC_SUCCESS)
986 		return (status);
987 	status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR,
988 		PSVC_SWITCH_OFF);
989 
990 	return (status);
991 }
992 
993 int32_t
994 psvc_fan_fault_check_policy_0(psvc_opaque_t hdlp, char *system)
995 {
996 	static char *fan_id[DAK_MAX_FANS] = {{NULL}};
997 	boolean_t enabled;
998 	int32_t speed;
999 	int32_t status = PSVC_SUCCESS;
1000 	int r;
1001 	static int8_t threshold_counter = 0;
1002 
1003 	if (fan_id[0] == NULL) {
1004 		for (r = 0; r < DAK_MAX_FANS; r++) {
1005 			status = psvc_get_attr(hdlp, system,
1006 			    PSVC_ASSOC_ID_ATTR, &(fan_id[r]), PSVC_FAN, r);
1007 			if (status != PSVC_SUCCESS)
1008 				return (status);
1009 		}
1010 	}
1011 
1012 	for (r = 0; r < DAK_MAX_FANS; r++) {
1013 		status = psvc_get_attr(hdlp, fan_id[r], PSVC_ENABLE_ATTR,
1014 		    &enabled);
1015 		if (status != PSVC_SUCCESS)
1016 			return (status);
1017 
1018 		if (enabled == PSVC_ENABLED) {
1019 			uint64_t features;
1020 			char *switch_id;
1021 			char switch_state[32], fan_state[32];
1022 			int fan_count, fans;
1023 			char *other_fan_id;
1024 			char fstate[32], ffault[32];
1025 
1026 			/*
1027 			 * If any other fan on the fan tray has an ERROR state,
1028 			 * mark this fan bad and return
1029 			 */
1030 			psvc_get_attr(hdlp, fan_id[r], PSVC_ASSOC_MATCHES_ATTR,
1031 			    &fan_count, PSVC_FAN_TRAY_FANS);
1032 			for (fans = 0; fans < fan_count; ++fans) {
1033 				status = psvc_get_attr(hdlp, fan_id[r],
1034 				    PSVC_ASSOC_ID_ATTR, &other_fan_id,
1035 				    PSVC_FAN_TRAY_FANS, fans);
1036 				if (status == PSVC_FAILURE)
1037 					return (status);
1038 				status = psvc_get_attr(hdlp, other_fan_id,
1039 				    PSVC_STATE_ATTR, fan_state);
1040 				if (status != PSVC_SUCCESS)
1041 					return (status);
1042 
1043 				if (strcmp(fan_state, PSVC_ERROR) == 0) {
1044 					strlcpy(ffault, PSVC_GEN_FAULT,
1045 					    sizeof (ffault));
1046 					status = psvc_set_attr(hdlp, fan_id[r],
1047 					    PSVC_FAULTID_ATTR, ffault);
1048 					if (status != PSVC_SUCCESS)
1049 						return (status);
1050 
1051 					strlcpy(fstate, PSVC_ERROR,
1052 					    sizeof (fstate));
1053 					status = psvc_set_attr(hdlp, fan_id[r],
1054 					    PSVC_STATE_ATTR, fstate);
1055 
1056 					return (status);
1057 				}
1058 			}
1059 
1060 			/*
1061 			 * Select tachometer for IO or CPU primary/secondary
1062 			 * fans.
1063 			 */
1064 			pthread_mutex_lock(&fan_mutex);
1065 
1066 			status = psvc_get_attr(hdlp, fan_id[r],
1067 			    PSVC_ASSOC_ID_ATTR, &switch_id,
1068 			    PSVC_FAN_PRIM_SEC_SELECTOR, 0);
1069 
1070 			if (status != PSVC_FAILURE) {
1071 				status = psvc_get_attr(hdlp, fan_id[r],
1072 				    PSVC_FEATURES_ATTR,	&features);
1073 				if (status == PSVC_FAILURE) {
1074 					pthread_mutex_unlock(&fan_mutex);
1075 					return (status);
1076 				}
1077 
1078 				if (features & PSVC_DEV_PRIMARY)
1079 					strlcpy(switch_state, PSVC_SWITCH_ON,
1080 					    sizeof (switch_state));
1081 				else
1082 					strlcpy(switch_state, PSVC_SWITCH_OFF,
1083 					    sizeof (switch_state));
1084 				status = psvc_set_attr(hdlp, switch_id,
1085 				    PSVC_SWITCH_STATE_ATTR, switch_state);
1086 				if (status == PSVC_FAILURE) {
1087 					pthread_mutex_unlock(&fan_mutex);
1088 					return (status);
1089 				}
1090 
1091 				/* allow time for speed to be determined */
1092 				(void) poll(NULL, 0, 250);
1093 			}
1094 
1095 			status = psvc_get_attr(hdlp, fan_id[r],
1096 			    PSVC_SENSOR_VALUE_ATTR, &speed);
1097 			if (status != PSVC_SUCCESS) {
1098 				pthread_mutex_unlock(&fan_mutex);
1099 				return (status);
1100 			}
1101 
1102 			pthread_mutex_unlock(&fan_mutex);
1103 
1104 			if (speed == 0) {
1105 				threshold_counter++;
1106 				if (threshold_counter ==
1107 				    PSVC_THRESHOLD_COUNTER) {
1108 					int32_t i;
1109 					int32_t led_count;
1110 					char led_state[32];
1111 					char *led_id;
1112 					char *slot_id;
1113 					char label[32];
1114 					char state[32], fault[32];
1115 
1116 					threshold_counter = 0;
1117 					strlcpy(fault, PSVC_GEN_FAULT,
1118 					    sizeof (fault));
1119 					status = psvc_set_attr(hdlp, fan_id[r],
1120 					    PSVC_FAULTID_ATTR, fault);
1121 					if (status != PSVC_SUCCESS)
1122 						return (status);
1123 
1124 					strlcpy(state, PSVC_ERROR,
1125 					    sizeof (state));
1126 					status = psvc_set_attr(hdlp, fan_id[r],
1127 					    PSVC_STATE_ATTR, state);
1128 					if (status != PSVC_SUCCESS)
1129 						return (status);
1130 
1131 					status = psvc_get_attr(hdlp, fan_id[r],
1132 					    PSVC_LABEL_ATTR, label);
1133 					if (status != PSVC_SUCCESS)
1134 						return (status);
1135 
1136 					syslog(LOG_ERR, DEVICE_FAILURE_MSG,
1137 					    label);
1138 
1139 					/* turn on fault LEDs */
1140 					psvc_get_attr(hdlp, fan_id[r],
1141 					    PSVC_ASSOC_MATCHES_ATTR, &led_count,
1142 					    PSVC_DEV_FAULT_LED);
1143 					strlcpy(led_state, PSVC_LED_ON,
1144 					    sizeof (led_state));
1145 					for (i = 0; i < led_count; ++i) {
1146 						status = psvc_get_attr(hdlp,
1147 						    fan_id[r],
1148 						    PSVC_ASSOC_ID_ATTR, &led_id,
1149 						    PSVC_DEV_FAULT_LED, i);
1150 						if (status == PSVC_FAILURE)
1151 							return (status);
1152 
1153 						status = psvc_set_attr(hdlp,
1154 						    led_id, PSVC_LED_STATE_ATTR,
1155 						    led_state);
1156 						if (status == PSVC_FAILURE)
1157 							return (status);
1158 					}
1159 
1160 					/* turn on OK to remove LEDs */
1161 
1162 					status = psvc_get_attr(hdlp, fan_id[r],
1163 					    PSVC_ASSOC_ID_ATTR, &slot_id,
1164 					    PSVC_PARENT, 0);
1165 					if (status != PSVC_SUCCESS)
1166 						return (status);
1167 
1168 					psvc_get_attr(hdlp, slot_id,
1169 					    PSVC_ASSOC_MATCHES_ATTR, &led_count,
1170 					    PSVC_SLOT_REMOVE_LED);
1171 					strlcpy(led_state, PSVC_LED_ON,
1172 					    sizeof (led_state));
1173 					for (i = 0; i < led_count; ++i) {
1174 						status = psvc_get_attr(hdlp,
1175 						    slot_id,
1176 						    PSVC_ASSOC_ID_ATTR, &led_id,
1177 						    PSVC_SLOT_REMOVE_LED, i);
1178 						if (status == PSVC_FAILURE)
1179 							return (status);
1180 
1181 						status = psvc_set_attr(hdlp,
1182 						    led_id, PSVC_LED_STATE_ATTR,
1183 						    led_state);
1184 						if (status == PSVC_FAILURE)
1185 							return (status);
1186 					}
1187 				}
1188 			}
1189 		}
1190 	}
1191 
1192 	return (PSVC_SUCCESS);
1193 }
1194 
1195 /*
1196  * This routine takes in the PSVC handle pointer, the PS name, and the
1197  * instance number (0, 1, or 2). It simply make a psvc_get call to get the
1198  * presence of each of the children under the PS. This call will set the
1199  * presence state of the child device if it was not there when the system
1200  * was booted.
1201  */
1202 static int
1203 handle_ps_hotplug_children_presence(psvc_opaque_t hdlp, char *id)
1204 {
1205 	char *sensor_id;
1206 	char fail_valid_switch_id[PICL_PROPNAMELEN_MAX];
1207 	int32_t	status = PSVC_SUCCESS;
1208 	boolean_t presence;
1209 	int j;
1210 
1211 	/* Get the Sensor Valid Switch presence */
1212 	snprintf(fail_valid_switch_id, sizeof (fail_valid_switch_id), "%s%s",
1213 	    id, "_SENSOR_VALID_SWITCH");
1214 
1215 	status = psvc_get_attr(hdlp, fail_valid_switch_id, PSVC_PRESENCE_ATTR,
1216 	    &presence);
1217 	if (status != PSVC_SUCCESS)
1218 		return (status);
1219 
1220 	/* Go through each PS's fault sensors */
1221 	for (j = 0; j < DAK_MAX_FAULT_SENSORS; j++) {
1222 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1223 		    &(sensor_id), PSVC_DEV_FAULT_SENSOR, j);
1224 		if (status != PSVC_SUCCESS)
1225 			return (status);
1226 		status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR,
1227 		    &presence);
1228 		if (status != PSVC_SUCCESS)
1229 			return (status);
1230 	}
1231 
1232 	/* Go through each PS's current sensors */
1233 	for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) {
1234 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1235 		    &(sensor_id), PSVC_PS_I_SENSOR, j);
1236 		if (status != PSVC_SUCCESS)
1237 			return (status);
1238 		status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR,
1239 		    &presence);
1240 		if (status != PSVC_SUCCESS)
1241 			return (status);
1242 
1243 	}
1244 
1245 	/* Go through each PS's onboard i2c hardware */
1246 	for (j = 0; j < 3; j++) {
1247 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1248 		    &(sensor_id), PSVC_PHYSICAL_DEVICE, j);
1249 		if (status != PSVC_SUCCESS)
1250 			return (status);
1251 		status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR,
1252 		    &presence);
1253 		if (status != PSVC_SUCCESS)
1254 			return (status);
1255 	}
1256 
1257 	return (status);
1258 }
1259 
1260 static i2c_hp_t devices[3][3] = {
1261 {{{0, 0x90}, "adio", "i2c-pcf8591"}, {{0, 0x70}, "ioexp", "i2c-pcf8574"},
1262 	{{0, 0xa0}, "fru", "i2c-at24c64"}},
1263 {{{0, 0x92}, "adio", "i2c-pcf8591"}, {{0, 0x72}, "ioexp", "i2c-pcf8574"},
1264 	{{0, 0xa2}, "fru", "i2c-at24c64"}},
1265 {{{0, 0x94}, "adio", "i2c-pcf8591"}, {{0, 0x74}, "ioexp", "i2c-pcf8574"},
1266 	{{0, 0xa4}, "fru", "i2c-at24c64"}},
1267 };
1268 
1269 int32_t
1270 psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp, char *id)
1271 {
1272 	boolean_t presence, previous_presence;
1273 	int32_t status = PSVC_SUCCESS;
1274 	char label[32], state[32], fault[32];
1275 	int32_t ps_instance, led_count;
1276 	char *switch_id, *led_id;
1277 	int i;
1278 	picl_nodehdl_t parent_node;
1279 	char parent_path[256], ps_path[256];
1280 	picl_nodehdl_t child_node;
1281 	devctl_hdl_t bus_handle, dev_handle;
1282 	devctl_ddef_t ddef_hdl;
1283 	char pcf8574_devpath[256], pcf8591_devpath[256], fru_devpath[256];
1284 	int8_t retry;
1285 
1286 	status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR,
1287 		&previous_presence);
1288 	if (status != PSVC_SUCCESS)
1289 		return (status);
1290 
1291 	retry = 0;
1292 	do {
1293 		if (retry)
1294 			sleep(1);
1295 
1296 		status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence);
1297 		if (status != PSVC_SUCCESS)
1298 			return (status);
1299 		retry++;
1300 	} while ((retry < PSVC_NUM_OF_RETRIES) &&
1301 	    (presence != previous_presence));
1302 
1303 	if (presence == previous_presence) {
1304 		/* No change */
1305 		return (status);
1306 	}
1307 
1308 	status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label);
1309 	if (status != PSVC_SUCCESS)
1310 		return (status);
1311 
1312 	/* convert name to node, and parent path */
1313 	psvcplugin_lookup(id, parent_path, &child_node);
1314 
1315 	if (presence == PSVC_PRESENT) {
1316 		/*
1317 		 * Run this code if Power Supply was just added into the
1318 		 * System.  This code toggles hotplug switch and adds the
1319 		 * PS and it's children to the picl tree. We then goto adding
1320 		 * device drivers at bottom of the routine.
1321 		 */
1322 		int32_t switch_count;
1323 		char state[32], fault[32];
1324 		char switch_state[32];
1325 
1326 		/* may detect presence before all connections are made */
1327 		(void) poll(NULL, 0, 500);
1328 
1329 		/* Device added */
1330 		syslog(LOG_ERR, DEVICE_INSERTED_MSG, label);
1331 
1332 		strcpy(state, PSVC_OK);
1333 		status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state);
1334 		if (status != PSVC_SUCCESS)
1335 			return (status);
1336 
1337 		strcpy(fault, PSVC_NO_FAULT);
1338 		status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault);
1339 		if (status != PSVC_SUCCESS)
1340 			return (status);
1341 
1342 		/* Enable i2c bus */
1343 		psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR,
1344 			&switch_count, PSVC_HOTPLUG_ENABLE_SWITCH);
1345 		for (i = 0; i < switch_count; ++i) {
1346 			status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1347 				&switch_id, PSVC_HOTPLUG_ENABLE_SWITCH, i);
1348 			if (status == PSVC_FAILURE)
1349 				return (status);
1350 
1351 			strcpy(switch_state, PSVC_SWITCH_OFF);
1352 			status = psvc_set_attr(hdlp, switch_id,
1353 				PSVC_SWITCH_STATE_ATTR, switch_state);
1354 			if (status == PSVC_FAILURE)
1355 				return (status);
1356 
1357 			strcpy(switch_state, PSVC_SWITCH_ON);
1358 			status = psvc_set_attr(hdlp, switch_id,
1359 				PSVC_SWITCH_STATE_ATTR, switch_state);
1360 			if (status == PSVC_FAILURE)
1361 				return (status);
1362 		}
1363 		ptree_get_node_by_path(parent_path, &parent_node);
1364 		ptree_add_node(parent_node, child_node);
1365 		snprintf(ps_path, sizeof (ps_path), "%s/%s", parent_path, id);
1366 		psvcplugin_add_children(ps_path);
1367 	} else {
1368 		/*
1369 		 * Run this code if PS was just removed from the system. We
1370 		 * delete the device from the picl tree and then shut off
1371 		 * all fault lights associated with the PS.  We also set the
1372 		 * device state to PSVC_REMOVED so that if we hit overcurrent
1373 		 * or fault checking code we can do a psvc call to see that
1374 		 * the device has not offically been added into the system.
1375 		 * We then will drop to code lower in the routine to remove
1376 		 * the device drivers for this PS.
1377 		 */
1378 
1379 		/* Device removed */
1380 		syslog(LOG_ERR, DEVICE_REMOVED_MSG, label);
1381 		ptree_delete_node(child_node);
1382 		psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count,
1383 			PSVC_DEV_FAULT_LED);
1384 
1385 		for (i = 0; i < led_count; i++) {
1386 			status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1387 				&led_id, PSVC_DEV_FAULT_LED, i);
1388 			if (status != PSVC_SUCCESS) {
1389 				return (status);
1390 			}
1391 
1392 			status = psvc_set_attr(hdlp, led_id,
1393 			    PSVC_LED_STATE_ATTR, PSVC_OFF);
1394 			if (status != PSVC_SUCCESS) {
1395 				syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id,
1396 					errno);
1397 				return (status);
1398 			}
1399 
1400 		}
1401 
1402 		strcpy(state, PSVC_OK);
1403 		strcpy(fault, PSVC_NO_FAULT);
1404 
1405 		status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state);
1406 		if (status != PSVC_SUCCESS)
1407 			return (status);
1408 		status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault);
1409 		if (status != PSVC_SUCCESS)
1410 			return (status);
1411 	}
1412 
1413 	status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence);
1414 	if (status != PSVC_SUCCESS)
1415 		return (status);
1416 
1417 	status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &ps_instance);
1418 	if (status != PSVC_SUCCESS)
1419 		return (status);
1420 
1421 	if (presence != PSVC_PRESENT) {
1422 		/*
1423 		 * This is the additional code needed to remove the PS from
1424 		 * the system.  It removes the device drivers from the
1425 		 * device tree.
1426 		 */
1427 		snprintf(pcf8574_devpath, sizeof (pcf8574_devpath), PCF8574,
1428 			devices[ps_instance][1].addr[1]);
1429 		snprintf(pcf8591_devpath, sizeof (pcf8591_devpath), PCF8591,
1430 			devices[ps_instance][0].addr[1]);
1431 		snprintf(fru_devpath, sizeof (fru_devpath), FRU,
1432 			devices[ps_instance][2].addr[1]);
1433 
1434 		dev_handle = devctl_device_acquire(pcf8591_devpath, 0);
1435 		if (dev_handle == NULL) {
1436 			syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG,
1437 				pcf8591_devpath, errno);
1438 			devctl_release(dev_handle);
1439 			return (PSVC_FAILURE);
1440 		} else if ((devctl_device_remove(dev_handle)) &&
1441 			(errno != ENXIO)) {
1442 				syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED,
1443 					pcf8591_devpath, errno);
1444 				devctl_release(dev_handle);
1445 				return (PSVC_FAILURE);
1446 			} else {
1447 				devctl_release(dev_handle);
1448 				status = PSVC_SUCCESS;
1449 			}
1450 
1451 		dev_handle = devctl_device_acquire(pcf8574_devpath, 0);
1452 		if (dev_handle == NULL) {
1453 			syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG,
1454 				pcf8574_devpath, errno);
1455 			devctl_release(dev_handle);
1456 			return (PSVC_FAILURE);
1457 		} else if ((devctl_device_remove(dev_handle)) &&
1458 			(errno != ENXIO)) {
1459 				syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED,
1460 					pcf8574_devpath, errno);
1461 				devctl_release(dev_handle);
1462 				return (PSVC_FAILURE);
1463 			} else {
1464 				devctl_release(dev_handle);
1465 				status = PSVC_SUCCESS;
1466 			}
1467 
1468 		dev_handle = devctl_device_acquire(fru_devpath, 0);
1469 		if (dev_handle == NULL) {
1470 			syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG,
1471 				fru_devpath, errno);
1472 			devctl_release(dev_handle);
1473 			return (PSVC_FAILURE);
1474 		} else if ((devctl_device_remove(dev_handle)) &&
1475 			(errno != ENXIO)) {
1476 				syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED,
1477 					fru_devpath, errno);
1478 				devctl_release(dev_handle);
1479 				return (PSVC_FAILURE);
1480 			} else {
1481 				devctl_release(dev_handle);
1482 				status = PSVC_SUCCESS;
1483 			}
1484 
1485 		return (status);
1486 	}
1487 
1488 	/*
1489 	 * This code is to update the presences of power supply child
1490 	 * devices in the event that picld was started without a power
1491 	 * supply present.  This call makes the devices available
1492 	 * after that initial insertion.
1493 	 */
1494 	status = handle_ps_hotplug_children_presence(hdlp, id);
1495 	if (status == PSVC_FAILURE) {
1496 		return (status);
1497 	}
1498 
1499 	/*
1500 	 * We fall through to here if the device has been inserted.
1501 	 * Add the devinfo tree node entry for the seeprom and attach
1502 	 * the i2c seeprom driver
1503 	 */
1504 
1505 	bus_handle = devctl_bus_acquire(I2C_NODE, 0);
1506 	if (bus_handle == NULL) {
1507 		syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, I2C_NODE, errno);
1508 		return (PSVC_FAILURE);
1509 	}
1510 	/* Create the deivce nodes for all 3 i2c parts on the PS */
1511 	for (i = 0; i < 3; i++) {
1512 		ddef_hdl = devctl_ddef_alloc(devices[ps_instance][i].name, 0);
1513 		if (ddef_hdl == NULL) {
1514 			syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG,
1515 				devices[ps_instance][i].name, errno);
1516 			return (PSVC_FAILURE);
1517 		}
1518 		status = devctl_ddef_string(ddef_hdl, "compatible",
1519 			devices[ps_instance][i].compatible);
1520 		if (status == -1) {
1521 			syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG,
1522 				devices[ps_instance][i].name, errno);
1523 			return (PSVC_FAILURE);
1524 		}
1525 		status = devctl_ddef_int_array(ddef_hdl, "reg", 2,
1526 			devices[ps_instance][i].addr);
1527 		if (status == -1) {
1528 			syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG,
1529 				devices[ps_instance][i].name, errno);
1530 			return (PSVC_FAILURE);
1531 		}
1532 		if (devctl_bus_dev_create(bus_handle, ddef_hdl, 0,
1533 			&dev_handle)) {
1534 			syslog(LOG_ERR, DEVTREE_NODE_CREATE_FAILED,
1535 				devices[ps_instance][i].name, errno);
1536 			return (PSVC_FAILURE);
1537 		} else
1538 			devctl_release(dev_handle);
1539 		devctl_ddef_free(ddef_hdl);
1540 	}
1541 	devctl_release(bus_handle);
1542 
1543 	return (status);
1544 }
1545 
1546 static void
1547 shutdown_routine()
1548 {
1549 	static boolean_t shutdown_flag = 0;
1550 
1551 	if (!(shutdown_flag)) {
1552 		system(shutdown_string);
1553 		shutdown_flag = 1;
1554 	}
1555 }
1556 
1557 /*
1558  * This policy checks temperature sensors to see if the fault attribute
1559  * is set to either High or Low Shutdown. If so then it shuts the system
1560  * down with a 1 minute warning period
1561  */
1562 int32_t
1563 psvc_shutdown_policy(psvc_opaque_t hdlp, char *id)
1564 {
1565 	int32_t	status;
1566 	char	fault[32] = {0};
1567 	boolean_t	pr;
1568 
1569 	status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr);
1570 	if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) {
1571 		return (status);
1572 	}
1573 
1574 	status = psvc_get_attr(hdlp, id, PSVC_FAULTID_ATTR, fault);
1575 	if (status != PSVC_SUCCESS)
1576 		return (status);
1577 
1578 	if ((strcmp(fault, PSVC_TEMP_LO_SHUT) == 0) ||
1579 	    (strcmp(fault, PSVC_TEMP_HI_SHUT) == 0)) {
1580 		shutdown_routine();
1581 	}
1582 
1583 	return (PSVC_SUCCESS);
1584 }
1585 
1586 int32_t
1587 psvc_check_disk_fault_policy_0(psvc_opaque_t hdlp, char *id)
1588 {
1589 	int32_t		status = PSVC_SUCCESS;
1590 	int32_t		i;
1591 	char		curr_state[32], prev_state[32], led_state[32];
1592 	char		disk_fault[32], disk_state[32];
1593 	static char	*disk_id[DAK_MAX_DISKS] = {{NULL}};
1594 	static char	*led_id[DAK_MAX_DISKS] = {{NULL}};
1595 	static char	*parent_id[DAK_MAX_DISKS] = {{NULL}};
1596 	boolean_t	present;
1597 	int8_t		retry;
1598 
1599 	/*
1600 	 * Check which disk faulted, now get the disks.
1601 	 * We are now going to get disk, disk parent,
1602 	 * parent's leds, and check to see if parent's leds are on
1603 	 */
1604 
1605 	if (disk_id[0] == NULL) {
1606 		for (i = 0; i < DAK_MAX_DISKS; i++) {
1607 			status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1608 			    &(disk_id[i]), PSVC_DISK, i);
1609 			if (status != PSVC_SUCCESS)
1610 				return (status);
1611 			status = psvc_get_attr(hdlp, disk_id[i],
1612 			    PSVC_ASSOC_ID_ATTR, &(parent_id[i]),
1613 			    PSVC_PARENT, 0);
1614 			if (status != PSVC_SUCCESS)
1615 				return (status);
1616 			status = psvc_get_attr(hdlp, parent_id[i],
1617 			    PSVC_ASSOC_ID_ATTR, &(led_id[i]),
1618 			    PSVC_SLOT_FAULT_LED, 0);
1619 			if (status != PSVC_SUCCESS)
1620 				return (status);
1621 
1622 		}
1623 	}
1624 
1625 	for (i = 0; i < DAK_MAX_DISKS; i++) {
1626 		curr_state[0] = 0;
1627 		prev_state[0] = 0;
1628 
1629 		status = psvc_get_attr(hdlp, disk_id[i], PSVC_PRESENCE_ATTR,
1630 			&present);
1631 		if (status != PSVC_SUCCESS)
1632 			return (status);
1633 
1634 		if (present == PSVC_ABSENT)
1635 			continue;
1636 
1637 		/*
1638 		 * Check if whether or not the led is on.
1639 		 * If so, then this disk has a problem and
1640 		 * set its fault and error states to bad.
1641 		 * If not, then set fault and error states to good.
1642 		 * If the disk underwent a change in state, then
1643 		 * print out what state it's now in.
1644 		 */
1645 
1646 		status = psvc_get_attr(hdlp, disk_id[i], PSVC_STATE_ATTR,
1647 		    prev_state);
1648 		if (status != PSVC_SUCCESS)
1649 			return (status);
1650 
1651 		retry = 0;
1652 		do {
1653 			if (retry)
1654 				sleep(1);
1655 			status = psvc_get_attr(hdlp, led_id[i], PSVC_STATE_ATTR,
1656 			    led_state);
1657 			if (status != PSVC_SUCCESS)
1658 				return (status);
1659 			retry++;
1660 			/*
1661 			 * check to see if we need to retry. the conditions are:
1662 			 *
1663 			 * prev_state		led_state		retry
1664 			 * --------------------------------------------------
1665 			 * PSVC_ERROR		PSVC_LED_ON		yes
1666 			 * PSVC_OK		PSVC_LED_OFF		yes
1667 			 * PSVC_ERROR		PSVC_LED_OFF		no
1668 			 * PSVC_OK		PSVC_LED_ON		no
1669 			 */
1670 		} while ((retry < PSVC_NUM_OF_RETRIES) &&
1671 		    change_of_state_str(prev_state, PSVC_OK,
1672 		    led_state, PSVC_LED_ON));
1673 
1674 		/*
1675 		 * Set the disk's state and fault id according to
1676 		 * what we found the disk fault sensor (disk_slot_fault_led)
1677 		 * to be.
1678 		 */
1679 		if (strcmp(led_state, PSVC_LED_ON) == 0) {
1680 			strcpy(disk_fault, PSVC_GEN_FAULT);
1681 			strcpy(disk_state, PSVC_ERROR);
1682 		} else {
1683 			strcpy(disk_fault, PSVC_NO_FAULT);
1684 			strcpy(disk_state, PSVC_OK);
1685 		}
1686 		status = psvc_set_attr(hdlp, disk_id[i], PSVC_STATE_ATTR,
1687 			disk_state);
1688 		if (status != PSVC_SUCCESS)
1689 			return (status);
1690 		status = psvc_set_attr(hdlp, disk_id[i], PSVC_FAULTID_ATTR,
1691 			disk_fault);
1692 		if (status != PSVC_SUCCESS)
1693 			return (status);
1694 		/*
1695 		 * Check disk states.  If they differ, then print out
1696 		 * the current state of the disk
1697 		 */
1698 		status = psvc_get_attr(hdlp, disk_id[i], PSVC_PREV_STATE_ATTR,
1699 			prev_state);
1700 		if (status != PSVC_SUCCESS)
1701 			return (status);
1702 
1703 		if (strcmp(disk_state, prev_state) != 0) {
1704 			if (strcmp(disk_state, PSVC_ERROR) == 0) {
1705 				syslog(LOG_ERR, DISK_FAULT_MSG, disk_id[i]);
1706 			} else {
1707 				syslog(LOG_ERR, DISK_OK_MSG, disk_id[i]);
1708 			}
1709 		}
1710 	}
1711 	return (PSVC_SUCCESS);
1712 }
1713 
1714 int32_t
1715 psvc_update_FSP_fault_led_policy_0(psvc_opaque_t hdlp, char *id)
1716 {
1717 	int32_t status = PSVC_SUCCESS;
1718 	int32_t i;
1719 	int32_t dev_count, fault_state = 0;
1720 	char	*dev_id;
1721 	char	dev_state[32], led_state[32];
1722 	boolean_t	present;
1723 
1724 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &dev_count,
1725 		PSVC_DEV_FAULT_SENSOR);
1726 	if (status != PSVC_SUCCESS)
1727 		return (status);
1728 
1729 	fault_state = 0;
1730 
1731 	for (i = 0; i < dev_count; i++) {
1732 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1733 			&dev_id, PSVC_DEV_FAULT_SENSOR, i);
1734 		if (status != PSVC_SUCCESS)
1735 			return (status);
1736 		status = psvc_get_attr(hdlp, dev_id, PSVC_PRESENCE_ATTR,
1737 			&present);
1738 		if (status != PSVC_SUCCESS)
1739 			return (status);
1740 
1741 		if (present == PSVC_ABSENT)
1742 			continue;
1743 
1744 		status = psvc_get_attr(hdlp, dev_id, PSVC_STATE_ATTR,
1745 			dev_state);
1746 		if (status != PSVC_SUCCESS)
1747 			return (status);
1748 
1749 		if (strcmp(dev_state, PSVC_ERROR) == 0) {
1750 			fault_state = 1;
1751 		}
1752 	}
1753 	if (fault_state == 1) {
1754 		status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state);
1755 		if (status != PSVC_SUCCESS)
1756 			return (status);
1757 		if (strcmp(led_state, PSVC_OFF) == 0) {
1758 			status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR,
1759 			    PSVC_ON);
1760 			if (status != PSVC_SUCCESS)
1761 				return (status);
1762 		}
1763 	} else {
1764 		status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state);
1765 		if (status != PSVC_SUCCESS)
1766 			return (status);
1767 		if (strcmp(led_state, PSVC_ON) == 0) {
1768 			status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR,
1769 			    PSVC_OFF);
1770 			if (status != PSVC_SUCCESS)
1771 				return (status);
1772 		}
1773 	}
1774 	status = update_gen_fault_led(hdlp, GEN_FAULT_LED);
1775 
1776 	return (status);
1777 }
1778 
1779 int32_t
1780 update_gen_fault_led(psvc_opaque_t hdlp, char *id)
1781 {
1782 	int32_t status = PSVC_SUCCESS;
1783 	int32_t i;
1784 	int32_t led_count, fault_state;
1785 	char	*led_id;
1786 	char	led_state[32];
1787 
1788 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count,
1789 		PSVC_DEV_FAULT_SENSOR);
1790 	if (status != PSVC_SUCCESS)
1791 		return (status);
1792 
1793 	fault_state = 0;
1794 
1795 	for (i = 0; i < led_count; i++) {
1796 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR,
1797 			&led_id, PSVC_DEV_FAULT_SENSOR, i);
1798 		if (status != PSVC_SUCCESS)
1799 			return (status);
1800 		status = psvc_get_attr(hdlp, led_id, PSVC_STATE_ATTR,
1801 			led_state);
1802 		if (status != PSVC_SUCCESS)
1803 			return (status);
1804 
1805 		if (strcmp(led_state, PSVC_ON) == 0) {
1806 			fault_state = 1;
1807 		}
1808 	}
1809 
1810 	if (fault_state == 1) {
1811 		status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state);
1812 		if (status != PSVC_SUCCESS)
1813 			return (status);
1814 		if (strcmp(led_state, PSVC_OFF) == 0) {
1815 			status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR,
1816 			    PSVC_ON);
1817 			if (status != PSVC_SUCCESS)
1818 				return (status);
1819 		}
1820 	} else {
1821 		status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state);
1822 		if (status != PSVC_SUCCESS)
1823 			return (status);
1824 		if (strcmp(led_state, PSVC_ON) == 0) {
1825 			status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR,
1826 			    PSVC_OFF);
1827 			if (status != PSVC_SUCCESS)
1828 				return (status);
1829 		}
1830 	}
1831 
1832 	return (status);
1833 }
1834 
1835 
1836 /*
1837  * This function detects whether the module present in the dakatari's
1838  * CPU slot is a CPU module or a Zulu (XVR-4000).
1839  * Based on this detection it also sets the appropriate temperature sensors
1840  * to HOTPLUGGED, so that it works properly with check_temp() function
1841  */
1842 #define	MAX_MODULE_SIZE		20
1843 #define	MAX_TEMP_SENSOR_SIZE	30
1844 
1845 int32_t
1846 psvc_update_cpu_module_card_node_0(psvc_opaque_t hdlp, char *id)
1847 {
1848 	int32_t	set_temp_sensor_properties(psvc_opaque_t, char *);
1849 	int32_t	remove_module_node(psvc_opaque_t, char *);
1850 	int32_t status = PSVC_SUCCESS;
1851 	fru_info_t fru_data;
1852 	char *fru, seg_name[2];
1853 	int8_t seg_count, module_card;
1854 	int32_t match_count, i, j, seg_desc_start = 0x1806, module_address;
1855 	int32_t seg_found;
1856 	boolean_t present;
1857 	seg_desc_t segment;
1858 	char other_module_id[MAX_MODULE_SIZE];
1859 	char cpu_temp_sensor1[MAX_TEMP_SENSOR_SIZE];
1860 	char cpu_temp_sensor2[MAX_TEMP_SENSOR_SIZE];
1861 	char zulu_temp_sensor1[MAX_TEMP_SENSOR_SIZE];
1862 	char zulu_temp_sensor2[MAX_TEMP_SENSOR_SIZE];
1863 	int offset = 0x7;
1864 
1865 	status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present);
1866 	if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) {
1867 		return (status);
1868 	}
1869 
1870 	status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count,
1871 	    PSVC_FRU);
1872 	if (status == PSVC_FAILURE) {
1873 		return (status);
1874 	}
1875 
1876 	for (i = 0; i < match_count; i++) {
1877 		seg_found = 0;
1878 		status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &fru,
1879 		    PSVC_FRU, i);
1880 		if (status != PSVC_SUCCESS)
1881 			return (status);
1882 
1883 		fru_data.buf_start = 0x1805;
1884 		fru_data.buf = (char *)&seg_count;
1885 		fru_data.read_size = 1;
1886 
1887 		status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
1888 		    &fru_data);
1889 		if (status != PSVC_SUCCESS) {
1890 			return (status);
1891 		}
1892 
1893 		for (j = 0; (j < seg_count) && (!seg_found); j++) {
1894 			fru_data.buf_start = seg_desc_start;
1895 			fru_data.buf = seg_name;
1896 			fru_data.read_size = 2;
1897 
1898 			status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
1899 			    &fru_data);
1900 			if (status != PSVC_SUCCESS) {
1901 				syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG);
1902 				return (status);
1903 			}
1904 
1905 			seg_desc_start = seg_desc_start + 2;
1906 			fru_data.buf_start = seg_desc_start;
1907 			fru_data.buf = (char *)&segment;
1908 			fru_data.read_size = sizeof (seg_desc_t);
1909 
1910 			status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
1911 			    &fru_data);
1912 			if (status != PSVC_SUCCESS) {
1913 				syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG);
1914 				return (status);
1915 			}
1916 			seg_desc_start = seg_desc_start + sizeof (seg_desc_t);
1917 			if (memcmp(seg_name, "SC", 2) == 0)
1918 				seg_found = 1;
1919 		}
1920 
1921 		if (seg_found) {
1922 			module_address = segment.segoffset + offset;
1923 			fru_data.buf_start = module_address;
1924 			fru_data.buf = (char *)&module_card;
1925 			fru_data.read_size = 1;
1926 			status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR,
1927 			    &fru_data);
1928 			if (status != PSVC_SUCCESS) {
1929 				syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG);
1930 				return (status);
1931 			}
1932 		} else {
1933 			syslog(LOG_ERR, NO_FRU_INFO_MSG, id);
1934 		}
1935 	}
1936 
1937 	if (strcmp(id, "ZULU_1_3_MOD_CARD") == 0) {
1938 		strlcpy(other_module_id, "CPU_1_3_MOD_CARD", MAX_MODULE_SIZE);
1939 
1940 		strlcpy(cpu_temp_sensor1, "CPU1_DIE_TEMPERATURE_SENSOR",
1941 		    MAX_TEMP_SENSOR_SIZE);
1942 		strlcpy(cpu_temp_sensor2, "CPU3_DIE_TEMPERATURE_SENSOR",
1943 		    MAX_TEMP_SENSOR_SIZE);
1944 
1945 		strlcpy(zulu_temp_sensor1, "ZULU1_DIE_TEMPERATURE_SENSOR",
1946 		    MAX_TEMP_SENSOR_SIZE);
1947 		strlcpy(zulu_temp_sensor2, "ZULU3_DIE_TEMPERATURE_SENSOR",
1948 		    MAX_TEMP_SENSOR_SIZE);
1949 	}
1950 
1951 	if (strcmp(id, "ZULU_4_6_MOD_CARD") == 0) {
1952 		strlcpy(other_module_id, "CPU_4_6_MOD_CARD", MAX_MODULE_SIZE);
1953 
1954 		strlcpy(cpu_temp_sensor1, "CPU4_DIE_TEMPERATURE_SENSOR",
1955 		    MAX_TEMP_SENSOR_SIZE);
1956 		strlcpy(cpu_temp_sensor2, "CPU6_DIE_TEMPERATURE_SENSOR",
1957 		    MAX_TEMP_SENSOR_SIZE);
1958 
1959 		strlcpy(zulu_temp_sensor1, "ZULU4_DIE_TEMPERATURE_SENSOR",
1960 		    MAX_TEMP_SENSOR_SIZE);
1961 		strlcpy(zulu_temp_sensor2, "ZULU6_DIE_TEMPERATURE_SENSOR",
1962 		    MAX_TEMP_SENSOR_SIZE);
1963 	}
1964 
1965 
1966 	/*
1967 	 * If the module in the CPU slot is a Zulu (XVR-4000), then
1968 	 * location 0x1EB0 in its FRUid prom has a value 0xFB.
1969 	 * If Zulu (XVR-4000) is detected, delete the CPU node, otherwise
1970 	 * delete the Zulu node. Also set the temperature sensor value to
1971 	 * HOTPLUGGED for absent temperature sensors.
1972 	 */
1973 	if ((module_card & 0xff) == 0xfb) {
1974 		status = set_temp_sensor_properties(hdlp, cpu_temp_sensor1);
1975 		if (status == PSVC_FAILURE) {
1976 			return (status);
1977 		}
1978 
1979 		status = set_temp_sensor_properties(hdlp, cpu_temp_sensor2);
1980 		if (status == PSVC_FAILURE) {
1981 			return (status);
1982 		}
1983 
1984 		/*
1985 		 * Remove CPU node
1986 		 */
1987 		status = remove_module_node(hdlp, other_module_id);
1988 		if (status == PSVC_FAILURE) {
1989 			return (status);
1990 		}
1991 	} else {
1992 		status = set_temp_sensor_properties(hdlp, zulu_temp_sensor1);
1993 		if (status == PSVC_FAILURE) {
1994 			return (status);
1995 		}
1996 		status = set_temp_sensor_properties(hdlp, zulu_temp_sensor2);
1997 		if (status == PSVC_FAILURE) {
1998 			return (status);
1999 		}
2000 
2001 		/*
2002 		 * Remove Zulu (XVR-4000) node
2003 		 */
2004 		status = remove_module_node(hdlp, id);
2005 		if (status == PSVC_FAILURE) {
2006 			return (status);
2007 		}
2008 	}
2009 
2010 	return (PSVC_SUCCESS);
2011 }
2012 
2013 
2014 /*
2015  * Remove the CPU slot's module node
2016  */
2017 int32_t
2018 remove_module_node(psvc_opaque_t hdlp, char *id)
2019 {
2020 	char parent_path[256];
2021 	picl_nodehdl_t child_node;
2022 
2023 	/* convert name to node, and parent path */
2024 	psvcplugin_lookup(id, parent_path, &child_node);
2025 	/* Device removed */
2026 	ptree_delete_node(child_node);
2027 
2028 	return (PSVC_SUCCESS);
2029 }
2030 
2031 
2032 /*
2033  * Set absent temperature sensor values to HOTPLUGGED
2034  */
2035 int32_t
2036 set_temp_sensor_properties(psvc_opaque_t hdlp, char *id)
2037 {
2038 	char state[32];
2039 	int32_t status = PSVC_SUCCESS;
2040 
2041 	status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state);
2042 	if (status == PSVC_FAILURE) {
2043 		return (status);
2044 	}
2045 
2046 	if (strcmp(state, PSVC_HOTPLUGGED) != 0) {
2047 		strcpy(state, PSVC_HOTPLUGGED);
2048 
2049 		status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state);
2050 		if (status == PSVC_FAILURE) {
2051 			return (status);
2052 		}
2053 	}
2054 
2055 	return (PSVC_SUCCESS);
2056 }
2057