xref: /titanic_52/usr/src/cmd/powertop/common/battery.c (revision 9bbf5ba14ae201f78f3d6b47a9fac96d68649275)
1b47b5b34SRafael Vanoni /*
2b47b5b34SRafael Vanoni  * Copyright 2009, Intel Corporation
3b47b5b34SRafael Vanoni  * Copyright 2009, Sun Microsystems, Inc
4b47b5b34SRafael Vanoni  *
5b47b5b34SRafael Vanoni  * This file is part of PowerTOP
6b47b5b34SRafael Vanoni  *
7b47b5b34SRafael Vanoni  * This program file is free software; you can redistribute it and/or modify it
8b47b5b34SRafael Vanoni  * under the terms of the GNU General Public License as published by the
9b47b5b34SRafael Vanoni  * Free Software Foundation; version 2 of the License.
10b47b5b34SRafael Vanoni  *
11b47b5b34SRafael Vanoni  * This program is distributed in the hope that it will be useful, but WITHOUT
12b47b5b34SRafael Vanoni  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13b47b5b34SRafael Vanoni  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14b47b5b34SRafael Vanoni  * for more details.
15b47b5b34SRafael Vanoni  *
16b47b5b34SRafael Vanoni  * You should have received a copy of the GNU General Public License
17b47b5b34SRafael Vanoni  * along with this program in a file named COPYING; if not, write to the
18b47b5b34SRafael Vanoni  * Free Software Foundation, Inc.,
19b47b5b34SRafael Vanoni  * 51 Franklin Street, Fifth Floor,
20b47b5b34SRafael Vanoni  * Boston, MA 02110-1301 USA
21b47b5b34SRafael Vanoni  *
22b47b5b34SRafael Vanoni  * Authors:
23b47b5b34SRafael Vanoni  *	Arjan van de Ven <arjan@linux.intel.com>
24b47b5b34SRafael Vanoni  *	Eric C Saxe <eric.saxe@sun.com>
25b47b5b34SRafael Vanoni  *	Aubrey Li <aubrey.li@intel.com>
26b47b5b34SRafael Vanoni  */
27b47b5b34SRafael Vanoni 
28b47b5b34SRafael Vanoni /*
29b47b5b34SRafael Vanoni  * GPL Disclaimer
30b47b5b34SRafael Vanoni  *
31b47b5b34SRafael Vanoni  * For the avoidance of doubt, except that if any license choice other
32b47b5b34SRafael Vanoni  * than GPL or LGPL is available it will apply instead, Sun elects to
33b47b5b34SRafael Vanoni  * use only the General Public License version 2 (GPLv2) at this time
34b47b5b34SRafael Vanoni  * for any software where a choice of GPL license versions is made
35b47b5b34SRafael Vanoni  * available with the language indicating that GPLv2 or any later
36b47b5b34SRafael Vanoni  * version may be used, or where a choice of which version of the GPL
37b47b5b34SRafael Vanoni  * is applied is otherwise unspecified.
38b47b5b34SRafael Vanoni  */
39b47b5b34SRafael Vanoni 
40b47b5b34SRafael Vanoni #include <string.h>
41b47b5b34SRafael Vanoni #include <kstat.h>
42b47b5b34SRafael Vanoni #include <errno.h>
43b47b5b34SRafael Vanoni #include "powertop.h"
44b47b5b34SRafael Vanoni 
45b47b5b34SRafael Vanoni #define	mW2W(value)	((value) / 1000)
46b47b5b34SRafael Vanoni 
47b47b5b34SRafael Vanoni typedef struct battery_state {
48b47b5b34SRafael Vanoni 	uint32_t exist;
49b47b5b34SRafael Vanoni 	uint32_t power_unit;
50b47b5b34SRafael Vanoni 	uint32_t bst_state;
51b47b5b34SRafael Vanoni 	double present_rate;
52b47b5b34SRafael Vanoni 	double remain_cap;
53b47b5b34SRafael Vanoni 	double last_cap;
54b47b5b34SRafael Vanoni } battery_state_t;
55b47b5b34SRafael Vanoni 
56b47b5b34SRafael Vanoni static char		*kstat_batt_mod[3] = {NULL, "battery", "acpi_drv"};
57b47b5b34SRafael Vanoni static uint_t		kstat_batt_idx;
58b47b5b34SRafael Vanoni static battery_state_t	battery_state;
59b47b5b34SRafael Vanoni 
60b47b5b34SRafael Vanoni static int		battery_stat_snapshot(void);
61b47b5b34SRafael Vanoni 
62b47b5b34SRafael Vanoni /*
63b47b5b34SRafael Vanoni  * Checks if the kstat module for battery information is present and
64b47b5b34SRafael Vanoni  * whether it's called 'battery' or 'acpi_drv'
65b47b5b34SRafael Vanoni  */
66b47b5b34SRafael Vanoni void
67b47b5b34SRafael Vanoni battery_mod_lookup(void)
68b47b5b34SRafael Vanoni {
69b47b5b34SRafael Vanoni 	kstat_ctl_t *kc = kstat_open();
70b47b5b34SRafael Vanoni 
71b47b5b34SRafael Vanoni 	if (kstat_lookup(kc, kstat_batt_mod[1], 0, NULL))
72b47b5b34SRafael Vanoni 		kstat_batt_idx = 1;
73b47b5b34SRafael Vanoni 	else
74b47b5b34SRafael Vanoni 		if (kstat_lookup(kc, kstat_batt_mod[2], 0, NULL))
75b47b5b34SRafael Vanoni 			kstat_batt_idx = 2;
76b47b5b34SRafael Vanoni 		else
77b47b5b34SRafael Vanoni 			kstat_batt_idx = 0;
78b47b5b34SRafael Vanoni 
79b47b5b34SRafael Vanoni 	(void) kstat_close(kc);
80b47b5b34SRafael Vanoni }
81b47b5b34SRafael Vanoni 
82b47b5b34SRafael Vanoni void
83*9bbf5ba1SRafael Vanoni pt_battery_print(void)
84b47b5b34SRafael Vanoni {
85b47b5b34SRafael Vanoni 	int err;
86b47b5b34SRafael Vanoni 
87b47b5b34SRafael Vanoni 	(void) memset(&battery_state, 0, sizeof (battery_state_t));
88b47b5b34SRafael Vanoni 
89b47b5b34SRafael Vanoni 	/*
90b47b5b34SRafael Vanoni 	 * The return value of battery_stat_snapshot() can be used for
91b47b5b34SRafael Vanoni 	 * debug or to show/hide the acpi power line. We currently don't
92b47b5b34SRafael Vanoni 	 * make the distinction of a system that runs only on AC and one
93b47b5b34SRafael Vanoni 	 * that runs on battery but has no kstat battery info.
94b47b5b34SRafael Vanoni 	 *
95b47b5b34SRafael Vanoni 	 * We still display the estimate power usage for systems
96b47b5b34SRafael Vanoni 	 * running on AC with a fully charged battery because some
97b47b5b34SRafael Vanoni 	 * batteries may still consume power.
98b47b5b34SRafael Vanoni 	 *
99b47b5b34SRafael Vanoni 	 * If battery_mod_lookup() didn't find a kstat battery module, don't
100b47b5b34SRafael Vanoni 	 * bother trying to take the snapshot
101b47b5b34SRafael Vanoni 	 */
102b47b5b34SRafael Vanoni 	if (kstat_batt_idx > 0) {
103b47b5b34SRafael Vanoni 		if ((err = battery_stat_snapshot()) < 0)
104b47b5b34SRafael Vanoni 			pt_error("%s : battery kstat not found %d\n", __FILE__,
105b47b5b34SRafael Vanoni 			    err);
106b47b5b34SRafael Vanoni 	}
107b47b5b34SRafael Vanoni 
108*9bbf5ba1SRafael Vanoni 	pt_display_acpi_power(battery_state.exist, battery_state.present_rate,
109b47b5b34SRafael Vanoni 	    battery_state.remain_cap, battery_state.last_cap,
110b47b5b34SRafael Vanoni 	    battery_state.bst_state);
111b47b5b34SRafael Vanoni }
112b47b5b34SRafael Vanoni 
113b47b5b34SRafael Vanoni static int
114b47b5b34SRafael Vanoni battery_stat_snapshot(void)
115b47b5b34SRafael Vanoni {
116b47b5b34SRafael Vanoni 	kstat_ctl_t	*kc;
117b47b5b34SRafael Vanoni 	kstat_t		*ksp;
118b47b5b34SRafael Vanoni 	kstat_named_t	*knp;
119b47b5b34SRafael Vanoni 
120b47b5b34SRafael Vanoni 	kc = kstat_open();
121b47b5b34SRafael Vanoni 
122b47b5b34SRafael Vanoni 	/*
123b47b5b34SRafael Vanoni 	 * power unit:
124b47b5b34SRafael Vanoni 	 * 	0 - Capacity information is reported in [mWh] and
125b47b5b34SRafael Vanoni 	 *	    charge/discharge rate information in [mW]
126b47b5b34SRafael Vanoni 	 *	1 - Capacity information is reported in [mAh] and
127b47b5b34SRafael Vanoni 	 *	    charge/discharge rate information in [mA].
128b47b5b34SRafael Vanoni 	 */
129b47b5b34SRafael Vanoni 	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
130b47b5b34SRafael Vanoni 	    "battery BIF0");
131b47b5b34SRafael Vanoni 
132b47b5b34SRafael Vanoni 	if (ksp == NULL) {
133b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
134b47b5b34SRafael Vanoni 		return (-1);
135b47b5b34SRafael Vanoni 	}
136b47b5b34SRafael Vanoni 
137b47b5b34SRafael Vanoni 	(void) kstat_read(kc, ksp, NULL);
138b47b5b34SRafael Vanoni 	knp = kstat_data_lookup(ksp, "bif_unit");
139b47b5b34SRafael Vanoni 
140b47b5b34SRafael Vanoni 	if (knp == NULL) {
141b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
142b47b5b34SRafael Vanoni 		return (-1);
143b47b5b34SRafael Vanoni 	}
144b47b5b34SRafael Vanoni 
145b47b5b34SRafael Vanoni 	battery_state.power_unit = knp->value.ui32;
146b47b5b34SRafael Vanoni 
147b47b5b34SRafael Vanoni 	/*
148b47b5b34SRafael Vanoni 	 * Present rate:
149b47b5b34SRafael Vanoni 	 *	the power or current being supplied or accepted
150b47b5b34SRafael Vanoni 	 *	through the battery's terminal
151b47b5b34SRafael Vanoni 	 */
152b47b5b34SRafael Vanoni 	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
153b47b5b34SRafael Vanoni 	    "battery BST0");
154b47b5b34SRafael Vanoni 
155b47b5b34SRafael Vanoni 	if (ksp == NULL) {
156b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
157b47b5b34SRafael Vanoni 		return (-1);
158b47b5b34SRafael Vanoni 	}
159b47b5b34SRafael Vanoni 
160b47b5b34SRafael Vanoni 	(void) kstat_read(kc, ksp, NULL);
161b47b5b34SRafael Vanoni 	knp = kstat_data_lookup(ksp, "bst_rate");
162b47b5b34SRafael Vanoni 
163b47b5b34SRafael Vanoni 	if (knp == NULL) {
164b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
165b47b5b34SRafael Vanoni 		return (-1);
166b47b5b34SRafael Vanoni 	}
167b47b5b34SRafael Vanoni 
168b47b5b34SRafael Vanoni 	if (knp->value.ui32 == 0xFFFFFFFF)
169b47b5b34SRafael Vanoni 		battery_state.present_rate = 0;
170b47b5b34SRafael Vanoni 	else {
171b47b5b34SRafael Vanoni 		battery_state.exist = 1;
172b47b5b34SRafael Vanoni 		battery_state.present_rate = mW2W((double)(knp->value.ui32));
173b47b5b34SRafael Vanoni 	}
174b47b5b34SRafael Vanoni 
175b47b5b34SRafael Vanoni 	/*
176b47b5b34SRafael Vanoni 	 * Last Full charge capacity:
177b47b5b34SRafael Vanoni 	 *	Predicted battery capacity when fully charged.
178b47b5b34SRafael Vanoni 	 */
179b47b5b34SRafael Vanoni 	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
180b47b5b34SRafael Vanoni 	    "battery BIF0");
181b47b5b34SRafael Vanoni 
182b47b5b34SRafael Vanoni 	if (ksp == NULL) {
183b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
184b47b5b34SRafael Vanoni 		return (-1);
185b47b5b34SRafael Vanoni 	}
186b47b5b34SRafael Vanoni 
187b47b5b34SRafael Vanoni 	(void) kstat_read(kc, ksp, NULL);
188b47b5b34SRafael Vanoni 	knp = kstat_data_lookup(ksp, "bif_last_cap");
189b47b5b34SRafael Vanoni 
190b47b5b34SRafael Vanoni 	if (knp == NULL) {
191b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
192b47b5b34SRafael Vanoni 		return (-1);
193b47b5b34SRafael Vanoni 	}
194b47b5b34SRafael Vanoni 
195b47b5b34SRafael Vanoni 	battery_state.last_cap = mW2W((double)(knp->value.ui32));
196b47b5b34SRafael Vanoni 
197b47b5b34SRafael Vanoni 	/*
198b47b5b34SRafael Vanoni 	 * Remaining capacity:
199b47b5b34SRafael Vanoni 	 *	the estimated remaining battery capacity
200b47b5b34SRafael Vanoni 	 */
201b47b5b34SRafael Vanoni 	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
202b47b5b34SRafael Vanoni 	    "battery BST0");
203b47b5b34SRafael Vanoni 
204b47b5b34SRafael Vanoni 	if (ksp == NULL) {
205b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
206b47b5b34SRafael Vanoni 		return (-1);
207b47b5b34SRafael Vanoni 	}
208b47b5b34SRafael Vanoni 
209b47b5b34SRafael Vanoni 	(void) kstat_read(kc, ksp, NULL);
210b47b5b34SRafael Vanoni 	knp = kstat_data_lookup(ksp, "bst_rem_cap");
211b47b5b34SRafael Vanoni 
212b47b5b34SRafael Vanoni 	if (knp == NULL) {
213b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
214b47b5b34SRafael Vanoni 		return (-1);
215b47b5b34SRafael Vanoni 	}
216b47b5b34SRafael Vanoni 
217b47b5b34SRafael Vanoni 	battery_state.remain_cap = mW2W((double)(knp->value.ui32));
218b47b5b34SRafael Vanoni 
219b47b5b34SRafael Vanoni 	/*
220b47b5b34SRafael Vanoni 	 * Battery State:
221b47b5b34SRafael Vanoni 	 *	Bit0 - 1 : discharging
222b47b5b34SRafael Vanoni 	 *	Bit1 - 1 : charging
223b47b5b34SRafael Vanoni 	 *	Bit2 - 1 : critical energy state
224b47b5b34SRafael Vanoni 	 */
225b47b5b34SRafael Vanoni 	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
226b47b5b34SRafael Vanoni 	    "battery BST0");
227b47b5b34SRafael Vanoni 
228b47b5b34SRafael Vanoni 	if (ksp == NULL) {
229b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
230b47b5b34SRafael Vanoni 		return (-1);
231b47b5b34SRafael Vanoni 	}
232b47b5b34SRafael Vanoni 
233b47b5b34SRafael Vanoni 	(void) kstat_read(kc, ksp, NULL);
234b47b5b34SRafael Vanoni 	knp = kstat_data_lookup(ksp, "bst_state");
235b47b5b34SRafael Vanoni 
236b47b5b34SRafael Vanoni 	if (knp == NULL) {
237b47b5b34SRafael Vanoni 		(void) kstat_close(kc);
238b47b5b34SRafael Vanoni 		return (-1);
239b47b5b34SRafael Vanoni 	}
240b47b5b34SRafael Vanoni 
241b47b5b34SRafael Vanoni 	battery_state.bst_state = knp->value.ui32;
242b47b5b34SRafael Vanoni 
243b47b5b34SRafael Vanoni 	(void) kstat_close(kc);
244b47b5b34SRafael Vanoni 
245b47b5b34SRafael Vanoni 	return (0);
246b47b5b34SRafael Vanoni }
247