Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/acpica/acpi_cmbat.c
Show All 30 Lines | |||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_acpi.h" | #include "opt_acpi.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/ioccom.h> | #include <sys/ioccom.h> | ||||
#include <sys/sysctl.h> | |||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
Show All 10 Lines | |||||
/* Hooks for the ACPI CA debugging infrastructure */ | /* Hooks for the ACPI CA debugging infrastructure */ | ||||
#define _COMPONENT ACPI_BATTERY | #define _COMPONENT ACPI_BATTERY | ||||
ACPI_MODULE_NAME("BATTERY") | ACPI_MODULE_NAME("BATTERY") | ||||
#define ACPI_BATTERY_BST_CHANGE 0x80 | #define ACPI_BATTERY_BST_CHANGE 0x80 | ||||
#define ACPI_BATTERY_BIF_CHANGE 0x81 | #define ACPI_BATTERY_BIF_CHANGE 0x81 | ||||
#define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE | #define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE | ||||
#define ACPI_BATTERY_BTP_WARNING_LEVEL 20 | |||||
struct acpi_cmbat_softc { | struct acpi_cmbat_softc { | ||||
device_t dev; | device_t dev; | ||||
int flags; | int flags; | ||||
struct acpi_bix bix; | struct acpi_bix bix; | ||||
struct acpi_bst bst; | struct acpi_bst bst; | ||||
struct timespec bst_lastupdated; | struct timespec bst_lastupdated; | ||||
bool acpi_btp_exists; | |||||
int btp_warning_level; | |||||
}; | }; | ||||
ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); | ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); | ||||
static int acpi_cmbat_probe(device_t dev); | static int acpi_cmbat_probe(device_t dev); | ||||
static int acpi_cmbat_attach(device_t dev); | static int acpi_cmbat_attach(device_t dev); | ||||
static int acpi_cmbat_detach(device_t dev); | static int acpi_cmbat_detach(device_t dev); | ||||
static int acpi_cmbat_resume(device_t dev); | static int acpi_cmbat_resume(device_t dev); | ||||
static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, | static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, | ||||
void *context); | void *context); | ||||
static int acpi_cmbat_info_expired(struct timespec *lastupdated); | static int acpi_cmbat_info_expired(struct timespec *lastupdated); | ||||
static void acpi_cmbat_info_updated(struct timespec *lastupdated); | static void acpi_cmbat_info_updated(struct timespec *lastupdated); | ||||
static void acpi_cmbat_get_bst(void *arg); | static void acpi_cmbat_get_bst(void *arg); | ||||
static void acpi_cmbat_get_bix_task(void *arg); | static void acpi_cmbat_get_bix_task(void *arg); | ||||
static void acpi_cmbat_get_bix(void *arg); | static void acpi_cmbat_get_bix(void *arg); | ||||
static int acpi_cmbat_bst(device_t, struct acpi_bst *); | static int acpi_cmbat_bst(device_t, struct acpi_bst *); | ||||
static int acpi_cmbat_bix(device_t, void *, size_t); | static int acpi_cmbat_bix(device_t, void *, size_t); | ||||
static void acpi_cmbat_btp(void *); | |||||
static int acpi_cmbat_btp_sysctl(SYSCTL_HANDLER_ARGS); | |||||
static void acpi_cmbat_init_battery(void *arg); | static void acpi_cmbat_init_battery(void *arg); | ||||
static device_method_t acpi_cmbat_methods[] = { | static device_method_t acpi_cmbat_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, acpi_cmbat_probe), | DEVMETHOD(device_probe, acpi_cmbat_probe), | ||||
DEVMETHOD(device_attach, acpi_cmbat_attach), | DEVMETHOD(device_attach, acpi_cmbat_attach), | ||||
DEVMETHOD(device_detach, acpi_cmbat_detach), | DEVMETHOD(device_detach, acpi_cmbat_detach), | ||||
DEVMETHOD(device_resume, acpi_cmbat_resume), | DEVMETHOD(device_resume, acpi_cmbat_resume), | ||||
▲ Show 20 Lines • Show All 423 Lines • ▼ Show 20 Lines | memcpy(bst, &sc->bst, sizeof(*bst)); | ||||
} else | } else | ||||
bst->state = ACPI_BATT_STAT_NOT_PRESENT; | bst->state = ACPI_BATT_STAT_NOT_PRESENT; | ||||
ACPI_SERIAL_END(cmbat); | ACPI_SERIAL_END(cmbat); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
acpi_cmbat_btp(void *arg) { | |||||
struct acpi_cmbat_softc *sc; | |||||
device_t dev; | |||||
ACPI_HANDLE h; | |||||
ACPI_STATUS as; | |||||
uint64_t newtp; | |||||
ACPI_SERIAL_ASSERT(cmbat); | |||||
dev = arg; | |||||
sc = device_get_softc(dev); | |||||
h = acpi_get_handle(dev); | |||||
/* | |||||
* Try to set a default warning level. | |||||
* If successful, we assume that _BTP exists, | |||||
* and create the sysctl. | |||||
*/ | |||||
sc->btp_warning_level= ACPI_BATTERY_BTP_WARNING_LEVEL; | |||||
newtp = sc->bix.lfcap * sc->btp_warning_level / 100; | |||||
as = acpi_SetInteger(h, "_BTP", (uint32_t) newtp); | |||||
if(as == AE_NOT_FOUND) | |||||
sc->acpi_btp_exists = FALSE; | |||||
else if (ACPI_FAILURE(as)) { | |||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | |||||
"error setting _BTP --%s\n", AcpiFormatException(as)); | |||||
sc->acpi_btp_exists = FALSE; | |||||
} | |||||
else { | |||||
sc->acpi_btp_exists = TRUE; | |||||
struct sysctl_oid *cmbat_oid = device_get_sysctl_tree(dev); | |||||
SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(cmbat_oid), OID_AUTO, | |||||
"warning_level", CTLTYPE_INT | CTLFLAG_RW, 0, 0, | |||||
acpi_cmbat_btp_sysctl, "I" ,"battery warning level"); | |||||
} | |||||
} | |||||
static int acpi_cmbat_btp_sysctl(SYSCTL_HANDLER_ARGS) { | |||||
struct sysctl_oid *parent; | |||||
struct acpi_cmbat_softc *sc; | |||||
device_t dev; | |||||
ACPI_HANDLE h; | |||||
ACPI_STATUS as; | |||||
long battery_index; | |||||
uint64_t newtp; | |||||
ACPI_SERIAL_BEGIN(cmbat); | |||||
parent = SYSCTL_PARENT(oidp); | |||||
battery_index = strtol(parent->oid_name, NULL, 0); | |||||
dev = devclass_get_device(acpi_cmbat_devclass, (int) battery_index); | |||||
h = acpi_get_handle(dev); | |||||
sc = device_get_softc(dev); | |||||
if(req->newptr) { | |||||
/* write request */ | |||||
SYSCTL_IN(req, &sc->btp_warning_level, sizeof(sc->btp_warning_level)); | |||||
/* correct bogus writes */ | |||||
if(sc->btp_warning_level < 1 || sc->btp_warning_level > 99) | |||||
sc->btp_warning_level = ACPI_BATTERY_BTP_WARNING_LEVEL; | |||||
takawata: How about allowing 0 to clear trip point ? | |||||
georg.lindenberg_web.deAuthorUnsubmitted Done Inline Actions
Yes, sounds good. georg.lindenberg_web.de: > How about allowing 0 to clear trip point ?
Yes, sounds good. | |||||
newtp = sc->bix.lfcap * sc->btp_warning_level / 100; | |||||
as = acpi_SetInteger(h, "_BTP", (uint32_t) newtp); | |||||
if(ACPI_FAILURE(as)) | |||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | |||||
"error setting _BTP -- %s\n", AcpiFormatException(as)); | |||||
} | |||||
else /* read request */ | |||||
SYSCTL_OUT(req, &sc->btp_warning_level, sizeof(sc->btp_warning_level)); | |||||
ACPI_SERIAL_END(cmbat); | |||||
return (0); | |||||
} | |||||
static void | |||||
acpi_cmbat_init_battery(void *arg) | acpi_cmbat_init_battery(void *arg) | ||||
{ | { | ||||
struct acpi_cmbat_softc *sc; | struct acpi_cmbat_softc *sc; | ||||
int retry, valid; | int retry, valid; | ||||
device_t dev; | device_t dev; | ||||
dev = (device_t)arg; | dev = (device_t)arg; | ||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | ||||
Show All 36 Lines | if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { | ||||
timespecclear(&sc->bst_lastupdated); | timespecclear(&sc->bst_lastupdated); | ||||
acpi_cmbat_get_bst(dev); | acpi_cmbat_get_bst(dev); | ||||
} | } | ||||
if (retry == 0 || !acpi_battery_bix_valid(&sc->bix)) | if (retry == 0 || !acpi_battery_bix_valid(&sc->bix)) | ||||
acpi_cmbat_get_bix(dev); | acpi_cmbat_get_bix(dev); | ||||
valid = acpi_battery_bst_valid(&sc->bst) && | valid = acpi_battery_bst_valid(&sc->bst) && | ||||
acpi_battery_bix_valid(&sc->bix); | acpi_battery_bix_valid(&sc->bix); | ||||
if(valid) | |||||
acpi_cmbat_btp(dev); | |||||
ACPI_SERIAL_END(cmbat); | ACPI_SERIAL_END(cmbat); | ||||
if (valid) | if (valid) | ||||
break; | break; | ||||
} | } | ||||
if (retry == ACPI_CMBAT_RETRY_MAX) { | if (retry == ACPI_CMBAT_RETRY_MAX) { | ||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | ||||
"battery initialization failed, giving up\n"); | "battery initialization failed, giving up\n"); | ||||
} else { | } else { | ||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), | ||||
"battery initialization done, tried %d times\n", retry + 1); | "battery initialization done, tried %d times\n", retry + 1); | ||||
} | } | ||||
} | } |
How about allowing 0 to clear trip point ?