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