17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*298b7f4cSjfrank * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Littleneck platform specific environment monitoring policies 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <syslog.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <stdio.h> 367c478bd9Sstevel@tonic-gate #include <libintl.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <fcntl.h> 427c478bd9Sstevel@tonic-gate #include <sys/time.h> 437c478bd9Sstevel@tonic-gate #include <sys/time_impl.h> 447c478bd9Sstevel@tonic-gate #include <sys/signal.h> 457c478bd9Sstevel@tonic-gate #include <sys/devctl.h> 467c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 477c478bd9Sstevel@tonic-gate #include <libdevice.h> 487c478bd9Sstevel@tonic-gate #include <picl.h> 497c478bd9Sstevel@tonic-gate #include <picltree.h> 50*298b7f4cSjfrank #include <limits.h> 51*298b7f4cSjfrank #include <sys/systeminfo.h> 527c478bd9Sstevel@tonic-gate #include <psvc_objects.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define LOWTEMP_CRITICAL_MSG \ 577c478bd9Sstevel@tonic-gate gettext("CRITICAL : LOW TEMPERATURE DETECTED %d, %s") 587c478bd9Sstevel@tonic-gate #define LOWTEMP_WARNING_MSG \ 597c478bd9Sstevel@tonic-gate gettext("WARNING : LOW TEMPERATURE DETECTED %d, %s") 607c478bd9Sstevel@tonic-gate #define HIGHTEMP_CRITICAL_MSG \ 617c478bd9Sstevel@tonic-gate gettext("CRITICAL : HIGH TEMPERATURE DETECTED %d, %s") 627c478bd9Sstevel@tonic-gate #define HIGHTEMP_WARNING_MSG \ 637c478bd9Sstevel@tonic-gate gettext("WARNING : HIGH TEMPERATURE DETECTED %d, %s") 647c478bd9Sstevel@tonic-gate #define DEVICE_INSERTED_MSG gettext("Device %s inserted") 657c478bd9Sstevel@tonic-gate #define DEVICE_REMOVED_MSG gettext("Device %s removed") 667c478bd9Sstevel@tonic-gate #define PS_TYPE_MSG \ 677c478bd9Sstevel@tonic-gate gettext("WARNING: Incorrect type power supply inserted, device %s") 687c478bd9Sstevel@tonic-gate #define DEVICE_FAILURE_MSG \ 697c478bd9Sstevel@tonic-gate gettext("WARNING: Device %s failure detected by sensor %s\n") 707c478bd9Sstevel@tonic-gate #define DEVICE_OK_MSG gettext("Device %s OK") 717c478bd9Sstevel@tonic-gate #define DEVTREE_NODE_CREATE_FAILED \ 727c478bd9Sstevel@tonic-gate gettext("psvc PICL plugin: Failed to create node for %s, errno = %d") 737c478bd9Sstevel@tonic-gate #define DEVTREE_NODE_DELETE_FAILED \ 747c478bd9Sstevel@tonic-gate gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d") 757c478bd9Sstevel@tonic-gate #define NO_FRU_INFO \ 767c478bd9Sstevel@tonic-gate gettext("No FRU Information for %s using default temperatures\n") 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\""; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate typedef struct seg_desc { 817c478bd9Sstevel@tonic-gate int32_t segdesc; 827c478bd9Sstevel@tonic-gate int16_t segoffset; 837c478bd9Sstevel@tonic-gate int16_t seglength; 847c478bd9Sstevel@tonic-gate } seg_desc_t; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate static int32_t find_segment(psvc_opaque_t hdlp, char *fru, seg_desc_t *segment, 877c478bd9Sstevel@tonic-gate char *seg_to_find); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static int temp_attr[] = { 907c478bd9Sstevel@tonic-gate PSVC_HW_HI_SHUT_ATTR, PSVC_HI_SHUT_ATTR, PSVC_HI_WARN_ATTR, 917c478bd9Sstevel@tonic-gate PSVC_LO_WARN_ATTR, PSVC_LO_SHUT_ATTR, PSVC_HW_LO_SHUT_ATTR 927c478bd9Sstevel@tonic-gate }; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate #define MAX_TEMP_ATTR (sizeof (temp_attr)/sizeof (temp_attr[0])) 957c478bd9Sstevel@tonic-gate #define TEMP_OFFSET 12 967c478bd9Sstevel@tonic-gate #define PART_NO_OFFSET 152 977c478bd9Sstevel@tonic-gate #define NUM_OF_SEG_ADDR 0x1805 987c478bd9Sstevel@tonic-gate #define SEG_DESC_START 0x1806 997c478bd9Sstevel@tonic-gate #define PSVC_NO_DEVICE -2 1007c478bd9Sstevel@tonic-gate 101*298b7f4cSjfrank /* 102*298b7f4cSjfrank * The I2C bus is noisy, and the state may be incorrectly reported as 103*298b7f4cSjfrank * having changed. When the state changes, we attempt to confirm by 104*298b7f4cSjfrank * retrying. If any retries indicate that the state has not changed, we 105*298b7f4cSjfrank * assume the state change(s) were incorrect and the state has not changed. 106*298b7f4cSjfrank * The following variables are used to store the tuneable values read in 107*298b7f4cSjfrank * from the optional i2cparam.conf file for this shared object library. 108*298b7f4cSjfrank */ 109*298b7f4cSjfrank static int n_retry_temp = PSVC_THRESHOLD_COUNTER; 110*298b7f4cSjfrank static int retry_sleep_temp = 1; 111*298b7f4cSjfrank static int n_retry_hotplug = PSVC_NUM_OF_RETRIES; 112*298b7f4cSjfrank static int retry_sleep_hotplug = 1; 113*298b7f4cSjfrank static int n_retry_temp_shutdown = PSVC_NUM_OF_RETRIES; 114*298b7f4cSjfrank static int retry_sleep_temp_shutdown = 1; 115*298b7f4cSjfrank 116*298b7f4cSjfrank typedef struct { 117*298b7f4cSjfrank int *pvar; 118*298b7f4cSjfrank char *texttag; 119*298b7f4cSjfrank } i2c_noise_param_t; 120*298b7f4cSjfrank 121*298b7f4cSjfrank static i2c_noise_param_t i2cparams[] = { 122*298b7f4cSjfrank &n_retry_temp, "n_retry_temp", 123*298b7f4cSjfrank &retry_sleep_temp, "retry_sleep_temp", 124*298b7f4cSjfrank &n_retry_hotplug, "n_retry_hotplug", 125*298b7f4cSjfrank &retry_sleep_hotplug, "retry_sleep_hotplug", 126*298b7f4cSjfrank NULL, NULL 127*298b7f4cSjfrank }; 128*298b7f4cSjfrank 129*298b7f4cSjfrank #pragma init(i2cparams_load) 130*298b7f4cSjfrank 131*298b7f4cSjfrank static void 132*298b7f4cSjfrank i2cparams_debug(i2c_noise_param_t *pi2cparams, char *platform, 133*298b7f4cSjfrank int usingDefaults) 134*298b7f4cSjfrank { 135*298b7f4cSjfrank char s[128]; 136*298b7f4cSjfrank i2c_noise_param_t *p; 137*298b7f4cSjfrank 138*298b7f4cSjfrank if (!usingDefaults) { 139*298b7f4cSjfrank (void) snprintf(s, sizeof (s), 140*298b7f4cSjfrank "# Values from /usr/platform/%s/lib/i2cparam.conf\n", 141*298b7f4cSjfrank platform); 142*298b7f4cSjfrank syslog(LOG_WARNING, "%s", s); 143*298b7f4cSjfrank } else { 144*298b7f4cSjfrank /* no file - we're using the defaults */ 145*298b7f4cSjfrank (void) snprintf(s, sizeof (s), 146*298b7f4cSjfrank "# No /usr/platform/%s/lib/i2cparam.conf file, using defaults\n", 147*298b7f4cSjfrank platform); 148*298b7f4cSjfrank } 149*298b7f4cSjfrank (void) fputs(s, stdout); 150*298b7f4cSjfrank p = pi2cparams; 151*298b7f4cSjfrank while (p->pvar != NULL) { 152*298b7f4cSjfrank (void) snprintf(s, sizeof (s), "%s %d\n", p->texttag, 153*298b7f4cSjfrank *(p->pvar)); 154*298b7f4cSjfrank if (!usingDefaults) 155*298b7f4cSjfrank syslog(LOG_WARNING, "%s", s); 156*298b7f4cSjfrank (void) fputs(s, stdout); 157*298b7f4cSjfrank p++; 158*298b7f4cSjfrank } 159*298b7f4cSjfrank } 160*298b7f4cSjfrank 161*298b7f4cSjfrank static void 162*298b7f4cSjfrank i2cparams_load(void) 163*298b7f4cSjfrank { 164*298b7f4cSjfrank FILE *fp; 165*298b7f4cSjfrank char filename[PATH_MAX]; 166*298b7f4cSjfrank char platform[64]; 167*298b7f4cSjfrank char s[128]; 168*298b7f4cSjfrank char var[128]; 169*298b7f4cSjfrank int val; 170*298b7f4cSjfrank i2c_noise_param_t *p; 171*298b7f4cSjfrank 172*298b7f4cSjfrank if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) == -1) { 173*298b7f4cSjfrank syslog(LOG_ERR, "sysinfo error %s\n", strerror(errno)); 174*298b7f4cSjfrank return; 175*298b7f4cSjfrank } 176*298b7f4cSjfrank (void) snprintf(filename, sizeof (filename), 177*298b7f4cSjfrank "/usr/platform/%s/lib/i2cparam.conf", platform); 178*298b7f4cSjfrank /* read thru the i2cparam.conf file and set variables */ 179*298b7f4cSjfrank if ((fp = fopen(filename, "r")) != NULL) { 180*298b7f4cSjfrank while (fgets(s, sizeof (s), fp) != NULL) { 181*298b7f4cSjfrank if (s[0] == '#') /* skip comment lines */ 182*298b7f4cSjfrank continue; 183*298b7f4cSjfrank /* try to find a string match and get the value */ 184*298b7f4cSjfrank if (sscanf(s, "%127s %d", var, &val) != 2) 185*298b7f4cSjfrank continue; 186*298b7f4cSjfrank if (val < 1) 187*298b7f4cSjfrank val = 1; /* clamp min value */ 188*298b7f4cSjfrank p = &(i2cparams[0]); 189*298b7f4cSjfrank while (p->pvar != NULL) { 190*298b7f4cSjfrank if (strncmp(p->texttag, var, sizeof (var)) == 191*298b7f4cSjfrank 0) { 192*298b7f4cSjfrank *(p->pvar) = val; 193*298b7f4cSjfrank break; 194*298b7f4cSjfrank } 195*298b7f4cSjfrank p++; 196*298b7f4cSjfrank } 197*298b7f4cSjfrank } 198*298b7f4cSjfrank (void) fclose(fp); 199*298b7f4cSjfrank } 200*298b7f4cSjfrank /* output the values of the parameters */ 201*298b7f4cSjfrank i2cparams_debug(&(i2cparams[0]), platform, ((fp == NULL)? 1 : 0)); 202*298b7f4cSjfrank } 203*298b7f4cSjfrank 204*298b7f4cSjfrank 2057c478bd9Sstevel@tonic-gate int32_t 2067c478bd9Sstevel@tonic-gate find_segment(psvc_opaque_t hdlp, char *fru, seg_desc_t *segment, 2077c478bd9Sstevel@tonic-gate char seg_to_find[2]) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate int32_t seg_found = 0, status; 2107c478bd9Sstevel@tonic-gate int32_t seg_desc_start = SEG_DESC_START, j; 2117c478bd9Sstevel@tonic-gate int8_t seg_count; 2127c478bd9Sstevel@tonic-gate char seg_name[2]; 2137c478bd9Sstevel@tonic-gate fru_info_t fru_data; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * Read the number of segments in the Read Only section 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate fru_data.buf_start = NUM_OF_SEG_ADDR; 2197c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&seg_count; 2207c478bd9Sstevel@tonic-gate fru_data.read_size = 1; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 2237c478bd9Sstevel@tonic-gate &fru_data); 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * We test for ENOENT and ENXIO because Littleneck does not 2267c478bd9Sstevel@tonic-gate * have actual presence sensors and so the only way to see 2277c478bd9Sstevel@tonic-gate * if a part is there or not is to actually make a call to 2287c478bd9Sstevel@tonic-gate * that part. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 2317c478bd9Sstevel@tonic-gate if ((errno == ENOENT) || (errno == ENXIO)) 2327c478bd9Sstevel@tonic-gate return (PSVC_NO_DEVICE); 2337c478bd9Sstevel@tonic-gate else 2347c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * Read in each segment to find the segment we are looking for 2387c478bd9Sstevel@tonic-gate */ 2397c478bd9Sstevel@tonic-gate for (j = 0; (j < seg_count) && (!(seg_found)); j++) { 2407c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 2417c478bd9Sstevel@tonic-gate fru_data.buf = seg_name; 2427c478bd9Sstevel@tonic-gate fru_data.read_size = 2; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 2457c478bd9Sstevel@tonic-gate &fru_data); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + 2; 2487c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 2497c478bd9Sstevel@tonic-gate fru_data.buf = (char *)segment; 2507c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (seg_desc_t); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 2537c478bd9Sstevel@tonic-gate &fru_data); 2547c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 2557c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2567c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 2577c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 2607c478bd9Sstevel@tonic-gate if (memcmp(seg_name, seg_to_find, 2) == 0) { 2617c478bd9Sstevel@tonic-gate seg_found = 1; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate return (seg_found); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate int32_t 2687c478bd9Sstevel@tonic-gate psvc_update_thresholds_0(psvc_opaque_t hdlp, char *id) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 2717c478bd9Sstevel@tonic-gate fru_info_t fru_data; 2727c478bd9Sstevel@tonic-gate char *fru, part_no[7]; 2737c478bd9Sstevel@tonic-gate int16_t data_offset; 2747c478bd9Sstevel@tonic-gate int32_t fru_count, i, j, temp_address; 2757c478bd9Sstevel@tonic-gate int32_t seg_found, temp; 2767c478bd9Sstevel@tonic-gate seg_desc_t segment; 2777c478bd9Sstevel@tonic-gate int8_t temps[MAX_TEMP_ATTR]; 2787c478bd9Sstevel@tonic-gate int32_t num_of_parts = 2; 2797c478bd9Sstevel@tonic-gate char fruless_parts[2][7] = {"5015988", "5015675"}; 2807c478bd9Sstevel@tonic-gate int fd; 2817c478bd9Sstevel@tonic-gate FILE *fp; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &fru_count, 2847c478bd9Sstevel@tonic-gate PSVC_FRU); 2857c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 2867c478bd9Sstevel@tonic-gate return (status); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate for (i = 0; i < fru_count; i++) { 2897c478bd9Sstevel@tonic-gate seg_found = 0; 2907c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 2917c478bd9Sstevel@tonic-gate &fru, PSVC_FRU, i); 2927c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 2937c478bd9Sstevel@tonic-gate return (status); 2947c478bd9Sstevel@tonic-gate seg_found = find_segment(hdlp, fru, &segment, "ES"); 2957c478bd9Sstevel@tonic-gate if (seg_found == PSVC_FAILURE) 2967c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 2977c478bd9Sstevel@tonic-gate else if (seg_found == PSVC_NO_DEVICE) 2987c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 2997c478bd9Sstevel@tonic-gate if (seg_found) { 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * For Littleneck we need to read the offset of the 3027c478bd9Sstevel@tonic-gate * die-sensor data record 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate temp_address = segment.segoffset + TEMP_OFFSET; 3057c478bd9Sstevel@tonic-gate fru_data.buf_start = temp_address; 3067c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&data_offset; 3077c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (data_offset); 3087c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 3097c478bd9Sstevel@tonic-gate &fru_data); 3107c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 3117c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3127c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 3137c478bd9Sstevel@tonic-gate return (status); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * Now go and get the new temperature settings 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate temp_address = segment.segoffset + data_offset; 3207c478bd9Sstevel@tonic-gate fru_data.buf_start = temp_address; 3217c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&temps; 3227c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (temps); 3237c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 3247c478bd9Sstevel@tonic-gate &fru_data); 3257c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 3267c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3277c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 3287c478bd9Sstevel@tonic-gate return (status); 3297c478bd9Sstevel@tonic-gate } else { 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Now set the updated Thresholds 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate for (j = 0; j < MAX_TEMP_ATTR; j++) { 3347c478bd9Sstevel@tonic-gate temp = temps[j]; 3357c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, 3367c478bd9Sstevel@tonic-gate temp_attr[j], &temp); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate } else { 3407c478bd9Sstevel@tonic-gate /* 3417c478bd9Sstevel@tonic-gate * For Littleneck only we need to check for the part 3427c478bd9Sstevel@tonic-gate * number of the CPU as there are parts that do not 3437c478bd9Sstevel@tonic-gate * have the ES segment programmed. 3447c478bd9Sstevel@tonic-gate */ 3457c478bd9Sstevel@tonic-gate seg_found = find_segment(hdlp, fru, &segment, "SD"); 3467c478bd9Sstevel@tonic-gate if (seg_found == PSVC_FAILURE) 3477c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 3487c478bd9Sstevel@tonic-gate if (seg_found) { 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * We now goto the SD segment to get the part 3517c478bd9Sstevel@tonic-gate * number. 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate fru_data.buf_start = 3547c478bd9Sstevel@tonic-gate segment.segoffset + PART_NO_OFFSET; 3557c478bd9Sstevel@tonic-gate fru_data.buf = part_no; 3567c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (part_no); 3577c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, 3587c478bd9Sstevel@tonic-gate PSVC_FRU_INFO_ATTR, &fru_data); 3597c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 3607c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Failed psvc_get_attr" 3617c478bd9Sstevel@tonic-gate "for FRU info\n"); 3627c478bd9Sstevel@tonic-gate return (status); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * We are go through the parts list to see 3667c478bd9Sstevel@tonic-gate * if the part number from the FRU is in 3677c478bd9Sstevel@tonic-gate * this list. If it is we simply return 3687c478bd9Sstevel@tonic-gate * as the FRU is not programmed. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate for (j = 0; j < num_of_parts; j++) { 3717c478bd9Sstevel@tonic-gate if (memcmp(fruless_parts[j], part_no, 3727c478bd9Sstevel@tonic-gate 7) == 0) { 3737c478bd9Sstevel@tonic-gate return (status); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * If the Part is not in the Part list and we 3807c478bd9Sstevel@tonic-gate * get to here this means that the FRU is 3817c478bd9Sstevel@tonic-gate * considered broken (no ES segment found) 3827c478bd9Sstevel@tonic-gate * and we need to report this. 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate /* 3857c478bd9Sstevel@tonic-gate * We make this open, write, close, call 3867c478bd9Sstevel@tonic-gate * because picld starts in rcS.d while print 3877c478bd9Sstevel@tonic-gate * services does not start until later 3887c478bd9Sstevel@tonic-gate * (either rc2.d or rc3.d). 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate fd = open("/dev/console", O_WRONLY | O_NOCTTY); 3917c478bd9Sstevel@tonic-gate if (fd != -1) { 3927c478bd9Sstevel@tonic-gate fp = fdopen(fd, "w+"); 3937c478bd9Sstevel@tonic-gate if (fp != NULL) { 3947c478bd9Sstevel@tonic-gate fprintf(fp, NO_FRU_INFO, id); 3957c478bd9Sstevel@tonic-gate fclose(fp); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate close(fd); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, NO_FRU_INFO, id); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate return (status); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate int32_t 4067c478bd9Sstevel@tonic-gate psvc_check_temperature_policy_0(psvc_opaque_t hdlp, char *id) 4077c478bd9Sstevel@tonic-gate { 4087c478bd9Sstevel@tonic-gate int32_t lo_warn, hi_warn, lo_shut, hi_shut; 4097c478bd9Sstevel@tonic-gate uint64_t features; 4107c478bd9Sstevel@tonic-gate int32_t temp; 4117c478bd9Sstevel@tonic-gate char previous_state[32]; 4127c478bd9Sstevel@tonic-gate char state[32]; 4137c478bd9Sstevel@tonic-gate char fault[32]; 4147c478bd9Sstevel@tonic-gate char label[32]; 4157c478bd9Sstevel@tonic-gate boolean_t pr; 4167c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 417*298b7f4cSjfrank int retry; 418*298b7f4cSjfrank int8_t temp_oor; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr); 4217c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) { 4227c478bd9Sstevel@tonic-gate return (status); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_FEATURES_ATTR, &features); 4267c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4277c478bd9Sstevel@tonic-gate return (status); 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LO_WARN_ATTR, &lo_warn); 4307c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4317c478bd9Sstevel@tonic-gate return (status); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LO_SHUT_ATTR, &lo_shut); 4347c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4357c478bd9Sstevel@tonic-gate return (status); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_HI_WARN_ATTR, &hi_warn); 4387c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4397c478bd9Sstevel@tonic-gate return (status); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_HI_SHUT_ATTR, &hi_shut); 4427c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4437c478bd9Sstevel@tonic-gate return (status); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 4467c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4477c478bd9Sstevel@tonic-gate return (status); 4487c478bd9Sstevel@tonic-gate 449*298b7f4cSjfrank retry = 0; 450*298b7f4cSjfrank do { 451*298b7f4cSjfrank if (retry) 452*298b7f4cSjfrank (void) sleep(retry_sleep_temp); 453*298b7f4cSjfrank status = psvc_get_attr(hdlp, id, PSVC_SENSOR_VALUE_ATTR, &temp); 454*298b7f4cSjfrank if (status != PSVC_SUCCESS) { 455*298b7f4cSjfrank if ((errno == ENOENT) || (errno == ENXIO)) 456*298b7f4cSjfrank return (PSVC_SUCCESS); 457*298b7f4cSjfrank else 458*298b7f4cSjfrank return (PSVC_FAILURE); 459*298b7f4cSjfrank } 460*298b7f4cSjfrank temp_oor = 0; 461*298b7f4cSjfrank if (((features & PSVC_LOW_SHUT) && temp <= lo_shut) || 462*298b7f4cSjfrank ((features & PSVC_LOW_WARN) && temp <= lo_warn) || 463*298b7f4cSjfrank ((features & PSVC_HIGH_SHUT) && temp >= hi_shut) || 464*298b7f4cSjfrank ((features & PSVC_HIGH_WARN) && temp >= hi_warn)) 465*298b7f4cSjfrank temp_oor = 1; 466*298b7f4cSjfrank retry++; 467*298b7f4cSjfrank } while ((retry < n_retry_temp) && temp_oor); 468*298b7f4cSjfrank 4697c478bd9Sstevel@tonic-gate if ((features & PSVC_LOW_SHUT) && temp <= lo_shut) { 4707c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 4717c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_LO_SHUT); 4727c478bd9Sstevel@tonic-gate syslog(LOG_ERR, LOWTEMP_CRITICAL_MSG, temp, label); 4737c478bd9Sstevel@tonic-gate } else if ((features & PSVC_LOW_WARN) && temp <= lo_warn) { 4747c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 4757c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_LO_WARN); 4767c478bd9Sstevel@tonic-gate syslog(LOG_ERR, LOWTEMP_WARNING_MSG, temp, label); 4777c478bd9Sstevel@tonic-gate } else if ((features & PSVC_HIGH_SHUT) && temp >= hi_shut) { 4787c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 4797c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_HI_SHUT); 4807c478bd9Sstevel@tonic-gate syslog(LOG_ERR, HIGHTEMP_CRITICAL_MSG, temp, label); 4817c478bd9Sstevel@tonic-gate } else if ((features & PSVC_HIGH_WARN) && temp >= hi_warn) { 4827c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 4837c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_TEMP_HI_WARN); 4847c478bd9Sstevel@tonic-gate syslog(LOG_ERR, HIGHTEMP_WARNING_MSG, temp, label); 4857c478bd9Sstevel@tonic-gate } else { 4867c478bd9Sstevel@tonic-gate /* within limits */ 4877c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 4887c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 4927c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4937c478bd9Sstevel@tonic-gate return (status); 4947c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 4957c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4967c478bd9Sstevel@tonic-gate return (status); 4977c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 4987c478bd9Sstevel@tonic-gate previous_state); 4997c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5007c478bd9Sstevel@tonic-gate return (status); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate if (strcmp(previous_state, state) != 0) { 5037c478bd9Sstevel@tonic-gate char *led_id; 5047c478bd9Sstevel@tonic-gate uint8_t _8bit_val; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate led_id = "SYSTEM_FAULT_LED_WR"; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, led_id, 5097c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 5107c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5117c478bd9Sstevel@tonic-gate return (status); 5127c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) 5137c478bd9Sstevel@tonic-gate _8bit_val &= 0xef; /* clear bit 4 */ 5147c478bd9Sstevel@tonic-gate else 5157c478bd9Sstevel@tonic-gate _8bit_val |= 0x10; /* set bit 4 */ 5167c478bd9Sstevel@tonic-gate _8bit_val |= 0xe4; /* set bits 3, 5, 6, 7 */ 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 5197c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 5207c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5217c478bd9Sstevel@tonic-gate return (status); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate static int32_t ps0_addr[] = {0, 0xac}; 5297c478bd9Sstevel@tonic-gate static int32_t ps1_addr[] = {0, 0xae}; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate int32_t 5327c478bd9Sstevel@tonic-gate psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp, char *id) 5337c478bd9Sstevel@tonic-gate { 5347c478bd9Sstevel@tonic-gate boolean_t presence, previous_presence; 5357c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 5367c478bd9Sstevel@tonic-gate char label[32]; 5377c478bd9Sstevel@tonic-gate int i; 5387c478bd9Sstevel@tonic-gate int32_t led_count; 5397c478bd9Sstevel@tonic-gate char state[32], fault[32]; 5407c478bd9Sstevel@tonic-gate boolean_t ps_type; 5417c478bd9Sstevel@tonic-gate char *sensor_id, *led_id; 5427c478bd9Sstevel@tonic-gate char led_state[32]; 5437c478bd9Sstevel@tonic-gate picl_nodehdl_t parent_node; 5447c478bd9Sstevel@tonic-gate char parent_path[256]; 5457c478bd9Sstevel@tonic-gate picl_nodehdl_t child_node; 5467c478bd9Sstevel@tonic-gate int ps_instance; 5477c478bd9Sstevel@tonic-gate devctl_hdl_t bus_handle, dev_handle; 5487c478bd9Sstevel@tonic-gate devctl_ddef_t ddef_hdl; 5497c478bd9Sstevel@tonic-gate char devpath[256]; 550*298b7f4cSjfrank int retry; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 5537c478bd9Sstevel@tonic-gate &previous_presence); 5547c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5557c478bd9Sstevel@tonic-gate return (status); 556*298b7f4cSjfrank retry = 0; 557*298b7f4cSjfrank do { 558*298b7f4cSjfrank if (retry) 559*298b7f4cSjfrank (void) sleep(retry_sleep_hotplug); 560*298b7f4cSjfrank status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 561*298b7f4cSjfrank if (status != PSVC_SUCCESS) 562*298b7f4cSjfrank return (status); 563*298b7f4cSjfrank retry++; 564*298b7f4cSjfrank } while ((retry < n_retry_hotplug) && (presence != previous_presence)); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate if (presence == previous_presence) { 5677c478bd9Sstevel@tonic-gate /* No change */ 5687c478bd9Sstevel@tonic-gate return (status); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 5727c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5737c478bd9Sstevel@tonic-gate return (status); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* Convert name to node and parent path */ 5767c478bd9Sstevel@tonic-gate psvcplugin_lookup(id, parent_path, &child_node); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if (presence == PSVC_PRESENT) { 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* may detect presence before all connections are made */ 5817c478bd9Sstevel@tonic-gate sleep(1); 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* Device added */ 5847c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* Verify P/S is correct type */ 5887c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 5897c478bd9Sstevel@tonic-gate &sensor_id, PSVC_DEV_TYPE_SENSOR, 0); 5907c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5917c478bd9Sstevel@tonic-gate return (status); 5927c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, 5937c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &ps_type); 5947c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5957c478bd9Sstevel@tonic-gate return (status); 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate if (ps_type == 1) { /* correct p/s */ 5987c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 5997c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 6007c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_OFF); 6017c478bd9Sstevel@tonic-gate } else { /* wrong type */ 6027c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 6037c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_PS_TYPE_FLT); 6047c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_ON); 6057c478bd9Sstevel@tonic-gate syslog(LOG_ERR, PS_TYPE_MSG, label); 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 6097c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6107c478bd9Sstevel@tonic-gate return (status); 6117c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 6127c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6137c478bd9Sstevel@tonic-gate return (status); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* Set state of fault LEDs */ 6167c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, PSVC_ASSOC_MATCHES_ATTR, 6177c478bd9Sstevel@tonic-gate &led_count, PSVC_DEV_FAULT_LED); 6187c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 6197c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 6207c478bd9Sstevel@tonic-gate gettext("Failed for PSVC_DEV_FAULT_LED\n")); 6217c478bd9Sstevel@tonic-gate return (status); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate for (i = 0; i < led_count; ++i) { 6247c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, 6257c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &led_id, 6267c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_LED, i); 6277c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6287c478bd9Sstevel@tonic-gate return (status); 6297c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 6307c478bd9Sstevel@tonic-gate PSVC_LED_STATE_ATTR, led_state); 6317c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6327c478bd9Sstevel@tonic-gate return (status); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate ptree_get_node_by_path(parent_path, &parent_node); 6357c478bd9Sstevel@tonic-gate ptree_add_node(parent_node, child_node); 6367c478bd9Sstevel@tonic-gate } else { 6377c478bd9Sstevel@tonic-gate /* Device removed */ 6387c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 6397c478bd9Sstevel@tonic-gate ptree_delete_node(child_node); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 6437c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6447c478bd9Sstevel@tonic-gate return (status); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &ps_instance); 6477c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6487c478bd9Sstevel@tonic-gate return (status); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if (presence != PSVC_PRESENT) { 6517c478bd9Sstevel@tonic-gate if (ps_instance == 0) 6527c478bd9Sstevel@tonic-gate strcpy(devpath, 6537c478bd9Sstevel@tonic-gate "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ac:power-supply"); 6547c478bd9Sstevel@tonic-gate else 6557c478bd9Sstevel@tonic-gate strcpy(devpath, 6567c478bd9Sstevel@tonic-gate "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ae:power-supply"); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate dev_handle = devctl_device_acquire(devpath, 0); 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate if (devctl_device_remove(dev_handle)) { 6617c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, label, 6627c478bd9Sstevel@tonic-gate errno); 6637c478bd9Sstevel@tonic-gate status = PSVC_FAILURE; 6647c478bd9Sstevel@tonic-gate } else { 6657c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 6667c478bd9Sstevel@tonic-gate status = PSVC_SUCCESS; 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate return (status); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * We fall through to here if the device has been inserted. 6737c478bd9Sstevel@tonic-gate * Add the devinfo tree node entry for the seeprom and attach 6747c478bd9Sstevel@tonic-gate * the i2c seeprom driver 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate ddef_hdl = devctl_ddef_alloc("power-supply", 0); 6777c478bd9Sstevel@tonic-gate (void) devctl_ddef_string(ddef_hdl, "compatible", "i2c-at24c64"); 6787c478bd9Sstevel@tonic-gate if (ps_instance == 0) { 6797c478bd9Sstevel@tonic-gate (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, ps0_addr); 6807c478bd9Sstevel@tonic-gate } else { 6817c478bd9Sstevel@tonic-gate (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, ps1_addr); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate bus_handle = devctl_bus_acquire( 6857c478bd9Sstevel@tonic-gate "/devices/pci@8,700000/ebus@5/i2c@1,30:i2c", 0); 6867c478bd9Sstevel@tonic-gate if (devctl_bus_dev_create(bus_handle, ddef_hdl, 0, &dev_handle)) { 6877c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_CREATE_FAILED, label, errno); 6887c478bd9Sstevel@tonic-gate status = PSVC_FAILURE; 6897c478bd9Sstevel@tonic-gate } else 6907c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate devctl_release(bus_handle); 6937c478bd9Sstevel@tonic-gate devctl_ddef_free(ddef_hdl); 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate return (status); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate int32_t 6997c478bd9Sstevel@tonic-gate psvc_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *id) 7007c478bd9Sstevel@tonic-gate { 7017c478bd9Sstevel@tonic-gate int32_t sensor_count; 7027c478bd9Sstevel@tonic-gate char *led_id, *sensor_id; 7037c478bd9Sstevel@tonic-gate int i; 7047c478bd9Sstevel@tonic-gate char state[32], fault[32], previous_state[32]; 7057c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 7067c478bd9Sstevel@tonic-gate boolean_t present; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 7097c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 7107c478bd9Sstevel@tonic-gate return (status); 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) { 7137c478bd9Sstevel@tonic-gate errno = ENODEV; 7147c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 7187c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_SENSOR); 7197c478bd9Sstevel@tonic-gate for (i = 0; i < sensor_count; ++i) { 7207c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 7217c478bd9Sstevel@tonic-gate &sensor_id, PSVC_DEV_FAULT_SENSOR, i); 7227c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7237c478bd9Sstevel@tonic-gate return (status); 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, 7267c478bd9Sstevel@tonic-gate PSVC_SWITCH_STATE_ATTR, state); 7277c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7287c478bd9Sstevel@tonic-gate return (status); 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_SWITCH_ON) == 0) { 7317c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 7327c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_GEN_FAULT); 7337c478bd9Sstevel@tonic-gate } else { 7347c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 7357c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 7397c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7407c478bd9Sstevel@tonic-gate return (status); 7417c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 7427c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7437c478bd9Sstevel@tonic-gate return (status); 7447c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 7457c478bd9Sstevel@tonic-gate previous_state); 7467c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7477c478bd9Sstevel@tonic-gate return (status); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (strcmp(state, previous_state) != 0) { 7507c478bd9Sstevel@tonic-gate char sensor_label[32]; 7517c478bd9Sstevel@tonic-gate char dev_label[32]; 7527c478bd9Sstevel@tonic-gate uint8_t _8bit_val; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, dev_label); 7557c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, sensor_id, PSVC_LABEL_ATTR, 7567c478bd9Sstevel@tonic-gate sensor_label); 7577c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) 7587c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label, 7597c478bd9Sstevel@tonic-gate sensor_label); 7607c478bd9Sstevel@tonic-gate else 7617c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_OK_MSG, dev_label); 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate led_id = "SYSTEM_FAULT_LED_WR"; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, led_id, 7667c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 7677c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7687c478bd9Sstevel@tonic-gate return (status); 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) 7717c478bd9Sstevel@tonic-gate _8bit_val &= 0xef; /* clear bit 4 */ 7727c478bd9Sstevel@tonic-gate else 7737c478bd9Sstevel@tonic-gate _8bit_val |= 0x10; /* set bit 4 */ 7747c478bd9Sstevel@tonic-gate _8bit_val |= 0xe4; /* set bits 3, 5, 6, 7 */ 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 7777c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 7787c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7797c478bd9Sstevel@tonic-gate return (status); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate int32_t 7887c478bd9Sstevel@tonic-gate psvc_init_led_policy_0(psvc_opaque_t hdlp, char *id) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 7917c478bd9Sstevel@tonic-gate uint8_t _8bit_val; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, 7947c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 7957c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7967c478bd9Sstevel@tonic-gate return (status); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate _8bit_val &= 0xef; /* clear bit 4 */ 7997c478bd9Sstevel@tonic-gate _8bit_val |= 0xf4; /* set bits 3, 5, 6, 7 */ 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, 8027c478bd9Sstevel@tonic-gate PSVC_GPIO_VALUE_ATTR, &_8bit_val); 8037c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 8047c478bd9Sstevel@tonic-gate return (status); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate return (status); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate static int32_t 8107c478bd9Sstevel@tonic-gate check_cpu_temp_fault(psvc_opaque_t hdlp, char *cpu, int32_t cpu_count) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate char *sensorid; 8137c478bd9Sstevel@tonic-gate int32_t sensor_count; 8147c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 8157c478bd9Sstevel@tonic-gate int32_t i; 8167c478bd9Sstevel@tonic-gate char fault[32]; 817*298b7f4cSjfrank int retry; 818*298b7f4cSjfrank int8_t temp_oor; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, cpu, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 8217c478bd9Sstevel@tonic-gate PSVC_DEV_TEMP_SENSOR); 8227c478bd9Sstevel@tonic-gate for (i = 0; i < sensor_count; ++i) { 8237c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, cpu, PSVC_ASSOC_ID_ATTR, 8247c478bd9Sstevel@tonic-gate &sensorid, PSVC_DEV_TEMP_SENSOR, i); 8257c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 8267c478bd9Sstevel@tonic-gate return (status); 8277c478bd9Sstevel@tonic-gate 828*298b7f4cSjfrank retry = 0; 829*298b7f4cSjfrank do { 830*298b7f4cSjfrank if (retry) 831*298b7f4cSjfrank (void) sleep(retry_sleep_temp_shutdown); 832*298b7f4cSjfrank status = psvc_get_attr(hdlp, sensorid, 833*298b7f4cSjfrank PSVC_FAULTID_ATTR, fault); 834*298b7f4cSjfrank if (status == PSVC_FAILURE) 835*298b7f4cSjfrank return (status); 836*298b7f4cSjfrank temp_oor = 0; 837*298b7f4cSjfrank if ((strcmp(fault, PSVC_TEMP_HI_SHUT) == 0) || 838*298b7f4cSjfrank (strcmp(fault, PSVC_TEMP_LO_SHUT) == 0)) { 839*298b7f4cSjfrank temp_oor = 1; 840*298b7f4cSjfrank } 841*298b7f4cSjfrank retry++; 842*298b7f4cSjfrank } while ((retry < n_retry_temp_shutdown) && temp_oor); 8437c478bd9Sstevel@tonic-gate 844*298b7f4cSjfrank if (temp_oor) { 8457c478bd9Sstevel@tonic-gate system(shutdown_string); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate return (status); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate int32_t 8537c478bd9Sstevel@tonic-gate psvc_shutdown_policy_0(psvc_opaque_t hdlp, char *id) 8547c478bd9Sstevel@tonic-gate { 8557c478bd9Sstevel@tonic-gate int32_t cpu_count; 8567c478bd9Sstevel@tonic-gate char *cpuid; 8577c478bd9Sstevel@tonic-gate int32_t i; 8587c478bd9Sstevel@tonic-gate boolean_t present; 8597c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &cpu_count, 8627c478bd9Sstevel@tonic-gate PSVC_CPU); 8637c478bd9Sstevel@tonic-gate for (i = 0; i < cpu_count; ++i) { 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &cpuid, 8667c478bd9Sstevel@tonic-gate PSVC_CPU, i); 8677c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 8687c478bd9Sstevel@tonic-gate return (status); 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, cpuid, 8717c478bd9Sstevel@tonic-gate PSVC_PRESENCE_ATTR, &present); 8727c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE && present == PSVC_PRESENT) 8737c478bd9Sstevel@tonic-gate return (status); 8747c478bd9Sstevel@tonic-gate if (present == PSVC_PRESENT) { 8757c478bd9Sstevel@tonic-gate status = check_cpu_temp_fault(hdlp, cpuid, cpu_count); 8767c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE && errno != ENODEV) 8777c478bd9Sstevel@tonic-gate return (status); 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 8827c478bd9Sstevel@tonic-gate } 883