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