2 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/dev/acpica/acpi_battery.c,v 1.8 2003/08/11 15:34:43 njl Exp $
27 * $DragonFly: src/sys/dev/acpica5/acpi_battery.c,v 1.3 2006/09/05 00:55:36 dillon Exp $
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
35 #include <sys/ioccom.h>
36 #include <sys/sysctl.h>
39 #include <dev/acpica5/acpivar.h>
40 #include <dev/acpica5/acpiio.h>
42 MALLOC_DEFINE(M_ACPIBATT
, "acpibatt", "ACPI generic battery data");
44 struct acpi_batteries
{
45 TAILQ_ENTRY(acpi_batteries
) link
;
46 struct acpi_battdesc battdesc
;
49 static TAILQ_HEAD(,acpi_batteries
) acpi_batteries
;
50 static int acpi_batteries_initted
= 0;
51 static int acpi_batteries_units
= 0;
52 static int acpi_battery_info_expire
= 5;
53 static struct acpi_battinfo acpi_battery_battinfo
;
56 acpi_battery_get_units(void)
58 return (acpi_batteries_units
);
62 acpi_battery_get_battdesc(int logical_unit
, struct acpi_battdesc
*battdesc
)
64 struct acpi_batteries
*bp
;
67 if (logical_unit
< 0 || logical_unit
>= acpi_batteries_units
)
71 TAILQ_FOREACH(bp
, &acpi_batteries
, link
) {
72 if (logical_unit
== i
) {
73 battdesc
->type
= bp
->battdesc
.type
;
74 battdesc
->phys_unit
= bp
->battdesc
.phys_unit
;
84 acpi_battery_get_battinfo(int unit
, struct acpi_battinfo
*battinfo
)
86 struct acpi_battdesc battdesc
;
91 error
= acpi_cmbat_get_battinfo(-1, battinfo
);
94 error
= acpi_battery_get_battdesc(unit
, &battdesc
);
98 switch (battdesc
.type
) {
99 case ACPI_BATT_TYPE_CMBAT
:
100 error
= acpi_cmbat_get_battinfo(battdesc
.phys_unit
, battinfo
);
113 acpi_battery_get_info_expire(void)
115 return (acpi_battery_info_expire
);
119 acpi_battery_ioctl(u_long cmd
, caddr_t addr
, void *arg
)
121 union acpi_battery_ioctl_arg
*ioctl_arg
;
122 int error
, logical_unit
;
124 ioctl_arg
= (union acpi_battery_ioctl_arg
*)addr
;
128 * No security check required: information retrieval only. If
129 * new functions are added here, a check might be required.
132 case ACPIIO_BATT_GET_UNITS
:
133 *(int *)addr
= acpi_battery_get_units();
135 case ACPIIO_BATT_GET_BATTDESC
:
136 logical_unit
= ioctl_arg
->unit
;
137 error
= acpi_battery_get_battdesc(logical_unit
, &ioctl_arg
->battdesc
);
139 case ACPIIO_BATT_GET_BATTINFO
:
140 logical_unit
= ioctl_arg
->unit
;
141 error
= acpi_battery_get_battinfo(logical_unit
, &ioctl_arg
->battinfo
);
152 acpi_battery_sysctl(SYSCTL_HANDLER_ARGS
)
156 acpi_battery_get_battinfo(-1, &acpi_battery_battinfo
);
157 val
= *(u_int
*)oidp
->oid_arg1
;
158 error
= sysctl_handle_int(oidp
, &val
, 0, req
);
163 acpi_battery_init(void)
165 struct acpi_softc
*sc
;
169 dev
= devclass_get_device(devclass_find("acpi"), 0);
172 sc
= device_get_softc(dev
);
177 TAILQ_INIT(&acpi_batteries
);
178 acpi_batteries_initted
= 1;
180 error
= acpi_register_ioctl(ACPIIO_BATT_GET_UNITS
, acpi_battery_ioctl
,
184 error
= acpi_register_ioctl(ACPIIO_BATT_GET_BATTDESC
, acpi_battery_ioctl
,
188 error
= acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO
, acpi_battery_ioctl
,
193 sysctl_ctx_init(&sc
->acpi_battery_sysctl_ctx
);
194 sc
->acpi_battery_sysctl_tree
= SYSCTL_ADD_NODE(&sc
->acpi_battery_sysctl_ctx
,
195 SYSCTL_CHILDREN(sc
->acpi_sysctl_tree
),
196 OID_AUTO
, "battery", CTLFLAG_RD
, 0, "");
197 SYSCTL_ADD_PROC(&sc
->acpi_battery_sysctl_ctx
,
198 SYSCTL_CHILDREN(sc
->acpi_battery_sysctl_tree
),
199 OID_AUTO
, "life", CTLTYPE_INT
| CTLFLAG_RD
,
200 &acpi_battery_battinfo
.cap
, 0, acpi_battery_sysctl
, "I", "");
201 SYSCTL_ADD_PROC(&sc
->acpi_battery_sysctl_ctx
,
202 SYSCTL_CHILDREN(sc
->acpi_battery_sysctl_tree
),
203 OID_AUTO
, "time", CTLTYPE_INT
| CTLFLAG_RD
,
204 &acpi_battery_battinfo
.min
, 0, acpi_battery_sysctl
, "I", "");
205 SYSCTL_ADD_PROC(&sc
->acpi_battery_sysctl_ctx
,
206 SYSCTL_CHILDREN(sc
->acpi_battery_sysctl_tree
),
207 OID_AUTO
, "state", CTLTYPE_INT
| CTLFLAG_RD
,
208 &acpi_battery_battinfo
.state
, 0, acpi_battery_sysctl
, "I", "");
209 SYSCTL_ADD_INT(&sc
->acpi_battery_sysctl_ctx
,
210 SYSCTL_CHILDREN(sc
->acpi_battery_sysctl_tree
),
211 OID_AUTO
, "units", CTLFLAG_RD
, &acpi_batteries_units
, 0, "");
212 SYSCTL_ADD_INT(&sc
->acpi_battery_sysctl_ctx
,
213 SYSCTL_CHILDREN(sc
->acpi_battery_sysctl_tree
),
214 OID_AUTO
, "info_expire", CTLFLAG_RD
| CTLFLAG_RW
,
215 &acpi_battery_info_expire
, 0, "");
221 acpi_battery_register(int type
, int phys_unit
)
223 struct acpi_batteries
*bp
;
227 bp
= kmalloc(sizeof(*bp
), M_ACPIBATT
, M_INTWAIT
);
228 bp
->battdesc
.type
= type
;
229 bp
->battdesc
.phys_unit
= phys_unit
;
230 if (acpi_batteries_initted
== 0) {
231 if ((error
= acpi_battery_init()) != 0) {
232 kfree(bp
, M_ACPIBATT
);
237 TAILQ_INSERT_TAIL(&acpi_batteries
, bp
, link
);
238 acpi_batteries_units
++;