blob: 1cf43ca93d0830bf69f0cd8f514b8f05d548792e [file] [log] [blame]
Chris Austenac4604a2015-10-13 12:43:27 -05001#ifndef __HOST_IPMI_SEN_HANDLER_H__
2#define __HOST_IPMI_SEN_HANDLER_H__
3
Chris Austen0012e9b2015-10-22 01:37:46 -05004#include <stdint.h>
Tom Joseph816e92b2017-09-06 19:23:00 +05305#include "types.hpp"
Chris Austen0012e9b2015-10-22 01:37:46 -05006
Chris Austenac4604a2015-10-13 12:43:27 -05007// IPMI commands for net functions.
8enum ipmi_netfn_sen_cmds
9{
Emily Shafferd06e0e72017-04-05 09:08:57 -070010 IPMI_CMD_GET_SDR_INFO = 0x20,
Emily Shafferbbef71c2017-05-08 16:36:17 -070011 IPMI_CMD_GET_SDR = 0x21,
Emily Shaffera344afc2017-04-13 15:09:39 -070012 IPMI_CMD_RESERVE_SDR_REPO = 0x22,
Chris Austen10ccc0f2015-12-10 18:27:04 -060013 IPMI_CMD_GET_SENSOR_READING = 0x2D,
Emily Shafferd06e0e72017-04-05 09:08:57 -070014 IPMI_CMD_GET_SENSOR_TYPE = 0x2F,
15 IPMI_CMD_SET_SENSOR = 0x30,
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -060016 IPMI_CMD_GET_SENSOR_THRESHOLDS = 0x27,
Chris Austenac4604a2015-10-13 12:43:27 -050017};
18
Emily Shaffer1fabf222017-04-05 08:53:21 -070019// Discrete sensor types.
20enum ipmi_sensor_types
21{
22 IPMI_SENSOR_TEMP = 0x01,
23 IPMI_SENSOR_VOLTAGE = 0x02,
24 IPMI_SENSOR_CURRENT = 0x03,
25 IPMI_SENSOR_FAN = 0x04,
Tom Joseph60cac722017-08-18 12:06:07 +053026 IPMI_SENSOR_TPM = 0xCC,
Emily Shaffer1fabf222017-04-05 08:53:21 -070027};
28
Chris Austen0012e9b2015-10-22 01:37:46 -050029#define MAX_DBUS_PATH 128
30struct dbus_interface_t {
31 uint8_t sensornumber;
32 uint8_t sensortype;
33
34 char bus[MAX_DBUS_PATH];
35 char path[MAX_DBUS_PATH];
36 char interface[MAX_DBUS_PATH];
37};
Tomd700e762016-09-20 18:24:13 +053038
39int set_sensor_dbus_state_s(uint8_t , const char *, const char *);
40int set_sensor_dbus_state_y(uint8_t , const char *, const uint8_t);
Emily Shaffer2ae09b92017-04-05 15:09:41 -070041int find_openbmc_path(uint8_t , dbus_interface_t *);
Tom05732372016-09-06 17:21:23 +053042
Tom Josephbe703f72017-03-09 12:34:35 +053043/**
Emily Shafferd06e0e72017-04-05 09:08:57 -070044 * Get SDR Info
45 */
46
47namespace get_sdr_info
48{
49namespace request
50{
51// Note: for some reason the ipmi_request_t appears to be the
52// raw value for this call.
53inline bool get_count(void* req)
54{
55 return (bool)((uint64_t)(req) & 1);
56}
57} // namespace request
58
59namespace response
60{
61#define SDR_INFO_RESP_SIZE 2
62inline void set_lun_present(int lun, uint8_t* resp)
63{
64 *resp |= 1 << lun;
65}
66inline void set_lun_not_present(int lun, uint8_t* resp)
67{
68 *resp &= ~(1 << lun);
69}
70inline void set_dynamic_population(uint8_t* resp)
71{
72 *resp |= 1 << 7;
73}
74inline void set_static_population(uint8_t* resp)
75{
76 *resp &= ~(1 << 7);
77}
78} // namespace response
79
80struct GetSdrInfoResp
81{
82 uint8_t count;
83 uint8_t luns_and_dynamic_population;
84};
85
86} // namespace get_sdr_info
Emily Shafferbbef71c2017-05-08 16:36:17 -070087
88/**
89 * Get SDR
90 */
91namespace get_sdr
92{
93
94struct GetSdrReq
95{
96 uint8_t reservation_id_lsb;
97 uint8_t reservation_id_msb;
98 uint8_t record_id_lsb;
99 uint8_t record_id_msb;
100 uint8_t offset;
101 uint8_t bytes_to_read;
102} __attribute__((packed));
103
104namespace request
105{
106
107inline uint8_t get_reservation_id(GetSdrReq* req)
108{
109 return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
110};
111
112inline uint8_t get_record_id(GetSdrReq* req)
113{
114 return (req->record_id_lsb + (req->record_id_msb << 8));
115};
116
117} // namespace request
118
119// Response
120struct GetSdrResp
121{
122 uint8_t next_record_id_lsb;
123 uint8_t next_record_id_msb;
124 uint8_t record_data[64];
125} __attribute__((packed));
126
127namespace response
128{
129
130inline void set_next_record_id(int next, GetSdrResp* resp)
131{
132 resp->next_record_id_lsb = next & 0xff;
133 resp->next_record_id_msb = (next >> 8) & 0xff;
134};
135
136} // namespace response
137
138// Record header
139struct SensorDataRecordHeader
140{
141 uint8_t record_id_lsb;
142 uint8_t record_id_msb;
143 uint8_t sdr_version;
144 uint8_t record_type;
145 uint8_t record_length; // Length not counting the header
146} __attribute__((packed));
147
148namespace header
149{
150
151inline void set_record_id(int id, SensorDataRecordHeader* hdr)
152{
153 hdr->record_id_lsb = (id & 0xFF);
154 hdr->record_id_msb = (id >> 8) & 0xFF;
155};
156
157} // namespace header
158
159enum SensorDataRecordType
160{
161 SENSOR_DATA_FULL_RECORD = 1,
162};
163
164// Record key
165struct SensorDataRecordKey
166{
167 uint8_t owner_id;
168 uint8_t owner_lun;
169 uint8_t sensor_number;
170} __attribute__((packed));
171
172namespace key
173{
174
175inline void set_owner_id_ipmb(SensorDataRecordKey* key)
176{
177 key->owner_id &= ~0x01;
178};
179
180inline void set_owner_id_system_sw(SensorDataRecordKey* key)
181{
182 key->owner_id |= 0x01;
183};
184
Tom Joseph96423912018-01-25 00:14:34 +0530185inline void set_owner_id_bmc(SensorDataRecordKey* key)
186{
187 key->owner_id |= 0x20;
188};
189
Emily Shafferbbef71c2017-05-08 16:36:17 -0700190inline void set_owner_id_address(uint8_t addr, SensorDataRecordKey* key)
191{
192 key->owner_id &= 0x01;
193 key->owner_id |= addr<<1;
194};
195
196inline void set_owner_lun(uint8_t lun, SensorDataRecordKey* key)
197{
198 key->owner_lun &= ~0x03;
199 key->owner_lun |= (lun&0x03);
200};
201
202inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
203{
204 key->owner_lun &= 0x0f;
205 key->owner_lun |= ((channel & 0xf)<<4);
206};
207
208} // namespace key
209
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600210/** @struct GetSensorThresholdsResponse
211 *
212 * Response structure for Get Sensor Thresholds command
213 */
214struct GetSensorThresholdsResponse
215{
216 uint8_t validMask; //Indicates which values are valid
217 uint8_t data[6]; //Container for threshold values
218} __attribute__((packed));
219
Emily Shafferbbef71c2017-05-08 16:36:17 -0700220// Body - full record
221#define FULL_RECORD_ID_STR_MAX_LENGTH 16
222struct SensorDataFullRecordBody
223{
224 uint8_t entity_id;
225 uint8_t entity_instance;
226 uint8_t sensor_initialization;
227 uint8_t sensor_capabilities; // no macro support
228 uint8_t sensor_type;
229 uint8_t event_reading_type;
230 uint8_t supported_assertions[2]; // no macro support
231 uint8_t supported_deassertions[2]; // no macro support
232 uint8_t discrete_reading_setting_mask[2]; // no macro support
233 uint8_t sensor_units_1;
234 uint8_t sensor_units_2_base;
235 uint8_t sensor_units_3_modifier;
236 uint8_t linearization;
237 uint8_t m_lsb;
238 uint8_t m_msb_and_tolerance;
239 uint8_t b_lsb;
240 uint8_t b_msb_and_accuracy_lsb;
241 uint8_t accuracy_and_sensor_direction;
242 uint8_t r_b_exponents;
243 uint8_t analog_characteristic_flags; //no macro support
244 uint8_t nominal_reading;
245 uint8_t normal_max;
246 uint8_t normal_min;
247 uint8_t sensor_max;
248 uint8_t sensor_min;
249 uint8_t upper_nonrecoverable_threshold;
250 uint8_t upper_critical_threshold;
251 uint8_t upper_noncritical_threshold;
252 uint8_t lower_nonrecoverable_threshold;
253 uint8_t lower_critical_threshold;
254 uint8_t lower_noncritical_threshold;
255 uint8_t positive_threshold_hysteresis;
256 uint8_t negative_threshold_hysteresis;
257 uint16_t reserved;
258 uint8_t oem_reserved;
259 uint8_t id_string_info;
Emily Shaffer10f49592017-05-10 12:01:10 -0700260 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
Emily Shafferbbef71c2017-05-08 16:36:17 -0700261} __attribute__((packed));
262
263namespace body
264{
265
266inline void set_entity_instance_number(uint8_t n,
267 SensorDataFullRecordBody* body)
268{
269 body->entity_instance &= 1<<7;
270 body->entity_instance |= (n & ~(1<<7));
271};
272inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
273{
274 body->entity_instance &= ~(1<<7);
275};
276inline void set_entity_logical_container(SensorDataFullRecordBody* body)
277{
278 body->entity_instance |= 1<<7;
279};
280
281inline void sensor_scanning_state(bool enabled,
282 SensorDataFullRecordBody* body)
283{
284 if (enabled)
285 {
286 body->sensor_initialization |= 1<<0;
287 }
288 else
289 {
290 body->sensor_initialization &= ~(1<<0);
291 };
292};
293inline void event_generation_state(bool enabled,
294 SensorDataFullRecordBody* body)
295{
296 if (enabled)
297 {
298 body->sensor_initialization |= 1<<1;
299 }
300 else
301 {
302 body->sensor_initialization &= ~(1<<1);
303 }
304};
305inline void init_types_state(bool enabled,
306 SensorDataFullRecordBody* body)
307{
308 if (enabled)
309 {
310 body->sensor_initialization |= 1<<2;
311 }
312 else
313 {
314 body->sensor_initialization &= ~(1<<2);
315 }
316};
317inline void init_hyst_state(bool enabled,
318 SensorDataFullRecordBody* body)
319{
320 if (enabled)
321 {
322 body->sensor_initialization |= 1<<3;
323 }
324 else
325 {
326 body->sensor_initialization &= ~(1<<3);
327 }
328};
329inline void init_thresh_state(bool enabled,
330 SensorDataFullRecordBody* body)
331{
332 if (enabled)
333 {
334 body->sensor_initialization |= 1<<4;
335 }
336 else
337 {
338 body->sensor_initialization &= ~(1<<4);
339 }
340};
341inline void init_events_state(bool enabled,
342 SensorDataFullRecordBody* body)
343{
344 if (enabled)
345 {
346 body->sensor_initialization |= 1<<5;
347 }
348 else
349 {
350 body->sensor_initialization &= ~(1<<5);
351 }
352};
353inline void init_scanning_state(bool enabled,
354 SensorDataFullRecordBody* body)
355{
356 if (enabled)
357 {
358 body->sensor_initialization |= 1<<6;
359 }
360 else
361 {
362 body->sensor_initialization &= ~(1<<6);
363 }
364};
365inline void init_settable_state(bool enabled,
366 SensorDataFullRecordBody* body)
367{
368 if (enabled)
369 {
370 body->sensor_initialization |= 1<<7;
371 }
372 else
373 {
374 body->sensor_initialization &= ~(1<<7);
375 }
376};
377
378inline void set_percentage(SensorDataFullRecordBody* body)
379{
380 body->sensor_units_1 |= 1<<0;
381};
382inline void unset_percentage(SensorDataFullRecordBody* body)
383{
384 body->sensor_units_1 &= ~(1<<0);
385};
386inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
387{
388 body->sensor_units_1 &= ~(3<<1);
389 body->sensor_units_1 |= (op & 0x3)<<1;
390};
391inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
392{
393 body->sensor_units_1 &= ~(7<<3);
394 body->sensor_units_1 |= (unit & 0x7)<<3;
395};
396inline void set_analog_data_format(uint8_t format,
397 SensorDataFullRecordBody* body)
398{
399 body->sensor_units_1 &= ~(3<<6);
400 body->sensor_units_1 |= (format & 0x3)<<6;
401};
402
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700403inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700404{
405 body->m_lsb = m & 0xff;
406 body->m_msb_and_tolerance &= ~(3<<6);
407 body->m_msb_and_tolerance |= ((m & (3<<8)) >> 2);
408};
409inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
410{
411 body->m_msb_and_tolerance &= ~0x3f;
412 body->m_msb_and_tolerance |= tol & 0x3f;
413};
414
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700415inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700416{
417 body->b_lsb = b & 0xff;
418 body->b_msb_and_accuracy_lsb &= ~(3<<6);
419 body->b_msb_and_accuracy_lsb |= ((b & (3<<8)) >> 2);
420};
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700421inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700422{
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700423 // bottom 6 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700424 body->b_msb_and_accuracy_lsb &= ~0x3f;
425 body->b_msb_and_accuracy_lsb |= acc & 0x3f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700426 // top 4 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700427 body->accuracy_and_sensor_direction &= 0x0f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700428 body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
Emily Shafferbbef71c2017-05-08 16:36:17 -0700429};
430inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
431{
432 body->accuracy_and_sensor_direction &= ~(3<<2);
433 body->accuracy_and_sensor_direction |= (exp & 3)<<2;
434};
435inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
436{
437 body->accuracy_and_sensor_direction &= ~(3<<0);
438 body->accuracy_and_sensor_direction |= (dir & 3);
439};
440
441inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
442{
443 body->r_b_exponents &= 0xf0;
444 body->r_b_exponents |= exp & 0x0f;
445};
446inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
447{
448 body->r_b_exponents &= 0x0f;
449 body->r_b_exponents |= (exp & 0x0f)<<4;
450};
451
452inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
453{
454 body->id_string_info &= ~(0x1f);
455 body->id_string_info |= len & 0x1f;
456};
457inline uint8_t get_id_strlen( SensorDataFullRecordBody* body)
458{
459 return body->id_string_info & 0x1f;
460};
461inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
462{
463 body->id_string_info &= ~(3<<6);
464 body->id_string_info |= (type & 0x3)<<6;
465};
466
467} // namespace body
468
469// More types contained in section 43.17 Sensor Unit Type Codes,
470// IPMI spec v2 rev 1.1
471enum SensorUnitTypeCodes
472{
473 SENSOR_UNIT_UNSPECIFIED = 0,
474 SENSOR_UNIT_DEGREES_C = 1,
475 SENSOR_UNIT_VOLTS = 4,
476 SENSOR_UNIT_AMPERES = 5,
477 SENSOR_UNIT_JOULES = 7,
478 SENSOR_UNIT_METERS = 34,
479 SENSOR_UNIT_REVOLUTIONS = 41,
480};
481
482struct SensorDataFullRecord
483{
484 SensorDataRecordHeader header;
485 SensorDataRecordKey key;
486 SensorDataFullRecordBody body;
487} __attribute__((packed));
488
489} // get_sdr
Tom Joseph816e92b2017-09-06 19:23:00 +0530490
491namespace ipmi
492{
493
494namespace sensor
495{
496
497/**
498 * @brief Map offset to the corresponding bit in the assertion byte.
499 *
Gunnar Mills8991dd62017-10-25 17:11:29 -0500500 * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
Tom Joseph816e92b2017-09-06 19:23:00 +0530501 * byte and offsets 8-14 in the second byte.
502 *
503 * @param[in] offset - offset number.
504 * @param[in/out] resp - get sensor reading response.
505 */
506inline void setOffset(uint8_t offset, ipmi::sensor::GetReadingResponse* resp)
507{
508 if (offset > 7)
509 {
510 resp->assertOffset8_14 |= 1 << (offset - 8);
511 }
512 else
513 {
514 resp->assertOffset0_7 |= 1 << offset;
515 }
516}
517
Tom Josephe4014fc2017-09-06 23:57:36 +0530518/**
519 * @brief Set the reading field in the response.
520 *
521 * @param[in] offset - offset number.
522 * @param[in/out] resp - get sensor reading response.
523 */
524inline void setReading(uint8_t value, ipmi::sensor::GetReadingResponse* resp)
525{
526 resp->reading = value;
527}
528
Tom Joseph295f17e2017-09-07 00:09:46 +0530529/**
530 * @brief Map the value to the assertion bytes. The assertion states are stored
531 * in 2 bytes.
532 *
533 * @param[in] value - value to mapped to the assertion byte.
534 * @param[in/out] resp - get sensor reading response.
535 */
536inline void setAssertionBytes(uint16_t value,
537 ipmi::sensor::GetReadingResponse* resp)
538{
539 resp->assertOffset0_7 = static_cast<uint8_t>(value & 0x00FF);
540 resp->assertOffset8_14 = static_cast<uint8_t>(value >> 8);
541}
542
Tom Josephe05b2922017-09-07 00:43:16 +0530543/**
544 * @brief Set the scanning enabled bit in the response.
545 *
546 * @param[in/out] resp - get sensor reading response.
547 */
548inline void enableScanning(ipmi::sensor::GetReadingResponse* resp)
549{
550 resp->operation = 1 << 6;
551}
552
Tom Joseph816e92b2017-09-06 19:23:00 +0530553} // namespace sensor
554
555} // namespace ipmi
Chris Austenac4604a2015-10-13 12:43:27 -0500556#endif