summaryrefslogtreecommitdiffstats
path: root/sensorhandler.hpp
diff options
context:
space:
mode:
authorPatrick Venture <venture@google.com>2018-09-07 19:26:25 -0700
committerPatrick Venture <venture@google.com>2018-09-25 10:06:33 -0700
commit46470a38d0a3b8f29cd8efc4af8a76adcace524a (patch)
treec3e2df8b2a238889aabb14b6ba4efd76c4607364 /sensorhandler.hpp
parent87651333c451cfa8090273366be5ec62bd1a9eea (diff)
downloadphosphor-host-ipmid-46470a38d0a3b8f29cd8efc4af8a76adcace524a.tar.gz
phosphor-host-ipmid-46470a38d0a3b8f29cd8efc4af8a76adcace524a.zip
rename headers to match style
Moving headers from ".h" to ".hpp" Reworked the header inclusion a bit so that host-ipmid is treated as a library, and local headers aren't. renamed apphandler.h => apphandler.hpp renamed chassishandler.h => chassishandler.hpp renamed globalhandler.h => globalhandler.hpp renamed sensorhandler.h => sensorhandler.hpp renamed storageaddsel.h => storageaddsel.hpp renamed storagehandler.h => storagehandler.hpp renamed systemintfcmds.h => systemintfcmds.hpp Change-Id: I9d4ce3dd57e2e996800f9020a10cc10cdf2c3914 Signed-off-by: Patrick Venture <venture@google.com>
Diffstat (limited to 'sensorhandler.hpp')
-rw-r--r--sensorhandler.hpp639
1 files changed, 639 insertions, 0 deletions
diff --git a/sensorhandler.hpp b/sensorhandler.hpp
new file mode 100644
index 0000000..b32034f
--- /dev/null
+++ b/sensorhandler.hpp
@@ -0,0 +1,639 @@
+#pragma once
+
+#include "types.hpp"
+
+#include <host-ipmid/ipmid-api.h>
+#include <stdint.h>
+
+// IPMI commands for net functions.
+enum ipmi_netfn_sen_cmds
+{
+ IPMI_CMD_GET_DEVICE_SDR_INFO = 0x20,
+ IPMI_CMD_GET_DEVICE_SDR = 0x21,
+ IPMI_CMD_RESERVE_DEVICE_SDR_REPO = 0x22,
+ IPMI_CMD_GET_SENSOR_READING = 0x2D,
+ IPMI_CMD_GET_SENSOR_TYPE = 0x2F,
+ IPMI_CMD_SET_SENSOR = 0x30,
+ IPMI_CMD_GET_SENSOR_THRESHOLDS = 0x27,
+};
+
+/**
+ * @enum device_type
+ * IPMI FRU device types
+ */
+enum device_type
+{
+ IPMI_PHYSICAL_FRU = 0x00,
+ IPMI_LOGICAL_FRU = 0x80,
+};
+
+// Discrete sensor types.
+enum ipmi_sensor_types
+{
+ IPMI_SENSOR_TEMP = 0x01,
+ IPMI_SENSOR_VOLTAGE = 0x02,
+ IPMI_SENSOR_CURRENT = 0x03,
+ IPMI_SENSOR_FAN = 0x04,
+ IPMI_SENSOR_TPM = 0xCC,
+};
+
+#define MAX_DBUS_PATH 128
+struct dbus_interface_t
+{
+ uint8_t sensornumber;
+ uint8_t sensortype;
+
+ char bus[MAX_DBUS_PATH];
+ char path[MAX_DBUS_PATH];
+ char interface[MAX_DBUS_PATH];
+};
+
+int set_sensor_dbus_state_s(uint8_t, const char*, const char*);
+int set_sensor_dbus_state_y(uint8_t, const char*, const uint8_t);
+int find_openbmc_path(uint8_t, dbus_interface_t*);
+
+ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context);
+
+ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context);
+
+static const uint16_t FRU_RECORD_ID_START = 256;
+static const uint8_t SDR_VERSION = 0x51;
+static const uint16_t END_OF_RECORD = 0xFFFF;
+static const uint8_t LENGTH_MASK = 0x1F;
+
+/**
+ * Get SDR Info
+ */
+
+namespace get_sdr_info
+{
+namespace request
+{
+// Note: for some reason the ipmi_request_t appears to be the
+// raw value for this call.
+inline bool get_count(void* req)
+{
+ return (bool)((uint64_t)(req)&1);
+}
+} // namespace request
+
+namespace response
+{
+#define SDR_INFO_RESP_SIZE 2
+inline void set_lun_present(int lun, uint8_t* resp)
+{
+ *resp |= 1 << lun;
+}
+inline void set_lun_not_present(int lun, uint8_t* resp)
+{
+ *resp &= ~(1 << lun);
+}
+inline void set_dynamic_population(uint8_t* resp)
+{
+ *resp |= 1 << 7;
+}
+inline void set_static_population(uint8_t* resp)
+{
+ *resp &= ~(1 << 7);
+}
+} // namespace response
+
+struct GetSdrInfoResp
+{
+ uint8_t count;
+ uint8_t luns_and_dynamic_population;
+};
+
+} // namespace get_sdr_info
+
+/**
+ * Get SDR
+ */
+namespace get_sdr
+{
+
+struct GetSdrReq
+{
+ uint8_t reservation_id_lsb;
+ uint8_t reservation_id_msb;
+ uint8_t record_id_lsb;
+ uint8_t record_id_msb;
+ uint8_t offset;
+ uint8_t bytes_to_read;
+} __attribute__((packed));
+
+namespace request
+{
+
+inline uint8_t get_reservation_id(GetSdrReq* req)
+{
+ return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
+};
+
+inline uint16_t get_record_id(GetSdrReq* req)
+{
+ return (req->record_id_lsb + (req->record_id_msb << 8));
+};
+
+} // namespace request
+
+// Response
+struct GetSdrResp
+{
+ uint8_t next_record_id_lsb;
+ uint8_t next_record_id_msb;
+ uint8_t record_data[64];
+} __attribute__((packed));
+
+namespace response
+{
+
+inline void set_next_record_id(uint16_t next, GetSdrResp* resp)
+{
+ resp->next_record_id_lsb = next & 0xff;
+ resp->next_record_id_msb = (next >> 8) & 0xff;
+};
+
+} // namespace response
+
+// Record header
+struct SensorDataRecordHeader
+{
+ uint8_t record_id_lsb;
+ uint8_t record_id_msb;
+ uint8_t sdr_version;
+ uint8_t record_type;
+ uint8_t record_length; // Length not counting the header
+} __attribute__((packed));
+
+namespace header
+{
+
+inline void set_record_id(int id, SensorDataRecordHeader* hdr)
+{
+ hdr->record_id_lsb = (id & 0xFF);
+ hdr->record_id_msb = (id >> 8) & 0xFF;
+};
+
+} // namespace header
+
+enum SensorDataRecordType
+{
+ SENSOR_DATA_FULL_RECORD = 0x1,
+ SENSOR_DATA_FRU_RECORD = 0x11,
+};
+
+// Record key
+struct SensorDataRecordKey
+{
+ uint8_t owner_id;
+ uint8_t owner_lun;
+ uint8_t sensor_number;
+} __attribute__((packed));
+
+/** @struct SensorDataFruRecordKey
+ *
+ * FRU Device Locator Record(key) - SDR Type 11
+ */
+struct SensorDataFruRecordKey
+{
+ uint8_t deviceAddress;
+ uint8_t fruID;
+ uint8_t accessLun;
+ uint8_t channelNumber;
+} __attribute__((packed));
+
+namespace key
+{
+
+inline void set_owner_id_ipmb(SensorDataRecordKey* key)
+{
+ key->owner_id &= ~0x01;
+};
+
+inline void set_owner_id_system_sw(SensorDataRecordKey* key)
+{
+ key->owner_id |= 0x01;
+};
+
+inline void set_owner_id_bmc(SensorDataRecordKey* key)
+{
+ key->owner_id |= 0x20;
+};
+
+inline void set_owner_id_address(uint8_t addr, SensorDataRecordKey* key)
+{
+ key->owner_id &= 0x01;
+ key->owner_id |= addr << 1;
+};
+
+inline void set_owner_lun(uint8_t lun, SensorDataRecordKey* key)
+{
+ key->owner_lun &= ~0x03;
+ key->owner_lun |= (lun & 0x03);
+};
+
+inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
+{
+ key->owner_lun &= 0x0f;
+ key->owner_lun |= ((channel & 0xf) << 4);
+};
+
+} // namespace key
+
+/** @struct GetSensorThresholdsResponse
+ *
+ * Response structure for Get Sensor Thresholds command
+ */
+struct GetSensorThresholdsResponse
+{
+ uint8_t validMask; //!< valid mask
+ uint8_t lowerNonCritical; //!< lower non-critical threshold
+ uint8_t lowerCritical; //!< lower critical threshold
+ uint8_t lowerNonRecoverable; //!< lower non-recoverable threshold
+ uint8_t upperNonCritical; //!< upper non-critical threshold
+ uint8_t upperCritical; //!< upper critical threshold
+ uint8_t upperNonRecoverable; //!< upper non-recoverable threshold
+} __attribute__((packed));
+
+// Body - full record
+#define FULL_RECORD_ID_STR_MAX_LENGTH 16
+
+static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
+
+struct SensorDataFullRecordBody
+{
+ uint8_t entity_id;
+ uint8_t entity_instance;
+ uint8_t sensor_initialization;
+ uint8_t sensor_capabilities; // no macro support
+ uint8_t sensor_type;
+ uint8_t event_reading_type;
+ uint8_t supported_assertions[2]; // no macro support
+ uint8_t supported_deassertions[2]; // no macro support
+ uint8_t discrete_reading_setting_mask[2]; // no macro support
+ uint8_t sensor_units_1;
+ uint8_t sensor_units_2_base;
+ uint8_t sensor_units_3_modifier;
+ uint8_t linearization;
+ uint8_t m_lsb;
+ uint8_t m_msb_and_tolerance;
+ uint8_t b_lsb;
+ uint8_t b_msb_and_accuracy_lsb;
+ uint8_t accuracy_and_sensor_direction;
+ uint8_t r_b_exponents;
+ uint8_t analog_characteristic_flags; // no macro support
+ uint8_t nominal_reading;
+ uint8_t normal_max;
+ uint8_t normal_min;
+ uint8_t sensor_max;
+ uint8_t sensor_min;
+ uint8_t upper_nonrecoverable_threshold;
+ uint8_t upper_critical_threshold;
+ uint8_t upper_noncritical_threshold;
+ uint8_t lower_nonrecoverable_threshold;
+ uint8_t lower_critical_threshold;
+ uint8_t lower_noncritical_threshold;
+ uint8_t positive_threshold_hysteresis;
+ uint8_t negative_threshold_hysteresis;
+ uint16_t reserved;
+ uint8_t oem_reserved;
+ uint8_t id_string_info;
+ char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
+} __attribute__((packed));
+
+/** @struct SensorDataFruRecordBody
+ *
+ * FRU Device Locator Record(body) - SDR Type 11
+ */
+struct SensorDataFruRecordBody
+{
+ uint8_t reserved;
+ uint8_t deviceType;
+ uint8_t deviceTypeModifier;
+ uint8_t entityID;
+ uint8_t entityInstance;
+ uint8_t oem;
+ uint8_t deviceIDLen;
+ char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
+} __attribute__((packed));
+
+namespace body
+{
+
+inline void set_entity_instance_number(uint8_t n,
+ SensorDataFullRecordBody* body)
+{
+ body->entity_instance &= 1 << 7;
+ body->entity_instance |= (n & ~(1 << 7));
+};
+inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
+{
+ body->entity_instance &= ~(1 << 7);
+};
+inline void set_entity_logical_container(SensorDataFullRecordBody* body)
+{
+ body->entity_instance |= 1 << 7;
+};
+
+inline void sensor_scanning_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 0;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 0);
+ };
+};
+inline void event_generation_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 1;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 1);
+ }
+};
+inline void init_types_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 2;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 2);
+ }
+};
+inline void init_hyst_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 3;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 3);
+ }
+};
+inline void init_thresh_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 4;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 4);
+ }
+};
+inline void init_events_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 5;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 5);
+ }
+};
+inline void init_scanning_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 6;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 6);
+ }
+};
+inline void init_settable_state(bool enabled, SensorDataFullRecordBody* body)
+{
+ if (enabled)
+ {
+ body->sensor_initialization |= 1 << 7;
+ }
+ else
+ {
+ body->sensor_initialization &= ~(1 << 7);
+ }
+};
+
+inline void set_percentage(SensorDataFullRecordBody* body)
+{
+ body->sensor_units_1 |= 1 << 0;
+};
+inline void unset_percentage(SensorDataFullRecordBody* body)
+{
+ body->sensor_units_1 &= ~(1 << 0);
+};
+inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
+{
+ body->sensor_units_1 &= ~(3 << 1);
+ body->sensor_units_1 |= (op & 0x3) << 1;
+};
+inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
+{
+ body->sensor_units_1 &= ~(7 << 3);
+ body->sensor_units_1 |= (unit & 0x7) << 3;
+};
+inline void set_analog_data_format(uint8_t format,
+ SensorDataFullRecordBody* body)
+{
+ body->sensor_units_1 &= ~(3 << 6);
+ body->sensor_units_1 |= (format & 0x3) << 6;
+};
+
+inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
+{
+ body->m_lsb = m & 0xff;
+ body->m_msb_and_tolerance &= ~(3 << 6);
+ body->m_msb_and_tolerance |= ((m & (3 << 8)) >> 2);
+};
+inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
+{
+ body->m_msb_and_tolerance &= ~0x3f;
+ body->m_msb_and_tolerance |= tol & 0x3f;
+};
+
+inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
+{
+ body->b_lsb = b & 0xff;
+ body->b_msb_and_accuracy_lsb &= ~(3 << 6);
+ body->b_msb_and_accuracy_lsb |= ((b & (3 << 8)) >> 2);
+};
+inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
+{
+ // bottom 6 bits
+ body->b_msb_and_accuracy_lsb &= ~0x3f;
+ body->b_msb_and_accuracy_lsb |= acc & 0x3f;
+ // top 4 bits
+ body->accuracy_and_sensor_direction &= 0x0f;
+ body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
+};
+inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
+{
+ body->accuracy_and_sensor_direction &= ~(3 << 2);
+ body->accuracy_and_sensor_direction |= (exp & 3) << 2;
+};
+inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
+{
+ body->accuracy_and_sensor_direction &= ~(3 << 0);
+ body->accuracy_and_sensor_direction |= (dir & 3);
+};
+
+inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
+{
+ body->r_b_exponents &= 0xf0;
+ body->r_b_exponents |= exp & 0x0f;
+};
+inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
+{
+ body->r_b_exponents &= 0x0f;
+ body->r_b_exponents |= (exp & 0x0f) << 4;
+};
+
+inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
+{
+ body->id_string_info &= ~(0x1f);
+ body->id_string_info |= len & 0x1f;
+};
+inline uint8_t get_id_strlen(SensorDataFullRecordBody* body)
+{
+ return body->id_string_info & 0x1f;
+};
+inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
+{
+ body->id_string_info &= ~(3 << 6);
+ body->id_string_info |= (type & 0x3) << 6;
+};
+
+inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
+{
+ body->deviceIDLen &= ~(LENGTH_MASK);
+ body->deviceIDLen |= len & LENGTH_MASK;
+};
+
+inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
+{
+ return body->deviceIDLen & LENGTH_MASK;
+};
+
+inline void set_readable_mask(uint8_t mask, SensorDataFullRecordBody* body)
+{
+ body->discrete_reading_setting_mask[1] = mask & 0x3F;
+}
+
+} // namespace body
+
+// More types contained in section 43.17 Sensor Unit Type Codes,
+// IPMI spec v2 rev 1.1
+enum SensorUnitTypeCodes
+{
+ SENSOR_UNIT_UNSPECIFIED = 0,
+ SENSOR_UNIT_DEGREES_C = 1,
+ SENSOR_UNIT_VOLTS = 4,
+ SENSOR_UNIT_AMPERES = 5,
+ SENSOR_UNIT_WATTS = 6,
+ SENSOR_UNIT_JOULES = 7,
+ SENSOR_UNIT_METERS = 34,
+ SENSOR_UNIT_REVOLUTIONS = 41,
+};
+
+struct SensorDataFullRecord
+{
+ SensorDataRecordHeader header;
+ SensorDataRecordKey key;
+ SensorDataFullRecordBody body;
+} __attribute__((packed));
+
+/** @struct SensorDataFruRecord
+ *
+ * FRU Device Locator Record - SDR Type 11
+ */
+struct SensorDataFruRecord
+{
+ SensorDataRecordHeader header;
+ SensorDataFruRecordKey key;
+ SensorDataFruRecordBody body;
+} __attribute__((packed));
+
+} // namespace get_sdr
+
+namespace ipmi
+{
+
+namespace sensor
+{
+
+/**
+ * @brief Map offset to the corresponding bit in the assertion byte.
+ *
+ * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
+ * byte and offsets 8-14 in the second byte.
+ *
+ * @param[in] offset - offset number.
+ * @param[in/out] resp - get sensor reading response.
+ */
+inline void setOffset(uint8_t offset, ipmi::sensor::GetReadingResponse* resp)
+{
+ if (offset > 7)
+ {
+ resp->assertOffset8_14 |= 1 << (offset - 8);
+ }
+ else
+ {
+ resp->assertOffset0_7 |= 1 << offset;
+ }
+}
+
+/**
+ * @brief Set the reading field in the response.
+ *
+ * @param[in] offset - offset number.
+ * @param[in/out] resp - get sensor reading response.
+ */
+inline void setReading(uint8_t value, ipmi::sensor::GetReadingResponse* resp)
+{
+ resp->reading = value;
+}
+
+/**
+ * @brief Map the value to the assertion bytes. The assertion states are stored
+ * in 2 bytes.
+ *
+ * @param[in] value - value to mapped to the assertion byte.
+ * @param[in/out] resp - get sensor reading response.
+ */
+inline void setAssertionBytes(uint16_t value,
+ ipmi::sensor::GetReadingResponse* resp)
+{
+ resp->assertOffset0_7 = static_cast<uint8_t>(value & 0x00FF);
+ resp->assertOffset8_14 = static_cast<uint8_t>(value >> 8);
+}
+
+/**
+ * @brief Set the scanning enabled bit in the response.
+ *
+ * @param[in/out] resp - get sensor reading response.
+ */
+inline void enableScanning(ipmi::sensor::GetReadingResponse* resp)
+{
+ resp->operation = 1 << 6;
+}
+
+} // namespace sensor
+
+} // namespace ipmi
OpenPOWER on IntegriCloud