xref: /openbmc/ipmitool/lib/ipmi_sensor.c (revision c18ec02f)
1*c18ec02fSPetter Reinholdtsen /*
2*c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3*c18ec02fSPetter Reinholdtsen  *
4*c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
5*c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
6*c18ec02fSPetter Reinholdtsen  * are met:
7*c18ec02fSPetter Reinholdtsen  *
8*c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
9*c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
10*c18ec02fSPetter Reinholdtsen  *
11*c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
12*c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
13*c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
14*c18ec02fSPetter Reinholdtsen  *
15*c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
16*c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
17*c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
18*c18ec02fSPetter Reinholdtsen  *
19*c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
20*c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21*c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22*c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23*c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24*c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25*c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26*c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27*c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28*c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29*c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30*c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31*c18ec02fSPetter Reinholdtsen  */
32*c18ec02fSPetter Reinholdtsen 
33*c18ec02fSPetter Reinholdtsen #include <string.h>
34*c18ec02fSPetter Reinholdtsen #include <math.h>
35*c18ec02fSPetter Reinholdtsen 
36*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
37*c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
38*c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
39*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
40*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sdr.h>
41*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sel.h>
42*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sensor.h>
43*c18ec02fSPetter Reinholdtsen 
44*c18ec02fSPetter Reinholdtsen extern int verbose;
45*c18ec02fSPetter Reinholdtsen void printf_sensor_get_usage();
46*c18ec02fSPetter Reinholdtsen 
47*c18ec02fSPetter Reinholdtsen // Macro's for Reading the current sensor Data.
48*c18ec02fSPetter Reinholdtsen #define SCANNING_DISABLED	0x40
49*c18ec02fSPetter Reinholdtsen #define READING_UNAVAILABLE	0x20
50*c18ec02fSPetter Reinholdtsen #define	INVALID_THRESHOLD	"Invalid Threshold data values. Cannot Set Threshold Data."
51*c18ec02fSPetter Reinholdtsen // static
52*c18ec02fSPetter Reinholdtsen int
53*c18ec02fSPetter Reinholdtsen ipmi_sensor_get_sensor_reading_factors(
54*c18ec02fSPetter Reinholdtsen 	struct ipmi_intf * intf,
55*c18ec02fSPetter Reinholdtsen 	struct sdr_record_full_sensor * sensor,
56*c18ec02fSPetter Reinholdtsen 	uint8_t reading)
57*c18ec02fSPetter Reinholdtsen {
58*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
59*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
60*c18ec02fSPetter Reinholdtsen 	uint8_t req_data[2];
61*c18ec02fSPetter Reinholdtsen 
62*c18ec02fSPetter Reinholdtsen 	char id[17];
63*c18ec02fSPetter Reinholdtsen 
64*c18ec02fSPetter Reinholdtsen 	if (intf == NULL || sensor == NULL)
65*c18ec02fSPetter Reinholdtsen 		return -1;
66*c18ec02fSPetter Reinholdtsen 
67*c18ec02fSPetter Reinholdtsen 	memset(id, 0, sizeof(id));
68*c18ec02fSPetter Reinholdtsen 	memcpy(id, sensor->id_string, 16);
69*c18ec02fSPetter Reinholdtsen 
70*c18ec02fSPetter Reinholdtsen 	req_data[0] = sensor->cmn.keys.sensor_num;
71*c18ec02fSPetter Reinholdtsen 	req_data[1] = reading;
72*c18ec02fSPetter Reinholdtsen 
73*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
74*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_SE;
75*c18ec02fSPetter Reinholdtsen 	req.msg.lun = sensor->cmn.keys.lun;
76*c18ec02fSPetter Reinholdtsen 	req.msg.cmd   = GET_SENSOR_FACTORS;
77*c18ec02fSPetter Reinholdtsen 	req.msg.data  = req_data;
78*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = sizeof(req_data);
79*c18ec02fSPetter Reinholdtsen 
80*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
81*c18ec02fSPetter Reinholdtsen 
82*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
83*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error updating reading factor for sensor %s (#%02x)",
84*c18ec02fSPetter Reinholdtsen 			id, sensor->cmn.keys.sensor_num);
85*c18ec02fSPetter Reinholdtsen 		return -1;
86*c18ec02fSPetter Reinholdtsen 	} else if (rsp->ccode) {
87*c18ec02fSPetter Reinholdtsen 		return -1;
88*c18ec02fSPetter Reinholdtsen 	} else {
89*c18ec02fSPetter Reinholdtsen 		/* Update SDR copy with updated Reading Factors for this reading */
90*c18ec02fSPetter Reinholdtsen 		/* Note:
91*c18ec02fSPetter Reinholdtsen 		 * The Format of the returned data is exactly as in the SDR definition (Little Endian Format),
92*c18ec02fSPetter Reinholdtsen 		 * therefore we can use raw copy operation here.
93*c18ec02fSPetter Reinholdtsen 		 * Note: rsp->data[0] would point to the next valid entry in the sampling table
94*c18ec02fSPetter Reinholdtsen 		 */
95*c18ec02fSPetter Reinholdtsen 		 // BUGBUG: uses 'hardcoded' length information from SDR Definition
96*c18ec02fSPetter Reinholdtsen 		memcpy(&sensor->mtol, &rsp->data[1], sizeof(sensor->mtol));
97*c18ec02fSPetter Reinholdtsen 		memcpy(&sensor->bacc, &rsp->data[3], sizeof(sensor->bacc));
98*c18ec02fSPetter Reinholdtsen 		return 0;
99*c18ec02fSPetter Reinholdtsen 	}
100*c18ec02fSPetter Reinholdtsen 
101*c18ec02fSPetter Reinholdtsen }
102*c18ec02fSPetter Reinholdtsen 
103*c18ec02fSPetter Reinholdtsen static
104*c18ec02fSPetter Reinholdtsen struct ipmi_rs *
105*c18ec02fSPetter Reinholdtsen ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
106*c18ec02fSPetter Reinholdtsen 				  uint8_t sensor,
107*c18ec02fSPetter Reinholdtsen 				  uint8_t threshold, uint8_t setting,
108*c18ec02fSPetter Reinholdtsen 				  uint8_t target, uint8_t lun, uint8_t channel)
109*c18ec02fSPetter Reinholdtsen {
110*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
111*c18ec02fSPetter Reinholdtsen 	static struct sensor_set_thresh_rq set_thresh_rq;
112*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
113*c18ec02fSPetter Reinholdtsen 	uint8_t  bridged_request = 0;
114*c18ec02fSPetter Reinholdtsen 	uint32_t save_addr;
115*c18ec02fSPetter Reinholdtsen 	uint32_t save_channel;
116*c18ec02fSPetter Reinholdtsen 
117*c18ec02fSPetter Reinholdtsen 	memset(&set_thresh_rq, 0, sizeof (set_thresh_rq));
118*c18ec02fSPetter Reinholdtsen 	set_thresh_rq.sensor_num = sensor;
119*c18ec02fSPetter Reinholdtsen 	set_thresh_rq.set_mask = threshold;
120*c18ec02fSPetter Reinholdtsen 	if (threshold == UPPER_NON_RECOV_SPECIFIED)
121*c18ec02fSPetter Reinholdtsen 		set_thresh_rq.upper_non_recov = setting;
122*c18ec02fSPetter Reinholdtsen 	else if (threshold == UPPER_CRIT_SPECIFIED)
123*c18ec02fSPetter Reinholdtsen 		set_thresh_rq.upper_crit = setting;
124*c18ec02fSPetter Reinholdtsen 	else if (threshold == UPPER_NON_CRIT_SPECIFIED)
125*c18ec02fSPetter Reinholdtsen 		set_thresh_rq.upper_non_crit = setting;
126*c18ec02fSPetter Reinholdtsen 	else if (threshold == LOWER_NON_CRIT_SPECIFIED)
127*c18ec02fSPetter Reinholdtsen 		set_thresh_rq.lower_non_crit = setting;
128*c18ec02fSPetter Reinholdtsen 	else if (threshold == LOWER_CRIT_SPECIFIED)
129*c18ec02fSPetter Reinholdtsen 		set_thresh_rq.lower_crit = setting;
130*c18ec02fSPetter Reinholdtsen 	else if (threshold == LOWER_NON_RECOV_SPECIFIED)
131*c18ec02fSPetter Reinholdtsen 		set_thresh_rq.lower_non_recov = setting;
132*c18ec02fSPetter Reinholdtsen 	else
133*c18ec02fSPetter Reinholdtsen 		return NULL;
134*c18ec02fSPetter Reinholdtsen 
135*c18ec02fSPetter Reinholdtsen 	if (BRIDGE_TO_SENSOR(intf, target, channel)) {
136*c18ec02fSPetter Reinholdtsen 		bridged_request = 1;
137*c18ec02fSPetter Reinholdtsen 		save_addr = intf->target_addr;
138*c18ec02fSPetter Reinholdtsen 		intf->target_addr = target;
139*c18ec02fSPetter Reinholdtsen 		save_channel = intf->target_channel;
140*c18ec02fSPetter Reinholdtsen 		intf->target_channel = channel;
141*c18ec02fSPetter Reinholdtsen 	}
142*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof (req));
143*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_SE;
144*c18ec02fSPetter Reinholdtsen 	req.msg.lun = lun;
145*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = SET_SENSOR_THRESHOLDS;
146*c18ec02fSPetter Reinholdtsen 	req.msg.data = (uint8_t *) & set_thresh_rq;
147*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = sizeof (set_thresh_rq);
148*c18ec02fSPetter Reinholdtsen 
149*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
150*c18ec02fSPetter Reinholdtsen 	if (bridged_request) {
151*c18ec02fSPetter Reinholdtsen 		intf->target_addr = save_addr;
152*c18ec02fSPetter Reinholdtsen 		intf->target_channel = save_channel;
153*c18ec02fSPetter Reinholdtsen 	}
154*c18ec02fSPetter Reinholdtsen 	return rsp;
155*c18ec02fSPetter Reinholdtsen }
156*c18ec02fSPetter Reinholdtsen 
157*c18ec02fSPetter Reinholdtsen static int
158*c18ec02fSPetter Reinholdtsen ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf,
159*c18ec02fSPetter Reinholdtsen 				struct sdr_record_common_sensor *sensor,
160*c18ec02fSPetter Reinholdtsen 				uint8_t sdr_record_type)
161*c18ec02fSPetter Reinholdtsen {
162*c18ec02fSPetter Reinholdtsen 	const char *id;
163*c18ec02fSPetter Reinholdtsen 	struct sensor_reading *sr;
164*c18ec02fSPetter Reinholdtsen 
165*c18ec02fSPetter Reinholdtsen 	sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
166*c18ec02fSPetter Reinholdtsen 
167*c18ec02fSPetter Reinholdtsen 	if (sr == NULL) {
168*c18ec02fSPetter Reinholdtsen 		return -1;
169*c18ec02fSPetter Reinholdtsen 	}
170*c18ec02fSPetter Reinholdtsen 
171*c18ec02fSPetter Reinholdtsen 	if (csv_output) {
172*c18ec02fSPetter Reinholdtsen 		/* NOT IMPLEMENTED */
173*c18ec02fSPetter Reinholdtsen 	} else {
174*c18ec02fSPetter Reinholdtsen 		if (verbose == 0) {
175*c18ec02fSPetter Reinholdtsen 			/* output format
176*c18ec02fSPetter Reinholdtsen 			 *   id value units status thresholds....
177*c18ec02fSPetter Reinholdtsen 			 */
178*c18ec02fSPetter Reinholdtsen 			printf("%-16s ", sr->s_id);
179*c18ec02fSPetter Reinholdtsen 			if (sr->s_reading_valid) {
180*c18ec02fSPetter Reinholdtsen 				if (sr->s_has_analog_value) {
181*c18ec02fSPetter Reinholdtsen 					/* don't show discrete component */
182*c18ec02fSPetter Reinholdtsen 					printf("| %-10s | %-10s | %-6s",
183*c18ec02fSPetter Reinholdtsen 					       sr->s_a_str, sr->s_a_units, "ok");
184*c18ec02fSPetter Reinholdtsen 				} else {
185*c18ec02fSPetter Reinholdtsen 					printf("| 0x%-8x | %-10s | 0x%02x%02x",
186*c18ec02fSPetter Reinholdtsen 					       sr->s_reading, "discrete",
187*c18ec02fSPetter Reinholdtsen 					       sr->s_data2, sr->s_data3);
188*c18ec02fSPetter Reinholdtsen 				}
189*c18ec02fSPetter Reinholdtsen 			} else {
190*c18ec02fSPetter Reinholdtsen 				printf("| %-10s | %-10s | %-6s",
191*c18ec02fSPetter Reinholdtsen 				       "na", "discrete", "na");
192*c18ec02fSPetter Reinholdtsen 			}
193*c18ec02fSPetter Reinholdtsen 			printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
194*c18ec02fSPetter Reinholdtsen 			       "na", "na", "na", "na", "na", "na");
195*c18ec02fSPetter Reinholdtsen 
196*c18ec02fSPetter Reinholdtsen 			printf("\n");
197*c18ec02fSPetter Reinholdtsen 		} else {
198*c18ec02fSPetter Reinholdtsen 			printf("Sensor ID              : %s (0x%x)\n",
199*c18ec02fSPetter Reinholdtsen 			       sr->s_id, sensor->keys.sensor_num);
200*c18ec02fSPetter Reinholdtsen 			printf(" Entity ID             : %d.%d\n",
201*c18ec02fSPetter Reinholdtsen 			       sensor->entity.id, sensor->entity.instance);
202*c18ec02fSPetter Reinholdtsen 			printf(" Sensor Type (Discrete): %s\n",
203*c18ec02fSPetter Reinholdtsen 			       ipmi_sdr_get_sensor_type_desc(sensor->sensor.
204*c18ec02fSPetter Reinholdtsen 							     type));
205*c18ec02fSPetter Reinholdtsen 			if( sr->s_reading_valid )
206*c18ec02fSPetter Reinholdtsen 			{
207*c18ec02fSPetter Reinholdtsen 				if (sr->s_has_analog_value) {
208*c18ec02fSPetter Reinholdtsen 					printf(" Sensor Reading        : %s %s\n", sr->s_a_str, sr->s_a_units);
209*c18ec02fSPetter Reinholdtsen 				}
210*c18ec02fSPetter Reinholdtsen 				ipmi_sdr_print_discrete_state("States Asserted",
211*c18ec02fSPetter Reinholdtsen 							sensor->sensor.type,
212*c18ec02fSPetter Reinholdtsen 							sensor->event_type,
213*c18ec02fSPetter Reinholdtsen 							sr->s_data2,
214*c18ec02fSPetter Reinholdtsen 							sr->s_data3);
215*c18ec02fSPetter Reinholdtsen 				printf("\n");
216*c18ec02fSPetter Reinholdtsen 			} else {
217*c18ec02fSPetter Reinholdtsen 			   printf(" Unable to read sensor: Device Not Present\n\n");
218*c18ec02fSPetter Reinholdtsen 			}
219*c18ec02fSPetter Reinholdtsen 	   }
220*c18ec02fSPetter Reinholdtsen 	}
221*c18ec02fSPetter Reinholdtsen 
222*c18ec02fSPetter Reinholdtsen 	return (sr->s_reading_valid ? 0 : -1 );
223*c18ec02fSPetter Reinholdtsen }
224*c18ec02fSPetter Reinholdtsen 
225*c18ec02fSPetter Reinholdtsen static void
226*c18ec02fSPetter Reinholdtsen print_thresh_setting(struct sdr_record_full_sensor *full,
227*c18ec02fSPetter Reinholdtsen 			 uint8_t thresh_is_avail, uint8_t setting,
228*c18ec02fSPetter Reinholdtsen 			 const char *field_sep,
229*c18ec02fSPetter Reinholdtsen 			 const char *analog_fmt,
230*c18ec02fSPetter Reinholdtsen 			 const char *discrete_fmt,
231*c18ec02fSPetter Reinholdtsen 			 const char *na_fmt)
232*c18ec02fSPetter Reinholdtsen {
233*c18ec02fSPetter Reinholdtsen 	printf("%s", field_sep);
234*c18ec02fSPetter Reinholdtsen 	if (!thresh_is_avail) {
235*c18ec02fSPetter Reinholdtsen 		printf(na_fmt, "na");
236*c18ec02fSPetter Reinholdtsen 		return;
237*c18ec02fSPetter Reinholdtsen 	}
238*c18ec02fSPetter Reinholdtsen 	if (full && !UNITS_ARE_DISCRETE(&full->cmn)) {
239*c18ec02fSPetter Reinholdtsen 		printf(analog_fmt, sdr_convert_sensor_reading (full, setting));
240*c18ec02fSPetter Reinholdtsen 	} else {
241*c18ec02fSPetter Reinholdtsen 		printf(discrete_fmt, setting);
242*c18ec02fSPetter Reinholdtsen 	}
243*c18ec02fSPetter Reinholdtsen }
244*c18ec02fSPetter Reinholdtsen 
245*c18ec02fSPetter Reinholdtsen static int
246*c18ec02fSPetter Reinholdtsen ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf,
247*c18ec02fSPetter Reinholdtsen 			      struct sdr_record_common_sensor *sensor,
248*c18ec02fSPetter Reinholdtsen 			      uint8_t sdr_record_type)
249*c18ec02fSPetter Reinholdtsen {
250*c18ec02fSPetter Reinholdtsen 	int thresh_available = 1;
251*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
252*c18ec02fSPetter Reinholdtsen 	struct sensor_reading *sr;
253*c18ec02fSPetter Reinholdtsen 
254*c18ec02fSPetter Reinholdtsen 	sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
255*c18ec02fSPetter Reinholdtsen 
256*c18ec02fSPetter Reinholdtsen 	if (sr == NULL) {
257*c18ec02fSPetter Reinholdtsen 		return -1;
258*c18ec02fSPetter Reinholdtsen 	}
259*c18ec02fSPetter Reinholdtsen 
260*c18ec02fSPetter Reinholdtsen 	const char *thresh_status = ipmi_sdr_get_thresh_status(sr, "ns");
261*c18ec02fSPetter Reinholdtsen 
262*c18ec02fSPetter Reinholdtsen 	/*
263*c18ec02fSPetter Reinholdtsen 	 * Get sensor thresholds
264*c18ec02fSPetter Reinholdtsen 	 */
265*c18ec02fSPetter Reinholdtsen 	rsp = ipmi_sdr_get_sensor_thresholds(intf,
266*c18ec02fSPetter Reinholdtsen 				sensor->keys.sensor_num, sensor->keys.owner_id,
267*c18ec02fSPetter Reinholdtsen 				sensor->keys.lun, sensor->keys.channel);
268*c18ec02fSPetter Reinholdtsen 
269*c18ec02fSPetter Reinholdtsen 	if ((rsp == NULL) || (rsp->ccode > 0) || (rsp->data_len == 0))
270*c18ec02fSPetter Reinholdtsen 		thresh_available = 0;
271*c18ec02fSPetter Reinholdtsen 
272*c18ec02fSPetter Reinholdtsen 	if (csv_output) {
273*c18ec02fSPetter Reinholdtsen 		/* NOT IMPLEMENTED */
274*c18ec02fSPetter Reinholdtsen 	} else {
275*c18ec02fSPetter Reinholdtsen 		if (verbose == 0) {
276*c18ec02fSPetter Reinholdtsen 			/* output format
277*c18ec02fSPetter Reinholdtsen 			 *   id value units status thresholds....
278*c18ec02fSPetter Reinholdtsen 			 */
279*c18ec02fSPetter Reinholdtsen 			printf("%-16s ", sr->s_id);
280*c18ec02fSPetter Reinholdtsen 			if (sr->s_reading_valid) {
281*c18ec02fSPetter Reinholdtsen 				if (sr->s_has_analog_value)
282*c18ec02fSPetter Reinholdtsen 					printf("| %-10.3f | %-10s | %-6s",
283*c18ec02fSPetter Reinholdtsen 					       sr->s_a_val, sr->s_a_units, thresh_status);
284*c18ec02fSPetter Reinholdtsen 				else
285*c18ec02fSPetter Reinholdtsen 					printf("| 0x%-8x | %-10s | %-6s",
286*c18ec02fSPetter Reinholdtsen 					       sr->s_reading, sr->s_a_units, thresh_status);
287*c18ec02fSPetter Reinholdtsen 			} else {
288*c18ec02fSPetter Reinholdtsen 				printf("| %-10s | %-10s | %-6s",
289*c18ec02fSPetter Reinholdtsen 				       "na", sr->s_a_units, "na");
290*c18ec02fSPetter Reinholdtsen 			}
291*c18ec02fSPetter Reinholdtsen 			if (thresh_available && sr->full) {
292*c18ec02fSPetter Reinholdtsen #define PTS(bit, dataidx) {						\
293*c18ec02fSPetter Reinholdtsen 	print_thresh_setting(sr->full, rsp->data[0] & (bit),  		\
294*c18ec02fSPetter Reinholdtsen 	    rsp->data[(dataidx)], "| ", "%-10.3f", "0x-8x", "%-10s");	\
295*c18ec02fSPetter Reinholdtsen }
296*c18ec02fSPetter Reinholdtsen 				PTS(LOWER_NON_RECOV_SPECIFIED,	3);
297*c18ec02fSPetter Reinholdtsen 				PTS(LOWER_CRIT_SPECIFIED,	2);
298*c18ec02fSPetter Reinholdtsen 				PTS(LOWER_NON_CRIT_SPECIFIED,	1);
299*c18ec02fSPetter Reinholdtsen 				PTS(UPPER_NON_CRIT_SPECIFIED,	4);
300*c18ec02fSPetter Reinholdtsen 				PTS(UPPER_CRIT_SPECIFIED,	5);
301*c18ec02fSPetter Reinholdtsen 				PTS(UPPER_NON_RECOV_SPECIFIED,	6);
302*c18ec02fSPetter Reinholdtsen #undef PTS
303*c18ec02fSPetter Reinholdtsen 			} else {
304*c18ec02fSPetter Reinholdtsen 				printf
305*c18ec02fSPetter Reinholdtsen 				    ("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
306*c18ec02fSPetter Reinholdtsen 				     "na", "na", "na", "na", "na", "na");
307*c18ec02fSPetter Reinholdtsen 			}
308*c18ec02fSPetter Reinholdtsen 
309*c18ec02fSPetter Reinholdtsen 			printf("\n");
310*c18ec02fSPetter Reinholdtsen 		} else {
311*c18ec02fSPetter Reinholdtsen 			printf("Sensor ID              : %s (0x%x)\n",
312*c18ec02fSPetter Reinholdtsen 			       sr->s_id, sensor->keys.sensor_num);
313*c18ec02fSPetter Reinholdtsen 
314*c18ec02fSPetter Reinholdtsen 			printf(" Entity ID             : %d.%d\n",
315*c18ec02fSPetter Reinholdtsen 			       sensor->entity.id, sensor->entity.instance);
316*c18ec02fSPetter Reinholdtsen 
317*c18ec02fSPetter Reinholdtsen 			printf(" Sensor Type (Threshold)  : %s\n",
318*c18ec02fSPetter Reinholdtsen 			       ipmi_sdr_get_sensor_type_desc(sensor->sensor.
319*c18ec02fSPetter Reinholdtsen 							     type));
320*c18ec02fSPetter Reinholdtsen 
321*c18ec02fSPetter Reinholdtsen 			printf(" Sensor Reading        : ");
322*c18ec02fSPetter Reinholdtsen 			if (sr->s_reading_valid) {
323*c18ec02fSPetter Reinholdtsen 				if (sr->full) {
324*c18ec02fSPetter Reinholdtsen 					uint16_t raw_tol = __TO_TOL(sr->full->mtol);
325*c18ec02fSPetter Reinholdtsen 					if (sr->s_has_analog_value) {
326*c18ec02fSPetter Reinholdtsen 						double tol =
327*c18ec02fSPetter Reinholdtsen 						    sdr_convert_sensor_tolerance(sr->full,
328*c18ec02fSPetter Reinholdtsen 									       raw_tol);
329*c18ec02fSPetter Reinholdtsen 						printf("%.*f (+/- %.*f) %s\n",
330*c18ec02fSPetter Reinholdtsen 						       (sr->s_a_val == (int)
331*c18ec02fSPetter Reinholdtsen 						       sr->s_a_val) ? 0 : 3,
332*c18ec02fSPetter Reinholdtsen 						       sr->s_a_val,
333*c18ec02fSPetter Reinholdtsen 						       (tol == (int) tol) ? 0 : 3, tol,
334*c18ec02fSPetter Reinholdtsen 						       sr->s_a_units);
335*c18ec02fSPetter Reinholdtsen 					} else {
336*c18ec02fSPetter Reinholdtsen 						printf("0x%x (+/- 0x%x) %s\n",
337*c18ec02fSPetter Reinholdtsen 						       sr->s_reading,
338*c18ec02fSPetter Reinholdtsen 						       raw_tol,
339*c18ec02fSPetter Reinholdtsen 						       sr->s_a_units);
340*c18ec02fSPetter Reinholdtsen 					}
341*c18ec02fSPetter Reinholdtsen 				} else {
342*c18ec02fSPetter Reinholdtsen 					printf("0x%x %s\n", sr->s_reading,
343*c18ec02fSPetter Reinholdtsen 					sr->s_a_units);
344*c18ec02fSPetter Reinholdtsen 				}
345*c18ec02fSPetter Reinholdtsen 				printf(" Status                : %s\n", thresh_status);
346*c18ec02fSPetter Reinholdtsen 
347*c18ec02fSPetter Reinholdtsen 				if (thresh_available) {
348*c18ec02fSPetter Reinholdtsen 					if (sr->full) {
349*c18ec02fSPetter Reinholdtsen #define PTS(bit, dataidx, str) { 			\
350*c18ec02fSPetter Reinholdtsen print_thresh_setting(sr->full, rsp->data[0] & (bit),	\
351*c18ec02fSPetter Reinholdtsen 		     rsp->data[(dataidx)], 		\
352*c18ec02fSPetter Reinholdtsen 		    (str), "%.3f\n", "0x%x\n", "%s\n"); \
353*c18ec02fSPetter Reinholdtsen }
354*c18ec02fSPetter Reinholdtsen 
355*c18ec02fSPetter Reinholdtsen 						PTS(LOWER_NON_RECOV_SPECIFIED,	3, " Lower Non-Recoverable : ");
356*c18ec02fSPetter Reinholdtsen 						PTS(LOWER_CRIT_SPECIFIED,	2, " Lower Critical        : ");
357*c18ec02fSPetter Reinholdtsen 						PTS(LOWER_NON_CRIT_SPECIFIED,	1, " Lower Non-Critical    : ");
358*c18ec02fSPetter Reinholdtsen 						PTS(UPPER_NON_CRIT_SPECIFIED,	4, " Upper Non-Critical    : ");
359*c18ec02fSPetter Reinholdtsen 						PTS(UPPER_CRIT_SPECIFIED,	5, " Upper Critical        : ");
360*c18ec02fSPetter Reinholdtsen 						PTS(UPPER_NON_RECOV_SPECIFIED,	6, " Upper Non-Recoverable : ");
361*c18ec02fSPetter Reinholdtsen #undef PTS
362*c18ec02fSPetter Reinholdtsen 
363*c18ec02fSPetter Reinholdtsen 					}
364*c18ec02fSPetter Reinholdtsen 					ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
365*c18ec02fSPetter Reinholdtsen 						sr->full ?  sr->full->threshold.hysteresis.positive :
366*c18ec02fSPetter Reinholdtsen 						sr->compact->threshold.hysteresis.positive,
367*c18ec02fSPetter Reinholdtsen 						"Positive Hysteresis");
368*c18ec02fSPetter Reinholdtsen 
369*c18ec02fSPetter Reinholdtsen 					ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
370*c18ec02fSPetter Reinholdtsen 						sr->full ?  sr->full->threshold.hysteresis.negative :
371*c18ec02fSPetter Reinholdtsen 						sr->compact->threshold.hysteresis.negative,
372*c18ec02fSPetter Reinholdtsen 						"Negative Hysteresis");
373*c18ec02fSPetter Reinholdtsen 				} else {
374*c18ec02fSPetter Reinholdtsen 					printf(" Sensor Threshold Settings not available\n");
375*c18ec02fSPetter Reinholdtsen 				}
376*c18ec02fSPetter Reinholdtsen 			} else {
377*c18ec02fSPetter Reinholdtsen 			  printf(" Unable to read sensor: Device Not Present\n\n");
378*c18ec02fSPetter Reinholdtsen 			}
379*c18ec02fSPetter Reinholdtsen 
380*c18ec02fSPetter Reinholdtsen 			ipmi_sdr_print_sensor_event_status(intf,
381*c18ec02fSPetter Reinholdtsen 							   sensor->keys.
382*c18ec02fSPetter Reinholdtsen 							   sensor_num,
383*c18ec02fSPetter Reinholdtsen 							   sensor->sensor.type,
384*c18ec02fSPetter Reinholdtsen 							   sensor->event_type,
385*c18ec02fSPetter Reinholdtsen 							   ANALOG_SENSOR,
386*c18ec02fSPetter Reinholdtsen 							   sensor->keys.owner_id,
387*c18ec02fSPetter Reinholdtsen 							   sensor->keys.lun,
388*c18ec02fSPetter Reinholdtsen 							   sensor->keys.channel);
389*c18ec02fSPetter Reinholdtsen 			ipmi_sdr_print_sensor_event_enable(intf,
390*c18ec02fSPetter Reinholdtsen 							   sensor->keys.
391*c18ec02fSPetter Reinholdtsen 							   sensor_num,
392*c18ec02fSPetter Reinholdtsen 							   sensor->sensor.type,
393*c18ec02fSPetter Reinholdtsen 							   sensor->event_type,
394*c18ec02fSPetter Reinholdtsen 							   ANALOG_SENSOR,
395*c18ec02fSPetter Reinholdtsen 							   sensor->keys.owner_id,
396*c18ec02fSPetter Reinholdtsen 							   sensor->keys.lun,
397*c18ec02fSPetter Reinholdtsen 							   sensor->keys.channel);
398*c18ec02fSPetter Reinholdtsen 
399*c18ec02fSPetter Reinholdtsen 			printf("\n");
400*c18ec02fSPetter Reinholdtsen 		}
401*c18ec02fSPetter Reinholdtsen 	}
402*c18ec02fSPetter Reinholdtsen 
403*c18ec02fSPetter Reinholdtsen 	return (sr->s_reading_valid ? 0 : -1 );
404*c18ec02fSPetter Reinholdtsen }
405*c18ec02fSPetter Reinholdtsen 
406*c18ec02fSPetter Reinholdtsen int
407*c18ec02fSPetter Reinholdtsen ipmi_sensor_print_fc(struct ipmi_intf *intf,
408*c18ec02fSPetter Reinholdtsen 		       struct sdr_record_common_sensor *sensor,
409*c18ec02fSPetter Reinholdtsen 			uint8_t sdr_record_type)
410*c18ec02fSPetter Reinholdtsen {
411*c18ec02fSPetter Reinholdtsen 	if (IS_THRESHOLD_SENSOR(sensor))
412*c18ec02fSPetter Reinholdtsen 		return ipmi_sensor_print_fc_threshold(intf, sensor, sdr_record_type);
413*c18ec02fSPetter Reinholdtsen 	else
414*c18ec02fSPetter Reinholdtsen 		return ipmi_sensor_print_fc_discrete(intf, sensor, sdr_record_type);
415*c18ec02fSPetter Reinholdtsen }
416*c18ec02fSPetter Reinholdtsen 
417*c18ec02fSPetter Reinholdtsen static int
418*c18ec02fSPetter Reinholdtsen ipmi_sensor_list(struct ipmi_intf *intf)
419*c18ec02fSPetter Reinholdtsen {
420*c18ec02fSPetter Reinholdtsen 	struct sdr_get_rs *header;
421*c18ec02fSPetter Reinholdtsen 	struct ipmi_sdr_iterator *itr;
422*c18ec02fSPetter Reinholdtsen 	int rc = 0;
423*c18ec02fSPetter Reinholdtsen 
424*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_DEBUG, "Querying SDR for sensor list");
425*c18ec02fSPetter Reinholdtsen 
426*c18ec02fSPetter Reinholdtsen 	itr = ipmi_sdr_start(intf, 0);
427*c18ec02fSPetter Reinholdtsen 	if (itr == NULL) {
428*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to open SDR for reading");
429*c18ec02fSPetter Reinholdtsen 		return -1;
430*c18ec02fSPetter Reinholdtsen 	}
431*c18ec02fSPetter Reinholdtsen 
432*c18ec02fSPetter Reinholdtsen 	while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
433*c18ec02fSPetter Reinholdtsen 		uint8_t *rec;
434*c18ec02fSPetter Reinholdtsen 
435*c18ec02fSPetter Reinholdtsen 		rec = ipmi_sdr_get_record(intf, header, itr);
436*c18ec02fSPetter Reinholdtsen 		if (rec == NULL) {
437*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_DEBUG, "rec == NULL");
438*c18ec02fSPetter Reinholdtsen 			continue;
439*c18ec02fSPetter Reinholdtsen 		}
440*c18ec02fSPetter Reinholdtsen 
441*c18ec02fSPetter Reinholdtsen 		switch (header->type) {
442*c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_FULL_SENSOR:
443*c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_COMPACT_SENSOR:
444*c18ec02fSPetter Reinholdtsen 			ipmi_sensor_print_fc(intf,
445*c18ec02fSPetter Reinholdtsen 						   (struct
446*c18ec02fSPetter Reinholdtsen 						    sdr_record_common_sensor *)
447*c18ec02fSPetter Reinholdtsen 						   rec,
448*c18ec02fSPetter Reinholdtsen 						   header->type);
449*c18ec02fSPetter Reinholdtsen 			break;
450*c18ec02fSPetter Reinholdtsen 		}
451*c18ec02fSPetter Reinholdtsen 		free(rec);
452*c18ec02fSPetter Reinholdtsen 		rec = NULL;
453*c18ec02fSPetter Reinholdtsen 
454*c18ec02fSPetter Reinholdtsen 		/* fix for CR6604909: */
455*c18ec02fSPetter Reinholdtsen 		/* mask failure of individual reads in sensor list command */
456*c18ec02fSPetter Reinholdtsen 		/* rc = (r == 0) ? rc : r; */
457*c18ec02fSPetter Reinholdtsen 	}
458*c18ec02fSPetter Reinholdtsen 
459*c18ec02fSPetter Reinholdtsen 	ipmi_sdr_end(intf, itr);
460*c18ec02fSPetter Reinholdtsen 
461*c18ec02fSPetter Reinholdtsen 	return rc;
462*c18ec02fSPetter Reinholdtsen }
463*c18ec02fSPetter Reinholdtsen 
464*c18ec02fSPetter Reinholdtsen static const struct valstr threshold_vals[] = {
465*c18ec02fSPetter Reinholdtsen 	{UPPER_NON_RECOV_SPECIFIED, "Upper Non-Recoverable"},
466*c18ec02fSPetter Reinholdtsen 	{UPPER_CRIT_SPECIFIED, "Upper Critical"},
467*c18ec02fSPetter Reinholdtsen 	{UPPER_NON_CRIT_SPECIFIED, "Upper Non-Critical"},
468*c18ec02fSPetter Reinholdtsen 	{LOWER_NON_RECOV_SPECIFIED, "Lower Non-Recoverable"},
469*c18ec02fSPetter Reinholdtsen 	{LOWER_CRIT_SPECIFIED, "Lower Critical"},
470*c18ec02fSPetter Reinholdtsen 	{LOWER_NON_CRIT_SPECIFIED, "Lower Non-Critical"},
471*c18ec02fSPetter Reinholdtsen 	{0x00, NULL},
472*c18ec02fSPetter Reinholdtsen };
473*c18ec02fSPetter Reinholdtsen 
474*c18ec02fSPetter Reinholdtsen static int
475*c18ec02fSPetter Reinholdtsen __ipmi_sensor_set_threshold(struct ipmi_intf *intf,
476*c18ec02fSPetter Reinholdtsen 			    uint8_t num, uint8_t mask, uint8_t setting,
477*c18ec02fSPetter Reinholdtsen 			    uint8_t target, uint8_t lun, uint8_t channel)
478*c18ec02fSPetter Reinholdtsen {
479*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
480*c18ec02fSPetter Reinholdtsen 
481*c18ec02fSPetter Reinholdtsen 	rsp = ipmi_sensor_set_sensor_thresholds(intf, num, mask, setting,
482*c18ec02fSPetter Reinholdtsen 				  target, lun, channel);
483*c18ec02fSPetter Reinholdtsen 
484*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
485*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error setting threshold");
486*c18ec02fSPetter Reinholdtsen 		return -1;
487*c18ec02fSPetter Reinholdtsen 	}
488*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
489*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error setting threshold: %s",
490*c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
491*c18ec02fSPetter Reinholdtsen 		return -1;
492*c18ec02fSPetter Reinholdtsen 	}
493*c18ec02fSPetter Reinholdtsen 
494*c18ec02fSPetter Reinholdtsen 	return 0;
495*c18ec02fSPetter Reinholdtsen }
496*c18ec02fSPetter Reinholdtsen 
497*c18ec02fSPetter Reinholdtsen static uint8_t
498*c18ec02fSPetter Reinholdtsen __ipmi_sensor_threshold_value_to_raw(struct sdr_record_full_sensor *full, double value)
499*c18ec02fSPetter Reinholdtsen {
500*c18ec02fSPetter Reinholdtsen 	if (!UNITS_ARE_DISCRETE(&full->cmn)) { /* Has an analog reading */
501*c18ec02fSPetter Reinholdtsen 		/* Has an analog reading and supports mx+b */
502*c18ec02fSPetter Reinholdtsen 		return sdr_convert_sensor_value_to_raw(full, value);
503*c18ec02fSPetter Reinholdtsen 	}
504*c18ec02fSPetter Reinholdtsen 	else {
505*c18ec02fSPetter Reinholdtsen 		/* Does not have an analog reading and/or does not support mx+b */
506*c18ec02fSPetter Reinholdtsen 		if (value > 255) {
507*c18ec02fSPetter Reinholdtsen 			return 255;
508*c18ec02fSPetter Reinholdtsen 		}
509*c18ec02fSPetter Reinholdtsen 		else if (value < 0) {
510*c18ec02fSPetter Reinholdtsen 			return 0;
511*c18ec02fSPetter Reinholdtsen 		}
512*c18ec02fSPetter Reinholdtsen 		else {
513*c18ec02fSPetter Reinholdtsen 			return (uint8_t )value;
514*c18ec02fSPetter Reinholdtsen 		}
515*c18ec02fSPetter Reinholdtsen 	}
516*c18ec02fSPetter Reinholdtsen }
517*c18ec02fSPetter Reinholdtsen 
518*c18ec02fSPetter Reinholdtsen 
519*c18ec02fSPetter Reinholdtsen static int
520*c18ec02fSPetter Reinholdtsen ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
521*c18ec02fSPetter Reinholdtsen {
522*c18ec02fSPetter Reinholdtsen 	char *id, *thresh;
523*c18ec02fSPetter Reinholdtsen 	uint8_t settingMask = 0;
524*c18ec02fSPetter Reinholdtsen 	double setting1 = 0.0, setting2 = 0.0, setting3 = 0.0;
525*c18ec02fSPetter Reinholdtsen 	int allUpper = 0, allLower = 0;
526*c18ec02fSPetter Reinholdtsen 	int ret = 0;
527*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
528*c18ec02fSPetter Reinholdtsen 	int i =0;
529*c18ec02fSPetter Reinholdtsen 	double val[10] = {0};
530*c18ec02fSPetter Reinholdtsen 
531*c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *sdr;
532*c18ec02fSPetter Reinholdtsen 
533*c18ec02fSPetter Reinholdtsen 	if (argc < 3 || strncmp(argv[0], "help", 4) == 0) {
534*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "sensor thresh <id> <threshold> <setting>");
535*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
536*c18ec02fSPetter Reinholdtsen 			"   id        : name of the sensor for which threshold is to be set");
537*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "   threshold : which threshold to set");
538*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
539*c18ec02fSPetter Reinholdtsen 			"                 unr = upper non-recoverable");
540*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "                 ucr = upper critical");
541*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
542*c18ec02fSPetter Reinholdtsen 			"                 unc = upper non-critical");
543*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
544*c18ec02fSPetter Reinholdtsen 			"                 lnc = lower non-critical");
545*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "                 lcr = lower critical");
546*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
547*c18ec02fSPetter Reinholdtsen 			"                 lnr = lower non-recoverable");
548*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
549*c18ec02fSPetter Reinholdtsen 			"   setting   : the value to set the threshold to");
550*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "");
551*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
552*c18ec02fSPetter Reinholdtsen 			"sensor thresh <id> lower <lnr> <lcr> <lnc>");
553*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
554*c18ec02fSPetter Reinholdtsen 			"   Set all lower thresholds at the same time");
555*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "");
556*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
557*c18ec02fSPetter Reinholdtsen 			"sensor thresh <id> upper <unc> <ucr> <unr>");
558*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
559*c18ec02fSPetter Reinholdtsen 			"   Set all upper thresholds at the same time");
560*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "");
561*c18ec02fSPetter Reinholdtsen 		return 0;
562*c18ec02fSPetter Reinholdtsen 	}
563*c18ec02fSPetter Reinholdtsen 
564*c18ec02fSPetter Reinholdtsen 	id = argv[0];
565*c18ec02fSPetter Reinholdtsen 	thresh = argv[1];
566*c18ec02fSPetter Reinholdtsen 
567*c18ec02fSPetter Reinholdtsen 	if (strncmp(thresh, "upper", 5) == 0) {
568*c18ec02fSPetter Reinholdtsen 		if (argc < 5) {
569*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
570*c18ec02fSPetter Reinholdtsen 				"usage: sensor thresh <id> upper <unc> <ucr> <unr>");
571*c18ec02fSPetter Reinholdtsen 			return -1;
572*c18ec02fSPetter Reinholdtsen 		}
573*c18ec02fSPetter Reinholdtsen 		allUpper = 1;
574*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[2], &setting1) != 0) {
575*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given unc '%s' is invalid.",
576*c18ec02fSPetter Reinholdtsen 					argv[2]);
577*c18ec02fSPetter Reinholdtsen 			return (-1);
578*c18ec02fSPetter Reinholdtsen 		}
579*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[3], &setting2) != 0) {
580*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given ucr '%s' is invalid.",
581*c18ec02fSPetter Reinholdtsen 					argv[3]);
582*c18ec02fSPetter Reinholdtsen 			return (-1);
583*c18ec02fSPetter Reinholdtsen 		}
584*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[4], &setting3) != 0) {
585*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given unr '%s' is invalid.",
586*c18ec02fSPetter Reinholdtsen 					argv[4]);
587*c18ec02fSPetter Reinholdtsen 			return (-1);
588*c18ec02fSPetter Reinholdtsen 		}
589*c18ec02fSPetter Reinholdtsen 	} else if (strncmp(thresh, "lower", 5) == 0) {
590*c18ec02fSPetter Reinholdtsen 		if (argc < 5) {
591*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
592*c18ec02fSPetter Reinholdtsen 				"usage: sensor thresh <id> lower <unc> <ucr> <unr>");
593*c18ec02fSPetter Reinholdtsen 			return -1;
594*c18ec02fSPetter Reinholdtsen 		}
595*c18ec02fSPetter Reinholdtsen 		allLower = 1;
596*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[2], &setting1) != 0) {
597*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given lnc '%s' is invalid.",
598*c18ec02fSPetter Reinholdtsen 					argv[2]);
599*c18ec02fSPetter Reinholdtsen 			return (-1);
600*c18ec02fSPetter Reinholdtsen 		}
601*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[3], &setting2) != 0) {
602*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given lcr '%s' is invalid.",
603*c18ec02fSPetter Reinholdtsen 					argv[3]);
604*c18ec02fSPetter Reinholdtsen 			return (-1);
605*c18ec02fSPetter Reinholdtsen 		}
606*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[4], &setting3) != 0) {
607*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Given lnr '%s' is invalid.",
608*c18ec02fSPetter Reinholdtsen 					argv[4]);
609*c18ec02fSPetter Reinholdtsen 			return (-1);
610*c18ec02fSPetter Reinholdtsen 		}
611*c18ec02fSPetter Reinholdtsen 	} else {
612*c18ec02fSPetter Reinholdtsen 		if (strncmp(thresh, "unr", 3) == 0)
613*c18ec02fSPetter Reinholdtsen 			settingMask = UPPER_NON_RECOV_SPECIFIED;
614*c18ec02fSPetter Reinholdtsen 		else if (strncmp(thresh, "ucr", 3) == 0)
615*c18ec02fSPetter Reinholdtsen 			settingMask = UPPER_CRIT_SPECIFIED;
616*c18ec02fSPetter Reinholdtsen 		else if (strncmp(thresh, "unc", 3) == 0)
617*c18ec02fSPetter Reinholdtsen 			settingMask = UPPER_NON_CRIT_SPECIFIED;
618*c18ec02fSPetter Reinholdtsen 		else if (strncmp(thresh, "lnc", 3) == 0)
619*c18ec02fSPetter Reinholdtsen 			settingMask = LOWER_NON_CRIT_SPECIFIED;
620*c18ec02fSPetter Reinholdtsen 		else if (strncmp(thresh, "lcr", 3) == 0)
621*c18ec02fSPetter Reinholdtsen 			settingMask = LOWER_CRIT_SPECIFIED;
622*c18ec02fSPetter Reinholdtsen 		else if (strncmp(thresh, "lnr", 3) == 0)
623*c18ec02fSPetter Reinholdtsen 			settingMask = LOWER_NON_RECOV_SPECIFIED;
624*c18ec02fSPetter Reinholdtsen 		else {
625*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
626*c18ec02fSPetter Reinholdtsen 				"Valid threshold '%s' for sensor '%s' not specified!",
627*c18ec02fSPetter Reinholdtsen 				thresh, id);
628*c18ec02fSPetter Reinholdtsen 			return -1;
629*c18ec02fSPetter Reinholdtsen 		}
630*c18ec02fSPetter Reinholdtsen 		if (str2double(argv[2], &setting1) != 0) {
631*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
632*c18ec02fSPetter Reinholdtsen 					"Given %s threshold value '%s' is invalid.",
633*c18ec02fSPetter Reinholdtsen 					thresh, argv[2]);
634*c18ec02fSPetter Reinholdtsen 			return (-1);
635*c18ec02fSPetter Reinholdtsen 		}
636*c18ec02fSPetter Reinholdtsen 	}
637*c18ec02fSPetter Reinholdtsen 
638*c18ec02fSPetter Reinholdtsen 	printf("Locating sensor record '%s'...\n", id);
639*c18ec02fSPetter Reinholdtsen 
640*c18ec02fSPetter Reinholdtsen 	/* lookup by sensor name */
641*c18ec02fSPetter Reinholdtsen 	sdr = ipmi_sdr_find_sdr_byid(intf, id);
642*c18ec02fSPetter Reinholdtsen 	if (sdr == NULL) {
643*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Sensor data record not found!");
644*c18ec02fSPetter Reinholdtsen 		return -1;
645*c18ec02fSPetter Reinholdtsen 	}
646*c18ec02fSPetter Reinholdtsen 
647*c18ec02fSPetter Reinholdtsen 	if (sdr->type != SDR_RECORD_TYPE_FULL_SENSOR) {
648*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid sensor type %02x", sdr->type);
649*c18ec02fSPetter Reinholdtsen 		return -1;
650*c18ec02fSPetter Reinholdtsen 	}
651*c18ec02fSPetter Reinholdtsen 
652*c18ec02fSPetter Reinholdtsen 	if (!IS_THRESHOLD_SENSOR(sdr->record.common)) {
653*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid sensor event type %02x", sdr->record.common->event_type);
654*c18ec02fSPetter Reinholdtsen 		return -1;
655*c18ec02fSPetter Reinholdtsen 	}
656*c18ec02fSPetter Reinholdtsen 
657*c18ec02fSPetter Reinholdtsen 
658*c18ec02fSPetter Reinholdtsen 	if (allUpper) {
659*c18ec02fSPetter Reinholdtsen 		settingMask = UPPER_NON_CRIT_SPECIFIED;
660*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
661*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
662*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting1);
663*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
664*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
665*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
666*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
667*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
668*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
669*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
670*c18ec02fSPetter Reinholdtsen 
671*c18ec02fSPetter Reinholdtsen 		settingMask = UPPER_CRIT_SPECIFIED;
672*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
673*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
674*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting2);
675*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
676*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
677*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
678*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
679*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
680*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
681*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
682*c18ec02fSPetter Reinholdtsen 
683*c18ec02fSPetter Reinholdtsen 		settingMask = UPPER_NON_RECOV_SPECIFIED;
684*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
685*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
686*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting3);
687*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
688*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
689*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
690*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
691*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
692*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
693*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
694*c18ec02fSPetter Reinholdtsen 	} else if (allLower) {
695*c18ec02fSPetter Reinholdtsen 		settingMask = LOWER_NON_RECOV_SPECIFIED;
696*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
697*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
698*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting1);
699*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
700*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
701*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
702*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
703*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
704*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
705*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
706*c18ec02fSPetter Reinholdtsen 
707*c18ec02fSPetter Reinholdtsen 		settingMask = LOWER_CRIT_SPECIFIED;
708*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
709*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
710*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting2);
711*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
712*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
713*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
714*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
715*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
716*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
717*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
718*c18ec02fSPetter Reinholdtsen 
719*c18ec02fSPetter Reinholdtsen 		settingMask = LOWER_NON_CRIT_SPECIFIED;
720*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
721*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
722*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting3);
723*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
724*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
725*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
726*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
727*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
728*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
729*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
730*c18ec02fSPetter Reinholdtsen 	} else {
731*c18ec02fSPetter Reinholdtsen 
732*c18ec02fSPetter Reinholdtsen 	/*
733*c18ec02fSPetter Reinholdtsen  	 * Current implementation doesn't check for the valid setting of upper non critical and other thresholds.
734*c18ec02fSPetter Reinholdtsen  	 * In the below logic:
735*c18ec02fSPetter Reinholdtsen  	 * 	Get all the current reading of the sensor i.e. unc, uc, lc,lnc.
736*c18ec02fSPetter Reinholdtsen  	 * 	Validate the values given by the user.
737*c18ec02fSPetter Reinholdtsen  	 * 	If the values are not correct, then popup with the Error message and return.
738*c18ec02fSPetter Reinholdtsen  	 */
739*c18ec02fSPetter Reinholdtsen 	/*
740*c18ec02fSPetter Reinholdtsen 	 * Get current reading
741*c18ec02fSPetter Reinholdtsen 	 */
742*c18ec02fSPetter Reinholdtsen 		rsp = ipmi_sdr_get_sensor_reading_ipmb(intf,
743*c18ec02fSPetter Reinholdtsen 					       sdr->record.common->keys.sensor_num,
744*c18ec02fSPetter Reinholdtsen 					       sdr->record.common->keys.owner_id,
745*c18ec02fSPetter Reinholdtsen 					       sdr->record.common->keys.lun,sdr->record.common->keys.channel);
746*c18ec02fSPetter Reinholdtsen 		rsp = ipmi_sdr_get_sensor_thresholds(intf,
747*c18ec02fSPetter Reinholdtsen 						sdr->record.common->keys.sensor_num,
748*c18ec02fSPetter Reinholdtsen 						sdr->record.common->keys.owner_id,
749*c18ec02fSPetter Reinholdtsen 						sdr->record.common->keys.lun,
750*c18ec02fSPetter Reinholdtsen 						sdr->record.common->keys.channel);
751*c18ec02fSPetter Reinholdtsen 		if ((rsp == NULL) || (rsp->ccode > 0)) {
752*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Sensor data record not found!");
753*c18ec02fSPetter Reinholdtsen 				return -1;
754*c18ec02fSPetter Reinholdtsen 		}
755*c18ec02fSPetter Reinholdtsen 		for(i=1;i<=6;i++) {
756*c18ec02fSPetter Reinholdtsen 			val[i] = sdr_convert_sensor_reading(sdr->record.full, rsp->data[i]);
757*c18ec02fSPetter Reinholdtsen 			if(val[i] < 0)
758*c18ec02fSPetter Reinholdtsen 				val[i] = 0;
759*c18ec02fSPetter Reinholdtsen 		}
760*c18ec02fSPetter Reinholdtsen 		/* Check for the valid Upper non recovarable Value.*/
761*c18ec02fSPetter Reinholdtsen 		if( (settingMask & UPPER_NON_RECOV_SPECIFIED) ) {
762*c18ec02fSPetter Reinholdtsen 
763*c18ec02fSPetter Reinholdtsen 			if( (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED) &&
764*c18ec02fSPetter Reinholdtsen 				(( (rsp->data[0] & UPPER_CRIT_SPECIFIED) && ( setting1 <= val[5])) ||
765*c18ec02fSPetter Reinholdtsen 					( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) && ( setting1 <= val[4]))) )
766*c18ec02fSPetter Reinholdtsen 			{
767*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, INVALID_THRESHOLD);
768*c18ec02fSPetter Reinholdtsen 				return -1;
769*c18ec02fSPetter Reinholdtsen 			}
770*c18ec02fSPetter Reinholdtsen 		} else if( (settingMask & UPPER_CRIT_SPECIFIED) ) { 		/* Check for the valid Upper critical Value.*/
771*c18ec02fSPetter Reinholdtsen 			if( (rsp->data[0] & UPPER_CRIT_SPECIFIED) &&
772*c18ec02fSPetter Reinholdtsen 				(((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&& ( setting1 >= val[6])) ||
773*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 <= val[4]))) )
774*c18ec02fSPetter Reinholdtsen 			{
775*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, INVALID_THRESHOLD);
776*c18ec02fSPetter Reinholdtsen 				return -1;
777*c18ec02fSPetter Reinholdtsen 			}
778*c18ec02fSPetter Reinholdtsen 		} else if( (settingMask & UPPER_NON_CRIT_SPECIFIED) ) {  		/* Check for the valid Upper non critical Value.*/
779*c18ec02fSPetter Reinholdtsen 			if( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) &&
780*c18ec02fSPetter Reinholdtsen 				(((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&&( setting1 >= val[6])) ||
781*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & UPPER_CRIT_SPECIFIED)&&( setting1 >= val[5])) ||
782*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 <= val[1]))) )
783*c18ec02fSPetter Reinholdtsen 			{
784*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, INVALID_THRESHOLD);
785*c18ec02fSPetter Reinholdtsen 				return -1;
786*c18ec02fSPetter Reinholdtsen 			}
787*c18ec02fSPetter Reinholdtsen 		} else if( (settingMask & LOWER_NON_CRIT_SPECIFIED) ) {		/* Check for the valid lower non critical Value.*/
788*c18ec02fSPetter Reinholdtsen 			if( (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED) &&
789*c18ec02fSPetter Reinholdtsen 				(((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 <= val[2])) ||
790*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))||
791*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 >= val[4]))) )
792*c18ec02fSPetter Reinholdtsen 			{
793*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, INVALID_THRESHOLD);
794*c18ec02fSPetter Reinholdtsen 				return -1;
795*c18ec02fSPetter Reinholdtsen 			}
796*c18ec02fSPetter Reinholdtsen 		} else if( (settingMask & LOWER_CRIT_SPECIFIED) ) {		/* Check for the valid lower critical Value.*/
797*c18ec02fSPetter Reinholdtsen 			if( (rsp->data[0] & LOWER_CRIT_SPECIFIED) &&
798*c18ec02fSPetter Reinholdtsen 				(((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
799*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))) )
800*c18ec02fSPetter Reinholdtsen 			{
801*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, INVALID_THRESHOLD);
802*c18ec02fSPetter Reinholdtsen 				return -1;
803*c18ec02fSPetter Reinholdtsen 			}
804*c18ec02fSPetter Reinholdtsen 		} else if( (settingMask & LOWER_NON_RECOV_SPECIFIED) ) {		/* Check for the valid lower non recovarable Value.*/
805*c18ec02fSPetter Reinholdtsen 			if( (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED) &&
806*c18ec02fSPetter Reinholdtsen 				(((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
807*c18ec02fSPetter Reinholdtsen 				((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 >= val[2]))) )
808*c18ec02fSPetter Reinholdtsen 			{
809*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, INVALID_THRESHOLD);
810*c18ec02fSPetter Reinholdtsen 				return -1;
811*c18ec02fSPetter Reinholdtsen 			}
812*c18ec02fSPetter Reinholdtsen 		} else {			/* None of this Then Return with error messages.*/
813*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, INVALID_THRESHOLD);
814*c18ec02fSPetter Reinholdtsen 			return -1;
815*c18ec02fSPetter Reinholdtsen 		}
816*c18ec02fSPetter Reinholdtsen 
817*c18ec02fSPetter Reinholdtsen 
818*c18ec02fSPetter Reinholdtsen 		printf("Setting sensor \"%s\" %s threshold to %.3f\n",
819*c18ec02fSPetter Reinholdtsen 		       sdr->record.full->id_string,
820*c18ec02fSPetter Reinholdtsen 		       val2str(settingMask, threshold_vals), setting1);
821*c18ec02fSPetter Reinholdtsen 
822*c18ec02fSPetter Reinholdtsen 		ret = __ipmi_sensor_set_threshold(intf,
823*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.
824*c18ec02fSPetter Reinholdtsen 						  sensor_num, settingMask,
825*c18ec02fSPetter Reinholdtsen 						  __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
826*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.owner_id,
827*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.lun,
828*c18ec02fSPetter Reinholdtsen 						  sdr->record.common->keys.channel);
829*c18ec02fSPetter Reinholdtsen 	}
830*c18ec02fSPetter Reinholdtsen 
831*c18ec02fSPetter Reinholdtsen 	return ret;
832*c18ec02fSPetter Reinholdtsen }
833*c18ec02fSPetter Reinholdtsen 
834*c18ec02fSPetter Reinholdtsen static int
835*c18ec02fSPetter Reinholdtsen ipmi_sensor_get_reading(struct ipmi_intf *intf, int argc, char **argv)
836*c18ec02fSPetter Reinholdtsen {
837*c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *sdr;
838*c18ec02fSPetter Reinholdtsen 	int i, rc=0;
839*c18ec02fSPetter Reinholdtsen 
840*c18ec02fSPetter Reinholdtsen 	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
841*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "sensor reading <id> ... [id]");
842*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "   id        : name of desired sensor");
843*c18ec02fSPetter Reinholdtsen 		return -1;
844*c18ec02fSPetter Reinholdtsen 	}
845*c18ec02fSPetter Reinholdtsen 
846*c18ec02fSPetter Reinholdtsen 	for (i = 0; i < argc; i++) {
847*c18ec02fSPetter Reinholdtsen 		sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
848*c18ec02fSPetter Reinholdtsen 		if (sdr == NULL) {
849*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Sensor \"%s\" not found!",
850*c18ec02fSPetter Reinholdtsen 				argv[i]);
851*c18ec02fSPetter Reinholdtsen 			rc = -1;
852*c18ec02fSPetter Reinholdtsen 			continue;
853*c18ec02fSPetter Reinholdtsen 		}
854*c18ec02fSPetter Reinholdtsen 
855*c18ec02fSPetter Reinholdtsen 		switch (sdr->type) {
856*c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_FULL_SENSOR:
857*c18ec02fSPetter Reinholdtsen 		case SDR_RECORD_TYPE_COMPACT_SENSOR:
858*c18ec02fSPetter Reinholdtsen 		{
859*c18ec02fSPetter Reinholdtsen 			struct sensor_reading *sr;
860*c18ec02fSPetter Reinholdtsen 			struct sdr_record_common_sensor	*sensor = sdr->record.common;
861*c18ec02fSPetter Reinholdtsen 			sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr->type, 3);
862*c18ec02fSPetter Reinholdtsen 
863*c18ec02fSPetter Reinholdtsen 			if (sr == NULL) {
864*c18ec02fSPetter Reinholdtsen 				rc = -1;
865*c18ec02fSPetter Reinholdtsen 				continue;
866*c18ec02fSPetter Reinholdtsen 			}
867*c18ec02fSPetter Reinholdtsen 
868*c18ec02fSPetter Reinholdtsen 			if (!sr->full)
869*c18ec02fSPetter Reinholdtsen 				continue;
870*c18ec02fSPetter Reinholdtsen 
871*c18ec02fSPetter Reinholdtsen 			if (!sr->s_reading_valid)
872*c18ec02fSPetter Reinholdtsen 				continue;
873*c18ec02fSPetter Reinholdtsen 
874*c18ec02fSPetter Reinholdtsen 			if (!sr->s_has_analog_value) {
875*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Sensor \"%s\" is a discrete sensor!", argv[i]);
876*c18ec02fSPetter Reinholdtsen 				continue;
877*c18ec02fSPetter Reinholdtsen 			}
878*c18ec02fSPetter Reinholdtsen 			if (csv_output)
879*c18ec02fSPetter Reinholdtsen 				printf("%s,%s\n", argv[i], sr->s_a_str);
880*c18ec02fSPetter Reinholdtsen 			else
881*c18ec02fSPetter Reinholdtsen 				printf("%-16s | %s\n", argv[i], sr->s_a_str);
882*c18ec02fSPetter Reinholdtsen 
883*c18ec02fSPetter Reinholdtsen 			break;
884*c18ec02fSPetter Reinholdtsen 		}
885*c18ec02fSPetter Reinholdtsen 		default:
886*c18ec02fSPetter Reinholdtsen 			continue;
887*c18ec02fSPetter Reinholdtsen 		}
888*c18ec02fSPetter Reinholdtsen 	}
889*c18ec02fSPetter Reinholdtsen 
890*c18ec02fSPetter Reinholdtsen 	return rc;
891*c18ec02fSPetter Reinholdtsen }
892*c18ec02fSPetter Reinholdtsen 
893*c18ec02fSPetter Reinholdtsen static int
894*c18ec02fSPetter Reinholdtsen ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv)
895*c18ec02fSPetter Reinholdtsen {
896*c18ec02fSPetter Reinholdtsen 	int i, v;
897*c18ec02fSPetter Reinholdtsen 	int rc = 0;
898*c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *sdr;
899*c18ec02fSPetter Reinholdtsen 
900*c18ec02fSPetter Reinholdtsen 	if (argc < 1) {
901*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Not enough parameters given.");
902*c18ec02fSPetter Reinholdtsen 		printf_sensor_get_usage();
903*c18ec02fSPetter Reinholdtsen 		return (-1);
904*c18ec02fSPetter Reinholdtsen 	} else if (strcmp(argv[0], "help") == 0) {
905*c18ec02fSPetter Reinholdtsen 		printf_sensor_get_usage();
906*c18ec02fSPetter Reinholdtsen 		return 0;
907*c18ec02fSPetter Reinholdtsen 	}
908*c18ec02fSPetter Reinholdtsen 	printf("Locating sensor record...\n");
909*c18ec02fSPetter Reinholdtsen 	/* lookup by sensor name */
910*c18ec02fSPetter Reinholdtsen 	for (i = 0; i < argc; i++) {
911*c18ec02fSPetter Reinholdtsen 		sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
912*c18ec02fSPetter Reinholdtsen 		if (sdr == NULL) {
913*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Sensor data record \"%s\" not found!",
914*c18ec02fSPetter Reinholdtsen 					argv[i]);
915*c18ec02fSPetter Reinholdtsen 			rc = -1;
916*c18ec02fSPetter Reinholdtsen 			continue;
917*c18ec02fSPetter Reinholdtsen 		}
918*c18ec02fSPetter Reinholdtsen 		/* need to set verbose level to 1 */
919*c18ec02fSPetter Reinholdtsen 		v = verbose;
920*c18ec02fSPetter Reinholdtsen 		verbose = 1;
921*c18ec02fSPetter Reinholdtsen 		if (ipmi_sdr_print_listentry(intf, sdr) < 0) {
922*c18ec02fSPetter Reinholdtsen 			rc = (-1);
923*c18ec02fSPetter Reinholdtsen 		}
924*c18ec02fSPetter Reinholdtsen 		verbose = v;
925*c18ec02fSPetter Reinholdtsen 		sdr = NULL;
926*c18ec02fSPetter Reinholdtsen 	}
927*c18ec02fSPetter Reinholdtsen 	return rc;
928*c18ec02fSPetter Reinholdtsen }
929*c18ec02fSPetter Reinholdtsen 
930*c18ec02fSPetter Reinholdtsen int
931*c18ec02fSPetter Reinholdtsen ipmi_sensor_main(struct ipmi_intf *intf, int argc, char **argv)
932*c18ec02fSPetter Reinholdtsen {
933*c18ec02fSPetter Reinholdtsen 	int rc = 0;
934*c18ec02fSPetter Reinholdtsen 
935*c18ec02fSPetter Reinholdtsen 	if (argc == 0) {
936*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sensor_list(intf);
937*c18ec02fSPetter Reinholdtsen 	} else if (strncmp(argv[0], "help", 4) == 0) {
938*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "Sensor Commands:  list thresh get reading");
939*c18ec02fSPetter Reinholdtsen 	} else if (strncmp(argv[0], "list", 4) == 0) {
940*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sensor_list(intf);
941*c18ec02fSPetter Reinholdtsen 	} else if (strncmp(argv[0], "thresh", 5) == 0) {
942*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sensor_set_threshold(intf, argc - 1, &argv[1]);
943*c18ec02fSPetter Reinholdtsen 	} else if (strncmp(argv[0], "get", 3) == 0) {
944*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sensor_get(intf, argc - 1, &argv[1]);
945*c18ec02fSPetter Reinholdtsen 	} else if (strncmp(argv[0], "reading", 7) == 0) {
946*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sensor_get_reading(intf, argc - 1, &argv[1]);
947*c18ec02fSPetter Reinholdtsen 	} else {
948*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid sensor command: %s", argv[0]);
949*c18ec02fSPetter Reinholdtsen 		rc = -1;
950*c18ec02fSPetter Reinholdtsen 	}
951*c18ec02fSPetter Reinholdtsen 
952*c18ec02fSPetter Reinholdtsen 	return rc;
953*c18ec02fSPetter Reinholdtsen }
954*c18ec02fSPetter Reinholdtsen 
955*c18ec02fSPetter Reinholdtsen /* printf_sensor_get_usage - print usage for # ipmitool sensor get NAC;
956*c18ec02fSPetter Reinholdtsen  *
957*c18ec02fSPetter Reinholdtsen  * @returns: void
958*c18ec02fSPetter Reinholdtsen  */
959*c18ec02fSPetter Reinholdtsen void
960*c18ec02fSPetter Reinholdtsen printf_sensor_get_usage()
961*c18ec02fSPetter Reinholdtsen {
962*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "sensor get <id> ... [id]");
963*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "   id        : name of desired sensor");
964*c18ec02fSPetter Reinholdtsen }
965