Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153543663
D23728.id68460.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
45 KB
Referenced Files
None
Subscribers
None
D23728.id68460.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D23728: Add _BIX (Battery Information Extended) object support to acpi_cmbat
Attached
Detach File
Event Timeline
Log In to Comment