diff options
Diffstat (limited to 'lib/ipmi_sensor.c')
-rw-r--r-- | lib/ipmi_sensor.c | 964 |
1 files changed, 964 insertions, 0 deletions
diff --git a/lib/ipmi_sensor.c b/lib/ipmi_sensor.c new file mode 100644 index 0000000..4ef5138 --- /dev/null +++ b/lib/ipmi_sensor.c @@ -0,0 +1,964 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <string.h> +#include <math.h> + +#include <ipmitool/ipmi.h> +#include <ipmitool/helper.h> +#include <ipmitool/log.h> +#include <ipmitool/ipmi_intf.h> +#include <ipmitool/ipmi_sdr.h> +#include <ipmitool/ipmi_sel.h> +#include <ipmitool/ipmi_sensor.h> + +extern int verbose; +void printf_sensor_get_usage(); + +// Macro's for Reading the current sensor Data. +#define SCANNING_DISABLED 0x40 +#define READING_UNAVAILABLE 0x20 +#define INVALID_THRESHOLD "Invalid Threshold data values. Cannot Set Threshold Data." +// static +int +ipmi_sensor_get_sensor_reading_factors( + struct ipmi_intf * intf, + struct sdr_record_full_sensor * sensor, + uint8_t reading) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + uint8_t req_data[2]; + + char id[17]; + + if (intf == NULL || sensor == NULL) + return -1; + + memset(id, 0, sizeof(id)); + memcpy(id, sensor->id_string, 16); + + req_data[0] = sensor->cmn.keys.sensor_num; + req_data[1] = reading; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.lun = sensor->cmn.keys.lun; + req.msg.cmd = GET_SENSOR_FACTORS; + req.msg.data = req_data; + req.msg.data_len = sizeof(req_data); + + rsp = intf->sendrecv(intf, &req); + + if (rsp == NULL) { + lprintf(LOG_ERR, "Error updating reading factor for sensor %s (#%02x)", + id, sensor->cmn.keys.sensor_num); + return -1; + } else if (rsp->ccode) { + return -1; + } else { + /* Update SDR copy with updated Reading Factors for this reading */ + /* Note: + * The Format of the returned data is exactly as in the SDR definition (Little Endian Format), + * therefore we can use raw copy operation here. + * Note: rsp->data[0] would point to the next valid entry in the sampling table + */ + // BUGBUG: uses 'hardcoded' length information from SDR Definition + memcpy(&sensor->mtol, &rsp->data[1], sizeof(sensor->mtol)); + memcpy(&sensor->bacc, &rsp->data[3], sizeof(sensor->bacc)); + return 0; + } + +} + +static +struct ipmi_rs * +ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf, + uint8_t sensor, + uint8_t threshold, uint8_t setting, + uint8_t target, uint8_t lun, uint8_t channel) +{ + struct ipmi_rq req; + static struct sensor_set_thresh_rq set_thresh_rq; + struct ipmi_rs *rsp; + uint8_t bridged_request = 0; + uint32_t save_addr; + uint32_t save_channel; + + memset(&set_thresh_rq, 0, sizeof (set_thresh_rq)); + set_thresh_rq.sensor_num = sensor; + set_thresh_rq.set_mask = threshold; + if (threshold == UPPER_NON_RECOV_SPECIFIED) + set_thresh_rq.upper_non_recov = setting; + else if (threshold == UPPER_CRIT_SPECIFIED) + set_thresh_rq.upper_crit = setting; + else if (threshold == UPPER_NON_CRIT_SPECIFIED) + set_thresh_rq.upper_non_crit = setting; + else if (threshold == LOWER_NON_CRIT_SPECIFIED) + set_thresh_rq.lower_non_crit = setting; + else if (threshold == LOWER_CRIT_SPECIFIED) + set_thresh_rq.lower_crit = setting; + else if (threshold == LOWER_NON_RECOV_SPECIFIED) + set_thresh_rq.lower_non_recov = setting; + else + return NULL; + + if (BRIDGE_TO_SENSOR(intf, target, channel)) { + bridged_request = 1; + save_addr = intf->target_addr; + intf->target_addr = target; + save_channel = intf->target_channel; + intf->target_channel = channel; + } + memset(&req, 0, sizeof (req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.lun = lun; + req.msg.cmd = SET_SENSOR_THRESHOLDS; + req.msg.data = (uint8_t *) & set_thresh_rq; + req.msg.data_len = sizeof (set_thresh_rq); + + rsp = intf->sendrecv(intf, &req); + if (bridged_request) { + intf->target_addr = save_addr; + intf->target_channel = save_channel; + } + return rsp; +} + +static int +ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf, + struct sdr_record_common_sensor *sensor, + uint8_t sdr_record_type) +{ + const char *id; + struct sensor_reading *sr; + + sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3); + + if (sr == NULL) { + return -1; + } + + if (csv_output) { + /* NOT IMPLEMENTED */ + } else { + if (verbose == 0) { + /* output format + * id value units status thresholds.... + */ + printf("%-16s ", sr->s_id); + if (sr->s_reading_valid) { + if (sr->s_has_analog_value) { + /* don't show discrete component */ + printf("| %-10s | %-10s | %-6s", + sr->s_a_str, sr->s_a_units, "ok"); + } else { + printf("| 0x%-8x | %-10s | 0x%02x%02x", + sr->s_reading, "discrete", + sr->s_data2, sr->s_data3); + } + } else { + printf("| %-10s | %-10s | %-6s", + "na", "discrete", "na"); + } + printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s", + "na", "na", "na", "na", "na", "na"); + + printf("\n"); + } else { + printf("Sensor ID : %s (0x%x)\n", + sr->s_id, sensor->keys.sensor_num); + printf(" Entity ID : %d.%d\n", + sensor->entity.id, sensor->entity.instance); + printf(" Sensor Type (Discrete): %s\n", + ipmi_sdr_get_sensor_type_desc(sensor->sensor. + type)); + if( sr->s_reading_valid ) + { + if (sr->s_has_analog_value) { + printf(" Sensor Reading : %s %s\n", sr->s_a_str, sr->s_a_units); + } + ipmi_sdr_print_discrete_state("States Asserted", + sensor->sensor.type, + sensor->event_type, + sr->s_data2, + sr->s_data3); + printf("\n"); + } else { + printf(" Unable to read sensor: Device Not Present\n\n"); + } + } + } + + return (sr->s_reading_valid ? 0 : -1 ); +} + +static void +print_thresh_setting(struct sdr_record_full_sensor *full, + uint8_t thresh_is_avail, uint8_t setting, + const char *field_sep, + const char *analog_fmt, + const char *discrete_fmt, + const char *na_fmt) +{ + printf("%s", field_sep); + if (!thresh_is_avail) { + printf(na_fmt, "na"); + return; + } + if (full && !UNITS_ARE_DISCRETE(&full->cmn)) { + printf(analog_fmt, sdr_convert_sensor_reading (full, setting)); + } else { + printf(discrete_fmt, setting); + } +} + +static int +ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf, + struct sdr_record_common_sensor *sensor, + uint8_t sdr_record_type) +{ + int thresh_available = 1; + struct ipmi_rs *rsp; + struct sensor_reading *sr; + + sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3); + + if (sr == NULL) { + return -1; + } + + const char *thresh_status = ipmi_sdr_get_thresh_status(sr, "ns"); + + /* + * Get sensor thresholds + */ + rsp = ipmi_sdr_get_sensor_thresholds(intf, + sensor->keys.sensor_num, sensor->keys.owner_id, + sensor->keys.lun, sensor->keys.channel); + + if ((rsp == NULL) || (rsp->ccode > 0) || (rsp->data_len == 0)) + thresh_available = 0; + + if (csv_output) { + /* NOT IMPLEMENTED */ + } else { + if (verbose == 0) { + /* output format + * id value units status thresholds.... + */ + printf("%-16s ", sr->s_id); + if (sr->s_reading_valid) { + if (sr->s_has_analog_value) + printf("| %-10.3f | %-10s | %-6s", + sr->s_a_val, sr->s_a_units, thresh_status); + else + printf("| 0x%-8x | %-10s | %-6s", + sr->s_reading, sr->s_a_units, thresh_status); + } else { + printf("| %-10s | %-10s | %-6s", + "na", sr->s_a_units, "na"); + } + if (thresh_available && sr->full) { +#define PTS(bit, dataidx) { \ + print_thresh_setting(sr->full, rsp->data[0] & (bit), \ + rsp->data[(dataidx)], "| ", "%-10.3f", "0x-8x", "%-10s"); \ +} + PTS(LOWER_NON_RECOV_SPECIFIED, 3); + PTS(LOWER_CRIT_SPECIFIED, 2); + PTS(LOWER_NON_CRIT_SPECIFIED, 1); + PTS(UPPER_NON_CRIT_SPECIFIED, 4); + PTS(UPPER_CRIT_SPECIFIED, 5); + PTS(UPPER_NON_RECOV_SPECIFIED, 6); +#undef PTS + } else { + printf + ("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s", + "na", "na", "na", "na", "na", "na"); + } + + printf("\n"); + } else { + printf("Sensor ID : %s (0x%x)\n", + sr->s_id, sensor->keys.sensor_num); + + printf(" Entity ID : %d.%d\n", + sensor->entity.id, sensor->entity.instance); + + printf(" Sensor Type (Threshold) : %s\n", + ipmi_sdr_get_sensor_type_desc(sensor->sensor. + type)); + + printf(" Sensor Reading : "); + if (sr->s_reading_valid) { + if (sr->full) { + uint16_t raw_tol = __TO_TOL(sr->full->mtol); + if (sr->s_has_analog_value) { + double tol = + sdr_convert_sensor_tolerance(sr->full, + raw_tol); + printf("%.*f (+/- %.*f) %s\n", + (sr->s_a_val == (int) + sr->s_a_val) ? 0 : 3, + sr->s_a_val, + (tol == (int) tol) ? 0 : 3, tol, + sr->s_a_units); + } else { + printf("0x%x (+/- 0x%x) %s\n", + sr->s_reading, + raw_tol, + sr->s_a_units); + } + } else { + printf("0x%x %s\n", sr->s_reading, + sr->s_a_units); + } + printf(" Status : %s\n", thresh_status); + + if (thresh_available) { + if (sr->full) { +#define PTS(bit, dataidx, str) { \ +print_thresh_setting(sr->full, rsp->data[0] & (bit), \ + rsp->data[(dataidx)], \ + (str), "%.3f\n", "0x%x\n", "%s\n"); \ +} + + PTS(LOWER_NON_RECOV_SPECIFIED, 3, " Lower Non-Recoverable : "); + PTS(LOWER_CRIT_SPECIFIED, 2, " Lower Critical : "); + PTS(LOWER_NON_CRIT_SPECIFIED, 1, " Lower Non-Critical : "); + PTS(UPPER_NON_CRIT_SPECIFIED, 4, " Upper Non-Critical : "); + PTS(UPPER_CRIT_SPECIFIED, 5, " Upper Critical : "); + PTS(UPPER_NON_RECOV_SPECIFIED, 6, " Upper Non-Recoverable : "); +#undef PTS + + } + ipmi_sdr_print_sensor_hysteresis(sensor, sr->full, + sr->full ? sr->full->threshold.hysteresis.positive : + sr->compact->threshold.hysteresis.positive, + "Positive Hysteresis"); + + ipmi_sdr_print_sensor_hysteresis(sensor, sr->full, + sr->full ? sr->full->threshold.hysteresis.negative : + sr->compact->threshold.hysteresis.negative, + "Negative Hysteresis"); + } else { + printf(" Sensor Threshold Settings not available\n"); + } + } else { + printf(" Unable to read sensor: Device Not Present\n\n"); + } + + ipmi_sdr_print_sensor_event_status(intf, + sensor->keys. + sensor_num, + sensor->sensor.type, + sensor->event_type, + ANALOG_SENSOR, + sensor->keys.owner_id, + sensor->keys.lun, + sensor->keys.channel); + ipmi_sdr_print_sensor_event_enable(intf, + sensor->keys. + sensor_num, + sensor->sensor.type, + sensor->event_type, + ANALOG_SENSOR, + sensor->keys.owner_id, + sensor->keys.lun, + sensor->keys.channel); + + printf("\n"); + } + } + + return (sr->s_reading_valid ? 0 : -1 ); +} + +int +ipmi_sensor_print_fc(struct ipmi_intf *intf, + struct sdr_record_common_sensor *sensor, + uint8_t sdr_record_type) +{ + if (IS_THRESHOLD_SENSOR(sensor)) + return ipmi_sensor_print_fc_threshold(intf, sensor, sdr_record_type); + else + return ipmi_sensor_print_fc_discrete(intf, sensor, sdr_record_type); +} + +static int +ipmi_sensor_list(struct ipmi_intf *intf) +{ + struct sdr_get_rs *header; + struct ipmi_sdr_iterator *itr; + int rc = 0; + + lprintf(LOG_DEBUG, "Querying SDR for sensor list"); + + itr = ipmi_sdr_start(intf, 0); + if (itr == NULL) { + lprintf(LOG_ERR, "Unable to open SDR for reading"); + return -1; + } + + while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) { + uint8_t *rec; + + rec = ipmi_sdr_get_record(intf, header, itr); + if (rec == NULL) { + lprintf(LOG_DEBUG, "rec == NULL"); + continue; + } + + switch (header->type) { + case SDR_RECORD_TYPE_FULL_SENSOR: + case SDR_RECORD_TYPE_COMPACT_SENSOR: + ipmi_sensor_print_fc(intf, + (struct + sdr_record_common_sensor *) + rec, + header->type); + break; + } + free(rec); + rec = NULL; + + /* fix for CR6604909: */ + /* mask failure of individual reads in sensor list command */ + /* rc = (r == 0) ? rc : r; */ + } + + ipmi_sdr_end(intf, itr); + + return rc; +} + +static const struct valstr threshold_vals[] = { + {UPPER_NON_RECOV_SPECIFIED, "Upper Non-Recoverable"}, + {UPPER_CRIT_SPECIFIED, "Upper Critical"}, + {UPPER_NON_CRIT_SPECIFIED, "Upper Non-Critical"}, + {LOWER_NON_RECOV_SPECIFIED, "Lower Non-Recoverable"}, + {LOWER_CRIT_SPECIFIED, "Lower Critical"}, + {LOWER_NON_CRIT_SPECIFIED, "Lower Non-Critical"}, + {0x00, NULL}, +}; + +static int +__ipmi_sensor_set_threshold(struct ipmi_intf *intf, + uint8_t num, uint8_t mask, uint8_t setting, + uint8_t target, uint8_t lun, uint8_t channel) +{ + struct ipmi_rs *rsp; + + rsp = ipmi_sensor_set_sensor_thresholds(intf, num, mask, setting, + target, lun, channel); + + if (rsp == NULL) { + lprintf(LOG_ERR, "Error setting threshold"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Error setting threshold: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + return 0; +} + +static uint8_t +__ipmi_sensor_threshold_value_to_raw(struct sdr_record_full_sensor *full, double value) +{ + if (!UNITS_ARE_DISCRETE(&full->cmn)) { /* Has an analog reading */ + /* Has an analog reading and supports mx+b */ + return sdr_convert_sensor_value_to_raw(full, value); + } + else { + /* Does not have an analog reading and/or does not support mx+b */ + if (value > 255) { + return 255; + } + else if (value < 0) { + return 0; + } + else { + return (uint8_t )value; + } + } +} + + +static int +ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv) +{ + char *id, *thresh; + uint8_t settingMask = 0; + double setting1 = 0.0, setting2 = 0.0, setting3 = 0.0; + int allUpper = 0, allLower = 0; + int ret = 0; + struct ipmi_rs *rsp; + int i =0; + double val[10] = {0}; + + struct sdr_record_list *sdr; + + if (argc < 3 || strncmp(argv[0], "help", 4) == 0) { + lprintf(LOG_NOTICE, "sensor thresh <id> <threshold> <setting>"); + lprintf(LOG_NOTICE, + " id : name of the sensor for which threshold is to be set"); + lprintf(LOG_NOTICE, " threshold : which threshold to set"); + lprintf(LOG_NOTICE, + " unr = upper non-recoverable"); + lprintf(LOG_NOTICE, " ucr = upper critical"); + lprintf(LOG_NOTICE, + " unc = upper non-critical"); + lprintf(LOG_NOTICE, + " lnc = lower non-critical"); + lprintf(LOG_NOTICE, " lcr = lower critical"); + lprintf(LOG_NOTICE, + " lnr = lower non-recoverable"); + lprintf(LOG_NOTICE, + " setting : the value to set the threshold to"); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, + "sensor thresh <id> lower <lnr> <lcr> <lnc>"); + lprintf(LOG_NOTICE, + " Set all lower thresholds at the same time"); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, + "sensor thresh <id> upper <unc> <ucr> <unr>"); + lprintf(LOG_NOTICE, + " Set all upper thresholds at the same time"); + lprintf(LOG_NOTICE, ""); + return 0; + } + + id = argv[0]; + thresh = argv[1]; + + if (strncmp(thresh, "upper", 5) == 0) { + if (argc < 5) { + lprintf(LOG_ERR, + "usage: sensor thresh <id> upper <unc> <ucr> <unr>"); + return -1; + } + allUpper = 1; + if (str2double(argv[2], &setting1) != 0) { + lprintf(LOG_ERR, "Given unc '%s' is invalid.", + argv[2]); + return (-1); + } + if (str2double(argv[3], &setting2) != 0) { + lprintf(LOG_ERR, "Given ucr '%s' is invalid.", + argv[3]); + return (-1); + } + if (str2double(argv[4], &setting3) != 0) { + lprintf(LOG_ERR, "Given unr '%s' is invalid.", + argv[4]); + return (-1); + } + } else if (strncmp(thresh, "lower", 5) == 0) { + if (argc < 5) { + lprintf(LOG_ERR, + "usage: sensor thresh <id> lower <unc> <ucr> <unr>"); + return -1; + } + allLower = 1; + if (str2double(argv[2], &setting1) != 0) { + lprintf(LOG_ERR, "Given lnc '%s' is invalid.", + argv[2]); + return (-1); + } + if (str2double(argv[3], &setting2) != 0) { + lprintf(LOG_ERR, "Given lcr '%s' is invalid.", + argv[3]); + return (-1); + } + if (str2double(argv[4], &setting3) != 0) { + lprintf(LOG_ERR, "Given lnr '%s' is invalid.", + argv[4]); + return (-1); + } + } else { + if (strncmp(thresh, "unr", 3) == 0) + settingMask = UPPER_NON_RECOV_SPECIFIED; + else if (strncmp(thresh, "ucr", 3) == 0) + settingMask = UPPER_CRIT_SPECIFIED; + else if (strncmp(thresh, "unc", 3) == 0) + settingMask = UPPER_NON_CRIT_SPECIFIED; + else if (strncmp(thresh, "lnc", 3) == 0) + settingMask = LOWER_NON_CRIT_SPECIFIED; + else if (strncmp(thresh, "lcr", 3) == 0) + settingMask = LOWER_CRIT_SPECIFIED; + else if (strncmp(thresh, "lnr", 3) == 0) + settingMask = LOWER_NON_RECOV_SPECIFIED; + else { + lprintf(LOG_ERR, + "Valid threshold '%s' for sensor '%s' not specified!", + thresh, id); + return -1; + } + if (str2double(argv[2], &setting1) != 0) { + lprintf(LOG_ERR, + "Given %s threshold value '%s' is invalid.", + thresh, argv[2]); + return (-1); + } + } + + printf("Locating sensor record '%s'...\n", id); + + /* lookup by sensor name */ + sdr = ipmi_sdr_find_sdr_byid(intf, id); + if (sdr == NULL) { + lprintf(LOG_ERR, "Sensor data record not found!"); + return -1; + } + + if (sdr->type != SDR_RECORD_TYPE_FULL_SENSOR) { + lprintf(LOG_ERR, "Invalid sensor type %02x", sdr->type); + return -1; + } + + if (!IS_THRESHOLD_SENSOR(sdr->record.common)) { + lprintf(LOG_ERR, "Invalid sensor event type %02x", sdr->record.common->event_type); + return -1; + } + + + if (allUpper) { + settingMask = UPPER_NON_CRIT_SPECIFIED; + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting1); + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + + settingMask = UPPER_CRIT_SPECIFIED; + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting2); + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + + settingMask = UPPER_NON_RECOV_SPECIFIED; + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting3); + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + } else if (allLower) { + settingMask = LOWER_NON_RECOV_SPECIFIED; + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting1); + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + + settingMask = LOWER_CRIT_SPECIFIED; + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting2); + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + + settingMask = LOWER_NON_CRIT_SPECIFIED; + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting3); + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + } else { + + /* + * Current implementation doesn't check for the valid setting of upper non critical and other thresholds. + * In the below logic: + * Get all the current reading of the sensor i.e. unc, uc, lc,lnc. + * Validate the values given by the user. + * If the values are not correct, then popup with the Error message and return. + */ + /* + * Get current reading + */ + rsp = ipmi_sdr_get_sensor_reading_ipmb(intf, + sdr->record.common->keys.sensor_num, + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun,sdr->record.common->keys.channel); + rsp = ipmi_sdr_get_sensor_thresholds(intf, + sdr->record.common->keys.sensor_num, + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + if ((rsp == NULL) || (rsp->ccode > 0)) { + lprintf(LOG_ERR, "Sensor data record not found!"); + return -1; + } + for(i=1;i<=6;i++) { + val[i] = sdr_convert_sensor_reading(sdr->record.full, rsp->data[i]); + if(val[i] < 0) + val[i] = 0; + } + /* Check for the valid Upper non recovarable Value.*/ + if( (settingMask & UPPER_NON_RECOV_SPECIFIED) ) { + + if( (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED) && + (( (rsp->data[0] & UPPER_CRIT_SPECIFIED) && ( setting1 <= val[5])) || + ( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) && ( setting1 <= val[4]))) ) + { + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + } else if( (settingMask & UPPER_CRIT_SPECIFIED) ) { /* Check for the valid Upper critical Value.*/ + if( (rsp->data[0] & UPPER_CRIT_SPECIFIED) && + (((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&& ( setting1 >= val[6])) || + ((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 <= val[4]))) ) + { + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + } else if( (settingMask & UPPER_NON_CRIT_SPECIFIED) ) { /* Check for the valid Upper non critical Value.*/ + if( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) && + (((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&&( setting1 >= val[6])) || + ((rsp->data[0] & UPPER_CRIT_SPECIFIED)&&( setting1 >= val[5])) || + ((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 <= val[1]))) ) + { + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + } else if( (settingMask & LOWER_NON_CRIT_SPECIFIED) ) { /* Check for the valid lower non critical Value.*/ + if( (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED) && + (((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 <= val[2])) || + ((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))|| + ((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 >= val[4]))) ) + { + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + } else if( (settingMask & LOWER_CRIT_SPECIFIED) ) { /* Check for the valid lower critical Value.*/ + if( (rsp->data[0] & LOWER_CRIT_SPECIFIED) && + (((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) || + ((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))) ) + { + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + } else if( (settingMask & LOWER_NON_RECOV_SPECIFIED) ) { /* Check for the valid lower non recovarable Value.*/ + if( (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED) && + (((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) || + ((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 >= val[2]))) ) + { + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + } else { /* None of this Then Return with error messages.*/ + lprintf(LOG_ERR, INVALID_THRESHOLD); + return -1; + } + + + printf("Setting sensor \"%s\" %s threshold to %.3f\n", + sdr->record.full->id_string, + val2str(settingMask, threshold_vals), setting1); + + ret = __ipmi_sensor_set_threshold(intf, + sdr->record.common->keys. + sensor_num, settingMask, + __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1), + sdr->record.common->keys.owner_id, + sdr->record.common->keys.lun, + sdr->record.common->keys.channel); + } + + return ret; +} + +static int +ipmi_sensor_get_reading(struct ipmi_intf *intf, int argc, char **argv) +{ + struct sdr_record_list *sdr; + int i, rc=0; + + if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { + lprintf(LOG_NOTICE, "sensor reading <id> ... [id]"); + lprintf(LOG_NOTICE, " id : name of desired sensor"); + return -1; + } + + for (i = 0; i < argc; i++) { + sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]); + if (sdr == NULL) { + lprintf(LOG_ERR, "Sensor \"%s\" not found!", + argv[i]); + rc = -1; + continue; + } + + switch (sdr->type) { + case SDR_RECORD_TYPE_FULL_SENSOR: + case SDR_RECORD_TYPE_COMPACT_SENSOR: + { + struct sensor_reading *sr; + struct sdr_record_common_sensor *sensor = sdr->record.common; + sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr->type, 3); + + if (sr == NULL) { + rc = -1; + continue; + } + + if (!sr->full) + continue; + + if (!sr->s_reading_valid) + continue; + + if (!sr->s_has_analog_value) { + lprintf(LOG_ERR, "Sensor \"%s\" is a discrete sensor!", argv[i]); + continue; + } + if (csv_output) + printf("%s,%s\n", argv[i], sr->s_a_str); + else + printf("%-16s | %s\n", argv[i], sr->s_a_str); + + break; + } + default: + continue; + } + } + + return rc; +} + +static int +ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv) +{ + int i, v; + int rc = 0; + struct sdr_record_list *sdr; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + printf_sensor_get_usage(); + return (-1); + } else if (strcmp(argv[0], "help") == 0) { + printf_sensor_get_usage(); + return 0; + } + printf("Locating sensor record...\n"); + /* lookup by sensor name */ + for (i = 0; i < argc; i++) { + sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]); + if (sdr == NULL) { + lprintf(LOG_ERR, "Sensor data record \"%s\" not found!", + argv[i]); + rc = -1; + continue; + } + /* need to set verbose level to 1 */ + v = verbose; + verbose = 1; + if (ipmi_sdr_print_listentry(intf, sdr) < 0) { + rc = (-1); + } + verbose = v; + sdr = NULL; + } + return rc; +} + +int +ipmi_sensor_main(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc == 0) { + rc = ipmi_sensor_list(intf); + } else if (strncmp(argv[0], "help", 4) == 0) { + lprintf(LOG_NOTICE, "Sensor Commands: list thresh get reading"); + } else if (strncmp(argv[0], "list", 4) == 0) { + rc = ipmi_sensor_list(intf); + } else if (strncmp(argv[0], "thresh", 5) == 0) { + rc = ipmi_sensor_set_threshold(intf, argc - 1, &argv[1]); + } else if (strncmp(argv[0], "get", 3) == 0) { + rc = ipmi_sensor_get(intf, argc - 1, &argv[1]); + } else if (strncmp(argv[0], "reading", 7) == 0) { + rc = ipmi_sensor_get_reading(intf, argc - 1, &argv[1]); + } else { + lprintf(LOG_ERR, "Invalid sensor command: %s", argv[0]); + rc = -1; + } + + return rc; +} + +/* printf_sensor_get_usage - print usage for # ipmitool sensor get NAC; + * + * @returns: void + */ +void +printf_sensor_get_usage() +{ + lprintf(LOG_NOTICE, "sensor get <id> ... [id]"); + lprintf(LOG_NOTICE, " id : name of desired sensor"); +} |