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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Littleneck platform specific environment monitoring policies
40 #include <sys/types.h>
43 #include <sys/time_impl.h>
44 #include <sys/signal.h>
45 #include <sys/devctl.h>
46 #include <libdevinfo.h>
47 #include <libdevice.h>
51 #include <sys/systeminfo.h>
52 #include <psvc_objects.h>
56 #define LOWTEMP_CRITICAL_MSG \
57 gettext("CRITICAL : LOW TEMPERATURE DETECTED %d, %s")
58 #define LOWTEMP_WARNING_MSG \
59 gettext("WARNING : LOW TEMPERATURE DETECTED %d, %s")
60 #define HIGHTEMP_CRITICAL_MSG \
61 gettext("CRITICAL : HIGH TEMPERATURE DETECTED %d, %s")
62 #define HIGHTEMP_WARNING_MSG \
63 gettext("WARNING : HIGH TEMPERATURE DETECTED %d, %s")
64 #define DEVICE_INSERTED_MSG gettext("Device %s inserted")
65 #define DEVICE_REMOVED_MSG gettext("Device %s removed")
67 gettext("WARNING: Incorrect type power supply inserted, device %s")
68 #define DEVICE_FAILURE_MSG \
69 gettext("WARNING: Device %s failure detected by sensor %s\n")
70 #define DEVICE_OK_MSG gettext("Device %s OK")
71 #define DEVTREE_NODE_CREATE_FAILED \
72 gettext("psvc PICL plugin: Failed to create node for %s, errno = %d")
73 #define DEVTREE_NODE_DELETE_FAILED \
74 gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d")
76 gettext("No FRU Information for %s using default temperatures\n")
78 static char *shutdown_string
= "shutdown -y -g 60 -i 5 \"OVERTEMP condition\"";
80 typedef struct seg_desc
{
86 static int32_t find_segment(psvc_opaque_t hdlp
, char *fru
, seg_desc_t
*segment
,
89 static int temp_attr
[] = {
90 PSVC_HW_HI_SHUT_ATTR
, PSVC_HI_SHUT_ATTR
, PSVC_HI_WARN_ATTR
,
91 PSVC_LO_WARN_ATTR
, PSVC_LO_SHUT_ATTR
, PSVC_HW_LO_SHUT_ATTR
94 #define MAX_TEMP_ATTR (sizeof (temp_attr)/sizeof (temp_attr[0]))
95 #define TEMP_OFFSET 12
96 #define PART_NO_OFFSET 152
97 #define NUM_OF_SEG_ADDR 0x1805
98 #define SEG_DESC_START 0x1806
99 #define PSVC_NO_DEVICE -2
102 * The I2C bus is noisy, and the state may be incorrectly reported as
103 * having changed. When the state changes, we attempt to confirm by
104 * retrying. If any retries indicate that the state has not changed, we
105 * assume the state change(s) were incorrect and the state has not changed.
106 * The following variables are used to store the tuneable values read in
107 * from the optional i2cparam.conf file for this shared object library.
109 static int n_retry_temp
= PSVC_THRESHOLD_COUNTER
;
110 static int retry_sleep_temp
= 1;
111 static int n_retry_hotplug
= PSVC_NUM_OF_RETRIES
;
112 static int retry_sleep_hotplug
= 1;
113 static int n_retry_temp_shutdown
= PSVC_NUM_OF_RETRIES
;
114 static int retry_sleep_temp_shutdown
= 1;
121 static i2c_noise_param_t i2cparams
[] = {
122 &n_retry_temp
, "n_retry_temp",
123 &retry_sleep_temp
, "retry_sleep_temp",
124 &n_retry_hotplug
, "n_retry_hotplug",
125 &retry_sleep_hotplug
, "retry_sleep_hotplug",
129 #pragma init(i2cparams_load)
132 i2cparams_debug(i2c_noise_param_t
*pi2cparams
, char *platform
,
136 i2c_noise_param_t
*p
;
138 if (!usingDefaults
) {
139 (void) snprintf(s
, sizeof (s
),
140 "# Values from /usr/platform/%s/lib/i2cparam.conf\n",
142 syslog(LOG_WARNING
, "%s", s
);
144 /* no file - we're using the defaults */
145 (void) snprintf(s
, sizeof (s
),
146 "# No /usr/platform/%s/lib/i2cparam.conf file, using defaults\n",
149 (void) fputs(s
, stdout
);
151 while (p
->pvar
!= NULL
) {
152 (void) snprintf(s
, sizeof (s
), "%s %d\n", p
->texttag
,
155 syslog(LOG_WARNING
, "%s", s
);
156 (void) fputs(s
, stdout
);
165 char filename
[PATH_MAX
];
170 i2c_noise_param_t
*p
;
172 if (sysinfo(SI_PLATFORM
, platform
, sizeof (platform
)) == -1) {
173 syslog(LOG_ERR
, "sysinfo error %s\n", strerror(errno
));
176 (void) snprintf(filename
, sizeof (filename
),
177 "/usr/platform/%s/lib/i2cparam.conf", platform
);
178 /* read thru the i2cparam.conf file and set variables */
179 if ((fp
= fopen(filename
, "r")) != NULL
) {
180 while (fgets(s
, sizeof (s
), fp
) != NULL
) {
181 if (s
[0] == '#') /* skip comment lines */
183 /* try to find a string match and get the value */
184 if (sscanf(s
, "%127s %d", var
, &val
) != 2)
187 val
= 1; /* clamp min value */
189 while (p
->pvar
!= NULL
) {
190 if (strncmp(p
->texttag
, var
, sizeof (var
)) ==
200 /* output the values of the parameters */
201 i2cparams_debug(&(i2cparams
[0]), platform
, ((fp
== NULL
)? 1 : 0));
206 find_segment(psvc_opaque_t hdlp
, char *fru
, seg_desc_t
*segment
,
209 int32_t seg_found
= 0, status
;
210 int32_t seg_desc_start
= SEG_DESC_START
, j
;
216 * Read the number of segments in the Read Only section
218 fru_data
.buf_start
= NUM_OF_SEG_ADDR
;
219 fru_data
.buf
= (char *)&seg_count
;
220 fru_data
.read_size
= 1;
222 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
225 * We test for ENOENT and ENXIO because Littleneck does not
226 * have actual presence sensors and so the only way to see
227 * if a part is there or not is to actually make a call to
230 if (status
!= PSVC_SUCCESS
) {
231 if ((errno
== ENOENT
) || (errno
== ENXIO
))
232 return (PSVC_NO_DEVICE
);
234 return (PSVC_FAILURE
);
237 * Read in each segment to find the segment we are looking for
239 for (j
= 0; (j
< seg_count
) && (!(seg_found
)); j
++) {
240 fru_data
.buf_start
= seg_desc_start
;
241 fru_data
.buf
= seg_name
;
242 fru_data
.read_size
= 2;
244 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
247 seg_desc_start
= seg_desc_start
+ 2;
248 fru_data
.buf_start
= seg_desc_start
;
249 fru_data
.buf
= (char *)segment
;
250 fru_data
.read_size
= sizeof (seg_desc_t
);
252 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
254 if (status
!= PSVC_SUCCESS
) {
256 "Failed psvc_get_attr for FRU info\n");
257 return (PSVC_FAILURE
);
259 seg_desc_start
= seg_desc_start
+ sizeof (seg_desc_t
);
260 if (memcmp(seg_name
, seg_to_find
, 2) == 0) {
268 psvc_update_thresholds_0(psvc_opaque_t hdlp
, char *id
)
270 int32_t status
= PSVC_SUCCESS
;
272 char *fru
, part_no
[7];
274 int32_t fru_count
, i
, j
, temp_address
;
275 int32_t seg_found
, temp
;
277 int8_t temps
[MAX_TEMP_ATTR
];
278 int32_t num_of_parts
= 2;
279 char fruless_parts
[2][7] = {"5015988", "5015675"};
283 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &fru_count
,
285 if (status
== PSVC_FAILURE
)
288 for (i
= 0; i
< fru_count
; i
++) {
290 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
292 if (status
!= PSVC_SUCCESS
)
294 seg_found
= find_segment(hdlp
, fru
, &segment
, "ES");
295 if (seg_found
== PSVC_FAILURE
)
296 return (PSVC_FAILURE
);
297 else if (seg_found
== PSVC_NO_DEVICE
)
298 return (PSVC_SUCCESS
);
301 * For Littleneck we need to read the offset of the
302 * die-sensor data record
304 temp_address
= segment
.segoffset
+ TEMP_OFFSET
;
305 fru_data
.buf_start
= temp_address
;
306 fru_data
.buf
= (char *)&data_offset
;
307 fru_data
.read_size
= sizeof (data_offset
);
308 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
310 if (status
!= PSVC_SUCCESS
) {
312 "Failed psvc_get_attr for FRU info\n");
317 * Now go and get the new temperature settings
319 temp_address
= segment
.segoffset
+ data_offset
;
320 fru_data
.buf_start
= temp_address
;
321 fru_data
.buf
= (char *)&temps
;
322 fru_data
.read_size
= sizeof (temps
);
323 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
325 if (status
!= PSVC_SUCCESS
) {
327 "Failed psvc_get_attr for FRU info\n");
331 * Now set the updated Thresholds
333 for (j
= 0; j
< MAX_TEMP_ATTR
; j
++) {
335 status
= psvc_set_attr(hdlp
, id
,
336 temp_attr
[j
], &temp
);
341 * For Littleneck only we need to check for the part
342 * number of the CPU as there are parts that do not
343 * have the ES segment programmed.
345 seg_found
= find_segment(hdlp
, fru
, &segment
, "SD");
346 if (seg_found
== PSVC_FAILURE
)
347 return (PSVC_FAILURE
);
350 * We now goto the SD segment to get the part
354 segment
.segoffset
+ PART_NO_OFFSET
;
355 fru_data
.buf
= part_no
;
356 fru_data
.read_size
= sizeof (part_no
);
357 status
= psvc_get_attr(hdlp
, fru
,
358 PSVC_FRU_INFO_ATTR
, &fru_data
);
359 if (status
!= PSVC_SUCCESS
) {
360 syslog(LOG_ERR
, "Failed psvc_get_attr"
365 * We are go through the parts list to see
366 * if the part number from the FRU is in
367 * this list. If it is we simply return
368 * as the FRU is not programmed.
370 for (j
= 0; j
< num_of_parts
; j
++) {
371 if (memcmp(fruless_parts
[j
], part_no
,
379 * If the Part is not in the Part list and we
380 * get to here this means that the FRU is
381 * considered broken (no ES segment found)
382 * and we need to report this.
385 * We make this open, write, close, call
386 * because picld starts in rcS.d while print
387 * services does not start until later
388 * (either rc2.d or rc3.d).
390 fd
= open("/dev/console", O_WRONLY
| O_NOCTTY
);
392 fp
= fdopen(fd
, "w+");
394 fprintf(fp
, NO_FRU_INFO
, id
);
399 syslog(LOG_NOTICE
, NO_FRU_INFO
, id
);
406 psvc_check_temperature_policy_0(psvc_opaque_t hdlp
, char *id
)
408 int32_t lo_warn
, hi_warn
, lo_shut
, hi_shut
;
411 char previous_state
[32];
416 int32_t status
= PSVC_SUCCESS
;
420 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &pr
);
421 if ((status
!= PSVC_SUCCESS
) || (pr
!= PSVC_PRESENT
)) {
425 status
= psvc_get_attr(hdlp
, id
, PSVC_FEATURES_ATTR
, &features
);
426 if (status
!= PSVC_SUCCESS
)
429 status
= psvc_get_attr(hdlp
, id
, PSVC_LO_WARN_ATTR
, &lo_warn
);
430 if (status
!= PSVC_SUCCESS
)
433 status
= psvc_get_attr(hdlp
, id
, PSVC_LO_SHUT_ATTR
, &lo_shut
);
434 if (status
!= PSVC_SUCCESS
)
437 status
= psvc_get_attr(hdlp
, id
, PSVC_HI_WARN_ATTR
, &hi_warn
);
438 if (status
!= PSVC_SUCCESS
)
441 status
= psvc_get_attr(hdlp
, id
, PSVC_HI_SHUT_ATTR
, &hi_shut
);
442 if (status
!= PSVC_SUCCESS
)
445 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, label
);
446 if (status
!= PSVC_SUCCESS
)
452 (void) sleep(retry_sleep_temp
);
453 status
= psvc_get_attr(hdlp
, id
, PSVC_SENSOR_VALUE_ATTR
, &temp
);
454 if (status
!= PSVC_SUCCESS
) {
455 if ((errno
== ENOENT
) || (errno
== ENXIO
))
456 return (PSVC_SUCCESS
);
458 return (PSVC_FAILURE
);
461 if (((features
& PSVC_LOW_SHUT
) && temp
<= lo_shut
) ||
462 ((features
& PSVC_LOW_WARN
) && temp
<= lo_warn
) ||
463 ((features
& PSVC_HIGH_SHUT
) && temp
>= hi_shut
) ||
464 ((features
& PSVC_HIGH_WARN
) && temp
>= hi_warn
))
467 } while ((retry
< n_retry_temp
) && temp_oor
);
469 if ((features
& PSVC_LOW_SHUT
) && temp
<= lo_shut
) {
470 strcpy(state
, PSVC_ERROR
);
471 strcpy(fault
, PSVC_TEMP_LO_SHUT
);
472 syslog(LOG_ERR
, LOWTEMP_CRITICAL_MSG
, temp
, label
);
473 } else if ((features
& PSVC_LOW_WARN
) && temp
<= lo_warn
) {
474 strcpy(state
, PSVC_ERROR
);
475 strcpy(fault
, PSVC_TEMP_LO_WARN
);
476 syslog(LOG_ERR
, LOWTEMP_WARNING_MSG
, temp
, label
);
477 } else if ((features
& PSVC_HIGH_SHUT
) && temp
>= hi_shut
) {
478 strcpy(state
, PSVC_ERROR
);
479 strcpy(fault
, PSVC_TEMP_HI_SHUT
);
480 syslog(LOG_ERR
, HIGHTEMP_CRITICAL_MSG
, temp
, label
);
481 } else if ((features
& PSVC_HIGH_WARN
) && temp
>= hi_warn
) {
482 strcpy(state
, PSVC_ERROR
);
483 strcpy(fault
, PSVC_TEMP_HI_WARN
);
484 syslog(LOG_ERR
, HIGHTEMP_WARNING_MSG
, temp
, label
);
487 strcpy(state
, PSVC_OK
);
488 strcpy(fault
, PSVC_NO_FAULT
);
491 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
492 if (status
!= PSVC_SUCCESS
)
494 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
, fault
);
495 if (status
!= PSVC_SUCCESS
)
497 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_STATE_ATTR
,
499 if (status
!= PSVC_SUCCESS
)
502 if (strcmp(previous_state
, state
) != 0) {
506 led_id
= "SYSTEM_FAULT_LED_WR";
508 status
= psvc_get_attr(hdlp
, led_id
,
509 PSVC_GPIO_VALUE_ATTR
, &_8bit_val
);
510 if (status
!= PSVC_SUCCESS
)
512 if (strcmp(state
, PSVC_ERROR
) == 0)
513 _8bit_val
&= 0xef; /* clear bit 4 */
515 _8bit_val
|= 0x10; /* set bit 4 */
516 _8bit_val
|= 0xe4; /* set bits 3, 5, 6, 7 */
518 status
= psvc_set_attr(hdlp
, led_id
,
519 PSVC_GPIO_VALUE_ATTR
, &_8bit_val
);
520 if (status
!= PSVC_SUCCESS
)
525 return (PSVC_SUCCESS
);
528 static int32_t ps0_addr
[] = {0, 0xac};
529 static int32_t ps1_addr
[] = {0, 0xae};
532 psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp
, char *id
)
534 boolean_t presence
, previous_presence
;
535 int32_t status
= PSVC_SUCCESS
;
539 char state
[32], fault
[32];
541 char *sensor_id
, *led_id
;
543 picl_nodehdl_t parent_node
;
544 char parent_path
[256];
545 picl_nodehdl_t child_node
;
547 devctl_hdl_t bus_handle
, dev_handle
;
548 devctl_ddef_t ddef_hdl
;
552 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_PRESENCE_ATTR
,
554 if (status
!= PSVC_SUCCESS
)
559 (void) sleep(retry_sleep_hotplug
);
560 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &presence
);
561 if (status
!= PSVC_SUCCESS
)
564 } while ((retry
< n_retry_hotplug
) && (presence
!= previous_presence
));
566 if (presence
== previous_presence
) {
571 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, label
);
572 if (status
!= PSVC_SUCCESS
)
575 /* Convert name to node and parent path */
576 psvcplugin_lookup(id
, parent_path
, &child_node
);
578 if (presence
== PSVC_PRESENT
) {
580 /* may detect presence before all connections are made */
584 syslog(LOG_ERR
, DEVICE_INSERTED_MSG
, label
);
587 /* Verify P/S is correct type */
588 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
589 &sensor_id
, PSVC_DEV_TYPE_SENSOR
, 0);
590 if (status
!= PSVC_SUCCESS
)
592 status
= psvc_get_attr(hdlp
, sensor_id
,
593 PSVC_GPIO_VALUE_ATTR
, &ps_type
);
594 if (status
!= PSVC_SUCCESS
)
597 if (ps_type
== 1) { /* correct p/s */
598 strcpy(state
, PSVC_OK
);
599 strcpy(fault
, PSVC_NO_FAULT
);
600 strcpy(led_state
, PSVC_LED_OFF
);
601 } else { /* wrong type */
602 strcpy(state
, PSVC_ERROR
);
603 strcpy(fault
, PSVC_PS_TYPE_FLT
);
604 strcpy(led_state
, PSVC_LED_ON
);
605 syslog(LOG_ERR
, PS_TYPE_MSG
, label
);
608 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
609 if (status
!= PSVC_SUCCESS
)
611 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
, fault
);
612 if (status
!= PSVC_SUCCESS
)
615 /* Set state of fault LEDs */
616 status
= psvc_get_attr(hdlp
, sensor_id
, PSVC_ASSOC_MATCHES_ATTR
,
617 &led_count
, PSVC_DEV_FAULT_LED
);
618 if (status
!= PSVC_SUCCESS
) {
620 gettext("Failed for PSVC_DEV_FAULT_LED\n"));
623 for (i
= 0; i
< led_count
; ++i
) {
624 status
= psvc_get_attr(hdlp
, sensor_id
,
625 PSVC_ASSOC_ID_ATTR
, &led_id
,
626 PSVC_DEV_FAULT_LED
, i
);
627 if (status
!= PSVC_SUCCESS
)
629 status
= psvc_set_attr(hdlp
, led_id
,
630 PSVC_LED_STATE_ATTR
, led_state
);
631 if (status
!= PSVC_SUCCESS
)
634 ptree_get_node_by_path(parent_path
, &parent_node
);
635 ptree_add_node(parent_node
, child_node
);
638 syslog(LOG_ERR
, DEVICE_REMOVED_MSG
, label
);
639 ptree_delete_node(child_node
);
642 status
= psvc_set_attr(hdlp
, id
, PSVC_PREV_PRESENCE_ATTR
, &presence
);
643 if (status
!= PSVC_SUCCESS
)
646 status
= psvc_get_attr(hdlp
, id
, PSVC_INSTANCE_ATTR
, &ps_instance
);
647 if (status
!= PSVC_SUCCESS
)
650 if (presence
!= PSVC_PRESENT
) {
651 if (ps_instance
== 0)
653 "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ac:power-supply");
656 "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ae:power-supply");
658 dev_handle
= devctl_device_acquire(devpath
, 0);
660 if (devctl_device_remove(dev_handle
)) {
661 syslog(LOG_ERR
, DEVTREE_NODE_DELETE_FAILED
, label
,
663 status
= PSVC_FAILURE
;
665 devctl_release(dev_handle
);
666 status
= PSVC_SUCCESS
;
672 * We fall through to here if the device has been inserted.
673 * Add the devinfo tree node entry for the seeprom and attach
674 * the i2c seeprom driver
676 ddef_hdl
= devctl_ddef_alloc("power-supply", 0);
677 (void) devctl_ddef_string(ddef_hdl
, "compatible", "i2c-at24c64");
678 if (ps_instance
== 0) {
679 (void) devctl_ddef_int_array(ddef_hdl
, "reg", 2, ps0_addr
);
681 (void) devctl_ddef_int_array(ddef_hdl
, "reg", 2, ps1_addr
);
684 bus_handle
= devctl_bus_acquire(
685 "/devices/pci@8,700000/ebus@5/i2c@1,30:i2c", 0);
686 if (devctl_bus_dev_create(bus_handle
, ddef_hdl
, 0, &dev_handle
)) {
687 syslog(LOG_ERR
, DEVTREE_NODE_CREATE_FAILED
, label
, errno
);
688 status
= PSVC_FAILURE
;
690 devctl_release(dev_handle
);
692 devctl_release(bus_handle
);
693 devctl_ddef_free(ddef_hdl
);
699 psvc_device_fail_notifier_policy_0(psvc_opaque_t hdlp
, char *id
)
701 int32_t sensor_count
;
702 char *led_id
, *sensor_id
;
704 char state
[32], fault
[32], previous_state
[32];
705 int32_t status
= PSVC_SUCCESS
;
708 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &present
);
709 if (status
== PSVC_FAILURE
)
712 if (present
== PSVC_ABSENT
) {
714 return (PSVC_FAILURE
);
717 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &sensor_count
,
718 PSVC_DEV_FAULT_SENSOR
);
719 for (i
= 0; i
< sensor_count
; ++i
) {
720 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
721 &sensor_id
, PSVC_DEV_FAULT_SENSOR
, i
);
722 if (status
!= PSVC_SUCCESS
)
725 status
= psvc_get_attr(hdlp
, sensor_id
,
726 PSVC_SWITCH_STATE_ATTR
, state
);
727 if (status
!= PSVC_SUCCESS
)
730 if (strcmp(state
, PSVC_SWITCH_ON
) == 0) {
731 strcpy(state
, PSVC_ERROR
);
732 strcpy(fault
, PSVC_GEN_FAULT
);
734 strcpy(state
, PSVC_OK
);
735 strcpy(fault
, PSVC_NO_FAULT
);
738 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
739 if (status
!= PSVC_SUCCESS
)
741 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
, fault
);
742 if (status
!= PSVC_SUCCESS
)
744 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_STATE_ATTR
,
746 if (status
!= PSVC_SUCCESS
)
749 if (strcmp(state
, previous_state
) != 0) {
750 char sensor_label
[32];
754 psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, dev_label
);
755 psvc_get_attr(hdlp
, sensor_id
, PSVC_LABEL_ATTR
,
757 if (strcmp(state
, PSVC_ERROR
) == 0)
758 syslog(LOG_ERR
, DEVICE_FAILURE_MSG
, dev_label
,
761 syslog(LOG_ERR
, DEVICE_OK_MSG
, dev_label
);
763 led_id
= "SYSTEM_FAULT_LED_WR";
765 status
= psvc_get_attr(hdlp
, led_id
,
766 PSVC_GPIO_VALUE_ATTR
, &_8bit_val
);
767 if (status
!= PSVC_SUCCESS
)
770 if (strcmp(state
, PSVC_ERROR
) == 0)
771 _8bit_val
&= 0xef; /* clear bit 4 */
773 _8bit_val
|= 0x10; /* set bit 4 */
774 _8bit_val
|= 0xe4; /* set bits 3, 5, 6, 7 */
776 status
= psvc_set_attr(hdlp
, led_id
,
777 PSVC_GPIO_VALUE_ATTR
, &_8bit_val
);
778 if (status
!= PSVC_SUCCESS
)
784 return (PSVC_SUCCESS
);
788 psvc_init_led_policy_0(psvc_opaque_t hdlp
, char *id
)
790 int32_t status
= PSVC_SUCCESS
;
793 status
= psvc_get_attr(hdlp
, id
,
794 PSVC_GPIO_VALUE_ATTR
, &_8bit_val
);
795 if (status
!= PSVC_SUCCESS
)
798 _8bit_val
&= 0xef; /* clear bit 4 */
799 _8bit_val
|= 0xf4; /* set bits 3, 5, 6, 7 */
801 status
= psvc_set_attr(hdlp
, id
,
802 PSVC_GPIO_VALUE_ATTR
, &_8bit_val
);
803 if (status
!= PSVC_SUCCESS
)
810 check_cpu_temp_fault(psvc_opaque_t hdlp
, char *cpu
, int32_t cpu_count
)
813 int32_t sensor_count
;
814 int32_t status
= PSVC_SUCCESS
;
820 psvc_get_attr(hdlp
, cpu
, PSVC_ASSOC_MATCHES_ATTR
, &sensor_count
,
821 PSVC_DEV_TEMP_SENSOR
);
822 for (i
= 0; i
< sensor_count
; ++i
) {
823 status
= psvc_get_attr(hdlp
, cpu
, PSVC_ASSOC_ID_ATTR
,
824 &sensorid
, PSVC_DEV_TEMP_SENSOR
, i
);
825 if (status
== PSVC_FAILURE
)
831 (void) sleep(retry_sleep_temp_shutdown
);
832 status
= psvc_get_attr(hdlp
, sensorid
,
833 PSVC_FAULTID_ATTR
, fault
);
834 if (status
== PSVC_FAILURE
)
837 if ((strcmp(fault
, PSVC_TEMP_HI_SHUT
) == 0) ||
838 (strcmp(fault
, PSVC_TEMP_LO_SHUT
) == 0)) {
842 } while ((retry
< n_retry_temp_shutdown
) && temp_oor
);
845 system(shutdown_string
);
853 psvc_shutdown_policy_0(psvc_opaque_t hdlp
, char *id
)
859 int32_t status
= PSVC_SUCCESS
;
861 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &cpu_count
,
863 for (i
= 0; i
< cpu_count
; ++i
) {
865 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
, &cpuid
,
867 if (status
== PSVC_FAILURE
)
870 status
= psvc_get_attr(hdlp
, cpuid
,
871 PSVC_PRESENCE_ATTR
, &present
);
872 if (status
== PSVC_FAILURE
&& present
== PSVC_PRESENT
)
874 if (present
== PSVC_PRESENT
) {
875 status
= check_cpu_temp_fault(hdlp
, cpuid
, cpu_count
);
876 if (status
== PSVC_FAILURE
&& errno
!= ENODEV
)
881 return (PSVC_SUCCESS
);