blob: 89954478c1bbec488e756e5e2ee212883e3a2d0a [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
Tom Joseph96423912018-01-25 00:14:34 +0530184inline void set_owner_id_bmc(SensorDataRecordKey* key)
185{
186 key->owner_id |= 0x20;
187};
188
Emily Shafferbbef71c2017-05-08 16:36:17 -0700189inline void set_owner_id_address(uint8_t addr, SensorDataRecordKey* key)
190{
191 key->owner_id &= 0x01;
192 key->owner_id |= addr<<1;
193};
194
195inline void set_owner_lun(uint8_t lun, SensorDataRecordKey* key)
196{
197 key->owner_lun &= ~0x03;
198 key->owner_lun |= (lun&0x03);
199};
200
201inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
202{
203 key->owner_lun &= 0x0f;
204 key->owner_lun |= ((channel & 0xf)<<4);
205};
206
207} // namespace key
208
209// Body - full record
210#define FULL_RECORD_ID_STR_MAX_LENGTH 16
211struct SensorDataFullRecordBody
212{
213 uint8_t entity_id;
214 uint8_t entity_instance;
215 uint8_t sensor_initialization;
216 uint8_t sensor_capabilities; // no macro support
217 uint8_t sensor_type;
218 uint8_t event_reading_type;
219 uint8_t supported_assertions[2]; // no macro support
220 uint8_t supported_deassertions[2]; // no macro support
221 uint8_t discrete_reading_setting_mask[2]; // no macro support
222 uint8_t sensor_units_1;
223 uint8_t sensor_units_2_base;
224 uint8_t sensor_units_3_modifier;
225 uint8_t linearization;
226 uint8_t m_lsb;
227 uint8_t m_msb_and_tolerance;
228 uint8_t b_lsb;
229 uint8_t b_msb_and_accuracy_lsb;
230 uint8_t accuracy_and_sensor_direction;
231 uint8_t r_b_exponents;
232 uint8_t analog_characteristic_flags; //no macro support
233 uint8_t nominal_reading;
234 uint8_t normal_max;
235 uint8_t normal_min;
236 uint8_t sensor_max;
237 uint8_t sensor_min;
238 uint8_t upper_nonrecoverable_threshold;
239 uint8_t upper_critical_threshold;
240 uint8_t upper_noncritical_threshold;
241 uint8_t lower_nonrecoverable_threshold;
242 uint8_t lower_critical_threshold;
243 uint8_t lower_noncritical_threshold;
244 uint8_t positive_threshold_hysteresis;
245 uint8_t negative_threshold_hysteresis;
246 uint16_t reserved;
247 uint8_t oem_reserved;
248 uint8_t id_string_info;
Emily Shaffer10f49592017-05-10 12:01:10 -0700249 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
Emily Shafferbbef71c2017-05-08 16:36:17 -0700250} __attribute__((packed));
251
252namespace body
253{
254
255inline void set_entity_instance_number(uint8_t n,
256 SensorDataFullRecordBody* body)
257{
258 body->entity_instance &= 1<<7;
259 body->entity_instance |= (n & ~(1<<7));
260};
261inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
262{
263 body->entity_instance &= ~(1<<7);
264};
265inline void set_entity_logical_container(SensorDataFullRecordBody* body)
266{
267 body->entity_instance |= 1<<7;
268};
269
270inline void sensor_scanning_state(bool enabled,
271 SensorDataFullRecordBody* body)
272{
273 if (enabled)
274 {
275 body->sensor_initialization |= 1<<0;
276 }
277 else
278 {
279 body->sensor_initialization &= ~(1<<0);
280 };
281};
282inline void event_generation_state(bool enabled,
283 SensorDataFullRecordBody* body)
284{
285 if (enabled)
286 {
287 body->sensor_initialization |= 1<<1;
288 }
289 else
290 {
291 body->sensor_initialization &= ~(1<<1);
292 }
293};
294inline void init_types_state(bool enabled,
295 SensorDataFullRecordBody* body)
296{
297 if (enabled)
298 {
299 body->sensor_initialization |= 1<<2;
300 }
301 else
302 {
303 body->sensor_initialization &= ~(1<<2);
304 }
305};
306inline void init_hyst_state(bool enabled,
307 SensorDataFullRecordBody* body)
308{
309 if (enabled)
310 {
311 body->sensor_initialization |= 1<<3;
312 }
313 else
314 {
315 body->sensor_initialization &= ~(1<<3);
316 }
317};
318inline void init_thresh_state(bool enabled,
319 SensorDataFullRecordBody* body)
320{
321 if (enabled)
322 {
323 body->sensor_initialization |= 1<<4;
324 }
325 else
326 {
327 body->sensor_initialization &= ~(1<<4);
328 }
329};
330inline void init_events_state(bool enabled,
331 SensorDataFullRecordBody* body)
332{
333 if (enabled)
334 {
335 body->sensor_initialization |= 1<<5;
336 }
337 else
338 {
339 body->sensor_initialization &= ~(1<<5);
340 }
341};
342inline void init_scanning_state(bool enabled,
343 SensorDataFullRecordBody* body)
344{
345 if (enabled)
346 {
347 body->sensor_initialization |= 1<<6;
348 }
349 else
350 {
351 body->sensor_initialization &= ~(1<<6);
352 }
353};
354inline void init_settable_state(bool enabled,
355 SensorDataFullRecordBody* body)
356{
357 if (enabled)
358 {
359 body->sensor_initialization |= 1<<7;
360 }
361 else
362 {
363 body->sensor_initialization &= ~(1<<7);
364 }
365};
366
367inline void set_percentage(SensorDataFullRecordBody* body)
368{
369 body->sensor_units_1 |= 1<<0;
370};
371inline void unset_percentage(SensorDataFullRecordBody* body)
372{
373 body->sensor_units_1 &= ~(1<<0);
374};
375inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
376{
377 body->sensor_units_1 &= ~(3<<1);
378 body->sensor_units_1 |= (op & 0x3)<<1;
379};
380inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
381{
382 body->sensor_units_1 &= ~(7<<3);
383 body->sensor_units_1 |= (unit & 0x7)<<3;
384};
385inline void set_analog_data_format(uint8_t format,
386 SensorDataFullRecordBody* body)
387{
388 body->sensor_units_1 &= ~(3<<6);
389 body->sensor_units_1 |= (format & 0x3)<<6;
390};
391
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700392inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700393{
394 body->m_lsb = m & 0xff;
395 body->m_msb_and_tolerance &= ~(3<<6);
396 body->m_msb_and_tolerance |= ((m & (3<<8)) >> 2);
397};
398inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
399{
400 body->m_msb_and_tolerance &= ~0x3f;
401 body->m_msb_and_tolerance |= tol & 0x3f;
402};
403
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700404inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700405{
406 body->b_lsb = b & 0xff;
407 body->b_msb_and_accuracy_lsb &= ~(3<<6);
408 body->b_msb_and_accuracy_lsb |= ((b & (3<<8)) >> 2);
409};
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700410inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
Emily Shafferbbef71c2017-05-08 16:36:17 -0700411{
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700412 // bottom 6 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700413 body->b_msb_and_accuracy_lsb &= ~0x3f;
414 body->b_msb_and_accuracy_lsb |= acc & 0x3f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700415 // top 4 bits
Emily Shafferbbef71c2017-05-08 16:36:17 -0700416 body->accuracy_and_sensor_direction &= 0x0f;
Emily Shaffer7cad3fc2017-08-30 17:50:37 -0700417 body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
Emily Shafferbbef71c2017-05-08 16:36:17 -0700418};
419inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
420{
421 body->accuracy_and_sensor_direction &= ~(3<<2);
422 body->accuracy_and_sensor_direction |= (exp & 3)<<2;
423};
424inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
425{
426 body->accuracy_and_sensor_direction &= ~(3<<0);
427 body->accuracy_and_sensor_direction |= (dir & 3);
428};
429
430inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
431{
432 body->r_b_exponents &= 0xf0;
433 body->r_b_exponents |= exp & 0x0f;
434};
435inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
436{
437 body->r_b_exponents &= 0x0f;
438 body->r_b_exponents |= (exp & 0x0f)<<4;
439};
440
441inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
442{
443 body->id_string_info &= ~(0x1f);
444 body->id_string_info |= len & 0x1f;
445};
446inline uint8_t get_id_strlen( SensorDataFullRecordBody* body)
447{
448 return body->id_string_info & 0x1f;
449};
450inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
451{
452 body->id_string_info &= ~(3<<6);
453 body->id_string_info |= (type & 0x3)<<6;
454};
455
456} // namespace body
457
458// More types contained in section 43.17 Sensor Unit Type Codes,
459// IPMI spec v2 rev 1.1
460enum SensorUnitTypeCodes
461{
462 SENSOR_UNIT_UNSPECIFIED = 0,
463 SENSOR_UNIT_DEGREES_C = 1,
464 SENSOR_UNIT_VOLTS = 4,
465 SENSOR_UNIT_AMPERES = 5,
466 SENSOR_UNIT_JOULES = 7,
467 SENSOR_UNIT_METERS = 34,
468 SENSOR_UNIT_REVOLUTIONS = 41,
469};
470
471struct SensorDataFullRecord
472{
473 SensorDataRecordHeader header;
474 SensorDataRecordKey key;
475 SensorDataFullRecordBody body;
476} __attribute__((packed));
477
478} // get_sdr
Tom Joseph816e92b2017-09-06 19:23:00 +0530479
480namespace ipmi
481{
482
483namespace sensor
484{
485
486/**
487 * @brief Map offset to the corresponding bit in the assertion byte.
488 *
Gunnar Mills8991dd62017-10-25 17:11:29 -0500489 * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
Tom Joseph816e92b2017-09-06 19:23:00 +0530490 * byte and offsets 8-14 in the second byte.
491 *
492 * @param[in] offset - offset number.
493 * @param[in/out] resp - get sensor reading response.
494 */
495inline void setOffset(uint8_t offset, ipmi::sensor::GetReadingResponse* resp)
496{
497 if (offset > 7)
498 {
499 resp->assertOffset8_14 |= 1 << (offset - 8);
500 }
501 else
502 {
503 resp->assertOffset0_7 |= 1 << offset;
504 }
505}
506
Tom Josephe4014fc2017-09-06 23:57:36 +0530507/**
508 * @brief Set the reading field in the response.
509 *
510 * @param[in] offset - offset number.
511 * @param[in/out] resp - get sensor reading response.
512 */
513inline void setReading(uint8_t value, ipmi::sensor::GetReadingResponse* resp)
514{
515 resp->reading = value;
516}
517
Tom Joseph295f17e2017-09-07 00:09:46 +0530518/**
519 * @brief Map the value to the assertion bytes. The assertion states are stored
520 * in 2 bytes.
521 *
522 * @param[in] value - value to mapped to the assertion byte.
523 * @param[in/out] resp - get sensor reading response.
524 */
525inline void setAssertionBytes(uint16_t value,
526 ipmi::sensor::GetReadingResponse* resp)
527{
528 resp->assertOffset0_7 = static_cast<uint8_t>(value & 0x00FF);
529 resp->assertOffset8_14 = static_cast<uint8_t>(value >> 8);
530}
531
Tom Josephe05b2922017-09-07 00:43:16 +0530532/**
533 * @brief Set the scanning enabled bit in the response.
534 *
535 * @param[in/out] resp - get sensor reading response.
536 */
537inline void enableScanning(ipmi::sensor::GetReadingResponse* resp)
538{
539 resp->operation = 1 << 6;
540}
541
Tom Joseph816e92b2017-09-06 19:23:00 +0530542} // namespace sensor
543
544} // namespace ipmi
Chris Austenac4604a2015-10-13 12:43:27 -0500545#endif