From 37cb538e5a1ce3bcc20f6d50d513002e1c583301 Mon Sep 17 00:00:00 2001 From: Carol Hebert Date: Thu, 29 Jan 2009 20:36:43 +0000 Subject: [PATCH] Holger Liebig patch (ID #1990560) to get readings from non-linear analog sensors --- ipmitool/include/ipmitool/ipmi_sensor.h | 2 +- ipmitool/lib/ipmi_sdr.c | 18 ++++--- ipmitool/lib/ipmi_sensor.c | 65 +++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/ipmitool/include/ipmitool/ipmi_sensor.h b/ipmitool/include/ipmitool/ipmi_sensor.h index 8c145cf..359d7c8 100644 --- a/ipmitool/include/ipmitool/ipmi_sensor.h +++ b/ipmitool/include/ipmitool/ipmi_sensor.h @@ -80,5 +80,5 @@ struct sensor_set_thresh_rq { int ipmi_sensor_main(struct ipmi_intf *, int, char **); int ipmi_sensor_print_full(struct ipmi_intf *, struct sdr_record_full_sensor *); int ipmi_sensor_print_compact(struct ipmi_intf *, struct sdr_record_compact_sensor *); - +int ipmi_sensor_get_sensor_reading_factors( struct ipmi_intf * intf, struct sdr_record_full_sensor * sensor, uint8_t reading); #endif /* IPMI_SENSOR_H */ diff --git a/ipmitool/lib/ipmi_sdr.c b/ipmitool/lib/ipmi_sdr.c index 1a7ae6f..df48442 100644 --- a/ipmitool/lib/ipmi_sdr.c +++ b/ipmitool/lib/ipmi_sdr.c @@ -1144,12 +1144,6 @@ ipmi_sdr_print_sensor_full(struct ipmi_intf *intf, memset(desc, 0, sizeof (desc)); snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string); - /* only handle linear sensors and linearized sensors (for now) */ - if (sensor->linearization >= SDR_SENSOR_L_NONLINEAR) { - printf("sensor %s non-linear!\n", desc); - return -1; - } - /* get sensor reading */ rsp = ipmi_sdr_get_sensor_reading_ipmb(intf, sensor->keys.sensor_num, sensor->keys.owner_id, sensor->keys.lun); @@ -1179,14 +1173,24 @@ ipmi_sdr_print_sensor_full(struct ipmi_intf *intf, validread = 0; if (rsp->data[0] != 0) { /* we might still get a valid reading */ + if (sensor->linearization>=SDR_SENSOR_L_NONLINEAR && sensor->linearization<=0x7F) + ipmi_sensor_get_sensor_reading_factors(intf, sensor, rsp->data[0]); val = sdr_convert_sensor_reading(sensor, rsp->data[0]); if (val != 0.0) validread = 1; } } else if (rsp->data[0] != 0) { + /* Non linear sensors might provide updated reading factors */ + if (sensor->linearization>=SDR_SENSOR_L_NONLINEAR && sensor->linearization<=0x7F) { + if (ipmi_sensor_get_sensor_reading_factors(intf, sensor, rsp->data[0]) < 0){ + validread = 0; + } + } /* convert RAW reading into units */ - val = sdr_convert_sensor_reading(sensor, rsp->data[0]); + if (rsp->data[0] != 0) { + val = sdr_convert_sensor_reading(sensor, rsp->data[0]); + } } } diff --git a/ipmitool/lib/ipmi_sensor.c b/ipmitool/lib/ipmi_sensor.c index 03284e7..c5ed3e3 100644 --- a/ipmitool/lib/ipmi_sensor.c +++ b/ipmitool/lib/ipmi_sensor.c @@ -46,6 +46,57 @@ extern int verbose; #define SCANNING_DISABLED 0x40 #define READING_UNAVAILABLE 0x20 +// 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->keys.sensor_num; + req_data[1] = reading; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + 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->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, @@ -188,11 +239,6 @@ ipmi_sensor_print_full_analog(struct ipmi_intf *intf, memset(id, 0, sizeof (id)); memcpy(id, sensor->id_string, 16); - /* only handle linear and linearized sensors (for now) */ - if (sensor->linearization >= SDR_SENSOR_L_NONLINEAR) { - printf("sensor %s non-linear!\n", id); - return -1; - } /* * Get current reading @@ -210,6 +256,15 @@ ipmi_sensor_print_full_analog(struct ipmi_intf *intf, } else if (!(rsp->data[1] & SCANNING_DISABLED)) { validread = 0; } else { + + /* Non linear sensors might provide updated reading factors */ + if (sensor->linearization>=SDR_SENSOR_L_NONLINEAR && sensor->linearization<=0x7F) { + if (ipmi_sensor_get_sensor_reading_factors(intf, sensor, rsp->data[0]) < 0){ + printf("sensor %s non-linear!\n", id); + return -1; + } + } + /* convert RAW reading into units */ val = (rsp->data[0] > 0) ? sdr_convert_sensor_reading(sensor, rsp->data[0])