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