acpi_battery.c revision 118783
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 118783 2003-08-11 15:34:43Z njl $ 2779282Smsmith */ 2879282Smsmith 29118783Snjl#include "opt_acpi.h" 3079282Smsmith#include <sys/param.h> 3179282Smsmith#include <sys/kernel.h> 3279282Smsmith#include <sys/malloc.h> 3379282Smsmith#include <sys/bus.h> 3479282Smsmith#include <sys/ioccom.h> 3579282Smsmith#include <sys/sysctl.h> 3679282Smsmith 3779282Smsmith#include "acpi.h" 3879282Smsmith#include <dev/acpica/acpivar.h> 3979282Smsmith#include <dev/acpica/acpiio.h> 4079282Smsmith 4182372SmsmithMALLOC_DEFINE(M_ACPIBATT, "acpibatt", "ACPI generic battery data"); 4279282Smsmith 4379282Smsmithstruct acpi_batteries { 44118783Snjl TAILQ_ENTRY(acpi_batteries) link; 45118783Snjl struct acpi_battdesc battdesc; 4679282Smsmith}; 4779282Smsmith 4879282Smsmithstatic TAILQ_HEAD(,acpi_batteries) acpi_batteries; 4979282Smsmithstatic int acpi_batteries_initted = 0; 5079282Smsmithstatic int acpi_batteries_units = 0; 5185729Siwasakistatic int acpi_battery_info_expire = 5; 5279282Smsmithstatic struct acpi_battinfo acpi_battery_battinfo; 5379282Smsmith 5485556Siwasakiint 5579282Smsmithacpi_battery_get_units(void) 5679282Smsmith{ 57118783Snjl return (acpi_batteries_units); 5879282Smsmith} 5979282Smsmith 6085556Siwasakiint 6179282Smsmithacpi_battery_get_battdesc(int logical_unit, struct acpi_battdesc *battdesc) 6279282Smsmith{ 63118783Snjl struct acpi_batteries *bp; 64118783Snjl int i; 6579282Smsmith 66118783Snjl if (logical_unit < 0 || logical_unit >= acpi_batteries_units) 67118783Snjl return (ENXIO); 6879282Smsmith 69118783Snjl i = 0; 70118783Snjl TAILQ_FOREACH(bp, &acpi_batteries, link) { 71118783Snjl if (logical_unit == i) { 72118783Snjl battdesc->type = bp->battdesc.type; 73118783Snjl battdesc->phys_unit = bp->battdesc.phys_unit; 74118783Snjl return (0); 7579282Smsmith } 76118783Snjl i++; 77118783Snjl } 7879282Smsmith 79118783Snjl return (ENXIO); 8079282Smsmith} 8179282Smsmith 8285556Siwasakiint 8379282Smsmithacpi_battery_get_battinfo(int unit, struct acpi_battinfo *battinfo) 8479282Smsmith{ 85118783Snjl struct acpi_battdesc battdesc; 86118783Snjl int error; 8779282Smsmith 88118783Snjl error = 0; 89118783Snjl if (unit == -1) { 90118783Snjl error = acpi_cmbat_get_battinfo(-1, battinfo); 91118783Snjl goto out; 92118783Snjl } else { 93118783Snjl error = acpi_battery_get_battdesc(unit, &battdesc); 94118783Snjl if (error != 0) 95118783Snjl goto out; 96118783Snjl 97118783Snjl switch (battdesc.type) { 98118783Snjl case ACPI_BATT_TYPE_CMBAT: 99118783Snjl error = acpi_cmbat_get_battinfo(battdesc.phys_unit, battinfo); 100118783Snjl break; 101118783Snjl default: 102118783Snjl error = ENXIO; 103118783Snjl break; 10479282Smsmith } 105118783Snjl } 106118783Snjl 10779282Smsmithout: 108118783Snjl return (error); 10979282Smsmith} 11079282Smsmith 11185729Siwasakiint 11285729Siwasakiacpi_battery_get_info_expire(void) 11385729Siwasaki{ 114118783Snjl return (acpi_battery_info_expire); 11585729Siwasaki} 11685729Siwasaki 11779282Smsmithstatic int 11879282Smsmithacpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg) 11979282Smsmith{ 120118783Snjl union acpi_battery_ioctl_arg *ioctl_arg; 121118783Snjl int error, logical_unit; 12279282Smsmith 123118783Snjl ioctl_arg = (union acpi_battery_ioctl_arg *)addr; 124118783Snjl error = 0; 125110894Stakawata 126118783Snjl /* 127118783Snjl * No security check required: information retrieval only. If 128118783Snjl * new functions are added here, a check might be required. 129118783Snjl */ 130118783Snjl switch (cmd) { 131118783Snjl case ACPIIO_BATT_GET_UNITS: 132118783Snjl *(int *)addr = acpi_battery_get_units(); 133118783Snjl break; 134118783Snjl case ACPIIO_BATT_GET_BATTDESC: 135118783Snjl logical_unit = ioctl_arg->unit; 136118783Snjl error = acpi_battery_get_battdesc(logical_unit, &ioctl_arg->battdesc); 137118783Snjl break; 138118783Snjl case ACPIIO_BATT_GET_BATTINFO: 139118783Snjl logical_unit = ioctl_arg->unit; 140118783Snjl error = acpi_battery_get_battinfo(logical_unit, &ioctl_arg->battinfo); 141118783Snjl break; 142118783Snjl default: 143118783Snjl error = EINVAL; 144118783Snjl break; 145118783Snjl } 146110894Stakawata 147118783Snjl return (error); 14879282Smsmith} 14979282Smsmith 15079282Smsmithstatic int 15179282Smsmithacpi_battery_sysctl(SYSCTL_HANDLER_ARGS) 15279282Smsmith{ 153118783Snjl int val, error; 15479282Smsmith 155118783Snjl acpi_battery_get_battinfo(-1, &acpi_battery_battinfo); 156118783Snjl val = *(u_int *)oidp->oid_arg1; 157118783Snjl error = sysctl_handle_int(oidp, &val, 0, req); 158118783Snjl return (error); 15979282Smsmith} 16079282Smsmith 16179282Smsmithstatic int 16279282Smsmithacpi_battery_init(void) 16379282Smsmith{ 164118783Snjl struct acpi_softc *sc; 165118783Snjl device_t dev; 166118783Snjl int error; 16779282Smsmith 168118783Snjl dev = devclass_get_device(devclass_find("acpi"), 0); 169118783Snjl if (dev == NULL) 170118783Snjl return (ENXIO); 171118783Snjl sc = device_get_softc(dev); 172118783Snjl if (sc == NULL) 173118783Snjl return (ENXIO); 17479282Smsmith 175118783Snjl error = 0; 176118783Snjl TAILQ_INIT(&acpi_batteries); 177118783Snjl acpi_batteries_initted = 1; 17879282Smsmith 179118783Snjl error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, 180118783Snjl NULL); 181118783Snjl if (error != 0) 182118783Snjl return (error); 183118783Snjl error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTDESC, acpi_battery_ioctl, 184118783Snjl NULL); 185118783Snjl if (error != 0) 186118783Snjl return (error); 187118783Snjl error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, 188118783Snjl NULL); 189118783Snjl if (error != 0) 190118783Snjl return (error); 19179282Smsmith 192118783Snjl sysctl_ctx_init(&sc->acpi_battery_sysctl_ctx); 193118783Snjl sc->acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_battery_sysctl_ctx, 194118783Snjl SYSCTL_CHILDREN(sc->acpi_sysctl_tree), 195118783Snjl OID_AUTO, "battery", CTLFLAG_RD, 0, ""); 196118783Snjl SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx, 197118783Snjl SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), 198118783Snjl OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD, 199118783Snjl &acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", ""); 200118783Snjl SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx, 201118783Snjl SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), 202118783Snjl OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD, 203118783Snjl &acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", ""); 204118783Snjl SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx, 205118783Snjl SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), 206118783Snjl OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD, 207118783Snjl &acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", ""); 208118783Snjl SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx, 209118783Snjl SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), 210118783Snjl OID_AUTO, "units", CTLFLAG_RD, &acpi_batteries_units, 0, ""); 211118783Snjl SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx, 212118783Snjl SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), 213118783Snjl OID_AUTO, "info_expire", CTLFLAG_RD | CTLFLAG_RW, 214118783Snjl &acpi_battery_info_expire, 0, ""); 21579282Smsmith 216118783Snjl return (error); 21779282Smsmith} 21879282Smsmith 21979282Smsmithint 22079282Smsmithacpi_battery_register(int type, int phys_unit) 22179282Smsmith{ 222118783Snjl struct acpi_batteries *bp; 223118783Snjl int error; 22479282Smsmith 225118783Snjl error = 0; 226118783Snjl bp = malloc(sizeof(*bp), M_ACPIBATT, M_NOWAIT); 227118783Snjl if (bp == NULL) 228118783Snjl return (ENOMEM); 22979282Smsmith 230118783Snjl bp->battdesc.type = type; 231118783Snjl bp->battdesc.phys_unit = phys_unit; 232118783Snjl if (acpi_batteries_initted == 0) { 233118783Snjl if ((error = acpi_battery_init()) != 0) { 234118783Snjl free(bp, M_ACPIBATT); 235118783Snjl return (error); 23679282Smsmith } 237118783Snjl } 23879282Smsmith 239118783Snjl TAILQ_INSERT_TAIL(&acpi_batteries, bp, link); 240118783Snjl acpi_batteries_units++; 24179282Smsmith 242118783Snjl return (0); 24379282Smsmith} 244