blob: e32405dbeec2cc9a3350e1be4bc4769384b13560 [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{
244 uint8_t validMask; //Indicates which values are valid
245 uint8_t data[6]; //Container for threshold values
246} __attribute__((packed));
247
Emily Shafferbbef71c2017-05-08 16:36:17 -0700248// Body - full record
249#define FULL_RECORD_ID_STR_MAX_LENGTH 16
Ratan Guptae0cc8552018-01-22 14:23:04 +0530250
251static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
252
Emily Shafferbbef71c2017-05-08 16:36:17 -0700253struct SensorDataFullRecordBody
254{
255 uint8_t entity_id;
256 uint8_t entity_instance;
257 uint8_t sensor_initialization;
258 uint8_t sensor_capabilities; // no macro support
259 uint8_t sensor_type;
260 uint8_t event_reading_type;
261 uint8_t supported_assertions[2]; // no macro support
262 uint8_t supported_deassertions[2]; // no macro support
263 uint8_t discrete_reading_setting_mask[2]; // no macro support
264 uint8_t sensor_units_1;
265 uint8_t sensor_units_2_base;
266 uint8_t sensor_units_3_modifier;
267 uint8_t linearization;
268 uint8_t m_lsb;
269 uint8_t m_msb_and_tolerance;
270 uint8_t b_lsb;
271 uint8_t b_msb_and_accuracy_lsb;
272 uint8_t accuracy_and_sensor_direction;
273 uint8_t r_b_exponents;
274 uint8_t analog_characteristic_flags; //no macro support
275 uint8_t nominal_reading;
276 uint8_t normal_max;
277 uint8_t normal_min;
278 uint8_t sensor_max;
279 uint8_t sensor_min;
280 uint8_t upper_nonrecoverable_threshold;
281 uint8_t upper_critical_threshold;
282 uint8_t upper_noncritical_threshold;
283 uint8_t lower_nonrecoverable_threshold;
284 uint8_t lower_critical_threshold;
285 uint8_t lower_noncritical_threshold;
286 uint8_t positive_threshold_hysteresis;
287 uint8_t negative_threshold_hysteresis;
288 uint16_t reserved;
289 uint8_t oem_reserved;
290 uint8_t id_string_info;
Emily Shaffer10f49592017-05-10 12:01:10 -0700291 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
Emily Shafferbbef71c2017-05-08 16:36:17 -0700292} __attribute__((packed));
293
Ratan Guptae0cc8552018-01-22 14:23:04 +0530294/** @struct SensorDataFruRecordBody
295 *
296 * FRU Device Locator Record(body) - SDR Type 11
297 */
298struct SensorDataFruRecordBody
299{
300 uint8_t reserved;
301 uint8_t deviceType;
302 uint8_t deviceTypeModifier;
303 uint8_t entityID;
304 uint8_t entityInstance;
305 uint8_t oem;
306 uint8_t deviceIDLen;
307 char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
308} __attribute__((packed));
309
Emily Shafferbbef71c2017-05-08 16:36:17 -0700310namespace body
311{
312
313inline void set_entity_instance_number(uint8_t n,
314 SensorDataFullRecordBody* body)
315{
316 body->entity_instance &= 1<<7;
317 body->entity_instance |= (n & ~(1<<7));
318};
319inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
320{
321 body->entity_instance &= ~(1<<7);
322};
323inline void set_entity_logical_container(SensorDataFullRecordBody* body)
324{
325 body->entity_instance |= 1<<7;
326};
327
328inline void sensor_scanning_state(bool enabled,
329 SensorDataFullRecordBody* body)
330{
331 if (enabled)
332 {
333 body->sensor_initialization |= 1<<0;
334 }
335 else
336 {
337 body->sensor_initialization &= ~(1<<0);
338 };
339};
340inline void event_generation_state(bool enabled,
341 SensorDataFullRecordBody* body)
342{
343 if (enabled)
344 {
345 body->sensor_initialization |= 1<<1;
346 }
347 else
348 {
349 body->sensor_initialization &= ~(1<<1);
350 }
351};
352inline void init_types_state(bool enabled,
353 SensorDataFullRecordBody* body)
354{
355 if (enabled)
356 {
357 body->sensor_initialization |= 1<<2;
358 }
359 else
360 {
361 body->sensor_initialization &= ~(1<<2);
362 }
363};
364inline void init_hyst_state(bool enabled,
365 SensorDataFullRecordBody* body)
366{
367 if (enabled)
368 {
369 body->sensor_initialization |= 1<<3;
370 }
371 else
372 {
373 body->sensor_initialization &= ~(1<<3);
374 }
375};
376inline void init_thresh_state(bool enabled,
377 SensorDataFullRecordBody* body)
378{
379 if (enabled)
380 {
381 body->sensor_initialization |= 1<<4;
382 }
383 else
384 {
385 body->sensor_initialization &= ~(1<<4);
386 }
387};
388inline void init_events_state(bool enabled,
389 SensorDataFullRecordBody* body)
390{
391 if (enabled)
392 {
393 body->sensor_initialization |= 1<<5;
394 }
395 else
396 {
397 body->sensor_initialization &= ~(1<<5);
398 }
399};
400inline void init_scanning_state(bool enabled,
401 SensorDataFullRecordBody* body)
402{
403 if (enabled)
404 {
405 body->sensor_initialization |= 1<<6;
406 }
407 else
408 {
409 body->sensor_initialization &= ~(1<<6);
410 }
411};
412inline void init_settable_state(bool enabled,
413 SensorDataFullRecordBody* body)
414{
415 if (enabled)
416 {
417 body->sensor_initialization |= 1<<7;
418 }
419 else
420 {
421 body->sensor_initialization &= ~(1<<7);
422 }
423};
424
425inline void set_percentage(SensorDataFullRecordBody* body)
426{
427 body->sensor_units_1 |= 1<<0;
428};
429inline void unset_percentage(SensorDataFullRecordBody* body)
430{
431 body->sensor_units_1 &= ~(1<<0);
432};
433inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
434{
435 body->sensor_units_1 &= ~(3<<1);
436 body->sensor_units_1 |= (op & 0x3)<<1;
437};
438inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
439{
440 body->sensor_units_1 &= ~(7<<3);
441 body->sensor_units_1 |= (unit & 0x7)<<3;
442};
443inline void set_analog_data_format(uint8_t format,
444 SensorDataFullRecordBody* body)
445{
446 body->sensor_units_1 &= ~(3<<6);
447 body->sensor_units_1 |= (format & 0x3)<<6;
448};
449
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700450inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700451{
452 body->m_lsb = m & 0xff;
453 body->m_msb_and_tolerance &= ~(3<<6);
454 body->m_msb_and_tolerance |= ((m & (3<<8)) >> 2);
455};
456inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
457{
458 body->m_msb_and_tolerance &= ~0x3f;
459 body->m_msb_and_tolerance |= tol & 0x3f;
460};
461
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700462inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700463{
464 body->b_lsb = b & 0xff;
465 body->b_msb_and_accuracy_lsb &= ~(3<<6);
466 body->b_msb_and_accuracy_lsb |= ((b & (3<<8)) >> 2);
467};
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700468inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700469{
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700470 // bottom 6 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700471 body->b_msb_and_accuracy_lsb &= ~0x3f;
472 body->b_msb_and_accuracy_lsb |= acc & 0x3f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700473 // top 4 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700474 body->accuracy_and_sensor_direction &= 0x0f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700475 body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
Emily Shafferbbef71c2017-05-08 16:36:17 -0700476};
477inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
478{
479 body->accuracy_and_sensor_direction &= ~(3<<2);
480 body->accuracy_and_sensor_direction |= (exp & 3)<<2;
481};
482inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
483{
484 body->accuracy_and_sensor_direction &= ~(3<<0);
485 body->accuracy_and_sensor_direction |= (dir & 3);
486};
487
488inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
489{
490 body->r_b_exponents &= 0xf0;
491 body->r_b_exponents |= exp & 0x0f;
492};
493inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
494{
495 body->r_b_exponents &= 0x0f;
496 body->r_b_exponents |= (exp & 0x0f)<<4;
497};
498
499inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
500{
501 body->id_string_info &= ~(0x1f);
502 body->id_string_info |= len & 0x1f;
503};
504inline uint8_t get_id_strlen( SensorDataFullRecordBody* body)
505{
506 return body->id_string_info & 0x1f;
507};
508inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
509{
510 body->id_string_info &= ~(3<<6);
511 body->id_string_info |= (type & 0x3)<<6;
512};
513
Ratan Guptae0cc8552018-01-22 14:23:04 +0530514inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
515{
516 body->deviceIDLen &= ~(LENGTH_MASK);
517 body->deviceIDLen |= len & LENGTH_MASK;
518};
519
520inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
521{
522 return body->deviceIDLen & LENGTH_MASK;
523};
524
Emily Shafferbbef71c2017-05-08 16:36:17 -0700525} // namespace body
526
527// More types contained in section 43.17 Sensor Unit Type Codes,
528// IPMI spec v2 rev 1.1
529enum SensorUnitTypeCodes
530{
531 SENSOR_UNIT_UNSPECIFIED = 0,
532 SENSOR_UNIT_DEGREES_C = 1,
533 SENSOR_UNIT_VOLTS = 4,
534 SENSOR_UNIT_AMPERES = 5,
535 SENSOR_UNIT_JOULES = 7,
536 SENSOR_UNIT_METERS = 34,
537 SENSOR_UNIT_REVOLUTIONS = 41,
538};
539
540struct SensorDataFullRecord
541{
542 SensorDataRecordHeader header;
543 SensorDataRecordKey key;
544 SensorDataFullRecordBody body;
545} __attribute__((packed));
546
Ratan Guptae0cc8552018-01-22 14:23:04 +0530547/** @struct SensorDataFruRecord
548 *
549 * FRU Device Locator Record - SDR Type 11
550 */
551struct SensorDataFruRecord
552{
553 SensorDataRecordHeader header;
554 SensorDataFruRecordKey key;
555 SensorDataFruRecordBody body;
556} __attribute__((packed));
557
Emily Shafferbbef71c2017-05-08 16:36:17 -0700558} // get_sdr
Tom Joseph816e92b2017-09-06 19:23:00 +0530559
560namespace ipmi
561{
562
563namespace sensor
564{
565
566/**
567 * @brief Map offset to the corresponding bit in the assertion byte.
568 *
Gunnar Mills8991dd62017-10-25 17:11:29 -0500569 * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
Tom Joseph816e92b2017-09-06 19:23:00 +0530570 * byte and offsets 8-14 in the second byte.
571 *
572 * @param[in] offset - offset number.
573 * @param[in/out] resp - get sensor reading response.
574 */
575inline void setOffset(uint8_t offset, ipmi::sensor::GetReadingResponse* resp)
576{
577 if (offset > 7)
578 {
579 resp->assertOffset8_14 |= 1 << (offset - 8);
580 }
581 else
582 {
583 resp->assertOffset0_7 |= 1 << offset;
584 }
585}
586
Tom Josephe4014fc2017-09-06 23:57:36 +0530587/**
588 * @brief Set the reading field in the response.
589 *
590 * @param[in] offset - offset number.
591 * @param[in/out] resp - get sensor reading response.
592 */
593inline void setReading(uint8_t value, ipmi::sensor::GetReadingResponse* resp)
594{
595 resp->reading = value;
596}
597
Tom Joseph295f17e2017-09-07 00:09:46 +0530598/**
599 * @brief Map the value to the assertion bytes. The assertion states are stored
600 * in 2 bytes.
601 *
602 * @param[in] value - value to mapped to the assertion byte.
603 * @param[in/out] resp - get sensor reading response.
604 */
605inline void setAssertionBytes(uint16_t value,
606 ipmi::sensor::GetReadingResponse* resp)
607{
608 resp->assertOffset0_7 = static_cast<uint8_t>(value & 0x00FF);
609 resp->assertOffset8_14 = static_cast<uint8_t>(value >> 8);
610}
611
Tom Josephe05b2922017-09-07 00:43:16 +0530612/**
613 * @brief Set the scanning enabled bit in the response.
614 *
615 * @param[in/out] resp - get sensor reading response.
616 */
617inline void enableScanning(ipmi::sensor::GetReadingResponse* resp)
618{
619 resp->operation = 1 << 6;
620}
621
Tom Joseph816e92b2017-09-06 19:23:00 +0530622} // namespace sensor
623
624} // namespace ipmi
Chris Austenac4604a2015-10-13 12:43:27 -0500625#endif