/* XXX There should be a cleaner way to do this locking. */ static void acpi_cmbat_get_bif_task(void *arg) { ACPI_SERIAL_BEGIN(cmbat); acpi_cmbat_get_bif(arg); ACPI_SERIAL_END(cmbat); }
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; if ((dev = devclass_get_device(acpi_cmbat_devclass, ioctl_arg->unit)) == NULL) { return (ENXIO); } if ((sc = device_get_softc(dev)) == NULL) { return (ENXIO); } /* * No security check required: information retrieval only. If * new functions are added here, a check might be required. */ switch (cmd) { case ACPIIO_CMBAT_GET_BIF: acpi_cmbat_get_bif(dev); bifp = &ioctl_arg->bif; bifp->unit = sc->bif.unit; 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; } return (0); }
static void acpi_cmbat_init_battery(void *arg) { struct acpi_cmbat_softc *sc; int retry, valid; device_t dev; dev = (device_t)arg; sc = device_get_softc(dev); ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "battery initialization start\n"); /* * Try repeatedly to get valid data from the battery. Since the * embedded controller isn't always ready just after boot, we may have * to wait a while. */ for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { /* batteries on DOCK can be ejected w/ DOCK during retrying */ if (!device_is_attached(dev)) return; if (!acpi_BatteryIsPresent(dev)) continue; /* * Only query the battery if this is the first try or the specific * type of info is still invalid. */ ACPI_SERIAL_BEGIN(cmbat); if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { timespecclear(&sc->bst_lastupdated); acpi_cmbat_get_bst(dev); } if (retry == 0 || !acpi_battery_bif_valid(&sc->bif)) acpi_cmbat_get_bif(dev); valid = acpi_battery_bst_valid(&sc->bst) && acpi_battery_bif_valid(&sc->bif); ACPI_SERIAL_END(cmbat); if (valid) break; } if (retry == ACPI_CMBAT_RETRY_MAX) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "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); } }
static void acpi_cmbat_init_battery(void *arg) { int retry; device_t dev = (device_t)arg; struct acpi_cmbat_softc *sc = device_get_softc(dev); #define ACPI_CMBAT_RETRY_MAX 6 if (sc->initializing) { return; } sc->initializing = 1; ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "battery initialization start\n"); for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10, 0)) { sc->present = acpi_BatteryIsPresent(dev); if (!sc->present) { continue; } timespecclear(&sc->bst_lastupdated); timespecclear(&sc->bif_lastupdated); acpi_cmbat_get_bst(dev); if (!acpi_cmbat_is_bst_valid(&sc->bst)) { continue; } acpi_cmbat_get_bif(dev); if (!acpi_cmbat_is_bif_valid(&sc->bif)) { continue; } break; } if (retry == ACPI_CMBAT_RETRY_MAX) ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "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); sc->initializing = 0; }