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