Date: Sun, 24 Jul 2005 02:29:39 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 80886 for review Message-ID: <200507240229.j6O2TdCG065705@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=80886 Change 80886 by rwatson@rwatson_zoo on 2005/07/24 02:29:32 Integrate netsmp. Affected files ... .. //depot/projects/netsmp/src/sys/dev/acpica/acpi_battery.c#2 integrate .. //depot/projects/netsmp/src/sys/dev/acpica/acpi_cmbat.c#2 integrate .. //depot/projects/netsmp/src/sys/dev/acpica/acpi_if.m#2 integrate .. //depot/projects/netsmp/src/sys/dev/acpica/acpiio.h#2 integrate .. //depot/projects/netsmp/src/sys/dev/acpica/acpivar.h#2 integrate .. //depot/projects/netsmp/src/sys/dev/ath/if_ath.c#4 integrate .. //depot/projects/netsmp/src/sys/i386/acpica/acpi_machdep.c#2 integrate .. //depot/projects/netsmp/src/sys/libkern/iconv.c#2 integrate .. //depot/projects/netsmp/src/sys/netgraph/ng_socket.c#2 integrate .. //depot/projects/netsmp/src/sys/netinet/ip_fastfwd.c#2 integrate .. //depot/projects/netsmp/src/sys/sys/param.h#2 integrate Differences ... ==== //depot/projects/netsmp/src/sys/dev/acpica/acpi_battery.c#2 (text+ko) ==== @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2005 Nate Lawson * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> * All rights reserved. * @@ -25,7 +26,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_battery.c,v 1.12 2005/03/17 22:42:49 njl Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_battery.c,v 1.13 2005/07/23 19:35:59 njl Exp $"); #include "opt_acpi.h" #include <sys/param.h> @@ -39,96 +40,248 @@ #include <dev/acpica/acpivar.h> #include <dev/acpica/acpiio.h> -MALLOC_DEFINE(M_ACPIBATT, "acpibatt", "ACPI generic battery data"); +/* Default seconds before re-sampling the battery state. */ +#define ACPI_BATTERY_INFO_EXPIRE 5 -struct acpi_batteries { - TAILQ_ENTRY(acpi_batteries) link; - struct acpi_battdesc battdesc; -}; +static int acpi_batteries_initted; +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; +static struct sysctl_oid *acpi_battery_sysctl_tree; -static TAILQ_HEAD(,acpi_batteries) acpi_batteries; -static int acpi_batteries_initted; -static int acpi_batteries_units; -static int acpi_battery_info_expire = 5; -static struct acpi_battinfo acpi_battery_battinfo; ACPI_SERIAL_DECL(battery, "ACPI generic battery"); +static void acpi_reset_battinfo(struct acpi_battinfo *info); +static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg); +static int acpi_battery_sysctl(SYSCTL_HANDLER_ARGS); +static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS); +static int acpi_battery_init(void); + +int +acpi_battery_register(device_t dev) +{ + int error; + + error = 0; + ACPI_SERIAL_BEGIN(battery); + if (!acpi_batteries_initted) + error = acpi_battery_init(); + ACPI_SERIAL_END(battery); + return (error); +} + int -acpi_battery_get_info_expire(void) +acpi_battery_remove(device_t dev) { - return (acpi_battery_info_expire); + + return (0); } int acpi_battery_get_units(void) { - return (acpi_batteries_units); + devclass_t batt_dc; + + batt_dc = devclass_find("battery"); + if (batt_dc == NULL) + return (0); + return (devclass_get_count(batt_dc)); } int -acpi_battery_get_battdesc(int unit, struct acpi_battdesc *battdesc) +acpi_battery_get_info_expire(void) { - struct acpi_batteries *bp; - int error, i; - error = ENXIO; - ACPI_SERIAL_BEGIN(battery); - if (unit < 0 || unit >= acpi_batteries_units) - goto out; + return (acpi_battery_info_expire); +} - i = 0; - TAILQ_FOREACH(bp, &acpi_batteries, link) { - if (unit == i) { - battdesc->type = bp->battdesc.type; - battdesc->phys_unit = bp->battdesc.phys_unit; - error = 0; - break; - } - i++; - } +/* Check _BST results for validity. */ +int +acpi_battery_bst_valid(struct acpi_bst *bst) +{ + if (bst->state >= ACPI_BATT_STAT_MAX || bst->cap == 0xffffffff || + bst->volt == 0xffffffff) + return (FALSE); + else + return (TRUE); +} -out: - ACPI_SERIAL_END(battery); - return (error); +/* Check _BIF results for validity. */ +int +acpi_battery_bif_valid(struct acpi_bif *bif) +{ + if (bif->lfcap == 0) + return (FALSE); + else + return (TRUE); } +/* Get info about one or all batteries. */ int -acpi_battery_get_battinfo(int unit, struct acpi_battinfo *battinfo) +acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo) { - struct acpi_battdesc battdesc; - int error; + int batt_stat, devcount, dev_idx, error, i; + int total_cap, total_min, valid_rate, valid_units; + devclass_t batt_dc; + device_t batt_dev; + struct acpi_bst *bst; + struct acpi_bif *bif; + struct acpi_battinfo *bi; + + /* + * Get the battery devclass and number of devices. If there are none + * or error, return immediately. + */ + batt_dc = devclass_find("battery"); + if (batt_dc == NULL) + return (ENXIO); + devcount = devclass_get_count(batt_dc); + if (devcount == 0) + return (ENXIO); + + /* + * Allocate storage for all _BST data, their derived battinfo data, + * and the current battery's _BIF data. + */ + bst = malloc(devcount * sizeof(*bst), M_TEMP, M_WAITOK); + bi = malloc(devcount * sizeof(*bi), M_TEMP, M_WAITOK); + bif = malloc(sizeof(*bif), M_TEMP, M_WAITOK); + + /* + * Pass 1: for each battery that is present and valid, get its status, + * calculate percent capacity remaining, and sum all the current + * discharge rates. + */ + dev_idx = -1; + batt_stat = valid_rate = valid_units = 0; + for (i = 0; i < devcount; i++) { + /* Find the device. If it disappeared, the user can try again. */ + batt_dev = devclass_get_device(batt_dc, i); + if (batt_dev == NULL) { + error = ENOMEM; + goto out; + } + + /* Default info for every battery is "not present". */ + acpi_reset_battinfo(&bi[i]); + + /* If examining a specific battery and this is it, record its index. */ + if (dev != NULL && dev == batt_dev) + dev_idx = i; + + /* Be sure we can get various info from the battery. */ + if (!acpi_BatteryIsPresent(batt_dev) || + ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 || + ACPI_BATT_GET_INFO(batt_dev, bif) != 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)) + continue; + + /* Record state and calculate percent capacity remaining. */ + valid_units++; + batt_stat |= bst[i].state; + bi[i].state = bst[i].state; + bi[i].cap = 100 * bst[i].cap / bif->lfcap; + + /* + * Some laptops report the "design-capacity" instead of the + * "real-capacity" when the battery is fully charged. That breaks + * the above arithmetic as it needs to be 100% maximum. + */ + if (bi[i].cap > 100) + bi[i].cap = 100; + + /* + * On systems with more than one battery, they may get used + * sequentially, thus bst.rate may only signify the one currently + * in use. For the remaining batteries, bst.rate will be zero, + * which makes it impossible to calculate the total remaining time. + * Therefore, we sum the bst.rate for batteries in the discharging + * state and use the sum to calculate the total remaining time. + */ + if (bst[i].rate > 0 && (bst[i].state & ACPI_BATT_STAT_DISCHARG)) + valid_rate += bst[i].rate; + } - error = 0; - if (unit == -1) { - error = acpi_cmbat_get_battinfo(-1, battinfo); + /* If the caller asked for a device but we didn't find it, error. */ + if (dev != NULL && dev_idx < 0) { + error = ENXIO; goto out; - } else { - error = acpi_battery_get_battdesc(unit, &battdesc); - if (error != 0) - goto out; + } + + /* Pass 2: calculate capacity and remaining time for all batteries. */ + total_cap = total_min = 0; + for (i = 0; i < devcount; i++) { + /* + * If any batteries are discharging, use the sum of the bst.rate + * values. Otherwise, we are on AC power, and there is infinite + * time remaining for this battery until we go offline. + */ + if (valid_rate > 0) + bi[i].min = 60 * bst[i].cap / valid_rate; + else + bi[i].min = 0; + total_min += bi[i].min; + total_cap += bi[i].cap; + } - switch (battdesc.type) { - case ACPI_BATT_TYPE_CMBAT: - error = acpi_cmbat_get_battinfo(battdesc.phys_unit, battinfo); - break; - default: - error = ENXIO; - break; + /* + * Return total battery percent and time remaining. If there are + * no valid batteries, report values as unknown. + */ + if (valid_units > 0) { + if (dev == NULL) { + battinfo->cap = total_cap / valid_units; + battinfo->min = total_min; + battinfo->state = batt_stat; + battinfo->rate = valid_rate; + } else { + battinfo->cap = bi[dev_idx].cap; + battinfo->min = bi[dev_idx].min; + battinfo->state = bi[dev_idx].state; + battinfo->rate = bst[dev_idx].rate; } - } + } else + acpi_reset_battinfo(battinfo); + + error = 0; out: + if (bi) + free(bi, M_TEMP); + if (bif) + free(bif, M_TEMP); + if (bst) + free(bst, M_TEMP); return (error); } +static void +acpi_reset_battinfo(struct acpi_battinfo *info) +{ + info->cap = -1; + info->min = -1; + info->state = ACPI_BATT_STAT_NOT_PRESENT; + info->rate = -1; +} + static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg) { union acpi_battery_ioctl_arg *ioctl_arg; int error, unit; + device_t dev; + error = ENXIO; ioctl_arg = (union acpi_battery_ioctl_arg *)addr; - error = 0; + unit = ioctl_arg->unit; + if (unit != ACPI_BATTERY_ALL_UNITS) + dev = devclass_get_device(devclass_find("battery"), unit); + else + dev = NULL; /* * No security check required: information retrieval only. If @@ -138,17 +291,20 @@ case ACPIIO_BATT_GET_UNITS: *(int *)addr = acpi_battery_get_units(); break; - case ACPIIO_BATT_GET_BATTDESC: - unit = ioctl_arg->unit; - error = acpi_battery_get_battdesc(unit, &ioctl_arg->battdesc); + case ACPIIO_BATT_GET_BATTINFO: + if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) + error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo); + break; + case ACPIIO_BATT_GET_BIF: + if (dev != NULL) + error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif); break; - case ACPIIO_BATT_GET_BATTINFO: - unit = ioctl_arg->unit; - error = acpi_battery_get_battinfo(unit, &ioctl_arg->battinfo); + case ACPIIO_BATT_GET_BST: + if (dev != NULL) + error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst); break; default: error = EINVAL; - break; } return (error); @@ -159,13 +315,23 @@ { int val, error; - acpi_battery_get_battinfo(-1, &acpi_battery_battinfo); + acpi_battery_get_battinfo(NULL, &acpi_battery_battinfo); val = *(u_int *)oidp->oid_arg1; error = sysctl_handle_int(oidp, &val, 0, req); return (error); } static int +acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS) +{ + int count, error; + + count = acpi_battery_get_units(); + error = sysctl_handle_int(oidp, &count, 0, req); + return (error); +} + +static int acpi_battery_init(void) { struct acpi_softc *sc; @@ -180,98 +346,54 @@ goto out; sc = device_get_softc(dev); - TAILQ_INIT(&acpi_batteries); - - /* XXX We should back out registered ioctls on error. */ error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, NULL); if (error != 0) goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTDESC, acpi_battery_ioctl, + error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, NULL); if (error != 0) goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, - NULL); + 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; - sysctl_ctx_init(&sc->acpi_battery_sysctl_ctx); - sc->acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_battery_sysctl_ctx, + 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, 0, ""); - SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx, - SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), + SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", ""); - SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx, - SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), + SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", ""); - SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx, - SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), + SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", ""); - SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx, - SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), - OID_AUTO, "units", CTLFLAG_RD, &acpi_batteries_units, 0, ""); - SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx, - SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree), + SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), + OID_AUTO, "units", CTLTYPE_INT | CTLFLAG_RD, + NULL, 0, acpi_battery_units_sysctl, "I", ""); + SYSCTL_ADD_INT(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "info_expire", CTLFLAG_RD | CTLFLAG_RW, &acpi_battery_info_expire, 0, ""); acpi_batteries_initted = TRUE; out: - return (error); -} - -int -acpi_battery_register(int type, int phys_unit) -{ - struct acpi_batteries *bp; - int error; - - error = 0; - bp = malloc(sizeof(*bp), M_ACPIBATT, M_NOWAIT); - if (bp == NULL) - return (ENOMEM); - - ACPI_SERIAL_BEGIN(battery); - if (!acpi_batteries_initted && (error = acpi_battery_init()) != 0) { - printf("acpi_battery_register failed for unit %d\n", phys_unit); - goto out; + if (error != 0) { + 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_BIF, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl); } - bp->battdesc.type = type; - bp->battdesc.phys_unit = phys_unit; - TAILQ_INSERT_TAIL(&acpi_batteries, bp, link); - acpi_batteries_units++; - -out: - ACPI_SERIAL_END(battery); - if (error) - free(bp, M_ACPIBATT); return (error); } - -int -acpi_battery_remove(int type, int phys_unit) -{ - struct acpi_batteries *bp, *tmp; - int ret; - - ret = ENOENT; - ACPI_SERIAL_BEGIN(battery); - TAILQ_FOREACH_SAFE(bp, &acpi_batteries, link, tmp) { - if (bp->battdesc.type == type && bp->battdesc.phys_unit == phys_unit) { - TAILQ_REMOVE(&acpi_batteries, bp, link); - acpi_batteries_units--; - ret = 0; - break; - } - } - ACPI_SERIAL_END(battery); - if (ret == 0) - free(bp, M_ACPIBATT); - return (ret); -} ==== //depot/projects/netsmp/src/sys/dev/acpica/acpi_cmbat.c#2 (text+ko) ==== @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2005 Nate Lawson * Copyright (c) 2000 Munehiro Matsuda * Copyright (c) 2000 Takanori Watanabe * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> @@ -24,10 +25,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/acpica/acpi_cmbat.c,v 1.39 2004/12/20 05:03:41 njl Exp $ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_cmbat.c,v 1.40 2005/07/23 19:35:59 njl Exp $"); + #include "opt_acpi.h" #include <sys/param.h> #include <sys/kernel.h> @@ -60,41 +62,29 @@ struct acpi_cmbat_softc { device_t dev; + int flags; struct acpi_bif bif; struct acpi_bst bst; struct timespec bif_lastupdated; struct timespec bst_lastupdated; - - int flags; - int present; - int cap; - int min; - int full_charge_time; - int initializing; - int phys_unit; }; -static struct timespec acpi_cmbat_info_lastupdated; ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); -/* XXX: devclass_get_maxunit() don't give us the current allocated units. */ -static int acpi_cmbat_units = 0; - -static int acpi_cmbat_info_expired(struct timespec *); -static void acpi_cmbat_info_updated(struct timespec *); -static void acpi_cmbat_get_bst(void *); -static void acpi_cmbat_get_bif(void *); -static void acpi_cmbat_notify_handler(ACPI_HANDLE, UINT32, void *); -static int acpi_cmbat_probe(device_t); -static int acpi_cmbat_attach(device_t); -static int acpi_cmbat_detach(device_t); -static int acpi_cmbat_resume(device_t); -static int acpi_cmbat_ioctl(u_long, caddr_t, void *); -static int acpi_cmbat_is_bst_valid(struct acpi_bst*); -static int acpi_cmbat_is_bif_valid(struct acpi_bif*); -static int acpi_cmbat_get_total_battinfo(struct acpi_battinfo *); -static void acpi_cmbat_init_battery(void *); +static int acpi_cmbat_probe(device_t dev); +static int acpi_cmbat_attach(device_t dev); +static int acpi_cmbat_detach(device_t dev); +static int acpi_cmbat_resume(device_t dev); +static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, + void *context); +static int acpi_cmbat_info_expired(struct timespec *lastupdated); +static void acpi_cmbat_info_updated(struct timespec *lastupdated); +static void acpi_cmbat_get_bst(device_t dev); +static void acpi_cmbat_get_bif(device_t dev); +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_init_battery(void *arg); static device_method_t acpi_cmbat_methods[] = { /* Device interface */ @@ -103,11 +93,15 @@ DEVMETHOD(device_detach, acpi_cmbat_detach), DEVMETHOD(device_resume, acpi_cmbat_resume), + /* ACPI battery interface */ + DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif), + DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst), + {0, 0} }; static driver_t acpi_cmbat_driver = { - "acpi_cmbat", + "battery", acpi_cmbat_methods, sizeof(struct acpi_cmbat_softc), }; @@ -117,6 +111,96 @@ MODULE_DEPEND(acpi_cmbat, acpi, 1, 1, 1); static int +acpi_cmbat_probe(device_t dev) +{ + static char *cmbat_ids[] = { "PNP0C0A", NULL }; + + if (acpi_disabled("cmbat") || + ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids) == NULL) + return (ENXIO); + + device_set_desc(dev, "ACPI Control Method Battery"); + return (0); +} + +static int +acpi_cmbat_attach(device_t dev) +{ + int error; + ACPI_HANDLE handle; + struct acpi_cmbat_softc *sc; + + sc = device_get_softc(dev); + handle = acpi_get_handle(dev); + sc->dev = dev; + + timespecclear(&sc->bif_lastupdated); + timespecclear(&sc->bst_lastupdated); + + error = acpi_battery_register(dev); + if (error != 0) { + device_printf(dev, "registering battery failed\n"); + return (error); + } + + /* + * Install a system notify handler in addition to the device notify. + * Toshiba notebook uses this alternate notify for its battery. + */ + AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, + acpi_cmbat_notify_handler, dev); + + AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); + + return (0); +} + +static int +acpi_cmbat_detach(device_t dev) +{ + + acpi_battery_remove(dev); + return (0); +} + +static int +acpi_cmbat_resume(device_t dev) +{ + + AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); + return (0); +} + +static void +acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) +{ + struct acpi_cmbat_softc *sc; + device_t dev; + + dev = (device_t)context; + sc = device_get_softc(dev); + + /* + * Clear the appropriate last updated time. The next call to retrieve + * the battery status will get the new value for us. We don't need to + * acquire a lock since we are only clearing the time stamp and since + * calling _BST/_BIF can trigger a notify, we could deadlock also. + */ + switch (notify) { + case ACPI_NOTIFY_DEVICE_CHECK: + case ACPI_BATTERY_BST_CHANGE: + timespecclear(&sc->bst_lastupdated); + break; + case ACPI_NOTIFY_BUS_CHECK: + case ACPI_BATTERY_BIF_CHANGE: + timespecclear(&sc->bif_lastupdated); + break; + } + + acpi_UserNotify("CMBAT", h, notify); +} + +static int acpi_cmbat_info_expired(struct timespec *lastupdated) { struct timespec curtime; @@ -145,9 +229,8 @@ } static void -acpi_cmbat_get_bst(void *context) +acpi_cmbat_get_bst(device_t dev) { - device_t dev; struct acpi_cmbat_softc *sc; ACPI_STATUS as; ACPI_OBJECT *res; @@ -156,7 +239,6 @@ ACPI_SERIAL_ASSERT(cmbat); - dev = context; sc = device_get_softc(dev); h = acpi_get_handle(dev); bst_buffer.Pointer = NULL; @@ -205,9 +287,8 @@ } static void -acpi_cmbat_get_bif(void *context) +acpi_cmbat_get_bif(device_t dev) { - device_t dev; struct acpi_cmbat_softc *sc; ACPI_STATUS as; ACPI_OBJECT *res; @@ -216,7 +297,6 @@ ACPI_SERIAL_ASSERT(cmbat); - dev = context; sc = device_get_softc(dev); h = acpi_get_handle(dev); bif_buffer.Pointer = NULL; @@ -273,319 +353,59 @@ AcpiOsFree(bif_buffer.Pointer); } -static void -acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) -{ - device_t dev; - struct acpi_cmbat_softc *sc; - - dev = (device_t)context; - sc = device_get_softc(dev); - - acpi_UserNotify("CMBAT", h, notify); - - /* - * Clear the appropriate last updated time. The next call to retrieve - * the battery status will get the new value for us. We don't need to - * acquire a lock since we are only clearing the time stamp and since - * calling _BST/_BIF can trigger a notify, we could deadlock also. - */ - switch (notify) { - case ACPI_NOTIFY_DEVICE_CHECK: - case ACPI_BATTERY_BST_CHANGE: - timespecclear(&sc->bst_lastupdated); - break; - case ACPI_NOTIFY_BUS_CHECK: - case ACPI_BATTERY_BIF_CHANGE: - timespecclear(&sc->bif_lastupdated); - break; - default: - break; - } -} - static int -acpi_cmbat_probe(device_t dev) +acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp) { - static char *cmbat_ids[] = { "PNP0C0A", NULL }; - - if (acpi_disabled("cmbat") || - ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids) == NULL) - return (ENXIO); - - device_set_desc(dev, "Control Method Battery"); - return (0); -} - -static int -acpi_cmbat_attach(device_t dev) -{ - int error; - ACPI_HANDLE handle; struct acpi_cmbat_softc *sc; sc = device_get_softc(dev); - handle = acpi_get_handle(dev); - sc->dev = dev; - /* - * Install a system notify handler in addition to the device notify. - * Toshiba notebook uses this alternate notify for its battery. - */ - AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, - acpi_cmbat_notify_handler, dev); - ACPI_SERIAL_BEGIN(cmbat); - timespecclear(&sc->bif_lastupdated); - timespecclear(&sc->bst_lastupdated); - - if (acpi_cmbat_units == 0) { - error = acpi_register_ioctl(ACPIIO_CMBAT_GET_BIF, - acpi_cmbat_ioctl, NULL); - if (error != 0) { - device_printf(dev, "register bif ioctl failed\n"); - return (error); - } - error = acpi_register_ioctl(ACPIIO_CMBAT_GET_BST, - acpi_cmbat_ioctl, NULL); - if (error != 0) { - device_printf(dev, "register bst ioctl failed\n"); - return (error); - } - } - - sc->phys_unit = acpi_cmbat_units; - error = acpi_battery_register(ACPI_BATT_TYPE_CMBAT, sc->phys_unit); - if (error != 0) { - device_printf(dev, "registering battery %d failed\n", sc->phys_unit); - return (error); - } - acpi_cmbat_units++; - timespecclear(&acpi_cmbat_info_lastupdated); + acpi_cmbat_get_bif(dev); + 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)); ACPI_SERIAL_END(cmbat); - AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); - return (0); } static int -acpi_cmbat_detach(device_t dev) +acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp) { struct acpi_cmbat_softc *sc; sc = device_get_softc(dev); - ACPI_SERIAL_BEGIN(cmbat); - acpi_battery_remove(ACPI_BATT_TYPE_CMBAT, sc->phys_unit); - acpi_cmbat_units--; - ACPI_SERIAL_END(cmbat); - return (0); -} - -static int -acpi_cmbat_resume(device_t dev) -{ - AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); - return (0); -} - -static int -acpi_cmbat_ioctl(u_long cmd, caddr_t addr, void *arg) -{ - device_t dev; - union acpi_battery_ioctl_arg *ioctl_arg; - struct acpi_cmbat_softc *sc; - struct acpi_bif *bifp; - struct acpi_bst *bstp; - - ioctl_arg = (union acpi_battery_ioctl_arg *)addr; - dev = devclass_get_device(acpi_cmbat_devclass, ioctl_arg->unit); - if (dev == NULL) - return (ENXIO); - sc = device_get_softc(dev); - /* - * No security check required: information retrieval only. If - * new functions are added here, a check might be required. - */ ACPI_SERIAL_BEGIN(cmbat); - switch (cmd) { - case ACPIIO_CMBAT_GET_BIF: - acpi_cmbat_get_bif(dev); - bifp = &ioctl_arg->bif; - 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)); - break; - case ACPIIO_CMBAT_GET_BST: - bstp = &ioctl_arg->bst; - 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; - } else { - bstp->state = ACPI_BATT_STAT_NOT_PRESENT; - } - break; - default: - break; - } + 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; + } else + bstp->state = ACPI_BATT_STAT_NOT_PRESENT; ACPI_SERIAL_END(cmbat); return (0); } -static int -acpi_cmbat_is_bst_valid(struct acpi_bst *bst) -{ - if (bst->state >= ACPI_BATT_STAT_MAX || bst->cap == 0xffffffff || - bst->volt == 0xffffffff) - return (FALSE); - else - return (TRUE); -} - -static int -acpi_cmbat_is_bif_valid(struct acpi_bif *bif) -{ - if (bif->lfcap == 0) - return (FALSE); - else - return (TRUE); -} - -static int -acpi_cmbat_get_total_battinfo(struct acpi_battinfo *battinfo) -{ - int i; - int error; - int batt_stat; - int valid_rate, valid_units; - int cap, min; - int total_cap, total_min, total_full; - struct acpi_cmbat_softc *sc; - - ACPI_SERIAL_ASSERT(cmbat); - - cap = min = -1; - batt_stat = ACPI_BATT_STAT_NOT_PRESENT; - error = 0; - - /* Get battery status, valid rate and valid units */ - batt_stat = valid_rate = valid_units = 0; - for (i = 0; i < acpi_cmbat_units; i++) { - sc = devclass_get_softc(acpi_cmbat_devclass, i); - if (sc == NULL) - continue; - sc->present = acpi_BatteryIsPresent(sc->dev); - if (!sc->present) - continue; - acpi_cmbat_get_bst(sc->dev); - - /* If battery not installed, we get strange values */ - if (!acpi_cmbat_is_bst_valid(&sc->bst) || - !acpi_cmbat_is_bif_valid(&sc->bif)) { - sc->present = FALSE; - continue; - } >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200507240229.j6O2TdCG065705>