Page MenuHomeFreeBSD

D23728.id68460.diff
No OneTemporary

D23728.id68460.diff

Index: share/man/man4/acpi_battery.4
===================================================================
--- share/man/man4/acpi_battery.4
+++ share/man/man4/acpi_battery.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 26, 2019
+.Dd February 16, 2020
.Dt ACPI_BATTERY 4
.Os
.Sh NAME
@@ -37,6 +37,7 @@
The
.Nm
is a driver for battery management features of the ACPI module.
+.Pp
An ACPI-compatible battery device supports either a Control
Method Battery interface or a Smart Battery subsystem interface.
The former is accessed by the AML
@@ -44,8 +45,11 @@
code control methods,
and the latter is controlled directly through the ACPI EC
.Pq Embedded Controller
-typically via an SMBus interface.
-This driver supports the
+typically via an
+.Xr smbus 4
+interface.
+.Pp
+This driver supports the
.Xr sysctl 8
and
.Xr ioctl 2
@@ -59,60 +63,88 @@
number as an argument,
and returns a specific structure for each request.
A special unit number
-.Li ACPI_BATTERY_ALL_UNITS
+.Dv ACPI_BATTERY_ALL_UNITS
specifies all of the attached units
and reports accumulated information.
.Bl -tag -width indent
-.It ACPIIO_BATT_GET_UNITS Vt int
+.It Dv ACPIIO_BATT_GET_UNITS Vt int
Returns the number of battery units in the system.
The unit number argument will be ignored.
-.It ACPIIO_BATT_GET_BATTINFO Vt struct acpi_battinfo
+.It Dv ACPIIO_BATT_GET_BATTINFO Vt struct acpi_battinfo
Returns the following:
.Bl -tag -width indent
-.It cap
+.It Va cap
Battery capacity in percent,
-.It min
+.It Va min
Remaining battery life in minutes,
-.It state
+.It Va state
Current status of the battery encoded in the following:
.Bl -tag -width indent
-.It ACPI_BATT_STAT_DISCHARG Pq 0x0001
+.It Dv ACPI_BATT_STAT_DISCHARG Pq 0x0001
Battery is discharging,
-.It ACPI_BATT_STAT_CHARGING Pq 0x0002
+.It Dv ACPI_BATT_STAT_CHARGING Pq 0x0002
Battery is being charged, or
-.It ACPI_BATT_STAT_CRITICAL Pq 0x0004
+.It Dv ACPI_BATT_STAT_CRITICAL Pq 0x0004
Remaining battery life is critically low.
.El
.Pp
Note that the status bits of each battery will be
consolidated when
-.Li ACPI_BATTERY_ALL_UNITS
+.Dv ACPI_BATTERY_ALL_UNITS
is specified.
-.It rate
+.It Va rate
Current battery discharging rate in mW.
.Li -1
means not discharging right now.
.El
-.It ACPIIO_BATT_GET_BIF Vt struct acpi_bif
+.It Dv ACPIIO_BATT_GET_BIX Vt struct acpi_bix
Returns battery information given by the ACPI
-.Li _BIF Pq Battery Information
+.Li _BIX Pq Battery Information
object,
which is the static portion of the Control Method
Battery information.
-In the case of a Smart Battery attached to SMBus,
+In the case of a Smart Battery attached to
+.Xr smbus 4
+or a Control Method Battery with
+a
+.Li _BIF
+object,
this ioctl will build a
-.Vt struct acpi_bif
+.Vt struct acpi_bix
structure based on the obtained information
and return it.
.Bl -tag -width indent
-.It units
+.It Va rev
+Revision number of the object.
+There are the following well-known values:
+.Bl -tag -width indent
+.It Dv ACPI_BIX_REV_0 Pq 0x0000
+A
+.Li _BIX
+object in ACPI 4.0.
+.It Dv ACPI_BIX_REV_1 Pq 0x0001
+A
+.Li _BIX
+object in ACPI 6.0.
+.It Dv ACPI_BIX_REV_BIF Pq 0xffff
+A
+.Li _BIX
+object built from the
+.Li _BIF
+object found on the system.
+.El
+.Pp
+Note that this field should be checked by using
+.Fn ACPI_BIX_REV_MIN_CHECK var rev
+macro when checking the minimum revision number.
+.It Va units
Indicates the units used by the battery to report its
capacity and charge rate encoded in the following:
.Bl -tag -width indent
-.It ACPI_BIF_UNITS_MW Pq 0x00000000
+.It ACPI_BIX_UNITS_MW Pq 0x00000000
in mW
.Pq power
-.It ACPI_BIF_UNITS_MA Pq 0x00000001
+.It ACPI_BIX_UNITS_MA Pq 0x00000001
in mA
.Pq current
.El
@@ -120,31 +152,69 @@
Note that capacity is expressed in mWh or mAh,
and rate is expressed in mW or mA,
respectively.
-.It dcap
+.It Va dcap
The Battery's design capacity,
which is the nominal capacity of a new battery.
This is expressed as power or current depending on
the value of
.Va units .
-.It lfcap
+.It Va lfcap
Predicted battery capacity when fully charged.
Typically this will decrease every charging cycle.
.It btech
Battery technology:
.Bl -tag -width indent
.It 0x00000000 Primary cell Pq non-rechargable
-.It 0x00000001 Secondery cell Pq rechargable
+.It 0x00000001 Secondary cell Pq rechargable
.El
-.It dvol
+.It Va dvol
Design voltage in mV,
which is the nominal voltage of a new battery.
-.It wcap
+.It Va wcap
Design capacity of warning.
When a discharging battery device reaches this capacity,
notification is sent to the system.
-.It lcap
+.It Va lcap
Design capacity of low.
-.It gra1
+.It Va cycles
+.Pq rev 0 or newer
+The number of cycles the battery has experienced.
+A cycle means an amount of discharge occurred which was
+approximately equal to the value of Design Capacity.
+.It Va accuracy
+.Pq rev 0 or newer
+The accuracy of the battery capacity measurement,
+in thousandth of a percent.
+.It Va stmax
+.Pq rev 0 or newer
+The Maximum Sampling Time of the battery in
+milliseconds.
+This is the maximum duration between two consecutive
+measurements of the battery's capacities specified in
+.Li _BST .
+If two succeeding readings of
+.Li _BST
+beyond this duration occur,
+two different results can be returned.
+.It Va stmin
+.Pq rev 0 or newer
+The Minimum Sampling Time of the battery in
+milliseconds.
+.It Va aimax
+.Pq rev 0 or newer
+The Maximum Average Interval of the battery in
+milliseconds.
+This is the length of time within which the battery
+averages the capacity measurements specified in
+.Li _BST .
+The Sampling Time specifies the frequency of measurements,
+and the Average Interval specifies the width of the time
+window of every measurement.
+.It Va aimin
+.Pq rev 0 or newer
+The Minimum Average Interval of the battery in
+milliseconds.
+.It Va gra1
Battery capacity granularity between
.Va low
and
@@ -152,7 +222,7 @@
This is expressed as power or current depending on
the value of
.Va units .
-.It gra2
+.It Va gra2
Battery capacity granularity between
.Va warning
and
@@ -160,45 +230,72 @@
This is expressed as power or current depending on
the value of
.Va units .
-.It model
+.It Va model
Model number of the battery as a string.
-.It serial
+.It Va serial
Serial number of the battery as a string.
-.It type
+.It Va type
Type identifier of the battery as a string.
-.It oeminfo
+.It Va oeminfo
OEM-specific information of the battery as a string.
+.It Va scap
+.Pq rev 1 or newer
+Battery swapping capability encoded in the following:
+.Bl -tag -width indent
+.It ACPI_BIX_SCAP_NO Pq 0x00000000
+Non-swappable
+.It ACPI_BIX_SCAP_COLD Pq 0x00000001
+Cold-swappable
+.It ACPI_BIX_SCAP_HOT Pq 0x00000010
+Hot-swappable
.El
+.El
+.It Dv ACPIIO_BATT_GET_BIF Vt struct acpi_bif
+.Pq deprecated
+Returns battery information given by the ACPI
+.Li _BIF Pq Battery Information
+object,
+which was deprecated in ACPI 4.0 specification.
+The data structure is a subset of
+.Vt struct acpi_bix .
+.Pp
+Note that this ioctl will built a
+.Vt struct acpi_bif
+structure based on the obtained information
+even if this object is not available and a
+.Li _BIX
+object is found.
.It ACPIIO_BATT_GET_BST Vt struct acpi_bst
Returns battery information given by the ACPI
.Li _BST Pq Battery Status
object,
which is the present battery status.
-In the case of a Smart Battery attached to SMBus,
+In the case of a Smart Battery attached to
+.Xr smbus 4 ,
this ioctl will build a
.Vt struct acpi_bst
structure based on the obtained information
and return it.
.Bl -tag -width indent
-.It state
+.It Va state
Battery state.
The value is encoded in the same way as
.Va state
of
.Vt struct acpi_battinfo .
-.It rate
+.It Va rate
Battery present rate of charging or discharging.
The unit of the value depends on
.Va unit
of
.Vt struct acpi_bif .
-.It cap
+.It Va cap
Battery remaining capacity.
The unit of this value depends on
.Va unit
of
.Vt struct acpi_bif .
-.It volt
+.It Va volt
Battery present voltage.
.El
.El
@@ -212,6 +309,8 @@
.It Va hw.acpi.battery.info_expire
Information cache expiration time in seconds.
The battery information obtained by
+.Li _BIX
+or
.Li _BIF
object will be stored and reused for successive
read access to this MIB within the specified period.
@@ -269,6 +368,7 @@
.El
.Sh SEE ALSO
.Xr acpi 4 ,
+.Xr smbus 4 ,
.Xr acpiconf 8
.Sh AUTHORS
.An -nosplit
@@ -276,8 +376,11 @@
.An Munehiro Matsuda ,
.An Takanori Watanabe Aq Mt takawata@FreeBSD.org ,
.An Mitsuru IWASAKI Aq Mt iwasaki@FreeBSD.org ,
+.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org ,
and
-.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org .
+.An Hiroki Sato Aq Mt hrs@FreeBSD.org .
.Pp
This manual page was written by
-.An Takanori Watanabe Aq Mt takawata@FreeBSD.org .
+.An Takanori Watanabe Aq Mt takawata@FreeBSD.org
+and
+.An Hiroki Sato Aq Mt hrs@FreeBSD.org .
Index: sys/dev/acpica/acpi_battery.c
===================================================================
--- sys/dev/acpica/acpi_battery.c
+++ sys/dev/acpica/acpi_battery.c
@@ -44,7 +44,7 @@
/* Default seconds before re-sampling the battery state. */
#define ACPI_BATTERY_INFO_EXPIRE 5
-static int acpi_batteries_initted;
+static int acpi_batteries_initialized;
static int acpi_battery_info_expire = ACPI_BATTERY_INFO_EXPIRE;
static struct acpi_battinfo acpi_battery_battinfo;
static struct sysctl_ctx_list acpi_battery_sysctl_ctx;
@@ -65,11 +65,10 @@
{
int error;
- error = 0;
ACPI_SERIAL_BEGIN(battery);
- if (!acpi_batteries_initted)
- error = acpi_battery_init();
+ error = acpi_battery_init();
ACPI_SERIAL_END(battery);
+
return (error);
}
@@ -107,11 +106,12 @@
bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN);
}
-/* Check _BIF results for validity. */
+/* Check _BI[FX] results for validity. */
int
-acpi_battery_bif_valid(struct acpi_bif *bif)
+acpi_battery_bix_valid(struct acpi_bix *bix)
{
- return (bif->lfcap != 0);
+
+ return (bix->lfcap != 0);
}
/* Get info about one or all batteries. */
@@ -123,7 +123,7 @@
devclass_t batt_dc;
device_t batt_dev;
struct acpi_bst *bst;
- struct acpi_bif *bif;
+ struct acpi_bix *bix;
struct acpi_battinfo *bi;
/*
@@ -139,11 +139,11 @@
/*
* Allocate storage for all _BST data, their derived battinfo data,
- * and the current battery's _BIF data.
+ * and the current battery's _BIX (or _BIF) data.
*/
bst = malloc(devcount * sizeof(*bst), M_TEMP, M_WAITOK | M_ZERO);
bi = malloc(devcount * sizeof(*bi), M_TEMP, M_WAITOK | M_ZERO);
- bif = malloc(sizeof(*bif), M_TEMP, M_WAITOK | M_ZERO);
+ bix = malloc(sizeof(*bix), M_TEMP, M_WAITOK | M_ZERO);
/*
* Pass 1: for each battery that is present and valid, get its status,
@@ -173,12 +173,12 @@
* Be sure we can get various info from the battery.
*/
if (ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 ||
- ACPI_BATT_GET_INFO(batt_dev, bif) != 0)
+ ACPI_BATT_GET_INFO(batt_dev, bix, sizeof(*bix)) != 0)
continue;
/* If a battery is not installed, we sometimes get strange values. */
if (!acpi_battery_bst_valid(&bst[i]) ||
- !acpi_battery_bif_valid(bif))
+ !acpi_battery_bix_valid(bix))
continue;
/*
@@ -197,18 +197,18 @@
* is 0 (due to some error reading the battery), skip this
* conversion.
*/
- if (bif->units == ACPI_BIF_UNITS_MA && bif->dvol != 0 && dev == NULL) {
- bst[i].rate = (bst[i].rate * bif->dvol) / 1000;
- bst[i].cap = (bst[i].cap * bif->dvol) / 1000;
- bif->lfcap = (bif->lfcap * bif->dvol) / 1000;
+ if (bix->units == ACPI_BIX_UNITS_MA && bix->dvol != 0 && dev == NULL) {
+ bst[i].rate = (bst[i].rate * bix->dvol) / 1000;
+ bst[i].cap = (bst[i].cap * bix->dvol) / 1000;
+ bix->lfcap = (bix->lfcap * bix->dvol) / 1000;
}
/*
- * The calculation above may set bif->lfcap to zero. This was
+ * The calculation above may set bix->lfcap to zero. This was
* seen on a laptop with a broken battery. The result of the
* division was rounded to zero.
*/
- if (!acpi_battery_bif_valid(bif))
+ if (!acpi_battery_bix_valid(bix))
continue;
/*
@@ -216,16 +216,16 @@
* "real-capacity" when the battery is fully charged. That breaks
* the above arithmetic as it needs to be 100% maximum.
*/
- if (bst[i].cap > bif->lfcap)
- bst[i].cap = bif->lfcap;
+ if (bst[i].cap > bix->lfcap)
+ bst[i].cap = bix->lfcap;
/* Calculate percent capacity remaining. */
- bi[i].cap = (100 * bst[i].cap) / bif->lfcap;
+ bi[i].cap = (100 * bst[i].cap) / bix->lfcap;
/* If this battery is not present, don't use its capacity. */
if (bi[i].cap != -1) {
total_cap += bst[i].cap;
- total_lfcap += bif->lfcap;
+ total_lfcap += bix->lfcap;
}
/*
@@ -291,12 +291,9 @@
error = 0;
out:
- if (bi)
- free(bi, M_TEMP);
- if (bif)
- free(bif, M_TEMP);
- if (bst)
- free(bst, M_TEMP);
+ free(bi, M_TEMP);
+ free(bix, M_TEMP);
+ free(bst, M_TEMP);
return (error);
}
@@ -365,23 +362,41 @@
unit = 0;
dev = NULL;
ioctl_arg = NULL;
- if (IOCPARM_LEN(cmd) == sizeof(*ioctl_arg)) {
+ if (IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg) ||
+ IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg_v1)) {
ioctl_arg = (union acpi_battery_ioctl_arg *)addr;
unit = ioctl_arg->unit;
if (unit != ACPI_BATTERY_ALL_UNITS)
dev = acpi_battery_find_dev(unit);
}
-
+ /* For debugging */
+ device_printf(dev, "%s: IOCPARM_LEN=%lu, cmd=%lu, "
+ "sizeof(ioctl_arg)=%zu, sizeof(ioctl_arg_v1)=%zu, "
+ "UNITScmd=%lu, "
+ "BIFcmd=%lu, BIXcmd=%lu, "
+ "BINFOcmd=%lu, BINFOv1cmd=%lu, "
+ "BSTcmd=%lu, BSTv1cmd=%lu"
+ "\n",
+ __func__,
+ IOCPARM_LEN(cmd), cmd, sizeof(union acpi_battery_ioctl_arg),
+ sizeof(union acpi_battery_ioctl_arg_v1),
+ ACPIIO_BATT_GET_UNITS,
+ ACPIIO_BATT_GET_BIF, ACPIIO_BATT_GET_BIX,
+ ACPIIO_BATT_GET_BATTINFO, ACPIIO_BATT_GET_BATTINFO_V1,
+ ACPIIO_BATT_GET_BST, ACPIIO_BATT_GET_BST_V1
+ );
/*
* No security check required: information retrieval only. If
* new functions are added here, a check might be required.
*/
+ /* Unit check */
switch (cmd) {
case ACPIIO_BATT_GET_UNITS:
*(int *)addr = acpi_battery_get_units();
error = 0;
break;
case ACPIIO_BATT_GET_BATTINFO:
+ case ACPIIO_BATT_GET_BATTINFO_V1:
if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) {
bzero(&ioctl_arg->battinfo, sizeof(ioctl_arg->battinfo));
error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo);
@@ -390,24 +405,19 @@
case ACPIIO_BATT_GET_BIF:
if (dev != NULL) {
bzero(&ioctl_arg->bif, sizeof(ioctl_arg->bif));
- error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif);
-
- /*
- * Remove invalid characters. Perhaps this should be done
- * within a convenience function so all callers get the
- * benefit.
- */
- acpi_battery_clean_str(ioctl_arg->bif.model,
- sizeof(ioctl_arg->bif.model));
- acpi_battery_clean_str(ioctl_arg->bif.serial,
- sizeof(ioctl_arg->bif.serial));
- acpi_battery_clean_str(ioctl_arg->bif.type,
- sizeof(ioctl_arg->bif.type));
- acpi_battery_clean_str(ioctl_arg->bif.oeminfo,
- sizeof(ioctl_arg->bif.oeminfo));
+ error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif,
+ sizeof(ioctl_arg->bif));
}
break;
+ case ACPIIO_BATT_GET_BIX:
+ if (dev != NULL) {
+ bzero(&ioctl_arg->bix, sizeof(ioctl_arg->bix));
+ error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bix,
+ sizeof(ioctl_arg->bix));
+ }
+ break;
case ACPIIO_BATT_GET_BST:
+ case ACPIIO_BATT_GET_BST_V1:
if (dev != NULL) {
bzero(&ioctl_arg->bst, sizeof(ioctl_arg->bst));
error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst);
@@ -417,6 +427,25 @@
error = EINVAL;
}
+ /* Sanitize the string members. */
+ switch (cmd) {
+ case ACPIIO_BATT_GET_BIX:
+ case ACPIIO_BATT_GET_BIF:
+ /*
+ * Remove invalid characters. Perhaps this should be done
+ * within a convenience function so all callers get the
+ * benefit.
+ */
+ acpi_battery_clean_str(ioctl_arg->bix.model,
+ sizeof(ioctl_arg->bix.model));
+ acpi_battery_clean_str(ioctl_arg->bix.serial,
+ sizeof(ioctl_arg->bix.serial));
+ acpi_battery_clean_str(ioctl_arg->bix.type,
+ sizeof(ioctl_arg->bix.type));
+ acpi_battery_clean_str(ioctl_arg->bix.oeminfo,
+ sizeof(ioctl_arg->bix.oeminfo));
+ };
+
return (error);
}
@@ -450,27 +479,30 @@
ACPI_SERIAL_ASSERT(battery);
+ if (acpi_batteries_initialized)
+ return(0);
+
error = ENXIO;
dev = devclass_get_device(devclass_find("acpi"), 0);
if (dev == NULL)
goto out;
sc = device_get_softc(dev);
- error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl,
- NULL);
- if (error != 0)
- goto out;
- error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl,
- NULL);
- if (error != 0)
- goto out;
- error = acpi_register_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL);
- if (error != 0)
- goto out;
- error = acpi_register_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL);
- if (error != 0)
- goto out;
+#define ACPI_REGISTER_IOCTL(a, b, c) do { \
+ error = acpi_register_ioctl(a, b, c); \
+ if (error) \
+ goto out; \
+ } while (0)
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, NULL);
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, NULL);
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl, NULL);
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL);
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl, NULL);
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL);
+ ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl, NULL);
+#undef ACPI_REGISTER_IOCTL
+
sysctl_ctx_init(&acpi_battery_sysctl_ctx);
acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&acpi_battery_sysctl_ctx,
SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, "battery", CTLFLAG_RD,
@@ -505,14 +537,17 @@
&acpi_battery_info_expire, 0,
"time in seconds until info is refreshed");
- acpi_batteries_initted = TRUE;
+ acpi_batteries_initialized = TRUE;
out:
- if (error != 0) {
+ if (error) {
acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl);
acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl);
+ acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl);
acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl);
+ acpi_deregister_ioctl(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl);
acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl);
+ acpi_deregister_ioctl(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl);
}
return (error);
}
Index: sys/dev/acpica/acpi_cmbat.c
===================================================================
--- sys/dev/acpica/acpi_cmbat.c
+++ sys/dev/acpica/acpi_cmbat.c
@@ -61,12 +61,13 @@
#define ACPI_BATTERY_BST_CHANGE 0x80
#define ACPI_BATTERY_BIF_CHANGE 0x81
+#define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE
struct acpi_cmbat_softc {
device_t dev;
int flags;
- struct acpi_bif bif;
+ struct acpi_bix bix;
struct acpi_bst bst;
struct timespec bst_lastupdated;
};
@@ -82,10 +83,10 @@
static int acpi_cmbat_info_expired(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_bif_task(void *arg);
-static void acpi_cmbat_get_bif(void *arg);
-static int acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp);
-static int acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp);
+static void acpi_cmbat_get_bix_task(void *arg);
+static void acpi_cmbat_get_bix(void *arg);
+static int acpi_cmbat_bst(device_t, struct acpi_bst *);
+static int acpi_cmbat_bix(device_t, void *, size_t);
static void acpi_cmbat_init_battery(void *arg);
static device_method_t acpi_cmbat_methods[] = {
@@ -96,7 +97,7 @@
DEVMETHOD(device_resume, acpi_cmbat_resume),
/* ACPI battery interface */
- DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif),
+ DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bix),
DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst),
DEVMETHOD_END
@@ -205,12 +206,12 @@
timespecclear(&sc->bst_lastupdated);
break;
case ACPI_NOTIFY_BUS_CHECK:
- case ACPI_BATTERY_BIF_CHANGE:
+ case ACPI_BATTERY_BIX_CHANGE:
/*
* Queue a callback to get the current battery info from thread
* context. It's not safe to block in a notify handler.
*/
- AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev);
+ AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bix_task, dev);
break;
}
@@ -269,15 +270,15 @@
as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer);
if (ACPI_FAILURE(as)) {
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
- "error fetching current battery status -- %s\n",
- AcpiFormatException(as));
+ "error fetching current battery status -- %s\n",
+ AcpiFormatException(as));
goto end;
}
res = (ACPI_OBJECT *)bst_buffer.Pointer;
if (!ACPI_PKG_VALID(res, 4)) {
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
- "battery status corrupted\n");
+ "battery status corrupted\n");
goto end;
}
@@ -307,119 +308,194 @@
sc->flags &= ~ACPI_BATT_STAT_CRITICAL;
end:
- if (bst_buffer.Pointer != NULL)
- AcpiOsFree(bst_buffer.Pointer);
+ AcpiOsFree(bst_buffer.Pointer);
}
/* XXX There should be a cleaner way to do this locking. */
static void
-acpi_cmbat_get_bif_task(void *arg)
+acpi_cmbat_get_bix_task(void *arg)
{
ACPI_SERIAL_BEGIN(cmbat);
- acpi_cmbat_get_bif(arg);
+ acpi_cmbat_get_bix(arg);
ACPI_SERIAL_END(cmbat);
}
static void
-acpi_cmbat_get_bif(void *arg)
+acpi_cmbat_get_bix(void *arg)
{
struct acpi_cmbat_softc *sc;
ACPI_STATUS as;
ACPI_OBJECT *res;
ACPI_HANDLE h;
- ACPI_BUFFER bif_buffer;
+ ACPI_BUFFER bix_buffer;
device_t dev;
+ int i, n;
+ const struct {
+ enum { _BIX, _BIF } type;
+ char *name;
+ } bobjs[] = {
+ { _BIX, "_BIX"},
+ { _BIF, "_BIF"},
+ };
ACPI_SERIAL_ASSERT(cmbat);
dev = arg;
sc = device_get_softc(dev);
h = acpi_get_handle(dev);
- bif_buffer.Pointer = NULL;
- bif_buffer.Length = ACPI_ALLOCATE_BUFFER;
+ bix_buffer.Pointer = NULL;
+ bix_buffer.Length = ACPI_ALLOCATE_BUFFER;
- as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer);
- if (ACPI_FAILURE(as)) {
+ for (n = 0; n < sizeof(bobjs); n++) {
+ as = AcpiEvaluateObject(h, bobjs[n].name, NULL, &bix_buffer);
+ if (!ACPI_FAILURE(as)) {
+ res = (ACPI_OBJECT *)bix_buffer.Pointer;
+ break;
+ }
+ AcpiOsFree(bix_buffer.Pointer);
+ bix_buffer.Pointer = NULL;
+ bix_buffer.Length = ACPI_ALLOCATE_BUFFER;
+ }
+ /* Both _BIF and _BIX were not found. */
+ if (n == sizeof(bobjs)) {
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
- "error fetching current battery info -- %s\n",
- AcpiFormatException(as));
+ "error fetching current battery info -- %s\n",
+ AcpiFormatException(as));
goto end;
}
- res = (ACPI_OBJECT *)bif_buffer.Pointer;
- if (!ACPI_PKG_VALID(res, 13)) {
- ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
- "battery info corrupted\n");
- goto end;
+ /*
+ * ACPI _BIX and _BIF revision mismatch check:
+ *
+ * 1. _BIF has no revision field. The number of fields must be 13.
+ *
+ * 2. _BIX has a revision field. As of ACPI 6.3 it must be "0" or
+ * "1". The number of fields will be checked---20 and 21,
+ * respectively.
+ *
+ * If the revision number is grater than "1" and the number of
+ * fields is grater than 21, it will be treated as compatible with
+ * ACPI 6.0 _BIX. If not, it will be ignored.
+ */
+ i = 0;
+ switch (bobjs[n].type) {
+ case _BIX:
+ if (acpi_PkgInt16(res, i++, &sc->bix.rev) != 0) {
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+ "_BIX revision error\n");
+ goto end;
+ }
+#define ACPI_BIX_REV_MISMATCH_ERR(x, r) do { \
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \
+ "_BIX revision mismatch (%u != %u)\n", x, r); \
+ goto end; \
+ } while (0)
+
+ if (ACPI_PKG_VALID_EQ(res, 21)) { /* ACPI 6.0 _BIX */
+ if (sc->bix.rev != ACPI_BIX_REV_1)
+ ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_1);
+ } else if (ACPI_PKG_VALID_EQ(res, 20)) {/* ACPI 4.0 _BIX */
+ if (sc->bix.rev != ACPI_BIX_REV_0)
+ ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_0);
+ } else if (ACPI_PKG_VALID(res, 22) &&
+ ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1 + 1)) {
+ /*
+ * Unknown _BIX with 22 or more members.
+ * Assume 21 members are compatible with 6.0 _BIX.
+ */
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+ "Unknown _BIX revision(%u). "
+ "Assuming compatible with revision %u.\n",
+ sc->bix.rev, ACPI_BIX_REV_1);
+ } else {
+ /* Invalid _BIX. Ignore it. */
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+ "Invalid _BIX found (rev=%u, count=%u). Ignored.\n",
+ sc->bix.rev, res->Package.Count);
+ goto end;
+ }
+ break;
+#undef ACPI_BIX_REV_MISMATCH_ERR
+ case _BIF:
+ if (ACPI_PKG_VALID_EQ(res, 13)) /* _BIF */
+ sc->bix.rev = ACPI_BIX_REV_BIF;
+ else {
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+ "Invalid _BIF found (count=%u). Ignored.\n",
+ res->Package.Count);
+ goto end;
+ }
+ break;
}
- if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0)
- goto end;
- if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0)
- goto end;
- if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0)
- goto end;
- if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0)
- goto end;
- if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0)
- goto end;
- if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0)
- goto end;
- if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0)
- goto end;
- if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0)
- goto end;
- if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0)
- goto end;
- if (acpi_PkgStr(res, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0)
- goto end;
- if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
- goto end;
- if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0)
- goto end;
- if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
- goto end;
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+ "rev = %04x\n", sc->bix.rev);
+#define BIX_GETU32(NAME) do { \
+ ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \
+ #NAME " = %u\n", sc->bix.NAME); \
+ if (acpi_PkgInt32(res, i++, &sc->bix.NAME) != 0) \
+ goto end; \
+ } while (0)
+ BIX_GETU32(units);
+ BIX_GETU32(dcap);
+ BIX_GETU32(lfcap);
+ BIX_GETU32(btech);
+ BIX_GETU32(dvol);
+ BIX_GETU32(wcap);
+ BIX_GETU32(lcap);
+ if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_0)) {
+ BIX_GETU32(cycles);
+ BIX_GETU32(accuracy);
+ BIX_GETU32(stmax);
+ BIX_GETU32(stmin);
+ BIX_GETU32(aimax);
+ BIX_GETU32(aimin);
+ }
+ BIX_GETU32(gra1);
+ BIX_GETU32(gra2);
+ if (acpi_PkgStr(res, i++, sc->bix.model, ACPI_CMBAT_MAXSTRLEN) != 0)
+ goto end;
+ if (acpi_PkgStr(res, i++, sc->bix.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
+ goto end;
+ if (acpi_PkgStr(res, i++, sc->bix.type, ACPI_CMBAT_MAXSTRLEN) != 0)
+ goto end;
+ if (acpi_PkgStr(res, i++, sc->bix.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
+ goto end;
+ if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1))
+ BIX_GETU32(scap);
+#undef BIX_GETU32
end:
- if (bif_buffer.Pointer != NULL)
- AcpiOsFree(bif_buffer.Pointer);
+ AcpiOsFree(bix_buffer.Pointer);
}
static int
-acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp)
+acpi_cmbat_bix(device_t dev, void *bix, size_t len)
{
struct acpi_cmbat_softc *sc;
+ if (len != sizeof(struct acpi_bix) &&
+ len != sizeof(struct acpi_bif))
+ return (-1);
+
sc = device_get_softc(dev);
/*
* Just copy the data. The only value that should change is the
* last-full capacity, so we only update when we get a notify that says
* the info has changed. Many systems apparently take a long time to
- * process a _BIF call so we avoid it if possible.
+ * process a _BI[FX] call so we avoid it if possible.
*/
ACPI_SERIAL_BEGIN(cmbat);
- bifp->units = sc->bif.units;
- bifp->dcap = sc->bif.dcap;
- bifp->lfcap = sc->bif.lfcap;
- bifp->btech = sc->bif.btech;
- bifp->dvol = sc->bif.dvol;
- bifp->wcap = sc->bif.wcap;
- bifp->lcap = sc->bif.lcap;
- bifp->gra1 = sc->bif.gra1;
- bifp->gra2 = sc->bif.gra2;
- strncpy(bifp->model, sc->bif.model, sizeof(sc->bif.model));
- strncpy(bifp->serial, sc->bif.serial, sizeof(sc->bif.serial));
- strncpy(bifp->type, sc->bif.type, sizeof(sc->bif.type));
- strncpy(bifp->oeminfo, sc->bif.oeminfo, sizeof(sc->bif.oeminfo));
+ memcpy(bix, &sc->bix, len);
ACPI_SERIAL_END(cmbat);
return (0);
}
static int
-acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp)
+acpi_cmbat_bst(device_t dev, struct acpi_bst *bst)
{
struct acpi_cmbat_softc *sc;
@@ -428,12 +504,9 @@
ACPI_SERIAL_BEGIN(cmbat);
if (acpi_BatteryIsPresent(dev)) {
acpi_cmbat_get_bst(dev);
- bstp->state = sc->bst.state;
- bstp->rate = sc->bst.rate;
- bstp->cap = sc->bst.cap;
- bstp->volt = sc->bst.volt;
+ memcpy(bst, &sc->bst, sizeof(*bst));
} else
- bstp->state = ACPI_BATT_STAT_NOT_PRESENT;
+ bst->state = ACPI_BATT_STAT_NOT_PRESENT;
ACPI_SERIAL_END(cmbat);
return (0);
@@ -448,7 +521,7 @@
dev = (device_t)arg;
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
- "battery initialization start\n");
+ "battery enitialization start\n");
/*
* Try repeatedly to get valid data from the battery. Since the
@@ -487,11 +560,11 @@
timespecclear(&sc->bst_lastupdated);
acpi_cmbat_get_bst(dev);
}
- if (retry == 0 || !acpi_battery_bif_valid(&sc->bif))
- acpi_cmbat_get_bif(dev);
+ if (retry == 0 || !acpi_battery_bix_valid(&sc->bix))
+ acpi_cmbat_get_bix(dev);
valid = acpi_battery_bst_valid(&sc->bst) &&
- acpi_battery_bif_valid(&sc->bif);
+ acpi_battery_bix_valid(&sc->bix);
ACPI_SERIAL_END(cmbat);
if (valid)
@@ -500,9 +573,9 @@
if (retry == ACPI_CMBAT_RETRY_MAX) {
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
- "battery initialization failed, giving up\n");
+ "battery initialization failed, giving up\n");
} else {
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);
}
}
Index: sys/dev/acpica/acpi_if.m
===================================================================
--- sys/dev/acpica/acpi_if.m
+++ sys/dev/acpica/acpi_if.m
@@ -53,6 +53,7 @@
typedef ACPI_STATUS (*acpi_scan_cb_t)(ACPI_HANDLE h, device_t *dev,
int level, void *arg);
+ struct acpi_bix;
struct acpi_bif;
struct acpi_bst;
};
@@ -210,14 +211,16 @@
};
#
-# Get battery information (_BIF format)
+# Get battery information (_BIF or _BIX format)
#
# device_t dev: Battery device
-# struct acpi_bif *bif: Pointer to storage for _BIF results
+# void *bix: Pointer to storage for _BIF or _BIX results
+# size_t len: length of acpi_bif or acpi_bix.
#
METHOD int batt_get_info {
device_t dev;
- struct acpi_bif *bif;
+ void *bix;
+ size_t len;
};
#
Index: sys/dev/acpica/acpi_package.c
===================================================================
--- sys/dev/acpica/acpi_package.c
+++ sys/dev/acpica/acpi_package.c
@@ -71,6 +71,19 @@
}
int
+acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst)
+{
+ UINT64 tmp;
+ int error;
+
+ error = acpi_PkgInt(res, idx, &tmp);
+ if (error == 0)
+ *dst = (uint16_t)tmp;
+
+ return (error);
+}
+
+int
acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size)
{
ACPI_OBJECT *obj;
Index: sys/dev/acpica/acpi_smbat.c
===================================================================
--- sys/dev/acpica/acpi_smbat.c
+++ sys/dev/acpica/acpi_smbat.c
@@ -46,9 +46,9 @@
uint8_t sb_base_addr;
device_t ec_dev;
- struct acpi_bif bif;
+ struct acpi_bix bix;
struct acpi_bst bst;
- struct timespec bif_lastupdated;
+ struct timespec bix_lastupdated;
struct timespec bst_lastupdated;
};
@@ -57,7 +57,7 @@
static int acpi_smbat_shutdown(device_t dev);
static int acpi_smbat_info_expired(struct timespec *lastupdated);
static void acpi_smbat_info_updated(struct timespec *lastupdated);
-static int acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif);
+static int acpi_smbat_get_bix(device_t dev, void *, size_t);
static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst);
ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery");
@@ -87,7 +87,7 @@
/* ACPI battery interface */
DEVMETHOD(acpi_batt_get_status, acpi_smbat_get_bst),
- DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bif),
+ DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bix),
DEVMETHOD_END
};
@@ -141,7 +141,7 @@
return (ENXIO);
}
- timespecclear(&sc->bif_lastupdated);
+ timespecclear(&sc->bix_lastupdated);
timespecclear(&sc->bst_lastupdated);
if (acpi_battery_register(dev) != 0) {
@@ -415,7 +415,7 @@
}
static int
-acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif)
+acpi_smbat_get_bix(device_t dev, void *bix, size_t len)
{
struct acpi_smbat_softc *sc;
int error;
@@ -423,70 +423,76 @@
uint16_t val;
uint8_t addr;
+ if (len != sizeof(struct acpi_bix) &&
+ len != sizeof(struct acpi_bif))
+ return (-1);
+
ACPI_SERIAL_BEGIN(smbat);
addr = SMBATT_ADDRESS;
error = ENXIO;
sc = device_get_softc(dev);
- if (!acpi_smbat_info_expired(&sc->bif_lastupdated)) {
+ if (!acpi_smbat_info_expired(&sc->bix_lastupdated)) {
error = 0;
goto out;
}
+ sc->bix.rev = ACPI_BIX_REV_BIF;
+
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val))
goto out;
if (val & SMBATT_BM_CAPACITY_MODE) {
factor = 10;
- sc->bif.units = ACPI_BIF_UNITS_MW;
+ sc->bix.units = ACPI_BIX_UNITS_MW;
} else {
factor = 1;
- sc->bif.units = ACPI_BIF_UNITS_MA;
+ sc->bix.units = ACPI_BIX_UNITS_MA;
}
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_CAPACITY, &val))
goto out;
- sc->bif.dcap = val * factor;
+ sc->bix.dcap = val * factor;
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_FULL_CHARGE_CAPACITY, &val))
goto out;
- sc->bif.lfcap = val * factor;
- sc->bif.btech = 1; /* secondary (rechargeable) */
+ sc->bix.lfcap = val * factor;
+ sc->bix.btech = 1; /* secondary (rechargeable) */
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_VOLTAGE, &val))
goto out;
- sc->bif.dvol = val;
+ sc->bix.dvol = val;
- sc->bif.wcap = sc->bif.dcap / 10;
- sc->bif.lcap = sc->bif.dcap / 10;
+ sc->bix.wcap = sc->bix.dcap / 10;
+ sc->bix.lcap = sc->bix.dcap / 10;
- sc->bif.gra1 = factor; /* not supported */
- sc->bif.gra2 = factor; /* not supported */
+ sc->bix.gra1 = factor; /* not supported */
+ sc->bix.gra2 = factor; /* not supported */
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_NAME,
- sc->bif.model, sizeof(sc->bif.model)))
+ sc->bix.model, sizeof(sc->bix.model)))
goto out;
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_SERIAL_NUMBER, &val))
goto out;
- snprintf(sc->bif.serial, sizeof(sc->bif.serial), "0x%04x", val);
+ snprintf(sc->bix.serial, sizeof(sc->bix.serial), "0x%04x", val);
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_CHEMISTRY,
- sc->bif.type, sizeof(sc->bif.type)))
+ sc->bix.type, sizeof(sc->bix.type)))
goto out;
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_MANUFACTURER_DATA,
- sc->bif.oeminfo, sizeof(sc->bif.oeminfo)))
+ sc->bix.oeminfo, sizeof(sc->bix.oeminfo)))
goto out;
/* XXX check if device was replugged during read? */
- acpi_smbat_info_updated(&sc->bif_lastupdated);
+ acpi_smbat_info_updated(&sc->bix_lastupdated);
error = 0;
out:
if (error == 0)
- memcpy(bif, &sc->bif, sizeof(sc->bif));
+ memcpy(bix, &sc->bix, len);
ACPI_SERIAL_END(smbat);
return (error);
}
Index: sys/dev/acpica/acpiio.h
===================================================================
--- sys/dev/acpica/acpiio.h
+++ sys/dev/acpica/acpiio.h
@@ -48,9 +48,13 @@
int rate; /* emptying rate */
};
+/*
+ * Battery Information object. Note that this object is deprecated in
+ * ACPI 4.0
+ */
#define ACPI_CMBAT_MAXSTRLEN 32
struct acpi_bif {
- uint32_t units; /* Units (mW or mA). */
+ uint32_t units; /* Power Unit (mW or mA). */
#define ACPI_BIF_UNITS_MW 0 /* Capacity in mWh, rate in mW. */
#define ACPI_BIF_UNITS_MA 1 /* Capacity in mAh, rate in mA. */
uint32_t dcap; /* Design Capacity */
@@ -67,6 +71,76 @@
char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */
};
+/*
+ * Members in acpi_bix are reordered so that the first part is compatible
+ * with acpi_bif.
+ */
+struct acpi_bix {
+/* _BIF-compatible */
+ uint32_t units; /* Power Unit (mW or mA). */
+#define ACPI_BIX_UNITS_MW 0 /* Capacity in mWh, rate in mW. */
+#define ACPI_BIX_UNITS_MA 1 /* Capacity in mAh, rate in mA. */
+ uint32_t dcap; /* Design Capacity */
+ uint32_t lfcap; /* Last Full capacity */
+ uint32_t btech; /* Battery Technology */
+ uint32_t dvol; /* Design voltage (mV) */
+ uint32_t wcap; /* WARN capacity */
+ uint32_t lcap; /* Low capacity */
+ uint32_t gra1; /* Granularity 1 (Warn to Low) */
+ uint32_t gra2; /* Granularity 2 (Full to Warn) */
+ char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */
+ char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */
+ char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */
+ char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */
+ /* ACPI 4.0 or later */
+ uint16_t rev; /* Revision */
+#define ACPI_BIX_REV_0 0 /* ACPI 4.0 _BIX */
+#define ACPI_BIX_REV_1 1 /* ACPI 6.0 _BIX */
+#define ACPI_BIX_REV_BIF 0xffff /* _BIF */
+#define ACPI_BIX_REV_MIN_CHECK(x, min) \
+ (((min) == ACPI_BIX_REV_BIF) ? ((x) == ACPI_BIX_REV_BIF) : \
+ (((x) == ACPI_BIX_REV_BIF) ? 0 : ((x) >= (min))))
+ uint32_t cycles; /* Cycle Count */
+ uint32_t accuracy; /* Measurement Accuracy */
+ uint32_t stmax; /* Max Sampling Time */
+ uint32_t stmin; /* Min Sampling Time */
+ uint32_t aimax; /* Max Average Interval */
+ uint32_t aimin; /* Min Average Interval */
+ /* ACPI 6.0 or later */
+ uint32_t scap; /* Battery Swapping Capability */
+#define ACPI_BIX_SCAP_NO 0x00000000
+#define ACPI_BIX_SCAP_COLD 0x00000001
+#define ACPI_BIX_SCAP_HOT 0x00000010
+ uint8_t bix_reserved[58]; /* padding */
+};
+
+#if 0
+/* acpi_bix in the original order just for reference */
+struct acpi_bix {
+ uint16_t rev; /* Revision */
+ uint32_t units; /* Power Unit (mW or mA). */
+ uint32_t dcap; /* Design Capacity */
+ uint32_t lfcap; /* Last Full capacity */
+ uint32_t btech; /* Battery Technology */
+ uint32_t dvol; /* Design voltage (mV) */
+ uint32_t wcap; /* Design Capacity of Warning */
+ uint32_t lcap; /* Design Capacity of Low */
+ uint32_t cycles; /* Cycle Count */
+ uint32_t accuracy; /* Measurement Accuracy */
+ uint32_t stmax; /* Max Sampling Time */
+ uint32_t stmin; /* Min Sampling Time */
+ uint32_t aimax; /* Max Average Interval */
+ uint32_t aimin; /* Min Average Interval */
+ uint32_t gra1; /* Granularity 1 (Warn to Low) */
+ uint32_t gra2; /* Granularity 2 (Full to Warn) */
+ char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */
+ char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */
+ char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */
+ char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */
+ uint32_t scap; /* Battery Swapping Capability */
+};
+#endif
+
struct acpi_bst {
uint32_t state; /* Battery State */
uint32_t rate; /* Present Rate */
@@ -91,23 +165,36 @@
(ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL)
#define ACPI_BATT_STAT_NOT_PRESENT ACPI_BATT_STAT_BST_MASK
+/* For backward compatibility */
+union acpi_battery_ioctl_arg_v1 {
+ int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */
+
+ struct acpi_battinfo battinfo;
+
+ struct acpi_bif bif;
+ struct acpi_bst bst;
+};
union acpi_battery_ioctl_arg {
int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */
struct acpi_battinfo battinfo;
+ struct acpi_bix bix;
struct acpi_bif bif;
struct acpi_bst bst;
};
#define ACPI_BATTERY_ALL_UNITS (-1)
-#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BIF value unknown. */
+#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BI[FX] value unknown. */
/* Common battery ioctls */
#define ACPIIO_BATT_GET_UNITS _IOR('B', 0x01, int)
#define ACPIIO_BATT_GET_BATTINFO _IOWR('B', 0x03, union acpi_battery_ioctl_arg)
-#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg)
+#define ACPIIO_BATT_GET_BATTINFO_V1 _IOWR('B', 0x03, union acpi_battery_ioctl_arg_v1)
+#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg_v1)
+#define ACPIIO_BATT_GET_BIX _IOWR('B', 0x10, union acpi_battery_ioctl_arg)
#define ACPIIO_BATT_GET_BST _IOWR('B', 0x11, union acpi_battery_ioctl_arg)
+#define ACPIIO_BATT_GET_BST_V1 _IOWR('B', 0x11, union acpi_battery_ioctl_arg_v1)
/* Control Method battery ioctls (deprecated) */
#define ACPIIO_CMBAT_GET_BIF ACPIIO_BATT_GET_BIF
Index: sys/dev/acpica/acpivar.h
===================================================================
--- sys/dev/acpica/acpivar.h
+++ sys/dev/acpica/acpivar.h
@@ -479,7 +479,7 @@
int acpi_battery_get_units(void);
int acpi_battery_get_info_expire(void);
int acpi_battery_bst_valid(struct acpi_bst *bst);
-int acpi_battery_bif_valid(struct acpi_bif *bif);
+int acpi_battery_bix_valid(struct acpi_bix *bix);
int acpi_battery_get_battinfo(device_t dev,
struct acpi_battinfo *info);
@@ -493,8 +493,12 @@
#define ACPI_PKG_VALID(pkg, size) \
((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \
(pkg)->Package.Count >= (size))
+#define ACPI_PKG_VALID_EQ(pkg, size) \
+ ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \
+ (pkg)->Package.Count == (size))
int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst);
int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst);
+int acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst);
int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size);
int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type,
int *rid, struct resource **dst, u_int flags);
Index: usr.sbin/acpi/acpiconf/acpiconf.c
===================================================================
--- usr.sbin/acpi/acpiconf/acpiconf.c
+++ usr.sbin/acpi/acpiconf/acpiconf.c
@@ -96,34 +96,61 @@
/* Print battery design information. */
battio.unit = num;
- if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1)
+ if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1)
err(EX_IOERR, "get battery info (%d) failed", num);
- amp = battio.bif.units;
+ amp = battio.bix.units;
pwr_units = amp ? "mA" : "mW";
- if (battio.bif.dcap == UNKNOWN_CAP)
+ if (battio.bix.dcap == UNKNOWN_CAP)
printf("Design capacity:\tunknown\n");
else
- printf("Design capacity:\t%d %sh\n", battio.bif.dcap,
+ printf("Design capacity:\t%d %sh\n", battio.bix.dcap,
pwr_units);
- if (battio.bif.lfcap == UNKNOWN_CAP)
+ if (battio.bix.lfcap == UNKNOWN_CAP)
printf("Last full capacity:\tunknown\n");
else
- printf("Last full capacity:\t%d %sh\n", battio.bif.lfcap,
+ printf("Last full capacity:\t%d %sh\n", battio.bix.lfcap,
pwr_units);
- printf("Technology:\t\t%s\n", battio.bif.btech == 0 ?
+ printf("Technology:\t\t%s\n", battio.bix.btech == 0 ?
"primary (non-rechargeable)" : "secondary (rechargeable)");
- if (battio.bif.dvol == UNKNOWN_CAP)
+ if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) {
+ printf("Battery Swappable Capability:\t");
+ if (battio.bix.scap == ACPI_BIX_SCAP_NO)
+ printf("Non-swappable\n");
+ else if (battio.bix.scap == ACPI_BIX_SCAP_COLD)
+ printf("cold swap\n");
+ else if (battio.bix.scap == ACPI_BIX_SCAP_HOT)
+ printf("hot swap\n");
+ else
+ printf("unknown\n");
+ }
+ if (battio.bix.dvol == UNKNOWN_CAP)
printf("Design voltage:\t\tunknown\n");
else
- printf("Design voltage:\t\t%d mV\n", battio.bif.dvol);
- printf("Capacity (warn):\t%d %sh\n", battio.bif.wcap, pwr_units);
- printf("Capacity (low):\t\t%d %sh\n", battio.bif.lcap, pwr_units);
- printf("Low/warn granularity:\t%d %sh\n", battio.bif.gra1, pwr_units);
- printf("Warn/full granularity:\t%d %sh\n", battio.bif.gra2, pwr_units);
- printf("Model number:\t\t%s\n", battio.bif.model);
- printf("Serial number:\t\t%s\n", battio.bif.serial);
- printf("Type:\t\t\t%s\n", battio.bif.type);
- printf("OEM info:\t\t%s\n", battio.bif.oeminfo);
+ printf("Design voltage:\t\t%d mV\n", battio.bix.dvol);
+ printf("Capacity (warn):\t%d %sh\n", battio.bix.wcap, pwr_units);
+ printf("Capacity (low):\t\t%d %sh\n", battio.bix.lcap, pwr_units);
+ if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) {
+ if (battio.bix.cycles != ACPI_BATT_UNKNOWN)
+ printf("Cycle Count:\t\t%d\n", battio.bix.cycles);
+ printf("Mesurement Accuracy:\t%d %%\n",
+ battio.bix.accuracy / 1000);
+ if (battio.bix.stmax != ACPI_BATT_UNKNOWN)
+ printf("Max Sampling Time:\t%d ms\n",
+ battio.bix.stmax);
+ if (battio.bix.stmin != ACPI_BATT_UNKNOWN)
+ printf("Min Sampling Time:\t%d ms\n",
+ battio.bix.stmin);
+ printf("Max Average Interval:\t%d ms\n",
+ battio.bix.aimax);
+ printf("Min Average Interval:\t%d ms\n",
+ battio.bix.aimin);
+ }
+ printf("Low/warn granularity:\t%d %sh\n", battio.bix.gra1, pwr_units);
+ printf("Warn/full granularity:\t%d %sh\n", battio.bix.gra2, pwr_units);
+ printf("Model number:\t\t%s\n", battio.bix.model);
+ printf("Serial number:\t\t%s\n", battio.bix.serial);
+ printf("Type:\t\t\t%s\n", battio.bix.type);
+ printf("OEM info:\t\t%s\n", battio.bix.oeminfo);
/* Fetch battery voltage information. */
volt = UNKNOWN_VOLTAGE;

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 22, 7:12 PM (16 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31995253
Default Alt Text
D23728.id68460.diff (45 KB)

Event Timeline