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