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