static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst) { struct acpi_smbat_softc *sc; int error; uint32_t factor; int16_t val; uint8_t addr; ACPI_SERIAL_BEGIN(smbat); addr = SMBATT_ADDRESS; error = ENXIO; sc = device_get_softc(dev); if (!acpi_smbat_info_expired(&sc->bst_lastupdated)) { error = 0; goto out; } if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val)) goto out; if (val & SMBATT_BM_CAPACITY_MODE) factor = 10; else factor = 1; /* get battery status */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_STATUS, &val)) goto out; sc->bst.state = 0; if (val & SMBATT_BS_DISCHARGING) sc->bst.state |= ACPI_BATT_STAT_DISCHARG; if (val & SMBATT_BS_REMAINING_CAPACITY_ALARM) sc->bst.state |= ACPI_BATT_STAT_CRITICAL; /* * If the rate is negative, it is discharging. Otherwise, * it is charging. */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_CURRENT, &val)) goto out; if (val > 0) { sc->bst.rate = val * factor; sc->bst.state &= ~SMBATT_BS_DISCHARGING; sc->bst.state |= ACPI_BATT_STAT_CHARGING; } else if (val < 0) sc->bst.rate = (-val) * factor; else sc->bst.rate = 0; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_REMAINING_CAPACITY, &val)) goto out; sc->bst.cap = val * factor; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_VOLTAGE, &val)) goto out; sc->bst.volt = val; acpi_smbat_info_updated(&sc->bst_lastupdated); error = 0; out: if (error == 0) memcpy(bst, &sc->bst, sizeof(sc->bst)); ACPI_SERIAL_END(smbat); return (error); }
static int acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif) { struct acpi_smbat_softc *sc; int error; uint32_t factor; uint16_t val; uint8_t addr; ACPI_SERIAL_BEGIN(smbat); addr = SMBATT_ADDRESS; error = ENXIO; sc = device_get_softc(dev); if (!acpi_smbat_info_expired(&sc->bif_lastupdated)) { error = 0; goto out; } 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; } else { factor = 1; sc->bif.units = ACPI_BIF_UNITS_MA; } if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_CAPACITY, &val)) goto out; sc->bif.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) */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_VOLTAGE, &val)) goto out; sc->bif.dvol = val; sc->bif.wcap = sc->bif.dcap / 10; sc->bif.lcap = sc->bif.dcap / 10; sc->bif.gra1 = factor; /* not supported */ sc->bif.gra2 = factor; /* not supported */ if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_NAME, sc->bif.model, sizeof(sc->bif.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); if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_CHEMISTRY, sc->bif.type, sizeof(sc->bif.type))) goto out; if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_MANUFACTURER_DATA, sc->bif.oeminfo, sizeof(sc->bif.oeminfo))) goto out; /* XXX check if device was replugged during read? */ acpi_smbat_info_updated(&sc->bif_lastupdated); error = 0; out: if (error == 0) memcpy(bif, &sc->bif, sizeof(sc->bif)); ACPI_SERIAL_END(smbat); return (error); }