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 < sizeof(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 == sizeof(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 if (sc->bix.rev != ACPI_BIX_REV_0) 402 ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_0); 403 } else if (ACPI_PKG_VALID(res, 22)) { 404 /* _BIX with 22 or more members. */ 405 if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1 + 1)) { 406 /* 407 * Unknown revision number. 408 * Assume 21 members are compatible with 6.0 _BIX. 409 */ 410 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 411 "Unknown _BIX revision(%u). " 412 "Assuming compatible with revision %u.\n", 413 sc->bix.rev, ACPI_BIX_REV_1); 414 } else { 415 /* 416 * Known revision number. Ignore the extra members. 417 */ 418 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 419 "Extra objects found in _BIX were ignored.\n"); 420 } 421 } else { 422 /* Invalid _BIX. Ignore it. */ 423 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 424 "Invalid _BIX found (rev=%u, count=%u). Ignored.\n", 425 sc->bix.rev, res->Package.Count); 426 goto end; 427 } 428 break; 429 #undef ACPI_BIX_REV_MISMATCH_ERR 430 case _BIF: 431 if (ACPI_PKG_VALID_EQ(res, 13)) /* _BIF */ 432 sc->bix.rev = ACPI_BIX_REV_BIF; 433 else { 434 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 435 "Invalid _BIF found (count=%u). Ignored.\n", 436 res->Package.Count); 437 goto end; 438 } 439 break; 440 } 441 442 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 443 "rev = %04x\n", sc->bix.rev); 444 #define BIX_GETU32(NAME) do { \ 445 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ 446 #NAME " = %u\n", sc->bix.NAME); \ 447 if (acpi_PkgInt32(res, i++, &sc->bix.NAME) != 0) \ 448 goto end; \ 449 } while (0) 450 451 BIX_GETU32(units); 452 BIX_GETU32(dcap); 453 BIX_GETU32(lfcap); 454 BIX_GETU32(btech); 455 BIX_GETU32(dvol); 456 BIX_GETU32(wcap); 457 BIX_GETU32(lcap); 458 if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_0)) { 459 BIX_GETU32(cycles); 460 BIX_GETU32(accuracy); 461 BIX_GETU32(stmax); 462 BIX_GETU32(stmin); 463 BIX_GETU32(aimax); 464 BIX_GETU32(aimin); 465 } 466 BIX_GETU32(gra1); 467 BIX_GETU32(gra2); 468 if (acpi_PkgStr(res, i++, sc->bix.model, ACPI_CMBAT_MAXSTRLEN) != 0) 469 goto end; 470 if (acpi_PkgStr(res, i++, sc->bix.serial, ACPI_CMBAT_MAXSTRLEN) != 0) 471 goto end; 472 if (acpi_PkgStr(res, i++, sc->bix.type, ACPI_CMBAT_MAXSTRLEN) != 0) 473 goto end; 474 if (acpi_PkgStr(res, i++, sc->bix.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) 475 goto end; 476 if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1)) 477 BIX_GETU32(scap); 478 #undef BIX_GETU32 479 end: 480 AcpiOsFree(bix_buffer.Pointer); 481 } 482 483 static int 484 acpi_cmbat_bix(device_t dev, void *bix, size_t len) 485 { 486 struct acpi_cmbat_softc *sc; 487 488 if (len != sizeof(struct acpi_bix) && 489 len != sizeof(struct acpi_bif)) 490 return (-1); 491 492 sc = device_get_softc(dev); 493 494 /* 495 * Just copy the data. The only value that should change is the 496 * last-full capacity, so we only update when we get a notify that says 497 * the info has changed. Many systems apparently take a long time to 498 * process a _BI[FX] call so we avoid it if possible. 499 */ 500 ACPI_SERIAL_BEGIN(cmbat); 501 memcpy(bix, &sc->bix, len); 502 ACPI_SERIAL_END(cmbat); 503 504 return (0); 505 } 506 507 static int 508 acpi_cmbat_bst(device_t dev, struct acpi_bst *bst) 509 { 510 struct acpi_cmbat_softc *sc; 511 512 sc = device_get_softc(dev); 513 514 ACPI_SERIAL_BEGIN(cmbat); 515 if (acpi_BatteryIsPresent(dev)) { 516 acpi_cmbat_get_bst(dev); 517 memcpy(bst, &sc->bst, sizeof(*bst)); 518 } else 519 bst->state = ACPI_BATT_STAT_NOT_PRESENT; 520 ACPI_SERIAL_END(cmbat); 521 522 return (0); 523 } 524 525 static void 526 acpi_cmbat_init_battery(void *arg) 527 { 528 struct acpi_cmbat_softc *sc; 529 int retry, valid; 530 device_t dev; 531 532 dev = (device_t)arg; 533 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 534 "battery initialization start\n"); 535 536 /* 537 * Try repeatedly to get valid data from the battery. Since the 538 * embedded controller isn't always ready just after boot, we may have 539 * to wait a while. 540 */ 541 for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { 542 /* 543 * Batteries on DOCK can be ejected w/ DOCK during retrying. 544 * 545 * If there is a valid softc pointer the device may be in 546 * attaching, attached or detaching state. If the state is 547 * different from attached retry getting the device state 548 * until it becomes stable. This solves a race if the ACPI 549 * notification handler is called during attach, because 550 * device_is_attached() doesn't return non-zero until after 551 * the attach code has been executed. 552 */ 553 ACPI_SERIAL_BEGIN(cmbat); 554 sc = device_get_softc(dev); 555 if (sc == NULL) { 556 ACPI_SERIAL_END(cmbat); 557 return; 558 } 559 560 if (!acpi_BatteryIsPresent(dev) || !device_is_attached(dev)) { 561 ACPI_SERIAL_END(cmbat); 562 continue; 563 } 564 565 /* 566 * Only query the battery if this is the first try or the specific 567 * type of info is still invalid. 568 */ 569 if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { 570 timespecclear(&sc->bst_lastupdated); 571 acpi_cmbat_get_bst(dev); 572 } 573 if (retry == 0 || !acpi_battery_bix_valid(&sc->bix)) 574 acpi_cmbat_get_bix(dev); 575 576 valid = acpi_battery_bst_valid(&sc->bst) && 577 acpi_battery_bix_valid(&sc->bix); 578 ACPI_SERIAL_END(cmbat); 579 580 if (valid) 581 break; 582 } 583 584 if (retry == ACPI_CMBAT_RETRY_MAX) { 585 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 586 "battery initialization failed, giving up\n"); 587 } else { 588 ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 589 "battery initialization done, tried %d times\n", retry + 1); 590 } 591 } 592