acpi_battery.c revision 85729
179282Smsmith/*-
279282Smsmith * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
379282Smsmith * All rights reserved.
479282Smsmith *
579282Smsmith * Redistribution and use in source and binary forms, with or without
679282Smsmith * modification, are permitted provided that the following conditions
779282Smsmith * are met:
879282Smsmith * 1. Redistributions of source code must retain the above copyright
979282Smsmith *    notice, this list of conditions and the following disclaimer.
1079282Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1179282Smsmith *    notice, this list of conditions and the following disclaimer in the
1279282Smsmith *    documentation and/or other materials provided with the distribution.
1379282Smsmith *
1479282Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1579282Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1679282Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1779282Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1879282Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1979282Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2079282Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2179282Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2279282Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2379282Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2479282Smsmith * SUCH DAMAGE.
2579282Smsmith *
2679282Smsmith *	$FreeBSD: head/sys/dev/acpica/acpi_battery.c 85729 2001-10-30 14:24:26Z iwasaki $
2779282Smsmith */
2879282Smsmith
2979282Smsmith#include "opt_acpi.h"		/* XXX trim includes */
3079282Smsmith#include <sys/param.h>
3179282Smsmith#include <sys/kernel.h>
3279282Smsmith#include <sys/proc.h>
3379282Smsmith#include <sys/lock.h>
3479282Smsmith#include <sys/malloc.h>
3579282Smsmith#include <sys/mutex.h>
3679282Smsmith#include <sys/bus.h>
3779282Smsmith#include <sys/conf.h>
3879282Smsmith#include <sys/ioccom.h>
3979282Smsmith#include <sys/reboot.h>
4079282Smsmith#include <sys/sysctl.h>
4179282Smsmith#include <sys/ctype.h>
4279282Smsmith
4379282Smsmith#include <machine/clock.h>
4479282Smsmith
4579282Smsmith#include <machine/resource.h>
4679282Smsmith
4779282Smsmith#include "acpi.h"
4879282Smsmith
4979282Smsmith#include <dev/acpica/acpivar.h>
5079282Smsmith#include <dev/acpica/acpiio.h>
5179282Smsmith
5282372SmsmithMALLOC_DEFINE(M_ACPIBATT, "acpibatt", "ACPI generic battery data");
5379282Smsmith
5479282Smsmith/*
5579282Smsmith * ACPI Battery Abstruction Layer.
5679282Smsmith */
5779282Smsmith
5879282Smsmithstruct acpi_batteries {
5979282Smsmith	TAILQ_ENTRY(acpi_batteries) link;
6079282Smsmith	struct	 acpi_battdesc battdesc;
6179282Smsmith};
6279282Smsmith
6379282Smsmithstatic TAILQ_HEAD(,acpi_batteries) acpi_batteries;
6479282Smsmithstatic int			acpi_batteries_initted = 0;
6579282Smsmithstatic int			acpi_batteries_units = 0;
6685729Siwasakistatic int			acpi_battery_info_expire = 5;
6779282Smsmithstatic struct acpi_battinfo	acpi_battery_battinfo;
6879282Smsmith
6985556Siwasakiint
7079282Smsmithacpi_battery_get_units(void)
7179282Smsmith{
7279282Smsmith
7379282Smsmith	return (acpi_batteries_units);
7479282Smsmith}
7579282Smsmith
7685556Siwasakiint
7779282Smsmithacpi_battery_get_battdesc(int logical_unit, struct acpi_battdesc *battdesc)
7879282Smsmith{
7979282Smsmith	int	 i;
8079282Smsmith	struct acpi_batteries	*bp;
8179282Smsmith
8279282Smsmith	if (logical_unit < 0 || logical_unit >= acpi_batteries_units) {
8379282Smsmith		return (ENXIO);
8479282Smsmith	}
8579282Smsmith
8679282Smsmith	i = 0;
8779282Smsmith	TAILQ_FOREACH(bp, &acpi_batteries, link) {
8879282Smsmith		if (logical_unit == i) {
8979282Smsmith			battdesc->type = bp->battdesc.type;
9079282Smsmith			battdesc->phys_unit = bp->battdesc.phys_unit;
9179282Smsmith			return (0);
9279282Smsmith		}
9379282Smsmith		i++;
9479282Smsmith	}
9579282Smsmith
9679282Smsmith	return (ENXIO);
9779282Smsmith}
9879282Smsmith
9985556Siwasakiint
10079282Smsmithacpi_battery_get_battinfo(int unit, struct acpi_battinfo *battinfo)
10179282Smsmith{
10279282Smsmith	int	 error;
10379282Smsmith	struct	 acpi_battdesc battdesc;
10479282Smsmith
10579282Smsmith	error = 0;
10679282Smsmith	if (unit == -1) {
10779282Smsmith		error = acpi_cmbat_get_battinfo(-1, battinfo);
10879282Smsmith		goto out;
10979282Smsmith	} else {
11079282Smsmith		if ((error = acpi_battery_get_battdesc(unit, &battdesc)) != 0) {
11179282Smsmith			goto out;
11279282Smsmith		}
11379282Smsmith		switch (battdesc.type) {
11479282Smsmith		case ACPI_BATT_TYPE_CMBAT:
11579282Smsmith			error = acpi_cmbat_get_battinfo(battdesc.phys_unit,
11679282Smsmith			   battinfo);
11779282Smsmith			break;
11879282Smsmith		default:
11979282Smsmith			error = ENXIO;
12079282Smsmith			break;
12179282Smsmith		}
12279282Smsmith	}
12379282Smsmithout:
12479282Smsmith	return (error);
12579282Smsmith}
12679282Smsmith
12785729Siwasakiint
12885729Siwasakiacpi_battery_get_info_expire(void)
12985729Siwasaki{
13085729Siwasaki
13185729Siwasaki	return (acpi_battery_info_expire);
13285729Siwasaki}
13385729Siwasaki
13479282Smsmithstatic int
13579282Smsmithacpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
13679282Smsmith{
13779282Smsmith	int	 error;
13879282Smsmith	int	 logical_unit;
13979282Smsmith	union acpi_battery_ioctl_arg	*ioctl_arg;
14079282Smsmith
14179282Smsmith	ioctl_arg = (union acpi_battery_ioctl_arg *)addr;
14279282Smsmith	error = 0;
14379282Smsmith	switch (cmd) {
14479282Smsmith	case ACPIIO_BATT_GET_UNITS:
14579282Smsmith		*(int *)addr = acpi_battery_get_units();
14679282Smsmith		break;
14779282Smsmith
14879282Smsmith	case ACPIIO_BATT_GET_BATTDESC:
14979282Smsmith		logical_unit = ioctl_arg->unit;
15079282Smsmith		error = acpi_battery_get_battdesc(logical_unit, &ioctl_arg->battdesc);
15179282Smsmith		break;
15279282Smsmith
15379282Smsmith	case ACPIIO_BATT_GET_BATTINFO:
15479282Smsmith		logical_unit = ioctl_arg->unit;
15579282Smsmith		error = acpi_battery_get_battinfo(logical_unit,
15679282Smsmith		    &ioctl_arg->battinfo);
15779282Smsmith		break;
15879282Smsmith
15979282Smsmith	default:
16079282Smsmith		error = EINVAL;
16179282Smsmith		break;
16279282Smsmith	}
16379282Smsmith
16479282Smsmith	return (error);
16579282Smsmith}
16679282Smsmith
16779282Smsmithstatic int
16879282Smsmithacpi_battery_sysctl(SYSCTL_HANDLER_ARGS)
16979282Smsmith{
17079282Smsmith	int	val;
17179282Smsmith	int	error;
17279282Smsmith
17379282Smsmith	acpi_battery_get_battinfo(-1, &acpi_battery_battinfo);
17479282Smsmith	val = *(u_int *)oidp->oid_arg1;
17579282Smsmith	error = sysctl_handle_int(oidp, &val, 0, req);
17679282Smsmith	return (error);
17779282Smsmith}
17879282Smsmith
17979282Smsmithstatic int
18079282Smsmithacpi_battery_init(void)
18179282Smsmith{
18279282Smsmith	device_t		 dev;
18379282Smsmith	struct acpi_softc	*sc;
18479282Smsmith	int	 		 error;
18579282Smsmith
18679282Smsmith	if ((dev = devclass_get_device(acpi_devclass, 0)) == NULL) {
18779282Smsmith		return (ENXIO);
18879282Smsmith	}
18979282Smsmith	if ((sc = device_get_softc(dev)) == NULL) {
19079282Smsmith		return (ENXIO);
19179282Smsmith	}
19279282Smsmith
19379282Smsmith	error = 0;
19479282Smsmith
19579282Smsmith	TAILQ_INIT(&acpi_batteries);
19679282Smsmith	acpi_batteries_initted = 1;
19779282Smsmith
19879282Smsmith	if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS,
19979282Smsmith			acpi_battery_ioctl, NULL)) != 0) {
20079282Smsmith		return (error);
20179282Smsmith	}
20279282Smsmith	if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTDESC,
20379282Smsmith			acpi_battery_ioctl, NULL)) != 0) {
20479282Smsmith		return (error);
20579282Smsmith	}
20679282Smsmith	if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO,
20779282Smsmith			acpi_battery_ioctl, NULL)) != 0) {
20879282Smsmith		return (error);
20979282Smsmith	}
21079282Smsmith
21179282Smsmith	sysctl_ctx_init(&sc->acpi_battery_sysctl_ctx);
21279282Smsmith	sc->acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_battery_sysctl_ctx,
21379282Smsmith				SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
21479282Smsmith				OID_AUTO, "battery", CTLFLAG_RD, 0, "");
21579282Smsmith	SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
21679282Smsmith		SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
21779282Smsmith		OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD,
21879282Smsmith		&acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", "");
21979282Smsmith	SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
22079282Smsmith		SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
22179282Smsmith		OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD,
22279282Smsmith		&acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", "");
22379282Smsmith	SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
22479282Smsmith		SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
22579282Smsmith		OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD,
22679282Smsmith		&acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", "");
22779282Smsmith	SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx,
22879282Smsmith		SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
22979282Smsmith		OID_AUTO, "units", CTLFLAG_RD, &acpi_batteries_units, 0, "");
23085729Siwasaki	SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx,
23185729Siwasaki		SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
23285729Siwasaki		OID_AUTO, "info_expire", CTLFLAG_RD | CTLFLAG_RW,
23385729Siwasaki		&acpi_battery_info_expire, 0, "");
23479282Smsmith
23579282Smsmith	return (error);
23679282Smsmith}
23779282Smsmith
23879282Smsmithint
23979282Smsmithacpi_battery_register(int type, int phys_unit)
24079282Smsmith{
24179282Smsmith	int	error;
24279282Smsmith	struct acpi_batteries	*bp;
24379282Smsmith
24479282Smsmith	error = 0;
24582372Smsmith	if ((bp = malloc(sizeof(*bp), M_ACPIBATT, M_NOWAIT)) == NULL) {
24679282Smsmith		return(ENOMEM);
24779282Smsmith	}
24879282Smsmith
24979282Smsmith	bp->battdesc.type = type;
25079282Smsmith	bp->battdesc.phys_unit = phys_unit;
25179282Smsmith	if (acpi_batteries_initted == 0) {
25279282Smsmith		if ((error = acpi_battery_init()) != 0) {
25382372Smsmith			free(bp, M_ACPIBATT);
25479282Smsmith			return(error);
25579282Smsmith		}
25679282Smsmith	}
25779282Smsmith
25879282Smsmith	TAILQ_INSERT_TAIL(&acpi_batteries, bp, link);
25979282Smsmith	acpi_batteries_units++;
26079282Smsmith
26179282Smsmith	return(0);
26279282Smsmith}
263