LCOV - code coverage report
Current view: top level - dev/acpi - acpibat.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 250 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: acpibat.c,v 1.67 2018/07/01 19:40:49 mlarkin Exp $ */
       2             : /*
       3             :  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16             :  */
      17             : 
      18             : #include <sys/param.h>
      19             : #include <sys/systm.h>
      20             : #include <sys/device.h>
      21             : #include <sys/malloc.h>
      22             : #include <sys/sensors.h>
      23             : 
      24             : #include <machine/apmvar.h>
      25             : 
      26             : #include <dev/acpi/acpireg.h>
      27             : #include <dev/acpi/acpivar.h>
      28             : #include <dev/acpi/acpidev.h>
      29             : #include <dev/acpi/amltypes.h>
      30             : #include <dev/acpi/dsdt.h>
      31             : 
      32             : int     acpibat_match(struct device *, void *, void *);
      33             : void    acpibat_attach(struct device *, struct device *, void *);
      34             : 
      35             : struct cfattach acpibat_ca = {
      36             :         sizeof(struct acpibat_softc), acpibat_match, acpibat_attach
      37             : };
      38             : 
      39             : struct cfdriver acpibat_cd = {
      40             :         NULL, "acpibat", DV_DULL
      41             : };
      42             : 
      43             : const char *acpibat_hids[] = {
      44             :         ACPI_DEV_CMB,
      45             :         NULL
      46             : };
      47             : 
      48             : void    acpibat_monitor(struct acpibat_softc *);
      49             : void    acpibat_refresh(void *);
      50             : int     acpibat_getbix(struct acpibat_softc *);
      51             : int     acpibat_getbst(struct acpibat_softc *);
      52             : int     acpibat_notify(struct aml_node *, int, void *);
      53             : 
      54             : int
      55           0 : acpibat_match(struct device *parent, void *match, void *aux)
      56             : {
      57           0 :         struct acpi_attach_args *aa = aux;
      58           0 :         struct cfdata           *cf = match;
      59             : 
      60           0 :         if (((struct acpi_softc *)parent)->sc_havesbs)
      61           0 :                 return (0);
      62             : 
      63             :         /* sanity */
      64           0 :         return (acpi_matchhids(aa, acpibat_hids, cf->cf_driver->cd_name));
      65           0 : }
      66             : 
      67             : void
      68           0 : acpibat_attach(struct device *parent, struct device *self, void *aux)
      69             : {
      70           0 :         struct acpibat_softc    *sc = (struct acpibat_softc *)self;
      71           0 :         struct acpi_attach_args *aa = aux;
      72           0 :         int64_t                 sta;
      73             : 
      74           0 :         sc->sc_acpi = (struct acpi_softc *)parent;
      75           0 :         sc->sc_devnode = aa->aaa_node;
      76             : 
      77           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, &sta)) {
      78             :                 dnprintf(10, "%s: no _STA\n", DEVNAME(sc));
      79           0 :                 return;
      80             :         }
      81             : 
      82           0 :         if ((sta & STA_BATTERY) != 0) {
      83           0 :                 sc->sc_bat_present = 1;
      84           0 :                 acpibat_getbix(sc);
      85           0 :                 acpibat_getbst(sc);
      86             : 
      87           0 :                 printf(": %s", sc->sc_devnode->name);
      88           0 :                 if (sc->sc_bix.bix_model[0])
      89           0 :                         printf(" model \"%s\"", sc->sc_bix.bix_model);
      90           0 :                 if (sc->sc_bix.bix_serial[0])
      91           0 :                         printf(" serial %s", sc->sc_bix.bix_serial);
      92           0 :                 if (sc->sc_bix.bix_type[0])
      93           0 :                         printf(" type %s", sc->sc_bix.bix_type);
      94           0 :                 if (sc->sc_bix.bix_oem[0])
      95           0 :                         printf(" oem \"%s\"", sc->sc_bix.bix_oem);
      96             : 
      97           0 :                 printf("\n");
      98           0 :         } else {
      99           0 :                 sc->sc_bat_present = 0;
     100           0 :                 printf(": %s not present\n", sc->sc_devnode->name);
     101             :         }
     102             : 
     103             :         /* create sensors */
     104           0 :         acpibat_monitor(sc);
     105             : 
     106             :         /* populate sensors */
     107           0 :         acpibat_refresh(sc);
     108             : 
     109           0 :         aml_register_notify(sc->sc_devnode, aa->aaa_dev,
     110             :             acpibat_notify, sc, ACPIDEV_POLL);
     111           0 : }
     112             : 
     113             : void
     114           0 : acpibat_monitor(struct acpibat_softc *sc)
     115             : {
     116             :         int                     type;
     117             : 
     118             :         /* assume _BIF/_BIX and _BST have been called */
     119           0 :         strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
     120             :             sizeof(sc->sc_sensdev.xname));
     121             : 
     122           0 :         type = sc->sc_bix.bix_power_unit ? SENSOR_AMPHOUR : SENSOR_WATTHOUR;
     123             : 
     124           0 :         strlcpy(sc->sc_sens[0].desc, "last full capacity",
     125             :             sizeof(sc->sc_sens[0].desc));
     126           0 :         sc->sc_sens[0].type = type;
     127           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]);
     128           0 :         sc->sc_sens[0].value = sc->sc_bix.bix_last_capacity * 1000;
     129             : 
     130           0 :         strlcpy(sc->sc_sens[1].desc, "warning capacity",
     131             :             sizeof(sc->sc_sens[1].desc));
     132           0 :         sc->sc_sens[1].type = type;
     133           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[1]);
     134           0 :         sc->sc_sens[1].value = sc->sc_bix.bix_warning * 1000;
     135             : 
     136           0 :         strlcpy(sc->sc_sens[2].desc, "low capacity",
     137             :             sizeof(sc->sc_sens[2].desc));
     138           0 :         sc->sc_sens[2].type = type;
     139           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[2]);
     140           0 :         sc->sc_sens[2].value = sc->sc_bix.bix_low * 1000;
     141             : 
     142           0 :         strlcpy(sc->sc_sens[3].desc, "voltage", sizeof(sc->sc_sens[3].desc));
     143           0 :         sc->sc_sens[3].type = SENSOR_VOLTS_DC;
     144           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[3]);
     145           0 :         sc->sc_sens[3].value = sc->sc_bix.bix_voltage * 1000;
     146             : 
     147           0 :         strlcpy(sc->sc_sens[4].desc, "battery unknown",
     148             :             sizeof(sc->sc_sens[4].desc));
     149           0 :         sc->sc_sens[4].type = SENSOR_INTEGER;
     150           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[4]);
     151           0 :         sc->sc_sens[4].value = sc->sc_bst.bst_state;
     152             : 
     153           0 :         strlcpy(sc->sc_sens[5].desc, "rate", sizeof(sc->sc_sens[5].desc));
     154           0 :         sc->sc_sens[5].type =
     155           0 :                 sc->sc_bix.bix_power_unit ? SENSOR_AMPS : SENSOR_WATTS;
     156           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[5]);
     157           0 :         sc->sc_sens[5].value = sc->sc_bst.bst_rate * 1000;
     158             : 
     159           0 :         strlcpy(sc->sc_sens[6].desc, "remaining capacity",
     160             :             sizeof(sc->sc_sens[6].desc));
     161           0 :         sc->sc_sens[6].type = type;
     162           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[6]);
     163           0 :         sc->sc_sens[6].value = sc->sc_bix.bix_capacity * 1000;
     164             : 
     165           0 :         strlcpy(sc->sc_sens[7].desc, "current voltage",
     166             :             sizeof(sc->sc_sens[7].desc));
     167           0 :         sc->sc_sens[7].type = SENSOR_VOLTS_DC;
     168           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[7]);
     169           0 :         sc->sc_sens[7].value = sc->sc_bix.bix_voltage * 1000;
     170             : 
     171           0 :         strlcpy(sc->sc_sens[8].desc, "design capacity",
     172             :             sizeof(sc->sc_sens[8].desc));
     173           0 :         sc->sc_sens[8].type = type;
     174           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[8]);
     175           0 :         sc->sc_sens[8].value = sc->sc_bix.bix_capacity * 1000;
     176             : 
     177           0 :         if (!sc->sc_use_bif) {
     178           0 :                 strlcpy(sc->sc_sens[9].desc, "discharge cycles",
     179             :                     sizeof(sc->sc_sens[9].desc));
     180           0 :                 sc->sc_sens[9].type = SENSOR_INTEGER;
     181           0 :                 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[9]);
     182           0 :                 sc->sc_sens[9].value = sc->sc_bix.bix_cycle_count;
     183           0 :         }
     184             : 
     185           0 :         sensordev_install(&sc->sc_sensdev);
     186           0 : }
     187             : 
     188             : void
     189           0 : acpibat_refresh(void *arg)
     190             : {
     191           0 :         struct acpibat_softc    *sc = arg;
     192             :         int                     i;
     193             : 
     194             :         dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc),
     195             :             sc->sc_devnode->name);
     196             : 
     197           0 :         if (!sc->sc_bat_present) {
     198           0 :                 for (i = 0; i < nitems(sc->sc_sens); i++) {
     199           0 :                         sc->sc_sens[i].value = 0;
     200           0 :                         sc->sc_sens[i].status = SENSOR_S_UNSPEC;
     201           0 :                         sc->sc_sens[i].flags = SENSOR_FINVALID;
     202             :                 }
     203             :                 /* override state */
     204           0 :                 strlcpy(sc->sc_sens[4].desc, "battery removed",
     205             :                     sizeof(sc->sc_sens[4].desc));
     206           0 :                 return;
     207             :         }
     208             : 
     209             :         /* _BIF/_BIX values are static, sensor 0..3 */
     210           0 :         if (sc->sc_bix.bix_last_capacity == BIX_UNKNOWN) {
     211           0 :                 sc->sc_sens[0].value = 0;
     212           0 :                 sc->sc_sens[0].status = SENSOR_S_UNKNOWN;
     213           0 :                 sc->sc_sens[0].flags = SENSOR_FUNKNOWN;
     214           0 :         } else {
     215           0 :                 sc->sc_sens[0].value = sc->sc_bix.bix_last_capacity * 1000;
     216           0 :                 sc->sc_sens[0].status = SENSOR_S_UNSPEC;
     217           0 :                 sc->sc_sens[0].flags = 0;
     218             :         }
     219           0 :         sc->sc_sens[1].value = sc->sc_bix.bix_warning * 1000;
     220           0 :         sc->sc_sens[1].flags = 0;
     221           0 :         sc->sc_sens[2].value = sc->sc_bix.bix_low * 1000;
     222           0 :         sc->sc_sens[2].flags = 0;
     223           0 :         if (sc->sc_bix.bix_voltage == BIX_UNKNOWN) {
     224           0 :                 sc->sc_sens[3].value = 0;
     225           0 :                 sc->sc_sens[3].status = SENSOR_S_UNKNOWN;
     226           0 :                 sc->sc_sens[3].flags = SENSOR_FUNKNOWN;
     227           0 :         } else {
     228           0 :                 sc->sc_sens[3].value = sc->sc_bix.bix_voltage * 1000;
     229           0 :                 sc->sc_sens[3].status = SENSOR_S_UNSPEC;
     230           0 :                 sc->sc_sens[3].flags = 0;
     231             :         }
     232             : 
     233             :         /* _BST values are dynamic, sensor 4..7 */
     234           0 :         sc->sc_sens[4].status = SENSOR_S_OK;
     235           0 :         sc->sc_sens[4].flags = 0;
     236           0 :         if (sc->sc_bix.bix_last_capacity == BIX_UNKNOWN ||
     237           0 :             sc->sc_bst.bst_capacity == BST_UNKNOWN) {
     238           0 :                 sc->sc_sens[4].status = SENSOR_S_UNKNOWN;
     239           0 :                 sc->sc_sens[4].flags = SENSOR_FUNKNOWN;
     240           0 :                 strlcpy(sc->sc_sens[4].desc, "battery unknown",
     241             :                     sizeof(sc->sc_sens[4].desc));
     242           0 :         } else if (sc->sc_bst.bst_capacity >= sc->sc_bix.bix_last_capacity)
     243           0 :                 strlcpy(sc->sc_sens[4].desc, "battery full",
     244             :                     sizeof(sc->sc_sens[4].desc));
     245           0 :         else if (sc->sc_bst.bst_state & BST_DISCHARGE)
     246           0 :                 strlcpy(sc->sc_sens[4].desc, "battery discharging",
     247             :                     sizeof(sc->sc_sens[4].desc));
     248           0 :         else if (sc->sc_bst.bst_state & BST_CHARGE)
     249           0 :                 strlcpy(sc->sc_sens[4].desc, "battery charging",
     250             :                     sizeof(sc->sc_sens[4].desc));
     251           0 :         else if (sc->sc_bst.bst_state & BST_CRITICAL) {
     252           0 :                 strlcpy(sc->sc_sens[4].desc, "battery critical",
     253             :                     sizeof(sc->sc_sens[4].desc));
     254           0 :                 sc->sc_sens[4].status = SENSOR_S_CRIT;
     255           0 :         } else
     256           0 :                 strlcpy(sc->sc_sens[4].desc, "battery idle",
     257             :                     sizeof(sc->sc_sens[4].desc));
     258           0 :         sc->sc_sens[4].value = sc->sc_bst.bst_state;
     259             : 
     260           0 :         if (sc->sc_bst.bst_rate == BST_UNKNOWN) {
     261           0 :                 sc->sc_sens[5].value = 0;
     262           0 :                 sc->sc_sens[5].status = SENSOR_S_UNKNOWN;
     263           0 :                 sc->sc_sens[5].flags = SENSOR_FUNKNOWN;
     264           0 :         } else {
     265           0 :                 sc->sc_sens[5].value = sc->sc_bst.bst_rate * 1000;
     266           0 :                 sc->sc_sens[5].status = SENSOR_S_UNSPEC;
     267           0 :                 sc->sc_sens[5].flags = 0;
     268             :         }
     269             : 
     270           0 :         if (sc->sc_bst.bst_capacity == BST_UNKNOWN) {
     271           0 :                 sc->sc_sens[6].value = 0;
     272           0 :                 sc->sc_sens[6].status = SENSOR_S_UNKNOWN;
     273           0 :                 sc->sc_sens[6].flags = SENSOR_FUNKNOWN;
     274           0 :         } else {
     275           0 :                 sc->sc_sens[6].value = sc->sc_bst.bst_capacity * 1000;
     276           0 :                 sc->sc_sens[6].flags = 0;
     277             : 
     278           0 :                 if (sc->sc_bst.bst_capacity < sc->sc_bix.bix_low)
     279             :                         /* XXX we should shutdown the system */
     280           0 :                         sc->sc_sens[6].status = SENSOR_S_CRIT;
     281           0 :                 else if (sc->sc_bst.bst_capacity < sc->sc_bix.bix_warning)
     282           0 :                         sc->sc_sens[6].status = SENSOR_S_WARN;
     283             :                 else
     284           0 :                         sc->sc_sens[6].status = SENSOR_S_OK;
     285             :         }
     286             : 
     287           0 :         if (sc->sc_bst.bst_voltage == BST_UNKNOWN) {
     288           0 :                 sc->sc_sens[7].value = 0;
     289           0 :                 sc->sc_sens[7].status = SENSOR_S_UNKNOWN;
     290           0 :                 sc->sc_sens[7].flags = SENSOR_FUNKNOWN;
     291           0 :         } else {
     292           0 :                 sc->sc_sens[7].value = sc->sc_bst.bst_voltage * 1000;
     293           0 :                 sc->sc_sens[7].status = SENSOR_S_UNSPEC;
     294           0 :                 sc->sc_sens[7].flags = 0;
     295             :         }
     296             : 
     297           0 :         if (sc->sc_bix.bix_capacity == BIX_UNKNOWN) {
     298           0 :                 sc->sc_sens[8].value = 0;
     299           0 :                 sc->sc_sens[8].status = SENSOR_S_UNKNOWN;
     300           0 :                 sc->sc_sens[8].flags = SENSOR_FUNKNOWN;
     301           0 :         } else {
     302           0 :                 sc->sc_sens[8].value = sc->sc_bix.bix_capacity * 1000;
     303           0 :                 sc->sc_sens[8].status = SENSOR_S_UNSPEC;
     304           0 :                 sc->sc_sens[8].flags = 0;
     305             :         }
     306             : 
     307           0 :         if (!sc->sc_use_bif) {
     308           0 :                 if (sc->sc_bix.bix_capacity == BIX_UNKNOWN) {
     309           0 :                         sc->sc_sens[9].value = 0;
     310           0 :                         sc->sc_sens[9].status = SENSOR_S_UNKNOWN;
     311           0 :                         sc->sc_sens[9].flags = SENSOR_FUNKNOWN;
     312           0 :                 } else {
     313           0 :                         sc->sc_sens[9].value = sc->sc_bix.bix_cycle_count;
     314           0 :                         sc->sc_sens[9].status = SENSOR_S_UNSPEC;
     315           0 :                         sc->sc_sens[9].flags = 0;
     316             :                 }
     317             :         }
     318             : 
     319           0 :         acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE);
     320           0 : }
     321             : 
     322             : int
     323           0 : acpibat_getbix(struct acpibat_softc *sc)
     324             : {
     325           0 :         struct aml_value        res;
     326             :         int                     rv = EINVAL;
     327             :         int                     n = 0;
     328             : 
     329           0 :         if (!sc->sc_bat_present) {
     330           0 :                 memset(&sc->sc_bix, 0, sizeof(sc->sc_bix));
     331           0 :                 return (0);
     332             :         }
     333             : 
     334           0 :         sc->sc_use_bif = 1;
     335             : 
     336           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BIX", 0, NULL,
     337           0 :             &res) == 0) {
     338           0 :                 if (res.length >= 20)
     339           0 :                         sc->sc_use_bif = 0;
     340             :                 else
     341             :                         dnprintf(10, "%s: invalid _BIX (%d < 20)\n",
     342             :                             DEVNAME(sc), res.length);
     343             :         }
     344             : 
     345           0 :         if (sc->sc_use_bif) {
     346           0 :                 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BIF", 0, NULL,
     347             :                     &res)) {
     348             :                         dnprintf(10, "%s: no _BIX or _BIF\n", DEVNAME(sc));
     349             :                         goto out;
     350             :                 }
     351             : 
     352           0 :                 if (res.length != 13) {
     353             :                         dnprintf(10, "%s: invalid _BIF (%d != 13)\n",
     354             :                             DEVNAME(sc), res.length);
     355             :                         goto out;
     356             :                 }
     357             :         }
     358             : 
     359           0 :         if (!sc->sc_use_bif)
     360           0 :                 sc->sc_bix.bix_revision = aml_val2int(res.v_package[n++]);
     361             : 
     362           0 :         sc->sc_bix.bix_power_unit = aml_val2int(res.v_package[n++]);
     363           0 :         sc->sc_bix.bix_capacity = aml_val2int(res.v_package[n++]);
     364           0 :         sc->sc_bix.bix_last_capacity = aml_val2int(res.v_package[n++]);
     365           0 :         sc->sc_bix.bix_technology = aml_val2int(res.v_package[n++]);
     366           0 :         sc->sc_bix.bix_voltage = aml_val2int(res.v_package[n++]);
     367           0 :         sc->sc_bix.bix_warning = aml_val2int(res.v_package[n++]);
     368           0 :         sc->sc_bix.bix_low = aml_val2int(res.v_package[n++]);
     369             : 
     370           0 :         if (!sc->sc_use_bif) {
     371           0 :                 sc->sc_bix.bix_cycle_count = aml_val2int(res.v_package[n++]);
     372           0 :                 sc->sc_bix.bix_accuracy = aml_val2int(res.v_package[n++]);
     373           0 :                 sc->sc_bix.bix_max_sample = aml_val2int(res.v_package[n++]);
     374           0 :                 sc->sc_bix.bix_min_sample = aml_val2int(res.v_package[n++]);
     375           0 :                 sc->sc_bix.bix_max_avg = aml_val2int(res.v_package[n++]);
     376           0 :                 sc->sc_bix.bix_min_avg = aml_val2int(res.v_package[n++]);
     377           0 :         }
     378             : 
     379           0 :         sc->sc_bix.bix_cap_granu1 = aml_val2int(res.v_package[n++]);
     380           0 :         sc->sc_bix.bix_cap_granu2 = aml_val2int(res.v_package[n++]);
     381             : 
     382           0 :         strlcpy(sc->sc_bix.bix_model, aml_val_to_string(res.v_package[n++]),
     383             :                 sizeof(sc->sc_bix.bix_model));
     384           0 :         strlcpy(sc->sc_bix.bix_serial, aml_val_to_string(res.v_package[n++]),
     385             :                 sizeof(sc->sc_bix.bix_serial));
     386           0 :         strlcpy(sc->sc_bix.bix_type, aml_val_to_string(res.v_package[n++]),
     387             :                 sizeof(sc->sc_bix.bix_type));
     388           0 :         strlcpy(sc->sc_bix.bix_oem, aml_val_to_string(res.v_package[n++]),
     389             :                 sizeof(sc->sc_bix.bix_oem));
     390             : 
     391           0 :         if (!sc->sc_use_bif)
     392             :                 dnprintf(60, "revision: %u ", sc->sc_bix.bix_revision);
     393             : 
     394             :         dnprintf(60, "power_unit: %u capacity: %u last_cap: %u "
     395             :             "tech: %u volt: %u warn: %u low: %u ",
     396             :             sc->sc_bix.bix_power_unit,
     397             :             sc->sc_bix.bix_capacity,
     398             :             sc->sc_bix.bix_last_capacity,
     399             :             sc->sc_bix.bix_technology,
     400             :             sc->sc_bix.bix_voltage,
     401             :             sc->sc_bix.bix_warning,
     402             :             sc->sc_bix.bix_low);
     403             : 
     404             :         if (!sc->sc_use_bif)
     405             :                 dnprintf(60, "cycles: %u accuracy: %u max_sample: %u "
     406             :                     "min_sample: %u max_avg: %u min_avg: %u ",
     407             :                     sc->sc_bix.bix_cycle_count,
     408             :                     sc->sc_bix.bix_accuracy,
     409             :                     sc->sc_bix.bix_max_sample,
     410             :                     sc->sc_bix.bix_min_sample,
     411             :                     sc->sc_bix.bix_max_avg,
     412             :                     sc->sc_bix.bix_min_avg);
     413             : 
     414             :         dnprintf(60, "gran1: %u gran2: %d model: %s serial: %s type: %s "
     415             :             "oem: %s\n",
     416             :             sc->sc_bix.bix_cap_granu1,
     417             :             sc->sc_bix.bix_cap_granu2,
     418             :             sc->sc_bix.bix_model,
     419             :             sc->sc_bix.bix_serial,
     420             :             sc->sc_bix.bix_type,
     421             :             sc->sc_bix.bix_oem);
     422             : 
     423           0 :         rv = 0;
     424             : out:
     425           0 :         aml_freevalue(&res);
     426           0 :         return (rv);
     427           0 : }
     428             : 
     429             : int
     430           0 : acpibat_getbst(struct acpibat_softc *sc)
     431             : {
     432           0 :         struct aml_value        res;
     433             :         int                     rv = EINVAL;
     434             : 
     435           0 :         if (!sc->sc_bat_present) {
     436           0 :                 memset(&sc->sc_bst, 0, sizeof(sc->sc_bst));
     437           0 :                 return (0);
     438             :         }
     439             : 
     440           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BST", 0, NULL, &res)) {
     441             :                 dnprintf(10, "%s: no _BST\n", DEVNAME(sc));
     442             :                 goto out;
     443             :         }
     444             : 
     445           0 :         if (res.length != 4) {
     446             :                 dnprintf(10, "%s: invalid _BST, battery status not saved\n",
     447             :                     DEVNAME(sc));
     448             :                 goto out;
     449             :         }
     450             : 
     451           0 :         sc->sc_bst.bst_state = aml_val2int(res.v_package[0]);
     452           0 :         sc->sc_bst.bst_rate = aml_val2int(res.v_package[1]);
     453           0 :         sc->sc_bst.bst_capacity = aml_val2int(res.v_package[2]);
     454           0 :         sc->sc_bst.bst_voltage = aml_val2int(res.v_package[3]);
     455             : 
     456             :         dnprintf(60, "state: %u rate: %u cap: %u volt: %u ",
     457             :             sc->sc_bst.bst_state,
     458             :             sc->sc_bst.bst_rate,
     459             :             sc->sc_bst.bst_capacity,
     460             :             sc->sc_bst.bst_voltage);
     461             : 
     462           0 :         rv = 0;
     463             : out:
     464           0 :         aml_freevalue(&res);
     465           0 :         return (rv);
     466           0 : }
     467             : 
     468             : /*
     469             :  * XXX it has been observed that some systems do not propagate battery
     470             :  * insertion events up to the driver.  What seems to happen is that DSDT
     471             :  * does receive an interrupt however the originator bit is not set.
     472             :  * This seems to happen when one inserts a 100% full battery.  Removal
     473             :  * of the power cord or insertion of a not 100% full battery breaks this
     474             :  * behavior and all events will then be sent upwards.  Currently there
     475             :  * is no known work-around for it.
     476             :  */
     477             : 
     478             : int
     479           0 : acpibat_notify(struct aml_node *node, int notify_type, void *arg)
     480             : {
     481           0 :         struct acpibat_softc    *sc = arg;
     482           0 :         int64_t                 sta;
     483             : 
     484             :         dnprintf(10, "acpibat_notify: %.2x %s\n", notify_type,
     485             :             sc->sc_devnode->name);
     486             : 
     487             :         /* Check if installed state of battery has changed */
     488           0 :         if (aml_evalinteger(sc->sc_acpi, node, "_STA", 0, NULL, &sta) == 0) {
     489           0 :                 if (sta & STA_BATTERY)
     490           0 :                         sc->sc_bat_present = 1;
     491             :                 else
     492           0 :                         sc->sc_bat_present = 0;
     493             :         }
     494             : 
     495           0 :         switch (notify_type) {
     496             :         case 0x00:      /* Poll sensors */
     497             :         case 0x80:      /* _BST changed */
     498           0 :                 acpibat_getbst(sc);
     499           0 :                 break;
     500             :         case 0x81:      /* _BIF/_BIX changed */
     501           0 :                 acpibat_getbix(sc);
     502           0 :                 break;
     503             :         default:
     504             :                 break;
     505             :         }
     506             : 
     507           0 :         acpibat_refresh(sc);
     508             : 
     509           0 :         return (0);
     510           0 : }

Generated by: LCOV version 1.13