1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Littleneck platform specific environment monitoring policies 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <syslog.h> 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <stdio.h> 36*7c478bd9Sstevel@tonic-gate #include <libintl.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/time_impl.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/devctl.h> 46*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 47*7c478bd9Sstevel@tonic-gate #include <libdevice.h> 48*7c478bd9Sstevel@tonic-gate #include <picl.h> 49*7c478bd9Sstevel@tonic-gate #include <picltree.h> 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include <psvc_objects.h> 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define LOWTEMP_CRITICAL_MSG \ 56*7c478bd9Sstevel@tonic-gate gettext("CRITICAL : LOW TEMPERATURE DETECTED %d, %s") 57*7c478bd9Sstevel@tonic-gate #define LOWTEMP_WARNING_MSG \ 58*7c478bd9Sstevel@tonic-gate gettext("WARNING : LOW TEMPERATURE DETECTED %d, %s") 59*7c478bd9Sstevel@tonic-gate #define HIGHTEMP_CRITICAL_MSG \ 60*7c478bd9Sstevel@tonic-gate gettext("CRITICAL : HIGH TEMPERATURE DETECTED %d, %s") 61*7c478bd9Sstevel@tonic-gate #define HIGHTEMP_WARNING_MSG \ 62*7c478bd9Sstevel@tonic-gate gettext("WARNING : HIGH TEMPERATURE DETECTED %d, %s") 63*7c478bd9Sstevel@tonic-gate #define DEVICE_INSERTED_MSG gettext("Device %s inserted") 64*7c478bd9Sstevel@tonic-gate #define DEVICE_REMOVED_MSG gettext("Device %s removed") 65*7c478bd9Sstevel@tonic-gate #define PS_TYPE_MSG \ 66*7c478bd9Sstevel@tonic-gate gettext("WARNING: Incorrect type power supply inserted, device %s") 67*7c478bd9Sstevel@tonic-gate #define DEVICE_FAILURE_MSG \ 68*7c478bd9Sstevel@tonic-gate gettext("WARNING: Device %s failure detected by sensor %s\n") 69*7c478bd9Sstevel@tonic-gate #define DEVICE_OK_MSG gettext("Device %s OK") 70*7c478bd9Sstevel@tonic-gate #define DEVTREE_NODE_CREATE_FAILED \ 71*7c478bd9Sstevel@tonic-gate gettext("psvc PICL plugin: Failed to create node for %s, errno = %d") 72*7c478bd9Sstevel@tonic-gate #define DEVTREE_NODE_DELETE_FAILED \ 73*7c478bd9Sstevel@tonic-gate gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d") 74*7c478bd9Sstevel@tonic-gate #define NO_FRU_INFO \ 75*7c478bd9Sstevel@tonic-gate gettext("No FRU Information for %s using default temperatures\n") 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\""; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate typedef struct seg_desc { 80*7c478bd9Sstevel@tonic-gate int32_t segdesc; 81*7c478bd9Sstevel@tonic-gate int16_t segoffset; 82*7c478bd9Sstevel@tonic-gate int16_t seglength; 83*7c478bd9Sstevel@tonic-gate } seg_desc_t; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static int32_t find_segment(psvc_opaque_t hdlp, char *fru, seg_desc_t *segment, 86*7c478bd9Sstevel@tonic-gate char *seg_to_find); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static int temp_attr[] = { 89*7c478bd9Sstevel@tonic-gate PSVC_HW_HI_SHUT_ATTR, PSVC_HI_SHUT_ATTR, PSVC_HI_WARN_ATTR, 90*7c478bd9Sstevel@tonic-gate PSVC_LO_WARN_ATTR, PSVC_LO_SHUT_ATTR, PSVC_HW_LO_SHUT_ATTR 91*7c478bd9Sstevel@tonic-gate }; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate #define MAX_TEMP_ATTR (sizeof (temp_attr)/sizeof (temp_attr[0])) 94*7c478bd9Sstevel@tonic-gate #define TEMP_OFFSET 12 95*7c478bd9Sstevel@tonic-gate #define PART_NO_OFFSET 152 96*7c478bd9Sstevel@tonic-gate #define NUM_OF_SEG_ADDR 0x1805 97*7c478bd9Sstevel@tonic-gate #define SEG_DESC_START 0x1806 98*7c478bd9Sstevel@tonic-gate #define PSVC_NO_DEVICE -2 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate int32_t 101*7c478bd9Sstevel@tonic-gate find_segment(psvc_opaque_t hdlp, char *fru, seg_desc_t *segment, 102*7c478bd9Sstevel@tonic-gate char seg_to_find[2]) 103*7c478bd9Sstevel@tonic-gate { 104*7c478bd9Sstevel@tonic-gate int32_t seg_found = 0, status; 105*7c478bd9Sstevel@tonic-gate int32_t seg_desc_start = SEG_DESC_START, j; 106*7c478bd9Sstevel@tonic-gate int8_t seg_count; 107*7c478bd9Sstevel@tonic-gate char seg_name[2]; 108*7c478bd9Sstevel@tonic-gate fru_info_t fru_data; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate /* 111*7c478bd9Sstevel@tonic-gate * Read the number of segments in the Read Only section 112*7c478bd9Sstevel@tonic-gate */ 113*7c478bd9Sstevel@tonic-gate fru_data.buf_start = NUM_OF_SEG_ADDR; 114*7c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&seg_count; 115*7c478bd9Sstevel@tonic-gate fru_data.read_size = 1; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 118*7c478bd9Sstevel@tonic-gate &fru_data); 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * We test for ENOENT and ENXIO because Littleneck does not 121*7c478bd9Sstevel@tonic-gate * have actual presence sensors and so the only way to see 122*7c478bd9Sstevel@tonic-gate * if a part is there or not is to actually make a call to 123*7c478bd9Sstevel@tonic-gate * that part. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 126*7c478bd9Sstevel@tonic-gate if ((errno == ENOENT) || (errno == ENXIO)) 127*7c478bd9Sstevel@tonic-gate return (PSVC_NO_DEVICE); 128*7c478bd9Sstevel@tonic-gate else 129*7c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate /* 132*7c478bd9Sstevel@tonic-gate * Read in each segment to find the segment we are looking for 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate for (j = 0; (j < seg_count) && (!(seg_found)); j++) { 135*7c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 136*7c478bd9Sstevel@tonic-gate fru_data.buf = seg_name; 137*7c478bd9Sstevel@tonic-gate fru_data.read_size = 2; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 140*7c478bd9Sstevel@tonic-gate &fru_data); 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + 2; 143*7c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 144*7c478bd9Sstevel@tonic-gate fru_data.buf = (char *)segment; 145*7c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (seg_desc_t); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 148*7c478bd9Sstevel@tonic-gate &fru_data); 149*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 150*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 151*7c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 152*7c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 155*7c478bd9Sstevel@tonic-gate if (memcmp(seg_name, seg_to_find, 2) == 0) { 156*7c478bd9Sstevel@tonic-gate seg_found = 1; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate return (seg_found); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate int32_t 163*7c478bd9Sstevel@tonic-gate psvc_update_thresholds_0(psvc_opaque_t hdlp, char *id) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 166*7c478bd9Sstevel@tonic-gate fru_info_t fru_data; 167*7c478bd9Sstevel@tonic-gate char *fru, part_no[7]; 168*7c478bd9Sstevel@tonic-gate int16_t data_offset; 169*7c478bd9Sstevel@tonic-gate int32_t fru_count, i, j, temp_address; 170*7c478bd9Sstevel@tonic-gate int32_t seg_found, temp; 171*7c478bd9Sstevel@tonic-gate seg_desc_t segment; 172*7c478bd9Sstevel@tonic-gate int8_t temps[MAX_TEMP_ATTR]; 173*7c478bd9Sstevel@tonic-gate int32_t num_of_parts = 2; 174*7c478bd9Sstevel@tonic-gate char fruless_parts[2][7] = {"5015988", "5015675"}; 175*7c478bd9Sstevel@tonic-gate int fd; 176*7c478bd9Sstevel@tonic-gate FILE *fp; 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &fru_count, 179*7c478bd9Sstevel@tonic-gate PSVC_FRU); 180*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 181*7c478bd9Sstevel@tonic-gate return (status); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate for (i = 0; i < fru_count; i++) { 184*7c478bd9Sstevel@tonic-gate seg_found = 0; 185*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 186*7c478bd9Sstevel@tonic-gate &fru, PSVC_FRU, i); 187*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 188*7c478bd9Sstevel@tonic-gate return (status); 189*7c478bd9Sstevel@tonic-gate seg_found = find_segment(hdlp, fru, &segment, "ES"); 190*7c478bd9Sstevel@tonic-gate if (seg_found == PSVC_FAILURE) 191*7c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 192*7c478bd9Sstevel@tonic-gate else if (seg_found == PSVC_NO_DEVICE) 193*7c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 194*7c478bd9Sstevel@tonic-gate if (seg_found) { 195*7c478bd9Sstevel@tonic-gate /* 196*7c478bd9Sstevel@tonic-gate * For Littleneck we need to read the offset of the 197*7c478bd9Sstevel@tonic-gate * die-sensor data record 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate temp_address = segment.segoffset + TEMP_OFFSET; 200*7c478bd9Sstevel@tonic-gate fru_data.buf_start = temp_address; 201*7c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&data_offset; 202*7c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (data_offset); 203*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 204*7c478bd9Sstevel@tonic-gate &fru_data); 205*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 206*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 207*7c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 208*7c478bd9Sstevel@tonic-gate return (status); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * Now go and get the new temperature settings 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate temp_address = segment.segoffset + data_offset; 215*7c478bd9Sstevel@tonic-gate fru_data.buf_start = temp_address; 216*7c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&temps; 217*7c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (temps); 218*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 219*7c478bd9Sstevel@tonic-gate &fru_data); 220*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 221*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 222*7c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 223*7c478bd9Sstevel@tonic-gate return (status); 224*7c478bd9Sstevel@tonic-gate } else { 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Now set the updated Thresholds 227*7c478bd9Sstevel@tonic-gate */ 228*7c478bd9Sstevel@tonic-gate for (j = 0; j < MAX_TEMP_ATTR; j++) { 229*7c478bd9Sstevel@tonic-gate temp = temps[j]; 230*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, 231*7c478bd9Sstevel@tonic-gate temp_attr[j], &temp); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate } else { 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * For Littleneck only we need to check for the part 237*7c478bd9Sstevel@tonic-gate * number of the CPU as there are parts that do not 238*7c478bd9Sstevel@tonic-gate * have the ES segment programmed. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate seg_found = find_segment(hdlp, fru, &segment, "SD"); 241*7c478bd9Sstevel@tonic-gate if (seg_found == PSVC_FAILURE) 242*7c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 243*7c478bd9Sstevel@tonic-gate if (seg_found) { 244*7c478bd9Sstevel@tonic-gate /* 245*7c478bd9Sstevel@tonic-gate * We now goto the SD segment to get the part 246*7c478bd9Sstevel@tonic-gate * number. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate fru_data.buf_start = 249*7c478bd9Sstevel@tonic-gate segment.segoffset + PART_NO_OFFSET; 250*7c478bd9Sstevel@tonic-gate fru_data.buf = part_no; 251*7c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (part_no); 252*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, 253*7c478bd9Sstevel@tonic-gate PSVC_FRU_INFO_ATTR, &fru_data); 254*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 255*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Failed psvc_get_attr" 256*7c478bd9Sstevel@tonic-gate "for FRU info\n"); 257*7c478bd9Sstevel@tonic-gate return (status); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * We are go through the parts list to see 261*7c478bd9Sstevel@tonic-gate * if the part number from the FRU is in 262*7c478bd9Sstevel@tonic-gate * this list. If it is we simply return 263*7c478bd9Sstevel@tonic-gate * as the FRU is not programmed. 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate for (j = 0; j < num_of_parts; j++) { 266*7c478bd9Sstevel@tonic-gate if (memcmp(fruless_parts[j], part_no, 267*7c478bd9Sstevel@tonic-gate 7) == 0) { 268*7c478bd9Sstevel@tonic-gate return (status); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* 274*7c478bd9Sstevel@tonic-gate * If the Part is not in the Part list and we 275*7c478bd9Sstevel@tonic-gate * get to here this means that the FRU is 276*7c478bd9Sstevel@tonic-gate * considered broken (no ES segment found) 277*7c478bd9Sstevel@tonic-gate * and we need to report this. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * We make this open, write, close, call 281*7c478bd9Sstevel@tonic-gate * because picld starts in rcS.d while print 282*7c478bd9Sstevel@tonic-gate * services does not start until later 283*7c478bd9Sstevel@tonic-gate * (either rc2.d or rc3.d). 284*7c478bd9Sstevel@tonic-gate */ 285*7c478bd9Sstevel@tonic-gate fd = open("/dev/console", O_WRONLY | O_NOCTTY); 286*7c478bd9Sstevel@tonic-gate if (fd != -1) { 287*7c478bd9Sstevel@tonic-gate fp = fdopen(fd, "w+"); 288*7c478bd9Sstevel@tonic-gate if (fp != NULL) { 289*7c478bd9Sstevel@tonic-gate fprintf(fp, NO_FRU_INFO, id); 290*7c478bd9Sstevel@tonic-gate fclose(fp); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate close(fd); 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, NO_FRU_INFO, id); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate return (status); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate int32_t 301*7c478bd9Sstevel@tonic-gate psvc_check_temperature_policy_0(psvc_opaque_t hdlp, char *id) 302*7c478bd9Sstevel@tonic-gate { 303*7c478bd9Sstevel@tonic-gate int32_t lo_warn, hi_warn, lo_shut, hi_shut; 304*7c478bd9Sstevel@tonic-gate uint64_t features; 305*7c478bd9Sstevel@tonic-gate int32_t temp; 306*7c478bd9Sstevel@tonic-gate char previous_state[32]; 307*7c478bd9Sstevel@tonic-gate char state[32]; 308*7c478bd9Sstevel@tonic-gate char fault[32]; 309*7c478bd9Sstevel@tonic-gate char label[32]; 310*7c478bd9Sstevel@tonic-gate boolean_t pr; 311*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr); 314*7c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) { 315*7c478bd9Sstevel@tonic-gate return (status); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_SENSOR_VALUE_ATTR, &temp); 319*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 320*7c478bd9Sstevel@tonic-gate if ((errno == ENOENT) || (errno == ENXIO)) 321*7c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 322*7c478bd9Sstevel@tonic-gate else 323*7c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_FEATURES_ATTR, &features); 327*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 328*7c478bd9Sstevel@tonic-gate return (status); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LO_WARN_ATTR, &lo_warn); 331*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 332*7c478bd9Sstevel@tonic-gate return (status); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LO_SHUT_ATTR, &lo_shut); 335*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 336*7c478bd9Sstevel@tonic-gate return (status); 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_HI_WARN_ATTR, &hi_warn); 339*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 340*7c478bd9Sstevel@tonic-gate return (status); 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_HI_SHUT_ATTR, &hi_shut); 343*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 344*7c478bd9Sstevel@tonic-gate return (status); 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 347*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 348*7c478bd9Sstevel@tonic-gate return (status); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if ((features & PSVC_LOW_SHUT) && temp <= lo_shut) { 351*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 352*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_LO_SHUT); 353*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, LOWTEMP_CRITICAL_MSG, temp, label); 354*7c478bd9Sstevel@tonic-gate } else if ((features & PSVC_LOW_WARN) && temp <= lo_warn) { 355*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 356*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_LO_WARN); 357*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, LOWTEMP_WARNING_MSG, temp, label); 358*7c478bd9Sstevel@tonic-gate } else if ((features & PSVC_HIGH_SHUT) && temp >= hi_shut) { 359*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 360*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_HI_SHUT); 361*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, HIGHTEMP_CRITICAL_MSG, temp, label); 362*7c478bd9Sstevel@tonic-gate } else if ((features & PSVC_HIGH_WARN) && temp >= hi_warn) { 363*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 364*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_HI_WARN); 365*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, HIGHTEMP_WARNING_MSG, temp, label); 366*7c478bd9Sstevel@tonic-gate } else { 367*7c478bd9Sstevel@tonic-gate /* within limits */ 368*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 369*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 373*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 374*7c478bd9Sstevel@tonic-gate return (status); 375*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 376*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 377*7c478bd9Sstevel@tonic-gate return (status); 378*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 379*7c478bd9Sstevel@tonic-gate previous_state); 380*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 381*7c478bd9Sstevel@tonic-gate return (status); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate if (strcmp(previous_state, state) != 0) { 384*7c478bd9Sstevel@tonic-gate char *led_id; 385*7c478bd9Sstevel@tonic-gate uint8_t _8bit_val; 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate led_id = "SYSTEM_FAULT_LED_WR"; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, led_id, 390*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 391*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 392*7c478bd9Sstevel@tonic-gate return (status); 393*7c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) 394*7c478bd9Sstevel@tonic-gate _8bit_val &= 0xef; /* clear bit 4 */ 395*7c478bd9Sstevel@tonic-gate else 396*7c478bd9Sstevel@tonic-gate _8bit_val |= 0x10; /* set bit 4 */ 397*7c478bd9Sstevel@tonic-gate _8bit_val |= 0xe4; /* set bits 3, 5, 6, 7 */ 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 400*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 401*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 402*7c478bd9Sstevel@tonic-gate return (status); 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate static int32_t ps0_addr[] = {0, 0xac}; 410*7c478bd9Sstevel@tonic-gate static int32_t ps1_addr[] = {0, 0xae}; 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate int32_t 413*7c478bd9Sstevel@tonic-gate psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp, char *id) 414*7c478bd9Sstevel@tonic-gate { 415*7c478bd9Sstevel@tonic-gate boolean_t presence, previous_presence; 416*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 417*7c478bd9Sstevel@tonic-gate char label[32]; 418*7c478bd9Sstevel@tonic-gate int i; 419*7c478bd9Sstevel@tonic-gate int32_t led_count; 420*7c478bd9Sstevel@tonic-gate char state[32], fault[32]; 421*7c478bd9Sstevel@tonic-gate boolean_t ps_type; 422*7c478bd9Sstevel@tonic-gate char *sensor_id, *led_id; 423*7c478bd9Sstevel@tonic-gate char led_state[32]; 424*7c478bd9Sstevel@tonic-gate picl_nodehdl_t parent_node; 425*7c478bd9Sstevel@tonic-gate char parent_path[256]; 426*7c478bd9Sstevel@tonic-gate picl_nodehdl_t child_node; 427*7c478bd9Sstevel@tonic-gate int ps_instance; 428*7c478bd9Sstevel@tonic-gate devctl_hdl_t bus_handle, dev_handle; 429*7c478bd9Sstevel@tonic-gate devctl_ddef_t ddef_hdl; 430*7c478bd9Sstevel@tonic-gate char devpath[256]; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 433*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 434*7c478bd9Sstevel@tonic-gate return (status); 435*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 436*7c478bd9Sstevel@tonic-gate &previous_presence); 437*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 438*7c478bd9Sstevel@tonic-gate return (status); 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate if (presence == previous_presence) { 441*7c478bd9Sstevel@tonic-gate /* No change */ 442*7c478bd9Sstevel@tonic-gate return (status); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 446*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 447*7c478bd9Sstevel@tonic-gate return (status); 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* Convert name to node and parent path */ 450*7c478bd9Sstevel@tonic-gate psvcplugin_lookup(id, parent_path, &child_node); 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (presence == PSVC_PRESENT) { 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* may detect presence before all connections are made */ 455*7c478bd9Sstevel@tonic-gate sleep(1); 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate /* Device added */ 458*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* Verify P/S is correct type */ 462*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 463*7c478bd9Sstevel@tonic-gate &sensor_id, PSVC_DEV_TYPE_SENSOR, 0); 464*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 465*7c478bd9Sstevel@tonic-gate return (status); 466*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, 467*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &ps_type); 468*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 469*7c478bd9Sstevel@tonic-gate return (status); 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate if (ps_type == 1) { /* correct p/s */ 472*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 473*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 474*7c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_OFF); 475*7c478bd9Sstevel@tonic-gate } else { /* wrong type */ 476*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 477*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_PS_TYPE_FLT); 478*7c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_ON); 479*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, PS_TYPE_MSG, label); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 483*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 484*7c478bd9Sstevel@tonic-gate return (status); 485*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 486*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 487*7c478bd9Sstevel@tonic-gate return (status); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* Set state of fault LEDs */ 490*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, PSVC_ASSOC_MATCHES_ATTR, 491*7c478bd9Sstevel@tonic-gate &led_count, PSVC_DEV_FAULT_LED); 492*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 493*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 494*7c478bd9Sstevel@tonic-gate gettext("Failed for PSVC_DEV_FAULT_LED\n")); 495*7c478bd9Sstevel@tonic-gate return (status); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate for (i = 0; i < led_count; ++i) { 498*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, 499*7c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &led_id, 500*7c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_LED, i); 501*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 502*7c478bd9Sstevel@tonic-gate return (status); 503*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 504*7c478bd9Sstevel@tonic-gate PSVC_LED_STATE_ATTR, led_state); 505*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 506*7c478bd9Sstevel@tonic-gate return (status); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate ptree_get_node_by_path(parent_path, &parent_node); 509*7c478bd9Sstevel@tonic-gate ptree_add_node(parent_node, child_node); 510*7c478bd9Sstevel@tonic-gate } else { 511*7c478bd9Sstevel@tonic-gate /* Device removed */ 512*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 513*7c478bd9Sstevel@tonic-gate ptree_delete_node(child_node); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 517*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 518*7c478bd9Sstevel@tonic-gate return (status); 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &ps_instance); 521*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 522*7c478bd9Sstevel@tonic-gate return (status); 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate if (presence != PSVC_PRESENT) { 525*7c478bd9Sstevel@tonic-gate if (ps_instance == 0) 526*7c478bd9Sstevel@tonic-gate strcpy(devpath, 527*7c478bd9Sstevel@tonic-gate "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ac:power-supply"); 528*7c478bd9Sstevel@tonic-gate else 529*7c478bd9Sstevel@tonic-gate strcpy(devpath, 530*7c478bd9Sstevel@tonic-gate "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ae:power-supply"); 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate dev_handle = devctl_device_acquire(devpath, 0); 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate if (devctl_device_remove(dev_handle)) { 535*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, label, 536*7c478bd9Sstevel@tonic-gate errno); 537*7c478bd9Sstevel@tonic-gate status = PSVC_FAILURE; 538*7c478bd9Sstevel@tonic-gate } else { 539*7c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 540*7c478bd9Sstevel@tonic-gate status = PSVC_SUCCESS; 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate return (status); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate /* 546*7c478bd9Sstevel@tonic-gate * We fall through to here if the device has been inserted. 547*7c478bd9Sstevel@tonic-gate * Add the devinfo tree node entry for the seeprom and attach 548*7c478bd9Sstevel@tonic-gate * the i2c seeprom driver 549*7c478bd9Sstevel@tonic-gate */ 550*7c478bd9Sstevel@tonic-gate ddef_hdl = devctl_ddef_alloc("power-supply", 0); 551*7c478bd9Sstevel@tonic-gate (void) devctl_ddef_string(ddef_hdl, "compatible", "i2c-at24c64"); 552*7c478bd9Sstevel@tonic-gate if (ps_instance == 0) { 553*7c478bd9Sstevel@tonic-gate (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, ps0_addr); 554*7c478bd9Sstevel@tonic-gate } else { 555*7c478bd9Sstevel@tonic-gate (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, ps1_addr); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate bus_handle = devctl_bus_acquire( 559*7c478bd9Sstevel@tonic-gate "/devices/pci@8,700000/ebus@5/i2c@1,30:i2c", 0); 560*7c478bd9Sstevel@tonic-gate if (devctl_bus_dev_create(bus_handle, ddef_hdl, 0, &dev_handle)) { 561*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_CREATE_FAILED, label, errno); 562*7c478bd9Sstevel@tonic-gate status = PSVC_FAILURE; 563*7c478bd9Sstevel@tonic-gate } else 564*7c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate devctl_release(bus_handle); 567*7c478bd9Sstevel@tonic-gate devctl_ddef_free(ddef_hdl); 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate return (status); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate int32_t 573*7c478bd9Sstevel@tonic-gate psvc_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *id) 574*7c478bd9Sstevel@tonic-gate { 575*7c478bd9Sstevel@tonic-gate int32_t sensor_count; 576*7c478bd9Sstevel@tonic-gate char *led_id, *sensor_id; 577*7c478bd9Sstevel@tonic-gate int i; 578*7c478bd9Sstevel@tonic-gate char state[32], fault[32], previous_state[32]; 579*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 580*7c478bd9Sstevel@tonic-gate boolean_t present; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 583*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 584*7c478bd9Sstevel@tonic-gate return (status); 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) { 587*7c478bd9Sstevel@tonic-gate errno = ENODEV; 588*7c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 592*7c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_SENSOR); 593*7c478bd9Sstevel@tonic-gate for (i = 0; i < sensor_count; ++i) { 594*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 595*7c478bd9Sstevel@tonic-gate &sensor_id, PSVC_DEV_FAULT_SENSOR, i); 596*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 597*7c478bd9Sstevel@tonic-gate return (status); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, 600*7c478bd9Sstevel@tonic-gate PSVC_SWITCH_STATE_ATTR, state); 601*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 602*7c478bd9Sstevel@tonic-gate return (status); 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_SWITCH_ON) == 0) { 605*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 606*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_GEN_FAULT); 607*7c478bd9Sstevel@tonic-gate } else { 608*7c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 609*7c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 613*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 614*7c478bd9Sstevel@tonic-gate return (status); 615*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 616*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 617*7c478bd9Sstevel@tonic-gate return (status); 618*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 619*7c478bd9Sstevel@tonic-gate previous_state); 620*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 621*7c478bd9Sstevel@tonic-gate return (status); 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (strcmp(state, previous_state) != 0) { 624*7c478bd9Sstevel@tonic-gate char sensor_label[32]; 625*7c478bd9Sstevel@tonic-gate char dev_label[32]; 626*7c478bd9Sstevel@tonic-gate uint8_t _8bit_val; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, dev_label); 629*7c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, sensor_id, PSVC_LABEL_ATTR, 630*7c478bd9Sstevel@tonic-gate sensor_label); 631*7c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) 632*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label, 633*7c478bd9Sstevel@tonic-gate sensor_label); 634*7c478bd9Sstevel@tonic-gate else 635*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_OK_MSG, dev_label); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate led_id = "SYSTEM_FAULT_LED_WR"; 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, led_id, 640*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 641*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 642*7c478bd9Sstevel@tonic-gate return (status); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) 645*7c478bd9Sstevel@tonic-gate _8bit_val &= 0xef; /* clear bit 4 */ 646*7c478bd9Sstevel@tonic-gate else 647*7c478bd9Sstevel@tonic-gate _8bit_val |= 0x10; /* set bit 4 */ 648*7c478bd9Sstevel@tonic-gate _8bit_val |= 0xe4; /* set bits 3, 5, 6, 7 */ 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 651*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 652*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 653*7c478bd9Sstevel@tonic-gate return (status); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate int32_t 662*7c478bd9Sstevel@tonic-gate psvc_init_led_policy_0(psvc_opaque_t hdlp, char *id) 663*7c478bd9Sstevel@tonic-gate { 664*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 665*7c478bd9Sstevel@tonic-gate uint8_t _8bit_val; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, 668*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 669*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 670*7c478bd9Sstevel@tonic-gate return (status); 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate _8bit_val &= 0xef; /* clear bit 4 */ 673*7c478bd9Sstevel@tonic-gate _8bit_val |= 0xf4; /* set bits 3, 5, 6, 7 */ 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, 676*7c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 677*7c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 678*7c478bd9Sstevel@tonic-gate return (status); 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate return (status); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate static int32_t 684*7c478bd9Sstevel@tonic-gate check_cpu_temp_fault(psvc_opaque_t hdlp, char *cpu, int32_t cpu_count) 685*7c478bd9Sstevel@tonic-gate { 686*7c478bd9Sstevel@tonic-gate char *sensorid; 687*7c478bd9Sstevel@tonic-gate int32_t sensor_count; 688*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 689*7c478bd9Sstevel@tonic-gate int32_t i; 690*7c478bd9Sstevel@tonic-gate char fault[32]; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, cpu, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 693*7c478bd9Sstevel@tonic-gate PSVC_DEV_TEMP_SENSOR); 694*7c478bd9Sstevel@tonic-gate for (i = 0; i < sensor_count; ++i) { 695*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, cpu, PSVC_ASSOC_ID_ATTR, 696*7c478bd9Sstevel@tonic-gate &sensorid, PSVC_DEV_TEMP_SENSOR, i); 697*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 698*7c478bd9Sstevel@tonic-gate return (status); 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensorid, PSVC_FAULTID_ATTR, 701*7c478bd9Sstevel@tonic-gate fault); 702*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 703*7c478bd9Sstevel@tonic-gate return (status); 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate if ((strcmp(fault, PSVC_TEMP_HI_SHUT) == 0) || 706*7c478bd9Sstevel@tonic-gate (strcmp(fault, PSVC_TEMP_LO_SHUT) == 0)) { 707*7c478bd9Sstevel@tonic-gate system(shutdown_string); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate return (status); 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate int32_t 715*7c478bd9Sstevel@tonic-gate psvc_shutdown_policy_0(psvc_opaque_t hdlp, char *id) 716*7c478bd9Sstevel@tonic-gate { 717*7c478bd9Sstevel@tonic-gate int32_t cpu_count; 718*7c478bd9Sstevel@tonic-gate char *cpuid; 719*7c478bd9Sstevel@tonic-gate int32_t i; 720*7c478bd9Sstevel@tonic-gate boolean_t present; 721*7c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &cpu_count, 724*7c478bd9Sstevel@tonic-gate PSVC_CPU); 725*7c478bd9Sstevel@tonic-gate for (i = 0; i < cpu_count; ++i) { 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &cpuid, 728*7c478bd9Sstevel@tonic-gate PSVC_CPU, i); 729*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 730*7c478bd9Sstevel@tonic-gate return (status); 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, cpuid, 733*7c478bd9Sstevel@tonic-gate PSVC_PRESENCE_ATTR, &present); 734*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE && present == PSVC_PRESENT) 735*7c478bd9Sstevel@tonic-gate return (status); 736*7c478bd9Sstevel@tonic-gate if (present == PSVC_PRESENT) { 737*7c478bd9Sstevel@tonic-gate status = check_cpu_temp_fault(hdlp, cpuid, cpu_count); 738*7c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE && errno != ENODEV) 739*7c478bd9Sstevel@tonic-gate return (status); 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 744*7c478bd9Sstevel@tonic-gate } 745