1 /*- 2 * Copyright (c) 2005 Nate Lawson 3 * Copyright (c) 2000 Munehiro Matsuda 4 * Copyright (c) 2000 Takanori Watanabe 5 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "opt_acpi.h" 34 #include <sys/param.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/bus.h> 38 #include <sys/ioccom.h> 39 40 #include <machine/bus.h> 41 #include <sys/rman.h> 42 #include <sys/malloc.h> 43 44 #include <contrib/dev/acpica/include/acpi.h> 45 46 #include <dev/acpica/acpivar.h> 47 #include <dev/acpica/acpiio.h> 48 49 static MALLOC_DEFINE(M_ACPICMBAT, "acpicmbat", 50 "ACPI control method battery data"); 51 52 /* Number of times to retry initialization before giving up. */ 53 #define ACPI_CMBAT_RETRY_MAX 6 54 55 /* Check the battery once a minute. */ 56 #define CMBAT_POLLRATE (60 * hz) 57 58 /* Hooks for the ACPI CA debugging infrastructure */ 59 #define _COMPONENT ACPI_BATTERY 60 ACPI_MODULE_NAME("BATTERY") 61 62 #define ACPI_BATTERY_BST_CHANGE 0x80 63 #define ACPI_BATTERY_BIF_CHANGE 0x81 64 #define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE 65 66 struct acpi_cmbat_softc { 67 device_t dev; 68 int flags; 69 70 struct acpi_bix bix; 71 struct acpi_bst bst; 72 struct timespec bst_lastupdated; 73 }; 74 75 ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); 76 77 static int acpi_cmbat_probe(device_t dev); 78 static int acpi_cmbat_attach(device_t dev); 79 static int acpi_cmbat_detach(device_t dev); 80 static int acpi_cmbat_resume(device_t dev); 81 static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, 82 void *context); 83 static int acpi_cmbat_info_expired(struct timespec *lastupdated); 84 static void acpi_cmbat_info_updated(struct timespec *lastupdated); 85 static void acpi_cmbat_get_bst(void *arg); 86 static void acpi_cmbat_get_bix_task(void *arg); 87 static void acpi_cmbat_get_bix(void *arg); 88 static int acpi_cmbat_bst(device_t, struct acpi_bst *); 89 static int acpi_cmbat_bix(device_t, void *, size_t); 90 static void acpi_cmbat_init_battery(void *arg); 91 92 static device_method_t acpi_cmbat_methods[] = { 93 /* Device interface */ 94 DEVMETHOD(device_probe, acpi_cmbat_probe), 95 DEVMETHOD(device_attach, acpi_cmbat_attach), 96 DEVMETHOD(device_detach, acpi_cmbat_detach), 97 DEVMETHOD(device_resume, acpi_cmbat_resume), 98 99 /* ACPI battery interface */ 100 DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bix), 101 DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst), 102 103 DEVMETHOD_END 104 }; 105 106 static driver_t acpi_cmbat_driver = { 107 "battery", 108 acpi_cmbat_methods, 109 sizeof(struct acpi_cmbat_softc), 110 }; 111 112 static devclass_t acpi_cmbat_devclass; 113 DRIVER_MODULE(acpi_cmbat, acpi, acpi_cmbat_driver, acpi_cmbat_devclass, 0, 0); 114 MODULE_DEPEND(acpi_cmbat, acpi, 1, 1, 1); 115 116 static int 117 acpi_cmbat_probe(device_t dev) 118 { 119 static char *cmbat_ids[] = { "PNP0C0A", NULL }; 120 int rv; 121 122 if (acpi_disabled("cmbat")) 123 return (ENXIO); 124 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids, NULL); 125 if (rv <= 0) 126 device_set_desc(dev, "ACPI Control Method Battery"); 127 return (rv); 128 } 129 130 static int 131 acpi_cmbat_attach(device_t dev) 132 { 133 int error; 134 ACPI_HANDLE handle; 135 struct acpi_cmbat_softc *sc; 136 137 sc = device_get_softc(dev); 138 handle = acpi_get_handle(dev); 139 sc->dev = dev; 140 141 timespecclear(&sc->bst_lastupdated); 142 143 error = acpi_battery_register(dev); 144 if (error != 0) { 145 device_printf(dev, "registering battery failed\n"); 146 return (error); 147 } 148 149 /* 150 * Install a system notify handler in addition to the device notify. 151 * Toshiba notebook uses this alternate notify for its battery. 152 */ 153 AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, 154 acpi_cmbat_notify_handler, dev); 155 156 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); 157 158 return (0); 159 } 160 161 static int 162 acpi_cmbat_detach(device_t dev) 163 { 164 ACPI_HANDLE handle; 165 166 handle = acpi_get_handle(dev); 167 AcpiRemoveNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler); 168 acpi_battery_remove(dev); 169 170 /* 171 * Force any pending notification handler calls to complete by 172 * requesting cmbat serialisation while freeing and clearing the 173 * softc pointer: 174 */ 175 ACPI_SERIAL_BEGIN(cmbat); 176 device_set_softc(dev, NULL); 177 ACPI_SERIAL_END(cmbat); 178 179 return (0); 180 } 181 182 static int 183 acpi_cmbat_resume(device_t dev) 184 { 185 186 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); 187 return (0); 188 } 189 190 static void 191 acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 192 { 193 struct acpi_cmbat_softc *sc; 194 device_t dev; 195 196 dev = (device_t)context; 197 sc = device_get_softc(dev); 198 199 switch (notify) { 200 case ACPI_NOTIFY_DEVICE_CHECK: 201 case ACPI_BATTERY_BST_CHANGE: 202 /* 203 * Clear the last updated time. The next call to retrieve the 204 * battery status will get the new value for us. 205 */ 206 timespecclear(&sc->bst_lastupdated); 207 break; 208 case ACPI_NOTIFY_BUS_CHECK: 209 case ACPI_BATTERY_BIX_CHANGE: 210 /* 211 * Queue a callback to get the current battery info from thread 212 * context. It's not safe to block in a notify handler. 213 */ 214 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bix_task, dev); 215 break; 216 } 217 218 acpi_UserNotify("CMBAT", h, notify); 219 } 220 221 static int 222 acpi_cmbat_info_expired(struct timespec *lastupdated) 223 { 224 struct timespec curtime; 225 226 ACPI_SERIAL_ASSERT(cmbat); 227 228 if (lastupdated == NULL) 229 return (TRUE); 230 if (!timespecisset(lastupdated)) 231 return (TRUE); 232 233 getnanotime(&curtime); 234 timespecsub(&curtime, lastupdated, &curtime); 235 return (curtime.tv_sec < 0 || 236 curtime.tv_sec > acpi_battery_get_info_expire()); 237 } 238 239 static void 240 acpi_cmbat_info_updated(struct timespec *lastupdated) 241 { 242 243 ACPI_SERIAL_ASSERT(cmbat); 244 245 if (lastupdated != NULL) 246 getnanotime(lastupdated); 247 } 248 249 static void 250 acpi_cmbat_get_bst(void *arg) 251 { 252 struct acpi_cmbat_softc *sc; 253 ACPI_STATUS as; 254 ACPI_OBJECT *res; 255 ACPI_HANDLE h; 256 ACPI_BUFFER bst_buffer; 257 device_t dev; 258 259 ACPI_SERIAL_ASSERT(cmbat); 260 261 dev = arg; 262 sc = device_get_softc(dev); 263 h = acpi_get_handle(dev); 264 bst_buffer.Pointer = NULL; 265 bst_buffer.Length = ACPI_ALLOCATE_BUFFER; 266 267 if (!acpi_cmbat_info_expired(&sc->bst_lastupdated)) 268 goto end; 269 270 as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer); 271 if (ACPI_FAILURE(as)) { 272 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 273 "error fetching current battery status -- %s\n", 274 AcpiFormatException(as)); 275 goto end; 276 } 277 278 res = (ACPI_OBJECT *)bst_buffer.Pointer; 279 if (!ACPI_PKG_VALID(res, 4)) { 280 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 281 "battery status corrupted\n"); 282 goto end; 283 } 284 285 if (acpi_PkgInt32(res, 0, &sc->bst.state) != 0) 286 goto end; 287 if (acpi_PkgInt32(res, 1, &sc->bst.rate) != 0) 288 goto end; 289 if (acpi_PkgInt32(res, 2, &sc->bst.cap) != 0) 290 goto end; 291 if (acpi_PkgInt32(res, 3, &sc->bst.volt) != 0) 292 goto end; 293 acpi_cmbat_info_updated(&sc->bst_lastupdated); 294 295 /* Clear out undefined/extended bits that might be set by hardware. */ 296 sc->bst.state &= ACPI_BATT_STAT_BST_MASK; 297 if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID) 298 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 299 "battery reports simultaneous charging and discharging\n"); 300 301 /* XXX If all batteries are critical, perhaps we should suspend. */ 302 if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) { 303 if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) { 304 sc->flags |= ACPI_BATT_STAT_CRITICAL; 305 device_printf(dev, "critically low charge!\n"); 306 } 307 } else 308 sc->flags &= ~ACPI_BATT_STAT_CRITICAL; 309 310 end: 311 AcpiOsFree(bst_buffer.Pointer); 312 } 313 314 /* XXX There should be a cleaner way to do this locking. */ 315 static void 316 acpi_cmbat_get_bix_task(void *arg) 317 { 318 319 ACPI_SERIAL_BEGIN(cmbat); 320 acpi_cmbat_get_bix(arg); 321 ACPI_SERIAL_END(cmbat); 322 } 323 324 static void 325 acpi_cmbat_get_bix(void *arg) 326 { 327 struct acpi_cmbat_softc *sc; 328 ACPI_STATUS as; 329 ACPI_OBJECT *res; 330 ACPI_HANDLE h; 331 ACPI_BUFFER bix_buffer; 332 device_t dev; 333 int i, n; 334 const struct { 335 enum { _BIX, _BIF } type; 336 char *name; 337 } bobjs[] = { 338 { _BIX, "_BIX"}, 339 { _BIF, "_BIF"}, 340 }; 341 342 ACPI_SERIAL_ASSERT(cmbat); 343 344 dev = arg; 345 sc = device_get_softc(dev); 346 h = acpi_get_handle(dev); 347 bix_buffer.Pointer = NULL; 348 bix_buffer.Length = ACPI_ALLOCATE_BUFFER; 349 350 for (n = 0; n < sizeof(bobjs); n++) { 351 as = AcpiEvaluateObject(h, bobjs[n].name, NULL, &bix_buffer); 352 if (!ACPI_FAILURE(as)) { 353 res = (ACPI_OBJECT *)bix_buffer.Pointer; 354 break; 355 } 356 AcpiOsFree(bix_buffer.Pointer); 357 bix_buffer.Pointer = NULL; 358 bix_buffer.Length = ACPI_ALLOCATE_BUFFER; 359 } 360 /* Both _BIF and _BIX were not found. */ 361 if (n == sizeof(bobjs)) { 362 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 363 "error fetching current battery info -- %s\n", 364 AcpiFormatException(as)); 365 goto end; 366 } 367 368 /* 369 * ACPI _BIX and _BIF revision mismatch check: 370 * 371 * 1. _BIF has no revision field. The number of fields must be 13. 372 * 373 * 2. _BIX has a revision field. As of ACPI 6.3 it must be "0" or 374 * "1". The number of fields will be checked---20 and 21, 375 * respectively. 376 * 377 * If the revision number is grater than "1" and the number of 378 * fields is grater than 21, it will be treated as compatible with 379 * ACPI 6.0 _BIX. If not, it will be ignored. 380 */ 381 i = 0; 382 switch (bobjs[n].type) { 383 case _BIX: 384 if (acpi_PkgInt16(res, i++, &sc->bix.rev) != 0) { 385 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 386 "_BIX revision error\n"); 387 goto end; 388 } 389 #define ACPI_BIX_REV_MISMATCH_ERR(x, r) do { \ 390 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ 391 "_BIX revision mismatch (%u != %u)\n", x, r); \ 392 goto end; \ 393 } while (0) 394 395 if (ACPI_PKG_VALID_EQ(res, 21)) { /* ACPI 6.0 _BIX */ 396 /* 397 * Some models have rev.0 _BIX with 21 members. 398 * In that case, treat the first 20 members as rev.0 _BIX. 399 */ 400 if (sc->bix.rev != ACPI_BIX_REV_0 && 401 sc->bix.rev != ACPI_BIX_REV_1) 402 ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_1); 403 } else if (ACPI_PKG_VALID_EQ(res, 20)) {/* ACPI 4.0 _BIX */ 404 if (sc->bix.rev != ACPI_BIX_REV_0) 405 ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_0); 406 } else if (ACPI_PKG_VALID(res, 22)) { 407 /* _BIX with 22 or more members. */ 408 if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1 + 1)) { 409 /* 410 * Unknown revision number. 411 * Assume 21 members are compatible with 6.0 _BIX. 412 */ 413 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 414 "Unknown _BIX revision(%u). " 415 "Assuming compatible with revision %u.\n", 416 sc->bix.rev, ACPI_BIX_REV_1); 417 } else { 418 /* 419 * Known revision number. Ignore the extra members. 420 */ 421 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 422 "Extra objects found in _BIX were ignored.\n"); 423 } 424 } else { 425 /* Invalid _BIX. Ignore it. */ 426 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 427 "Invalid _BIX found (rev=%u, count=%u). Ignored.\n", 428 sc->bix.rev, res->Package.Count); 429 goto end; 430 } 431 break; 432 #undef ACPI_BIX_REV_MISMATCH_ERR 433 case _BIF: 434 if (ACPI_PKG_VALID_EQ(res, 13)) /* _BIF */ 435 sc->bix.rev = ACPI_BIX_REV_BIF; 436 else { 437 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 438 "Invalid _BIF found (count=%u). Ignored.\n", 439 res->Package.Count); 440 goto end; 441 } 442 break; 443 } 444 445 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 446 "rev = %04x\n", sc->bix.rev); 447 #define BIX_GETU32(NAME) do { \ 448 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ 449 #NAME " = %u\n", sc->bix.NAME); \ 450 if (acpi_PkgInt32(res, i++, &sc->bix.NAME) != 0) \ 451 goto end; \ 452 } while (0) 453 454 BIX_GETU32(units); 455 BIX_GETU32(dcap); 456 BIX_GETU32(lfcap); 457 BIX_GETU32(btech); 458 BIX_GETU32(dvol); 459 BIX_GETU32(wcap); 460 BIX_GETU32(lcap); 461 if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_0)) { 462 BIX_GETU32(cycles); 463 BIX_GETU32(accuracy); 464 BIX_GETU32(stmax); 465 BIX_GETU32(stmin); 466 BIX_GETU32(aimax); 467 BIX_GETU32(aimin); 468 } 469 BIX_GETU32(gra1); 470 BIX_GETU32(gra2); 471 if (acpi_PkgStr(res, i++, sc->bix.model, ACPI_CMBAT_MAXSTRLEN) != 0) 472 goto end; 473 if (acpi_PkgStr(res, i++, sc->bix.serial, ACPI_CMBAT_MAXSTRLEN) != 0) 474 goto end; 475 if (acpi_PkgStr(res, i++, sc->bix.type, ACPI_CMBAT_MAXSTRLEN) != 0) 476 goto end; 477 if (acpi_PkgStr(res, i++, sc->bix.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) 478 goto end; 479 if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1)) 480 BIX_GETU32(scap); 481 #undef BIX_GETU32 482 end: 483 AcpiOsFree(bix_buffer.Pointer); 484 } 485 486 static int 487 acpi_cmbat_bix(device_t dev, void *bix, size_t len) 488 { 489 struct acpi_cmbat_softc *sc; 490 491 if (len != sizeof(struct acpi_bix) && 492 len != sizeof(struct acpi_bif)) 493 return (-1); 494 495 sc = device_get_softc(dev); 496 497 /* 498 * Just copy the data. The only value that should change is the 499 * last-full capacity, so we only update when we get a notify that says 500 * the info has changed. Many systems apparently take a long time to 501 * process a _BI[FX] call so we avoid it if possible. 502 */ 503 ACPI_SERIAL_BEGIN(cmbat); 504 memcpy(bix, &sc->bix, len); 505 ACPI_SERIAL_END(cmbat); 506 507 return (0); 508 } 509 510 static int 511 acpi_cmbat_bst(device_t dev, struct acpi_bst *bst) 512 { 513 struct acpi_cmbat_softc *sc; 514 515 sc = device_get_softc(dev); 516 517 ACPI_SERIAL_BEGIN(cmbat); 518 if (acpi_BatteryIsPresent(dev)) { 519 acpi_cmbat_get_bst(dev); 520 memcpy(bst, &sc->bst, sizeof(*bst)); 521 } else 522 bst->state = ACPI_BATT_STAT_NOT_PRESENT; 523 ACPI_SERIAL_END(cmbat); 524 525 return (0); 526 } 527 528 static void 529 acpi_cmbat_init_battery(void *arg) 530 { 531 struct acpi_cmbat_softc *sc; 532 int retry, valid; 533 device_t dev; 534 535 dev = (device_t)arg; 536 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 537 "battery enitialization start\n"); 538 539 /* 540 * Try repeatedly to get valid data from the battery. Since the 541 * embedded controller isn't always ready just after boot, we may have 542 * to wait a while. 543 */ 544 for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { 545 /* 546 * Batteries on DOCK can be ejected w/ DOCK during retrying. 547 * 548 * If there is a valid softc pointer the device may be in 549 * attaching, attached or detaching state. If the state is 550 * different from attached retry getting the device state 551 * until it becomes stable. This solves a race if the ACPI 552 * notification handler is called during attach, because 553 * device_is_attached() doesn't return non-zero until after 554 * the attach code has been executed. 555 */ 556 ACPI_SERIAL_BEGIN(cmbat); 557 sc = device_get_softc(dev); 558 if (sc == NULL) { 559 ACPI_SERIAL_END(cmbat); 560 return; 561 } 562 563 if (!acpi_BatteryIsPresent(dev) || !device_is_attached(dev)) { 564 ACPI_SERIAL_END(cmbat); 565 continue; 566 } 567 568 /* 569 * Only query the battery if this is the first try or the specific 570 * type of info is still invalid. 571 */ 572 if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { 573 timespecclear(&sc->bst_lastupdated); 574 acpi_cmbat_get_bst(dev); 575 } 576 if (retry == 0 || !acpi_battery_bix_valid(&sc->bix)) 577 acpi_cmbat_get_bix(dev); 578 579 valid = acpi_battery_bst_valid(&sc->bst) && 580 acpi_battery_bix_valid(&sc->bix); 581 ACPI_SERIAL_END(cmbat); 582 583 if (valid) 584 break; 585 } 586 587 if (retry == ACPI_CMBAT_RETRY_MAX) { 588 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 589 "battery initialization failed, giving up\n"); 590 } else { 591 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 592 "battery initialization done, tried %d times\n", retry + 1); 593 } 594 } 595