1 /*- 2 * Copyright (c) 2000 Munehiro Matsuda 3 * Copyright (c) 2000 Takanori Watanabe 4 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include "opt_acpi.h" 32 #include <sys/param.h> 33 #include <sys/kernel.h> 34 #include <sys/module.h> 35 #include <sys/bus.h> 36 #include <sys/ioccom.h> 37 38 #include <machine/bus.h> 39 #include <sys/rman.h> 40 #include <sys/malloc.h> 41 42 #include "acpi.h" 43 #include <dev/acpica/acpivar.h> 44 #include <dev/acpica/acpiio.h> 45 46 MALLOC_DEFINE(M_ACPICMBAT, "acpicmbat", "ACPI control method battery data"); 47 48 /* Number of times to retry initialization before giving up. */ 49 #define ACPI_CMBAT_RETRY_MAX 6 50 51 /* Check the battery once a minute. */ 52 #define CMBAT_POLLRATE (60 * hz) 53 54 /* Hooks for the ACPI CA debugging infrastructure */ 55 #define _COMPONENT ACPI_BATTERY 56 ACPI_MODULE_NAME("BATTERY") 57 58 #define ACPI_BATTERY_BST_CHANGE 0x80 59 #define ACPI_BATTERY_BIF_CHANGE 0x81 60 61 struct acpi_cmbat_softc { 62 device_t dev; 63 64 struct acpi_bif bif; 65 struct acpi_bst bst; 66 struct timespec bif_lastupdated; 67 struct timespec bst_lastupdated; 68 69 int flags; 70 int present; 71 int cap; 72 int min; 73 int full_charge_time; 74 int initializing; 75 int phys_unit; 76 }; 77 78 static struct timespec acpi_cmbat_info_lastupdated; 79 ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); 80 81 /* XXX: devclass_get_maxunit() don't give us the current allocated units. */ 82 static int acpi_cmbat_units = 0; 83 84 static int acpi_cmbat_info_expired(struct timespec *); 85 static void acpi_cmbat_info_updated(struct timespec *); 86 static void acpi_cmbat_get_bst(void *); 87 static void acpi_cmbat_get_bif(void *); 88 static void acpi_cmbat_notify_handler(ACPI_HANDLE, UINT32, void *); 89 static int acpi_cmbat_probe(device_t); 90 static int acpi_cmbat_attach(device_t); 91 static int acpi_cmbat_detach(device_t); 92 static int acpi_cmbat_resume(device_t); 93 static int acpi_cmbat_ioctl(u_long, caddr_t, void *); 94 static int acpi_cmbat_is_bst_valid(struct acpi_bst*); 95 static int acpi_cmbat_is_bif_valid(struct acpi_bif*); 96 static int acpi_cmbat_get_total_battinfo(struct acpi_battinfo *); 97 static void acpi_cmbat_init_battery(void *); 98 99 static device_method_t acpi_cmbat_methods[] = { 100 /* Device interface */ 101 DEVMETHOD(device_probe, acpi_cmbat_probe), 102 DEVMETHOD(device_attach, acpi_cmbat_attach), 103 DEVMETHOD(device_detach, acpi_cmbat_detach), 104 DEVMETHOD(device_resume, acpi_cmbat_resume), 105 106 {0, 0} 107 }; 108 109 static driver_t acpi_cmbat_driver = { 110 "acpi_cmbat", 111 acpi_cmbat_methods, 112 sizeof(struct acpi_cmbat_softc), 113 }; 114 115 static devclass_t acpi_cmbat_devclass; 116 DRIVER_MODULE(acpi_cmbat, acpi, acpi_cmbat_driver, acpi_cmbat_devclass, 0, 0); 117 MODULE_DEPEND(acpi_cmbat, acpi, 1, 1, 1); 118 119 static int 120 acpi_cmbat_info_expired(struct timespec *lastupdated) 121 { 122 struct timespec curtime; 123 124 ACPI_SERIAL_ASSERT(cmbat); 125 126 if (lastupdated == NULL) 127 return (TRUE); 128 if (!timespecisset(lastupdated)) 129 return (TRUE); 130 131 getnanotime(&curtime); 132 timespecsub(&curtime, lastupdated); 133 return (curtime.tv_sec < 0 || 134 curtime.tv_sec > acpi_battery_get_info_expire()); 135 } 136 137 static void 138 acpi_cmbat_info_updated(struct timespec *lastupdated) 139 { 140 141 ACPI_SERIAL_ASSERT(cmbat); 142 143 if (lastupdated != NULL) 144 getnanotime(lastupdated); 145 } 146 147 static void 148 acpi_cmbat_get_bst(void *context) 149 { 150 device_t dev; 151 struct acpi_cmbat_softc *sc; 152 ACPI_STATUS as; 153 ACPI_OBJECT *res; 154 ACPI_HANDLE h; 155 ACPI_BUFFER bst_buffer; 156 157 ACPI_SERIAL_ASSERT(cmbat); 158 159 dev = context; 160 sc = device_get_softc(dev); 161 h = acpi_get_handle(dev); 162 bst_buffer.Pointer = NULL; 163 bst_buffer.Length = ACPI_ALLOCATE_BUFFER; 164 165 if (!acpi_cmbat_info_expired(&sc->bst_lastupdated)) 166 goto end; 167 168 as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer); 169 if (ACPI_FAILURE(as)) { 170 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 171 "error fetching current battery status -- %s\n", 172 AcpiFormatException(as)); 173 goto end; 174 } 175 176 res = (ACPI_OBJECT *)bst_buffer.Pointer; 177 if (!ACPI_PKG_VALID(res, 4)) { 178 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 179 "battery status corrupted\n"); 180 goto end; 181 } 182 183 if (acpi_PkgInt32(res, 0, &sc->bst.state) != 0) 184 goto end; 185 if (acpi_PkgInt32(res, 1, &sc->bst.rate) != 0) 186 goto end; 187 if (acpi_PkgInt32(res, 2, &sc->bst.cap) != 0) 188 goto end; 189 if (acpi_PkgInt32(res, 3, &sc->bst.volt) != 0) 190 goto end; 191 acpi_cmbat_info_updated(&sc->bst_lastupdated); 192 193 /* XXX If all batteries are critical, perhaps we should suspend. */ 194 if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) { 195 if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) { 196 sc->flags |= ACPI_BATT_STAT_CRITICAL; 197 device_printf(dev, "critically low charge!\n"); 198 } 199 } else 200 sc->flags &= ~ACPI_BATT_STAT_CRITICAL; 201 202 end: 203 if (bst_buffer.Pointer != NULL) 204 AcpiOsFree(bst_buffer.Pointer); 205 } 206 207 static void 208 acpi_cmbat_get_bif(void *context) 209 { 210 device_t dev; 211 struct acpi_cmbat_softc *sc; 212 ACPI_STATUS as; 213 ACPI_OBJECT *res; 214 ACPI_HANDLE h; 215 ACPI_BUFFER bif_buffer; 216 217 ACPI_SERIAL_ASSERT(cmbat); 218 219 dev = context; 220 sc = device_get_softc(dev); 221 h = acpi_get_handle(dev); 222 bif_buffer.Pointer = NULL; 223 bif_buffer.Length = ACPI_ALLOCATE_BUFFER; 224 225 if (!acpi_cmbat_info_expired(&sc->bif_lastupdated)) 226 goto end; 227 228 as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer); 229 if (ACPI_FAILURE(as)) { 230 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 231 "error fetching current battery info -- %s\n", 232 AcpiFormatException(as)); 233 goto end; 234 } 235 236 res = (ACPI_OBJECT *)bif_buffer.Pointer; 237 if (!ACPI_PKG_VALID(res, 13)) { 238 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 239 "battery info corrupted\n"); 240 goto end; 241 } 242 243 if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0) 244 goto end; 245 if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0) 246 goto end; 247 if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0) 248 goto end; 249 if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0) 250 goto end; 251 if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0) 252 goto end; 253 if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0) 254 goto end; 255 if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0) 256 goto end; 257 if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0) 258 goto end; 259 if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0) 260 goto end; 261 if (acpi_PkgStr(res, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0) 262 goto end; 263 if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0) 264 goto end; 265 if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0) 266 goto end; 267 if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) 268 goto end; 269 acpi_cmbat_info_updated(&sc->bif_lastupdated); 270 271 end: 272 if (bif_buffer.Pointer != NULL) 273 AcpiOsFree(bif_buffer.Pointer); 274 } 275 276 static void 277 acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 278 { 279 device_t dev; 280 struct acpi_cmbat_softc *sc; 281 282 dev = (device_t)context; 283 sc = device_get_softc(dev); 284 285 acpi_UserNotify("CMBAT", h, notify); 286 287 /* 288 * Clear the appropriate last updated time. The next call to retrieve 289 * the battery status will get the new value for us. We don't need to 290 * acquire a lock since we are only clearing the time stamp and since 291 * calling _BST/_BIF can trigger a notify, we could deadlock also. 292 */ 293 switch (notify) { 294 case ACPI_NOTIFY_DEVICE_CHECK: 295 case ACPI_BATTERY_BST_CHANGE: 296 timespecclear(&sc->bst_lastupdated); 297 break; 298 case ACPI_NOTIFY_BUS_CHECK: 299 case ACPI_BATTERY_BIF_CHANGE: 300 timespecclear(&sc->bif_lastupdated); 301 break; 302 default: 303 break; 304 } 305 } 306 307 static int 308 acpi_cmbat_probe(device_t dev) 309 { 310 static char *cmbat_ids[] = { "PNP0C0A", NULL }; 311 312 if (acpi_disabled("cmbat") || 313 ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids) == NULL) 314 return (ENXIO); 315 316 device_set_desc(dev, "Control Method Battery"); 317 return (0); 318 } 319 320 static int 321 acpi_cmbat_attach(device_t dev) 322 { 323 int error; 324 ACPI_HANDLE handle; 325 struct acpi_cmbat_softc *sc; 326 327 sc = device_get_softc(dev); 328 handle = acpi_get_handle(dev); 329 sc->dev = dev; 330 331 /* 332 * Install a system notify handler in addition to the device notify. 333 * Toshiba notebook uses this alternate notify for its battery. 334 */ 335 AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, 336 acpi_cmbat_notify_handler, dev); 337 338 ACPI_SERIAL_BEGIN(cmbat); 339 timespecclear(&sc->bif_lastupdated); 340 timespecclear(&sc->bst_lastupdated); 341 342 if (acpi_cmbat_units == 0) { 343 error = acpi_register_ioctl(ACPIIO_CMBAT_GET_BIF, 344 acpi_cmbat_ioctl, NULL); 345 if (error != 0) { 346 device_printf(dev, "register bif ioctl failed\n"); 347 return (error); 348 } 349 error = acpi_register_ioctl(ACPIIO_CMBAT_GET_BST, 350 acpi_cmbat_ioctl, NULL); 351 if (error != 0) { 352 device_printf(dev, "register bst ioctl failed\n"); 353 return (error); 354 } 355 } 356 357 sc->phys_unit = acpi_cmbat_units; 358 error = acpi_battery_register(ACPI_BATT_TYPE_CMBAT, sc->phys_unit); 359 if (error != 0) { 360 device_printf(dev, "registering battery %d failed\n", sc->phys_unit); 361 return (error); 362 } 363 acpi_cmbat_units++; 364 timespecclear(&acpi_cmbat_info_lastupdated); 365 ACPI_SERIAL_END(cmbat); 366 367 AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); 368 369 return (0); 370 } 371 372 static int 373 acpi_cmbat_detach(device_t dev) 374 { 375 struct acpi_cmbat_softc *sc; 376 377 sc = device_get_softc(dev); 378 ACPI_SERIAL_BEGIN(cmbat); 379 acpi_battery_remove(ACPI_BATT_TYPE_CMBAT, sc->phys_unit); 380 acpi_cmbat_units--; 381 ACPI_SERIAL_END(cmbat); 382 return (0); 383 } 384 385 static int 386 acpi_cmbat_resume(device_t dev) 387 { 388 AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); 389 return (0); 390 } 391 392 static int 393 acpi_cmbat_ioctl(u_long cmd, caddr_t addr, void *arg) 394 { 395 device_t dev; 396 union acpi_battery_ioctl_arg *ioctl_arg; 397 struct acpi_cmbat_softc *sc; 398 struct acpi_bif *bifp; 399 struct acpi_bst *bstp; 400 401 ioctl_arg = (union acpi_battery_ioctl_arg *)addr; 402 dev = devclass_get_device(acpi_cmbat_devclass, ioctl_arg->unit); 403 if (dev == NULL) 404 return (ENXIO); 405 sc = device_get_softc(dev); 406 407 /* 408 * No security check required: information retrieval only. If 409 * new functions are added here, a check might be required. 410 */ 411 ACPI_SERIAL_BEGIN(cmbat); 412 switch (cmd) { 413 case ACPIIO_CMBAT_GET_BIF: 414 acpi_cmbat_get_bif(dev); 415 bifp = &ioctl_arg->bif; 416 bifp->units = sc->bif.units; 417 bifp->dcap = sc->bif.dcap; 418 bifp->lfcap = sc->bif.lfcap; 419 bifp->btech = sc->bif.btech; 420 bifp->dvol = sc->bif.dvol; 421 bifp->wcap = sc->bif.wcap; 422 bifp->lcap = sc->bif.lcap; 423 bifp->gra1 = sc->bif.gra1; 424 bifp->gra2 = sc->bif.gra2; 425 strncpy(bifp->model, sc->bif.model, sizeof(sc->bif.model)); 426 strncpy(bifp->serial, sc->bif.serial, sizeof(sc->bif.serial)); 427 strncpy(bifp->type, sc->bif.type, sizeof(sc->bif.type)); 428 strncpy(bifp->oeminfo, sc->bif.oeminfo, sizeof(sc->bif.oeminfo)); 429 break; 430 case ACPIIO_CMBAT_GET_BST: 431 bstp = &ioctl_arg->bst; 432 if (acpi_BatteryIsPresent(dev)) { 433 acpi_cmbat_get_bst(dev); 434 bstp->state = sc->bst.state; 435 bstp->rate = sc->bst.rate; 436 bstp->cap = sc->bst.cap; 437 bstp->volt = sc->bst.volt; 438 } else { 439 bstp->state = ACPI_BATT_STAT_NOT_PRESENT; 440 } 441 break; 442 default: 443 break; 444 } 445 ACPI_SERIAL_END(cmbat); 446 447 return (0); 448 } 449 450 static int 451 acpi_cmbat_is_bst_valid(struct acpi_bst *bst) 452 { 453 if (bst->state >= ACPI_BATT_STAT_MAX || bst->cap == 0xffffffff || 454 bst->volt == 0xffffffff) 455 return (FALSE); 456 else 457 return (TRUE); 458 } 459 460 static int 461 acpi_cmbat_is_bif_valid(struct acpi_bif *bif) 462 { 463 if (bif->lfcap == 0) 464 return (FALSE); 465 else 466 return (TRUE); 467 } 468 469 static int 470 acpi_cmbat_get_total_battinfo(struct acpi_battinfo *battinfo) 471 { 472 int i; 473 int error; 474 int batt_stat; 475 int valid_rate, valid_units; 476 int cap, min; 477 int total_cap, total_min, total_full; 478 struct acpi_cmbat_softc *sc; 479 480 ACPI_SERIAL_ASSERT(cmbat); 481 482 cap = min = -1; 483 batt_stat = ACPI_BATT_STAT_NOT_PRESENT; 484 error = 0; 485 486 /* Get battery status, valid rate and valid units */ 487 batt_stat = valid_rate = valid_units = 0; 488 for (i = 0; i < acpi_cmbat_units; i++) { 489 sc = devclass_get_softc(acpi_cmbat_devclass, i); 490 if (sc == NULL) 491 continue; 492 sc->present = acpi_BatteryIsPresent(sc->dev); 493 if (!sc->present) 494 continue; 495 acpi_cmbat_get_bst(sc->dev); 496 497 /* If battery not installed, we get strange values */ 498 if (!acpi_cmbat_is_bst_valid(&sc->bst) || 499 !acpi_cmbat_is_bif_valid(&sc->bif)) { 500 sc->present = FALSE; 501 continue; 502 } 503 504 valid_units++; 505 sc->cap = 100 * sc->bst.cap / sc->bif.lfcap; 506 507 /* 508 * Some laptops report the "design-capacity" instead of the 509 * "real-capacity" when the battery is fully charged. 510 * That breaks the above arithmetic as it needs to be 100% maximum. 511 */ 512 if (sc->cap > 100) 513 sc->cap = 100; 514 515 batt_stat |= sc->bst.state; 516 517 /* 518 * XXX Hack to calculate total battery time. 519 * 520 * On systems with more than one battery, they may get used 521 * sequentially, thus bst.rate may only signify the one in use. 522 * For the remaining batteries, bst.rate will be zero, which 523 * makes it impossible to calculate the remaining time. Some 524 * other systems may need the sum of all the bst.rate values 525 * when discharging. Therefore, we sum the bst.rate for valid 526 * batteries (ones in the discharging state) and use the sum 527 * to calculate the total remaining time. 528 */ 529 if (sc->bst.rate > 0) { 530 if (sc->bst.state & ACPI_BATT_STAT_DISCHARG) 531 valid_rate += sc->bst.rate; 532 } 533 } 534 535 /* Calculate total battery capacity and time */ 536 total_cap = total_min = total_full = 0; 537 for (i = 0; i < acpi_cmbat_units; i++) { 538 sc = devclass_get_softc(acpi_cmbat_devclass, i); 539 if (!sc->present) 540 continue; 541 542 /* 543 * If any batteries are discharging, use the sum of the bst.rate 544 * values. Otherwise, use the full charge time to estimate 545 * remaining time. If neither are available, assume no charge. 546 */ 547 if (valid_rate > 0) 548 sc->min = 60 * sc->bst.cap / valid_rate; 549 else if (sc->full_charge_time > 0) 550 sc->min = (sc->full_charge_time * sc->cap) / 100; 551 else 552 sc->min = 0; 553 total_min += sc->min; 554 total_cap += sc->cap; 555 total_full += sc->full_charge_time; 556 } 557 558 /* Battery life */ 559 if (valid_units == 0) { 560 cap = -1; 561 batt_stat = ACPI_BATT_STAT_NOT_PRESENT; 562 } else 563 cap = total_cap / valid_units; 564 565 /* Battery time */ 566 if (valid_units == 0) 567 min = -1; 568 else if (valid_rate == 0 || (batt_stat & ACPI_BATT_STAT_CHARGING)) { 569 if (total_full == 0) 570 min = -1; 571 else 572 min = (total_full * cap) / 100; 573 } else 574 min = total_min; 575 acpi_cmbat_info_updated(&acpi_cmbat_info_lastupdated); 576 577 battinfo->cap = cap; 578 battinfo->min = min; 579 battinfo->state = batt_stat; 580 581 return (error); 582 } 583 584 static void 585 acpi_cmbat_init_battery(void *arg) 586 { 587 struct acpi_cmbat_softc *sc; 588 int retry; 589 device_t dev; 590 591 dev = (device_t)arg; 592 sc = device_get_softc(dev); 593 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 594 "battery initialization start\n"); 595 596 for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { 597 sc->present = acpi_BatteryIsPresent(dev); 598 if (!sc->present) 599 continue; 600 601 ACPI_SERIAL_BEGIN(cmbat); 602 timespecclear(&sc->bst_lastupdated); 603 timespecclear(&sc->bif_lastupdated); 604 acpi_cmbat_get_bst(dev); 605 acpi_cmbat_get_bif(dev); 606 ACPI_SERIAL_END(cmbat); 607 608 if (acpi_cmbat_is_bst_valid(&sc->bst) && 609 acpi_cmbat_is_bif_valid(&sc->bif)) 610 break; 611 } 612 613 if (retry == ACPI_CMBAT_RETRY_MAX) { 614 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 615 "battery initialization failed, giving up\n"); 616 } else { 617 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 618 "battery initialization done, tried %d times\n", retry + 1); 619 } 620 } 621 622 /* 623 * Public interfaces. 624 */ 625 int 626 acpi_cmbat_get_battinfo(int unit, struct acpi_battinfo *battinfo) 627 { 628 int error; 629 struct acpi_cmbat_softc *sc; 630 631 ACPI_SERIAL_BEGIN(cmbat); 632 error = acpi_cmbat_get_total_battinfo(battinfo); 633 if (unit == -1 || error) 634 goto out; 635 636 error = ENXIO; 637 if (unit >= acpi_cmbat_units) 638 goto out; 639 if ((sc = devclass_get_softc(acpi_cmbat_devclass, unit)) == NULL) 640 goto out; 641 642 if (!sc->present) { 643 battinfo->cap = -1; 644 battinfo->min = -1; 645 battinfo->state = ACPI_BATT_STAT_NOT_PRESENT; 646 } else { 647 battinfo->cap = sc->cap; 648 battinfo->min = sc->min; 649 battinfo->state = sc->bst.state; 650 } 651 error = 0; 652 653 out: 654 ACPI_SERIAL_END(cmbat); 655 return (error); 656 } 657