blob: 4dd079da795b2fd94def7e582a08b7e347aa5d41 [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
Ratan Guptae0cc8552018-01-22 14:23:04 +053019/**
20 * @enum device_type
21 * IPMI FRU device types
22 */
23enum device_type
24{
25 IPMI_PHYSICAL_FRU = 0x00,
26 IPMI_LOGICAL_FRU = 0x80,
27};
28
Emily Shaffer1fabf222017-04-05 08:53:21 -070029// Discrete sensor types.
30enum ipmi_sensor_types
31{
32 IPMI_SENSOR_TEMP = 0x01,
33 IPMI_SENSOR_VOLTAGE = 0x02,
34 IPMI_SENSOR_CURRENT = 0x03,
35 IPMI_SENSOR_FAN = 0x04,
Tom Joseph60cac722017-08-18 12:06:07 +053036 IPMI_SENSOR_TPM = 0xCC,
Emily Shaffer1fabf222017-04-05 08:53:21 -070037};
38
Chris Austen0012e9b2015-10-22 01:37:46 -050039#define MAX_DBUS_PATH 128
40struct dbus_interface_t {
41 uint8_t sensornumber;
42 uint8_t sensortype;
43
44 char bus[MAX_DBUS_PATH];
45 char path[MAX_DBUS_PATH];
46 char interface[MAX_DBUS_PATH];
47};
Tomd700e762016-09-20 18:24:13 +053048
49int set_sensor_dbus_state_s(uint8_t , const char *, const char *);
50int set_sensor_dbus_state_y(uint8_t , const char *, const uint8_t);
Emily Shaffer2ae09b92017-04-05 15:09:41 -070051int find_openbmc_path(uint8_t , dbus_interface_t *);
Tom05732372016-09-06 17:21:23 +053052
Ratan Guptae0cc8552018-01-22 14:23:04 +053053static const uint16_t FRU_RECORD_ID_START = 256;
54static const uint8_t SDR_VERSION = 0x51;
55static const uint16_t END_OF_RECORD = 0xFFFF;
56static const uint8_t LENGTH_MASK = 0x1F;
57
Tom Josephbe703f72017-03-09 12:34:35 +053058/**
Emily Shafferd06e0e72017-04-05 09:08:57 -070059 * Get SDR Info
60 */
61
62namespace get_sdr_info
63{
64namespace request
65{
66// Note: for some reason the ipmi_request_t appears to be the
67// raw value for this call.
68inline bool get_count(void* req)
69{
70 return (bool)((uint64_t)(req) & 1);
71}
72} // namespace request
73
74namespace response
75{
76#define SDR_INFO_RESP_SIZE 2
77inline void set_lun_present(int lun, uint8_t* resp)
78{
79 *resp |= 1 << lun;
80}
81inline void set_lun_not_present(int lun, uint8_t* resp)
82{
83 *resp &= ~(1 << lun);
84}
85inline void set_dynamic_population(uint8_t* resp)
86{
87 *resp |= 1 << 7;
88}
89inline void set_static_population(uint8_t* resp)
90{
91 *resp &= ~(1 << 7);
92}
93} // namespace response
94
95struct GetSdrInfoResp
96{
97 uint8_t count;
98 uint8_t luns_and_dynamic_population;
99};
100
101} // namespace get_sdr_info
Emily Shafferbbef71c2017-05-08 16:36:17 -0700102
103/**
104 * Get SDR
105 */
106namespace get_sdr
107{
108
109struct GetSdrReq
110{
111 uint8_t reservation_id_lsb;
112 uint8_t reservation_id_msb;
113 uint8_t record_id_lsb;
114 uint8_t record_id_msb;
115 uint8_t offset;
116 uint8_t bytes_to_read;
117} __attribute__((packed));
118
119namespace request
120{
121
122inline uint8_t get_reservation_id(GetSdrReq* req)
123{
124 return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
125};
126
Ratan Guptae0cc8552018-01-22 14:23:04 +0530127inline uint16_t get_record_id(GetSdrReq* req)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700128{
129 return (req->record_id_lsb + (req->record_id_msb << 8));
130};
131
132} // namespace request
133
134// Response
135struct GetSdrResp
136{
137 uint8_t next_record_id_lsb;
138 uint8_t next_record_id_msb;
139 uint8_t record_data[64];
140} __attribute__((packed));
141
142namespace response
143{
144
Ratan Guptae0cc8552018-01-22 14:23:04 +0530145inline void set_next_record_id(uint16_t next, GetSdrResp* resp)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700146{
147 resp->next_record_id_lsb = next & 0xff;
148 resp->next_record_id_msb = (next >> 8) & 0xff;
149};
150
151} // namespace response
152
153// Record header
154struct SensorDataRecordHeader
155{
156 uint8_t record_id_lsb;
157 uint8_t record_id_msb;
158 uint8_t sdr_version;
159 uint8_t record_type;
160 uint8_t record_length; // Length not counting the header
161} __attribute__((packed));
162
163namespace header
164{
165
166inline void set_record_id(int id, SensorDataRecordHeader* hdr)
167{
168 hdr->record_id_lsb = (id & 0xFF);
169 hdr->record_id_msb = (id >> 8) & 0xFF;
170};
171
172} // namespace header
173
174enum SensorDataRecordType
175{
Ratan Guptae0cc8552018-01-22 14:23:04 +0530176 SENSOR_DATA_FULL_RECORD = 0x1,
177 SENSOR_DATA_FRU_RECORD = 0x11,
Emily Shafferbbef71c2017-05-08 16:36:17 -0700178};
179
180// Record key
181struct SensorDataRecordKey
182{
183 uint8_t owner_id;
184 uint8_t owner_lun;
185 uint8_t sensor_number;
186} __attribute__((packed));
187
Ratan Guptae0cc8552018-01-22 14:23:04 +0530188/** @struct SensorDataFruRecordKey
189 *
190 * FRU Device Locator Record(key) - SDR Type 11
191 */
192struct SensorDataFruRecordKey
193{
194 uint8_t deviceAddress;
195 uint8_t fruID;
196 uint8_t accessLun;
197 uint8_t channelNumber;
198} __attribute__((packed));
199
Emily Shafferbbef71c2017-05-08 16:36:17 -0700200namespace key
201{
202
203inline void set_owner_id_ipmb(SensorDataRecordKey* key)
204{
205 key->owner_id &= ~0x01;
206};
207
208inline void set_owner_id_system_sw(SensorDataRecordKey* key)
209{
210 key->owner_id |= 0x01;
211};
212
Tom Joseph96423912018-01-25 00:14:34 +0530213inline void set_owner_id_bmc(SensorDataRecordKey* key)
214{
215 key->owner_id |= 0x20;
216};
217
Emily Shafferbbef71c2017-05-08 16:36:17 -0700218inline void set_owner_id_address(uint8_t addr, SensorDataRecordKey* key)
219{
220 key->owner_id &= 0x01;
221 key->owner_id |= addr<<1;
222};
223
224inline void set_owner_lun(uint8_t lun, SensorDataRecordKey* key)
225{
226 key->owner_lun &= ~0x03;
227 key->owner_lun |= (lun&0x03);
228};
229
230inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
231{
232 key->owner_lun &= 0x0f;
233 key->owner_lun |= ((channel & 0xf)<<4);
234};
235
236} // namespace key
237
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600238/** @struct GetSensorThresholdsResponse
239 *
240 * Response structure for Get Sensor Thresholds command
241 */
242struct GetSensorThresholdsResponse
243{
Tom Joseph0ac0dd22018-02-16 09:14:45 +0530244 uint8_t validMask; //!< valid mask
245 uint8_t lowerNonCritical; //!< lower non-critical threshold
246 uint8_t lowerCritical; //!< lower critical threshold
247 uint8_t lowerNonRecoverable;//!< lower non-recoverable threshold
248 uint8_t upperNonCritical; //!< upper non-critical threshold
249 uint8_t upperCritical; //!< upper critical threshold
250 uint8_t upperNonRecoverable;//!< upper non-recoverable threshold
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600251} __attribute__((packed));
252
Emily Shafferbbef71c2017-05-08 16:36:17 -0700253// Body - full record
254#define FULL_RECORD_ID_STR_MAX_LENGTH 16
Ratan Guptae0cc8552018-01-22 14:23:04 +0530255
256static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
257
Emily Shafferbbef71c2017-05-08 16:36:17 -0700258struct SensorDataFullRecordBody
259{
260 uint8_t entity_id;
261 uint8_t entity_instance;
262 uint8_t sensor_initialization;
263 uint8_t sensor_capabilities; // no macro support
264 uint8_t sensor_type;
265 uint8_t event_reading_type;
266 uint8_t supported_assertions[2]; // no macro support
267 uint8_t supported_deassertions[2]; // no macro support
268 uint8_t discrete_reading_setting_mask[2]; // no macro support
269 uint8_t sensor_units_1;
270 uint8_t sensor_units_2_base;
271 uint8_t sensor_units_3_modifier;
272 uint8_t linearization;
273 uint8_t m_lsb;
274 uint8_t m_msb_and_tolerance;
275 uint8_t b_lsb;
276 uint8_t b_msb_and_accuracy_lsb;
277 uint8_t accuracy_and_sensor_direction;
278 uint8_t r_b_exponents;
279 uint8_t analog_characteristic_flags; //no macro support
280 uint8_t nominal_reading;
281 uint8_t normal_max;
282 uint8_t normal_min;
283 uint8_t sensor_max;
284 uint8_t sensor_min;
285 uint8_t upper_nonrecoverable_threshold;
286 uint8_t upper_critical_threshold;
287 uint8_t upper_noncritical_threshold;
288 uint8_t lower_nonrecoverable_threshold;
289 uint8_t lower_critical_threshold;
290 uint8_t lower_noncritical_threshold;
291 uint8_t positive_threshold_hysteresis;
292 uint8_t negative_threshold_hysteresis;
293 uint16_t reserved;
294 uint8_t oem_reserved;
295 uint8_t id_string_info;
Emily Shaffer10f49592017-05-10 12:01:10 -0700296 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
Emily Shafferbbef71c2017-05-08 16:36:17 -0700297} __attribute__((packed));
298
Ratan Guptae0cc8552018-01-22 14:23:04 +0530299/** @struct SensorDataFruRecordBody
300 *
301 * FRU Device Locator Record(body) - SDR Type 11
302 */
303struct SensorDataFruRecordBody
304{
305 uint8_t reserved;
306 uint8_t deviceType;
307 uint8_t deviceTypeModifier;
308 uint8_t entityID;
309 uint8_t entityInstance;
310 uint8_t oem;
311 uint8_t deviceIDLen;
312 char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
313} __attribute__((packed));
314
Emily Shafferbbef71c2017-05-08 16:36:17 -0700315namespace body
316{
317
318inline void set_entity_instance_number(uint8_t n,
319 SensorDataFullRecordBody* body)
320{
321 body->entity_instance &= 1<<7;
322 body->entity_instance |= (n & ~(1<<7));
323};
324inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
325{
326 body->entity_instance &= ~(1<<7);
327};
328inline void set_entity_logical_container(SensorDataFullRecordBody* body)
329{
330 body->entity_instance |= 1<<7;
331};
332
333inline void sensor_scanning_state(bool enabled,
334 SensorDataFullRecordBody* body)
335{
336 if (enabled)
337 {
338 body->sensor_initialization |= 1<<0;
339 }
340 else
341 {
342 body->sensor_initialization &= ~(1<<0);
343 };
344};
345inline void event_generation_state(bool enabled,
346 SensorDataFullRecordBody* body)
347{
348 if (enabled)
349 {
350 body->sensor_initialization |= 1<<1;
351 }
352 else
353 {
354 body->sensor_initialization &= ~(1<<1);
355 }
356};
357inline void init_types_state(bool enabled,
358 SensorDataFullRecordBody* body)
359{
360 if (enabled)
361 {
362 body->sensor_initialization |= 1<<2;
363 }
364 else
365 {
366 body->sensor_initialization &= ~(1<<2);
367 }
368};
369inline void init_hyst_state(bool enabled,
370 SensorDataFullRecordBody* body)
371{
372 if (enabled)
373 {
374 body->sensor_initialization |= 1<<3;
375 }
376 else
377 {
378 body->sensor_initialization &= ~(1<<3);
379 }
380};
381inline void init_thresh_state(bool enabled,
382 SensorDataFullRecordBody* body)
383{
384 if (enabled)
385 {
386 body->sensor_initialization |= 1<<4;
387 }
388 else
389 {
390 body->sensor_initialization &= ~(1<<4);
391 }
392};
393inline void init_events_state(bool enabled,
394 SensorDataFullRecordBody* body)
395{
396 if (enabled)
397 {
398 body->sensor_initialization |= 1<<5;
399 }
400 else
401 {
402 body->sensor_initialization &= ~(1<<5);
403 }
404};
405inline void init_scanning_state(bool enabled,
406 SensorDataFullRecordBody* body)
407{
408 if (enabled)
409 {
410 body->sensor_initialization |= 1<<6;
411 }
412 else
413 {
414 body->sensor_initialization &= ~(1<<6);
415 }
416};
417inline void init_settable_state(bool enabled,
418 SensorDataFullRecordBody* body)
419{
420 if (enabled)
421 {
422 body->sensor_initialization |= 1<<7;
423 }
424 else
425 {
426 body->sensor_initialization &= ~(1<<7);
427 }
428};
429
430inline void set_percentage(SensorDataFullRecordBody* body)
431{
432 body->sensor_units_1 |= 1<<0;
433};
434inline void unset_percentage(SensorDataFullRecordBody* body)
435{
436 body->sensor_units_1 &= ~(1<<0);
437};
438inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
439{
440 body->sensor_units_1 &= ~(3<<1);
441 body->sensor_units_1 |= (op & 0x3)<<1;
442};
443inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
444{
445 body->sensor_units_1 &= ~(7<<3);
446 body->sensor_units_1 |= (unit & 0x7)<<3;
447};
448inline void set_analog_data_format(uint8_t format,
449 SensorDataFullRecordBody* body)
450{
451 body->sensor_units_1 &= ~(3<<6);
452 body->sensor_units_1 |= (format & 0x3)<<6;
453};
454
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700455inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700456{
457 body->m_lsb = m & 0xff;
458 body->m_msb_and_tolerance &= ~(3<<6);
459 body->m_msb_and_tolerance |= ((m & (3<<8)) >> 2);
460};
461inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
462{
463 body->m_msb_and_tolerance &= ~0x3f;
464 body->m_msb_and_tolerance |= tol & 0x3f;
465};
466
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700467inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700468{
469 body->b_lsb = b & 0xff;
470 body->b_msb_and_accuracy_lsb &= ~(3<<6);
471 body->b_msb_and_accuracy_lsb |= ((b & (3<<8)) >> 2);
472};
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700473inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700474{
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700475 // bottom 6 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700476 body->b_msb_and_accuracy_lsb &= ~0x3f;
477 body->b_msb_and_accuracy_lsb |= acc & 0x3f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700478 // top 4 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700479 body->accuracy_and_sensor_direction &= 0x0f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700480 body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
Emily Shafferbbef71c2017-05-08 16:36:17 -0700481};
482inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
483{
484 body->accuracy_and_sensor_direction &= ~(3<<2);
485 body->accuracy_and_sensor_direction |= (exp & 3)<<2;
486};
487inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
488{
489 body->accuracy_and_sensor_direction &= ~(3<<0);
490 body->accuracy_and_sensor_direction |= (dir & 3);
491};
492
493inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
494{
495 body->r_b_exponents &= 0xf0;
496 body->r_b_exponents |= exp & 0x0f;
497};
498inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
499{
500 body->r_b_exponents &= 0x0f;
501 body->r_b_exponents |= (exp & 0x0f)<<4;
502};
503
504inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
505{
506 body->id_string_info &= ~(0x1f);
507 body->id_string_info |= len & 0x1f;
508};
509inline uint8_t get_id_strlen( SensorDataFullRecordBody* body)
510{
511 return body->id_string_info & 0x1f;
512};
513inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
514{
515 body->id_string_info &= ~(3<<6);
516 body->id_string_info |= (type & 0x3)<<6;
517};
518
Ratan Guptae0cc8552018-01-22 14:23:04 +0530519inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
520{
521 body->deviceIDLen &= ~(LENGTH_MASK);
522 body->deviceIDLen |= len & LENGTH_MASK;
523};
524
525inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
526{
527 return body->deviceIDLen & LENGTH_MASK;
528};
529
Tom Josephdc212b22018-02-16 09:59:57 +0530530inline void set_readable_mask(uint8_t mask, SensorDataFullRecordBody* body)
531{
532 body->discrete_reading_setting_mask[1] = mask & 0x3F;
533}
534
Emily Shafferbbef71c2017-05-08 16:36:17 -0700535} // namespace body
536
537// More types contained in section 43.17 Sensor Unit Type Codes,
538// IPMI spec v2 rev 1.1
539enum SensorUnitTypeCodes
540{
541 SENSOR_UNIT_UNSPECIFIED = 0,
542 SENSOR_UNIT_DEGREES_C = 1,
543 SENSOR_UNIT_VOLTS = 4,
544 SENSOR_UNIT_AMPERES = 5,
Tom Josephdc212b22018-02-16 09:59:57 +0530545 SENSOR_UNIT_WATTS = 6,
Emily Shafferbbef71c2017-05-08 16:36:17 -0700546 SENSOR_UNIT_JOULES = 7,
547 SENSOR_UNIT_METERS = 34,
548 SENSOR_UNIT_REVOLUTIONS = 41,
549};
550
551struct SensorDataFullRecord
552{
553 SensorDataRecordHeader header;
554 SensorDataRecordKey key;
555 SensorDataFullRecordBody body;
556} __attribute__((packed));
557
Ratan Guptae0cc8552018-01-22 14:23:04 +0530558/** @struct SensorDataFruRecord
559 *
560 * FRU Device Locator Record - SDR Type 11
561 */
562struct SensorDataFruRecord
563{
564 SensorDataRecordHeader header;
565 SensorDataFruRecordKey key;
566 SensorDataFruRecordBody body;
567} __attribute__((packed));
568
Emily Shafferbbef71c2017-05-08 16:36:17 -0700569} // get_sdr
Tom Joseph816e92b2017-09-06 19:23:00 +0530570
571namespace ipmi
572{
573
574namespace sensor
575{
576
577/**
578 * @brief Map offset to the corresponding bit in the assertion byte.
579 *
Gunnar Mills8991dd62017-10-25 17:11:29 -0500580 * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
Tom Joseph816e92b2017-09-06 19:23:00 +0530581 * byte and offsets 8-14 in the second byte.
582 *
583 * @param[in] offset - offset number.
584 * @param[in/out] resp - get sensor reading response.
585 */
586inline void setOffset(uint8_t offset, ipmi::sensor::GetReadingResponse* resp)
587{
588 if (offset > 7)
589 {
590 resp->assertOffset8_14 |= 1 << (offset - 8);
591 }
592 else
593 {
594 resp->assertOffset0_7 |= 1 << offset;
595 }
596}
597
Tom Josephe4014fc2017-09-06 23:57:36 +0530598/**
599 * @brief Set the reading field in the response.
600 *
601 * @param[in] offset - offset number.
602 * @param[in/out] resp - get sensor reading response.
603 */
604inline void setReading(uint8_t value, ipmi::sensor::GetReadingResponse* resp)
605{
606 resp->reading = value;
607}
608
Tom Joseph295f17e2017-09-07 00:09:46 +0530609/**
610 * @brief Map the value to the assertion bytes. The assertion states are stored
611 * in 2 bytes.
612 *
613 * @param[in] value - value to mapped to the assertion byte.
614 * @param[in/out] resp - get sensor reading response.
615 */
616inline void setAssertionBytes(uint16_t value,
617 ipmi::sensor::GetReadingResponse* resp)
618{
619 resp->assertOffset0_7 = static_cast<uint8_t>(value & 0x00FF);
620 resp->assertOffset8_14 = static_cast<uint8_t>(value >> 8);
621}
622
Tom Josephe05b2922017-09-07 00:43:16 +0530623/**
624 * @brief Set the scanning enabled bit in the response.
625 *
626 * @param[in/out] resp - get sensor reading response.
627 */
628inline void enableScanning(ipmi::sensor::GetReadingResponse* resp)
629{
630 resp->operation = 1 << 6;
631}
632
Tom Joseph816e92b2017-09-06 19:23:00 +0530633} // namespace sensor
634
635} // namespace ipmi
Chris Austenac4604a2015-10-13 12:43:27 -0500636#endif