acpi.c revision 1.281
1/* $OpenBSD: acpi.c,v 1.281 2015/01/17 04:18:49 deraadt Exp $ */ 2/* 3 * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> 4 * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/param.h> 20#include <sys/systm.h> 21#include <sys/buf.h> 22#include <sys/device.h> 23#include <sys/malloc.h> 24#include <sys/fcntl.h> 25#include <sys/ioccom.h> 26#include <sys/event.h> 27#include <sys/signalvar.h> 28#include <sys/proc.h> 29#include <sys/kthread.h> 30#include <sys/sched.h> 31#include <sys/reboot.h> 32#include <sys/sysctl.h> 33 34#ifdef HIBERNATE 35#include <sys/hibernate.h> 36#endif 37 38#include <machine/conf.h> 39#include <machine/cpufunc.h> 40#include <machine/bus.h> 41 42#include <dev/rndvar.h> 43#include <dev/pci/pcivar.h> 44#include <dev/acpi/acpireg.h> 45#include <dev/acpi/acpivar.h> 46#include <dev/acpi/amltypes.h> 47#include <dev/acpi/acpidev.h> 48#include <dev/acpi/dsdt.h> 49#include <dev/wscons/wsdisplayvar.h> 50 51#include <dev/pci/pcidevs.h> 52#include <dev/pci/ppbreg.h> 53 54#include <dev/pci/pciidereg.h> 55#include <dev/pci/pciidevar.h> 56 57#include <machine/apmvar.h> 58#define APMUNIT(dev) (minor(dev)&0xf0) 59#define APMDEV(dev) (minor(dev)&0x0f) 60#define APMDEV_NORMAL 0 61#define APMDEV_CTL 8 62 63#include "wd.h" 64#include "wsdisplay.h" 65 66#ifdef ACPI_DEBUG 67int acpi_debug = 16; 68#endif 69 70int acpi_poll_enabled; 71int acpi_hasprocfvs; 72 73#define ACPIEN_RETRIES 15 74 75void acpi_pci_match(struct device *, struct pci_attach_args *); 76pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t); 77void acpi_pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int, int); 78int acpi_pci_notify(struct aml_node *, int, void *); 79 80int acpi_match(struct device *, void *, void *); 81void acpi_attach(struct device *, struct device *, void *); 82int acpi_submatch(struct device *, void *, void *); 83int acpi_print(void *, const char *); 84 85void acpi_map_pmregs(struct acpi_softc *); 86 87int acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *); 88 89int _acpi_matchhids(const char *, const char *[]); 90 91int acpi_inidev(struct aml_node *, void *); 92int acpi_foundprt(struct aml_node *, void *); 93 94struct acpi_q *acpi_maptable(struct acpi_softc *, paddr_t, const char *, 95 const char *, const char *, int); 96 97int acpi_enable(struct acpi_softc *); 98void acpi_init_states(struct acpi_softc *); 99 100void acpi_gpe_task(void *, int); 101void acpi_sbtn_task(void *, int); 102void acpi_pbtn_task(void *, int); 103 104#ifndef SMALL_KERNEL 105 106int acpi_thinkpad_enabled; 107int acpi_toshiba_enabled; 108int acpi_asus_enabled; 109int acpi_saved_boothowto; 110int acpi_enabled; 111 112int acpi_matchhids(struct acpi_attach_args *aa, const char *hids[], 113 const char *driver); 114 115void acpi_thread(void *); 116void acpi_create_thread(void *); 117void acpi_init_pm(struct acpi_softc *); 118void acpi_init_gpes(struct acpi_softc *); 119void acpi_indicator(struct acpi_softc *, int); 120 121int acpi_founddock(struct aml_node *, void *); 122int acpi_foundpss(struct aml_node *, void *); 123int acpi_foundhid(struct aml_node *, void *); 124int acpi_foundec(struct aml_node *, void *); 125int acpi_foundtmp(struct aml_node *, void *); 126int acpi_foundprw(struct aml_node *, void *); 127int acpi_foundvideo(struct aml_node *, void *); 128int acpi_foundsony(struct aml_node *node, void *arg); 129 130int acpi_foundide(struct aml_node *node, void *arg); 131int acpiide_notify(struct aml_node *, int, void *); 132void wdcattach(struct channel_softc *); 133int wdcdetach(struct channel_softc *, int); 134int is_ejectable_bay(struct aml_node *node); 135int is_ata(struct aml_node *node); 136int is_ejectable(struct aml_node *node); 137 138struct idechnl { 139 struct acpi_softc *sc; 140 int64_t addr; 141 int64_t chnl; 142 int64_t sta; 143}; 144 145int acpi_add_device(struct aml_node *node, void *arg); 146 147struct gpe_block *acpi_find_gpe(struct acpi_softc *, int); 148void acpi_enable_onegpe(struct acpi_softc *, int); 149int acpi_gpe(struct acpi_softc *, int, void *); 150 151void acpi_enable_rungpes(struct acpi_softc *); 152void acpi_enable_wakegpes(struct acpi_softc *, int); 153void acpi_disable_allgpes(struct acpi_softc *); 154 155#endif /* SMALL_KERNEL */ 156 157/* XXX move this into dsdt softc at some point */ 158extern struct aml_node aml_root; 159 160struct cfattach acpi_ca = { 161 sizeof(struct acpi_softc), acpi_match, acpi_attach 162}; 163 164struct cfdriver acpi_cd = { 165 NULL, "acpi", DV_DULL 166}; 167 168struct acpi_softc *acpi_softc; 169 170#define acpi_bus_space_map _bus_space_map 171#define acpi_bus_space_unmap _bus_space_unmap 172 173#ifndef SMALL_KERNEL 174/* 175 * This is a list of Synaptics devices with a 'top button area' 176 * based on the list in Linux supplied by Synaptics 177 * Synaptics clickpads with the following pnp ids will get a unique 178 * wscons mouse type that is used to define trackpad regions that will 179 * emulate mouse buttons 180 */ 181static const char *sbtn_pnp[] = { 182 "LEN0017", 183 "LEN0018", 184 "LEN0019", 185 "LEN0023", 186 "LEN002A", 187 "LEN002B", 188 "LEN002C", 189 "LEN002D", 190 "LEN002E", 191 "LEN0033", 192 "LEN0034", 193 "LEN0035", 194 "LEN0036", 195 "LEN0037", 196 "LEN0038", 197 "LEN0039", 198 "LEN0041", 199 "LEN0042", 200 "LEN0045", 201 "LEN0046", 202 "LEN0047", 203 "LEN0048", 204 "LEN0049", 205 "LEN2000", 206 "LEN2001", 207 "LEN2002", 208 "LEN2003", 209 "LEN2004", 210 "LEN2005", 211 "LEN2006", 212 "LEN2007", 213 "LEN2008", 214 "LEN2009", 215 "LEN200A", 216 "LEN200B", 217}; 218 219int mouse_has_softbtn; 220#endif 221 222int 223acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, 224 int access_size, int len, void *buffer) 225{ 226 u_int8_t *pb; 227 bus_space_tag_t iot; 228 bus_space_handle_t ioh; 229 pci_chipset_tag_t pc; 230 pcitag_t tag; 231 int reg, idx, ival, sval; 232 233 dnprintf(50, "gasio: %.2x 0x%.8llx %s\n", 234 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); 235 236 KASSERT((len % access_size) == 0); 237 238 pb = (u_int8_t *)buffer; 239 switch (iospace) { 240 case GAS_SYSTEM_MEMORY: 241 case GAS_SYSTEM_IOSPACE: 242 if (iospace == GAS_SYSTEM_MEMORY) 243 iot = sc->sc_memt; 244 else 245 iot = sc->sc_iot; 246 247 if (acpi_bus_space_map(iot, address, len, 0, &ioh) != 0) { 248 printf("%s: unable to map iospace\n", DEVNAME(sc)); 249 return (-1); 250 } 251 for (reg = 0; reg < len; reg += access_size) { 252 if (iodir == ACPI_IOREAD) { 253 switch (access_size) { 254 case 1: 255 *(uint8_t *)(pb + reg) = 256 bus_space_read_1(iot, ioh, reg); 257 dnprintf(80, "os_in8(%llx) = %x\n", 258 reg+address, *(uint8_t *)(pb+reg)); 259 break; 260 case 2: 261 *(uint16_t *)(pb + reg) = 262 bus_space_read_2(iot, ioh, reg); 263 dnprintf(80, "os_in16(%llx) = %x\n", 264 reg+address, *(uint16_t *)(pb+reg)); 265 break; 266 case 4: 267 *(uint32_t *)(pb + reg) = 268 bus_space_read_4(iot, ioh, reg); 269 break; 270 default: 271 printf("%s: rdio: invalid size %d\n", 272 DEVNAME(sc), access_size); 273 return (-1); 274 } 275 } else { 276 switch (access_size) { 277 case 1: 278 bus_space_write_1(iot, ioh, reg, 279 *(uint8_t *)(pb + reg)); 280 dnprintf(80, "os_out8(%llx,%x)\n", 281 reg+address, *(uint8_t *)(pb+reg)); 282 break; 283 case 2: 284 bus_space_write_2(iot, ioh, reg, 285 *(uint16_t *)(pb + reg)); 286 dnprintf(80, "os_out16(%llx,%x)\n", 287 reg+address, *(uint16_t *)(pb+reg)); 288 break; 289 case 4: 290 bus_space_write_4(iot, ioh, reg, 291 *(uint32_t *)(pb + reg)); 292 break; 293 default: 294 printf("%s: wrio: invalid size %d\n", 295 DEVNAME(sc), access_size); 296 return (-1); 297 } 298 } 299 } 300 acpi_bus_space_unmap(iot, ioh, len, NULL); 301 break; 302 303 case GAS_PCI_CFG_SPACE: 304 /* format of address: 305 * bits 00..15 = register 306 * bits 16..31 = function 307 * bits 32..47 = device 308 * bits 48..63 = bus 309 */ 310 pc = NULL; 311 tag = pci_make_tag(pc, 312 ACPI_PCI_BUS(address), ACPI_PCI_DEV(address), 313 ACPI_PCI_FN(address)); 314 315 /* XXX: This is ugly. read-modify-write does a byte at a time */ 316 reg = ACPI_PCI_REG(address); 317 for (idx = reg; idx < reg+len; idx++) { 318 ival = pci_conf_read(pc, tag, idx & ~0x3); 319 if (iodir == ACPI_IOREAD) { 320 *pb = ival >> (8 * (idx & 0x3)); 321 } else { 322 sval = *pb; 323 ival &= ~(0xFF << (8* (idx & 0x3))); 324 ival |= sval << (8* (idx & 0x3)); 325 pci_conf_write(pc, tag, idx & ~0x3, ival); 326 } 327 pb++; 328 } 329 break; 330 331 case GAS_EMBEDDED: 332 if (sc->sc_ec == NULL) { 333 printf("%s: WARNING EC not initialized\n", DEVNAME(sc)); 334 return (-1); 335 } 336#ifndef SMALL_KERNEL 337 if (iodir == ACPI_IOREAD) 338 acpiec_read(sc->sc_ec, (u_int8_t)address, len, buffer); 339 else 340 acpiec_write(sc->sc_ec, (u_int8_t)address, len, buffer); 341#endif 342 break; 343 } 344 return (0); 345} 346 347int 348acpi_inidev(struct aml_node *node, void *arg) 349{ 350 struct acpi_softc *sc = (struct acpi_softc *)arg; 351 int64_t st; 352 353 /* 354 * Per the ACPI spec 6.5.1, only run _INI when device is there or 355 * when there is no _STA. We terminate the tree walk (with return 1) 356 * early if necessary. 357 */ 358 359 /* Evaluate _STA to decide _INI fate and walk fate */ 360 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &st)) 361 st = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 362 363 /* Evaluate _INI if we are present */ 364 if (st & STA_PRESENT) 365 aml_evalnode(sc, node, 0, NULL, NULL); 366 367 /* If we are functioning, we walk/search our children */ 368 if (st & STA_DEV_OK) 369 return 0; 370 371 /* If we are not enabled, or not present, terminate search */ 372 if (!(st & (STA_PRESENT|STA_ENABLED))) 373 return 1; 374 375 /* Default just continue search */ 376 return 0; 377} 378 379int 380acpi_foundprt(struct aml_node *node, void *arg) 381{ 382 struct acpi_softc *sc = (struct acpi_softc *)arg; 383 struct device *self = (struct device *)arg; 384 struct acpi_attach_args aaa; 385 int64_t st = 0; 386 387 dnprintf(10, "found prt entry: %s\n", node->parent->name); 388 389 /* Evaluate _STA to decide _PRT fate and walk fate */ 390 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &st)) 391 st = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 392 393 if (st & STA_PRESENT) { 394 memset(&aaa, 0, sizeof(aaa)); 395 aaa.aaa_iot = sc->sc_iot; 396 aaa.aaa_memt = sc->sc_memt; 397 aaa.aaa_node = node; 398 aaa.aaa_name = "acpiprt"; 399 400 config_found(self, &aaa, acpi_print); 401 } 402 403 /* If we are functioning, we walk/search our children */ 404 if (st & STA_DEV_OK) 405 return 0; 406 407 /* If we are not enabled, or not present, terminate search */ 408 if (!(st & (STA_PRESENT|STA_ENABLED))) 409 return 1; 410 411 /* Default just continue search */ 412 return 0; 413} 414 415int 416acpi_match(struct device *parent, void *match, void *aux) 417{ 418 struct bios_attach_args *ba = aux; 419 struct cfdata *cf = match; 420 421 /* sanity */ 422 if (strcmp(ba->ba_name, cf->cf_driver->cd_name)) 423 return (0); 424 425 if (!acpi_probe(parent, cf, ba)) 426 return (0); 427 428 return (1); 429} 430 431TAILQ_HEAD(, acpi_pci) acpi_pcidevs = 432 TAILQ_HEAD_INITIALIZER(acpi_pcidevs); 433TAILQ_HEAD(, acpi_pci) acpi_pcirootdevs = 434 TAILQ_HEAD_INITIALIZER(acpi_pcirootdevs); 435 436int acpi_getpci(struct aml_node *node, void *arg); 437int acpi_getminbus(union acpi_resource *crs, void *arg); 438 439int 440acpi_getminbus(union acpi_resource *crs, void *arg) 441{ 442 int *bbn = arg; 443 int typ = AML_CRSTYPE(crs); 444 445 /* Check for embedded bus number */ 446 if (typ == LR_WORD && crs->lr_word.type == 2) { 447 /* If _MIN > _MAX, the resource is considered to be invalid. */ 448 if (crs->lr_word._min > crs->lr_word._max) 449 return -1; 450 *bbn = crs->lr_word._min; 451 } 452 return 0; 453} 454 455int 456_acpi_matchhids(const char *hid, const char *hids[]) 457{ 458 int i; 459 460 for (i = 0; hids[i]; i++) 461 if (!strcmp(hid, hids[i])) 462 return (1); 463 return (0); 464} 465 466#ifndef SMALL_KERNEL 467int 468acpi_matchhids(struct acpi_attach_args *aa, const char *hids[], 469 const char *driver) 470{ 471 if (aa->aaa_dev == NULL || aa->aaa_node == NULL) 472 return (0); 473 if (_acpi_matchhids(aa->aaa_dev, hids)) { 474 dnprintf(5, "driver %s matches at least one hid\n", driver); 475 return (1); 476 } 477 478 return (0); 479} 480#endif /* SMALL_KERNEL */ 481 482/* Map ACPI device node to PCI */ 483int 484acpi_getpci(struct aml_node *node, void *arg) 485{ 486 const char *pcihid[] = { ACPI_DEV_PCIB, ACPI_DEV_PCIEB, "HWP0002", 0 }; 487 struct acpi_pci *pci, *ppci; 488 struct aml_value res; 489 struct acpi_softc *sc = arg; 490 pci_chipset_tag_t pc = NULL; 491 pcitag_t tag; 492 uint64_t val; 493 uint32_t reg; 494 495 if (!node->value || node->value->type != AML_OBJTYPE_DEVICE) 496 return 0; 497 if (!aml_evalhid(node, &res)) { 498 /* Check if this is a PCI Root node */ 499 if (_acpi_matchhids(res.v_string, pcihid)) { 500 aml_freevalue(&res); 501 502 pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO); 503 504 pci->bus = -1; 505 if (!aml_evalinteger(sc, node, "_SEG", 0, NULL, &val)) 506 pci->seg = val; 507 if (!aml_evalname(sc, node, "_CRS", 0, NULL, &res)) { 508 aml_parse_resource(&res, acpi_getminbus, 509 &pci->bus); 510 dnprintf(10, "%s post-crs: %d\n", aml_nodename(node), 511 pci->bus); 512 } 513 if (!aml_evalinteger(sc, node, "_BBN", 0, NULL, &val)) { 514 dnprintf(10, "%s post-bbn: %d, %lld\n", aml_nodename(node), 515 pci->bus, val); 516 if (pci->bus == -1) 517 pci->bus = val; 518 } 519 pci->sub = pci->bus; 520 node->pci = pci; 521 dnprintf(10, "found PCI root: %s %d\n", 522 aml_nodename(node), pci->bus); 523 TAILQ_INSERT_TAIL(&acpi_pcirootdevs, pci, next); 524 } 525 aml_freevalue(&res); 526 return 0; 527 } 528 529 /* If parent is not PCI, or device does not have _ADR, return */ 530 if (!node->parent || (ppci = node->parent->pci) == NULL) 531 return 0; 532 if (aml_evalinteger(sc, node, "_ADR", 0, NULL, &val)) 533 return 0; 534 535 pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO); 536 pci->bus = ppci->sub; 537 pci->dev = ACPI_ADR_PCIDEV(val); 538 pci->fun = ACPI_ADR_PCIFUN(val); 539 pci->node = node; 540 pci->sub = -1; 541 542 dnprintf(10, "%.2x:%.2x.%x -> %s\n", 543 pci->bus, pci->dev, pci->fun, 544 aml_nodename(node)); 545 546 /* Collect device power state information. */ 547 if (aml_evalinteger(sc, node, "_S3D", 0, NULL, &val) == 0) 548 pci->_s3d = val; 549 else 550 pci->_s3d = -1; 551 if (aml_evalinteger(sc, node, "_S3W", 0, NULL, &val) == 0) 552 pci->_s3w = val; 553 else 554 pci->_s3w = -1; 555 if (aml_evalinteger(sc, node, "_S4D", 0, NULL, &val) == 0) 556 pci->_s4d = val; 557 else 558 pci->_s4d = -1; 559 if (aml_evalinteger(sc, node, "_S4W", 0, NULL, &val) == 0) 560 pci->_s4w = val; 561 else 562 pci->_s4w = -1; 563 564 /* Check if PCI device exists */ 565 if (pci->dev > 0x1F || pci->fun > 7) { 566 free(pci, M_DEVBUF, 0); 567 return (1); 568 } 569 tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun); 570 reg = pci_conf_read(pc, tag, PCI_ID_REG); 571 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) { 572 free(pci, M_DEVBUF, 0); 573 return (1); 574 } 575 node->pci = pci; 576 577 TAILQ_INSERT_TAIL(&acpi_pcidevs, pci, next); 578 579 /* Check if this is a PCI bridge */ 580 reg = pci_conf_read(pc, tag, PCI_CLASS_REG); 581 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE && 582 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) { 583 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO); 584 pci->sub = PPB_BUSINFO_SECONDARY(reg); 585 586 dnprintf(10, "found PCI bridge: %s %d\n", 587 aml_nodename(node), pci->sub); 588 589 /* Continue scanning */ 590 return (0); 591 } 592 593 /* Device does not have children, stop scanning */ 594 return (1); 595} 596 597void 598acpi_pci_match(struct device *dev, struct pci_attach_args *pa) 599{ 600 struct acpi_pci *pdev; 601 int state; 602 603 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 604 if (pdev->bus != pa->pa_bus || 605 pdev->dev != pa->pa_device || 606 pdev->fun != pa->pa_function) 607 continue; 608 609 dnprintf(10,"%s at acpi0 %s\n", dev->dv_xname, 610 aml_nodename(pdev->node)); 611 612 pdev->device = dev; 613 614 /* 615 * If some Power Resources are dependent on this device 616 * initialize them. 617 */ 618 state = pci_get_powerstate(pa->pa_pc, pa->pa_tag); 619 acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 1); 620 acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 0); 621 622 aml_register_notify(pdev->node, NULL, acpi_pci_notify, pdev, 0); 623 } 624} 625 626pcireg_t 627acpi_pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag) 628{ 629 struct acpi_pci *pdev; 630 int bus, dev, fun; 631 int state = -1, defaultstate = pci_get_powerstate(pc, tag); 632 633 pci_decompose_tag(pc, tag, &bus, &dev, &fun); 634 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 635 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) { 636 switch (acpi_softc->sc_state) { 637 case ACPI_STATE_S3: 638 defaultstate = PCI_PMCSR_STATE_D3; 639 state = MAX(pdev->_s3d, pdev->_s3w); 640 break; 641 case ACPI_STATE_S4: 642 state = MAX(pdev->_s4d, pdev->_s4w); 643 break; 644 case ACPI_STATE_S5: 645 default: 646 break; 647 } 648 649 if (state >= PCI_PMCSR_STATE_D0 && 650 state <= PCI_PMCSR_STATE_D3) 651 return state; 652 } 653 } 654 655 return defaultstate; 656} 657 658void 659acpi_pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state, int pre) 660{ 661#if NACPIPWRRES > 0 662 struct acpi_softc *sc = acpi_softc; 663 struct acpi_pwrres *pr; 664 struct acpi_pci *pdev; 665 int bus, dev, fun; 666 char name[5]; 667 668 pci_decompose_tag(pc, tag, &bus, &dev, &fun); 669 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 670 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) 671 break; 672 } 673 674 /* XXX Add a check to discard nodes without Power Resources? */ 675 if (pdev == NULL) 676 return; 677 678 SIMPLEQ_FOREACH(pr, &sc->sc_pwrresdevs, p_next) { 679 if (pr->p_node != pdev->node) 680 continue; 681 682 /* 683 * If the firmware is already aware that the device 684 * is in the given state, there's nothing to do. 685 */ 686 if (pr->p_state == state) 687 continue; 688 689 if (pre) { 690 /* 691 * If a Resource is dependent on this device for 692 * the given state, make sure it is turned "_ON". 693 */ 694 if (pr->p_res_state == state) 695 acpipwrres_ref_incr(pr->p_res_sc, pr->p_node); 696 } else { 697 /* 698 * If a Resource was referenced for the state we 699 * left, drop a reference and turn it "_OFF" if 700 * it was the last one. 701 */ 702 if (pr->p_res_state == pr->p_state) 703 acpipwrres_ref_decr(pr->p_res_sc, pr->p_node); 704 705 if (pr->p_res_state == state) { 706 snprintf(name, sizeof(name), "_PS%d", state); 707 aml_evalname(sc, pr->p_node, name, 0, 708 NULL, NULL); 709 } 710 711 pr->p_state = state; 712 } 713 714 } 715#endif /* NACPIPWRRES > 0 */ 716} 717 718int 719acpi_pci_notify(struct aml_node *node, int ntype, void *arg) 720{ 721 struct acpi_pci *pdev = arg; 722 pci_chipset_tag_t pc = NULL; 723 pcitag_t tag; 724 pcireg_t reg; 725 int offset; 726 727 /* We're only interested in Device Wake notifications. */ 728 if (ntype != 2) 729 return (0); 730 731 tag = pci_make_tag(pc, pdev->bus, pdev->dev, pdev->fun); 732 if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { 733 /* Clear the PME Status bit if it is set. */ 734 reg = pci_conf_read(pc, tag, offset + PCI_PMCSR); 735 pci_conf_write(pc, tag, offset + PCI_PMCSR, reg); 736 } 737 738 return (0); 739} 740 741void 742acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr) 743{ 744 struct acpi_pci *pdev; 745 struct pcibus_attach_args *pba = aux; 746 747 KASSERT(pba->pba_busex != NULL); 748 749 TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) { 750 if (extent_alloc_region(pba->pba_busex, pdev->bus, 751 1, EX_NOWAIT) != 0) 752 continue; 753 pba->pba_bus = pdev->bus; 754 config_found(dev, pba, pr); 755 } 756} 757 758void 759acpi_attach(struct device *parent, struct device *self, void *aux) 760{ 761 struct bios_attach_args *ba = aux; 762 struct acpi_softc *sc = (struct acpi_softc *)self; 763 struct acpi_mem_map handle; 764 struct acpi_rsdp *rsdp; 765 struct acpi_q *entry; 766 struct acpi_dsdt *p_dsdt; 767#ifndef SMALL_KERNEL 768 int wakeup_dev_ct; 769 struct acpi_wakeq *wentry; 770 struct device *dev; 771 struct acpi_ac *ac; 772 struct acpi_bat *bat; 773 int s; 774#endif /* SMALL_KERNEL */ 775 paddr_t facspa; 776 777 sc->sc_iot = ba->ba_iot; 778 sc->sc_memt = ba->ba_memt; 779 780 rw_init(&sc->sc_lck, "acpilk"); 781 782 acpi_softc = sc; 783 784 if (acpi_map(ba->ba_acpipbase, sizeof(struct acpi_rsdp), &handle)) { 785 printf(": can't map memory\n"); 786 return; 787 } 788 789 rsdp = (struct acpi_rsdp *)handle.va; 790 sc->sc_revision = (int)rsdp->rsdp_revision; 791 printf(": rev %d", sc->sc_revision); 792 793 SIMPLEQ_INIT(&sc->sc_tables); 794 SIMPLEQ_INIT(&sc->sc_wakedevs); 795#if NACPIPWRRES > 0 796 SIMPLEQ_INIT(&sc->sc_pwrresdevs); 797#endif /* NACPIPWRRES > 0 */ 798 799 800#ifndef SMALL_KERNEL 801 sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT | M_ZERO); 802 if (sc->sc_note == NULL) { 803 printf(", can't allocate memory\n"); 804 acpi_unmap(&handle); 805 return; 806 } 807#endif /* SMALL_KERNEL */ 808 809 if (acpi_loadtables(sc, rsdp)) { 810 printf(", can't load tables\n"); 811 acpi_unmap(&handle); 812 return; 813 } 814 815 acpi_unmap(&handle); 816 817 /* 818 * Find the FADT 819 */ 820 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 821 if (memcmp(entry->q_table, FADT_SIG, 822 sizeof(FADT_SIG) - 1) == 0) { 823 sc->sc_fadt = entry->q_table; 824 break; 825 } 826 } 827 if (sc->sc_fadt == NULL) { 828 printf(", no FADT\n"); 829 return; 830 } 831 832 /* 833 * Check if we are able to enable ACPI control 834 */ 835 if (sc->sc_fadt->smi_cmd && 836 (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) { 837 printf(", ACPI control unavailable\n"); 838 return; 839 } 840 841 /* 842 * Set up a pointer to the firmware control structure 843 */ 844 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0) 845 facspa = sc->sc_fadt->firmware_ctl; 846 else 847 facspa = sc->sc_fadt->x_firmware_ctl; 848 849 if (acpi_map(facspa, sizeof(struct acpi_facs), &handle)) 850 printf(" !FACS"); 851 else 852 sc->sc_facs = (struct acpi_facs *)handle.va; 853 854 /* Create opcode hashtable */ 855 aml_hashopcodes(); 856 857 /* Create Default AML objects */ 858 aml_create_defaultobjects(); 859 860 /* 861 * Load the DSDT from the FADT pointer -- use the 862 * extended (64-bit) pointer if it exists 863 */ 864 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0) 865 entry = acpi_maptable(sc, sc->sc_fadt->dsdt, NULL, NULL, NULL, -1); 866 else 867 entry = acpi_maptable(sc, sc->sc_fadt->x_dsdt, NULL, NULL, NULL, -1); 868 869 if (entry == NULL) 870 printf(" !DSDT"); 871 872 p_dsdt = entry->q_table; 873 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 874 sizeof(p_dsdt->hdr)); 875 876 /* Load SSDT's */ 877 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 878 if (memcmp(entry->q_table, SSDT_SIG, 879 sizeof(SSDT_SIG) - 1) == 0) { 880 p_dsdt = entry->q_table; 881 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 882 sizeof(p_dsdt->hdr)); 883 } 884 } 885 886 /* Perform post-parsing fixups */ 887 aml_postparse(); 888 889 /* Find available sleeping states */ 890 acpi_init_states(sc); 891 892#ifndef SMALL_KERNEL 893 /* Find available sleep/resume related methods. */ 894 acpi_init_pm(sc); 895#endif /* SMALL_KERNEL */ 896 897 /* Map Power Management registers */ 898 acpi_map_pmregs(sc); 899 900#ifndef SMALL_KERNEL 901 /* Initialize GPE handlers */ 902 s = spltty(); 903 acpi_init_gpes(sc); 904 splx(s); 905 906 /* some devices require periodic polling */ 907 timeout_set(&sc->sc_dev_timeout, acpi_poll, sc); 908 909 acpi_enabled = 1; 910#endif /* SMALL_KERNEL */ 911 912 /* 913 * Take over ACPI control. Note that once we do this, we 914 * effectively tell the system that we have ownership of 915 * the ACPI hardware registers, and that SMI should leave 916 * them alone 917 * 918 * This may prevent thermal control on some systems where 919 * that actually does work 920 */ 921 if (sc->sc_fadt->smi_cmd) { 922 if (acpi_enable(sc)) { 923 printf(", can't enable ACPI\n"); 924 return; 925 } 926 } 927 928 printf("\n%s: tables", DEVNAME(sc)); 929 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 930 printf(" %.4s", (char *)entry->q_table); 931 } 932 printf("\n"); 933 934#ifndef SMALL_KERNEL 935 /* Display wakeup devices and lowest S-state */ 936 wakeup_dev_ct = 0; 937 printf("%s: wakeup devices", DEVNAME(sc)); 938 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { 939 if (wakeup_dev_ct < 16) 940 printf(" %.4s(S%d)", wentry->q_node->name, 941 wentry->q_state); 942 else if (wakeup_dev_ct == 16) 943 printf(" [...]"); 944 wakeup_dev_ct ++; 945 } 946 printf("\n"); 947 948 /* 949 * ACPI is enabled now -- attach timer 950 */ 951 { 952 struct acpi_attach_args aaa; 953 954 memset(&aaa, 0, sizeof(aaa)); 955 aaa.aaa_name = "acpitimer"; 956 aaa.aaa_iot = sc->sc_iot; 957 aaa.aaa_memt = sc->sc_memt; 958#if 0 959 aaa.aaa_pcit = sc->sc_pcit; 960 aaa.aaa_smbust = sc->sc_smbust; 961#endif 962 config_found(self, &aaa, acpi_print); 963 } 964#endif /* SMALL_KERNEL */ 965 966 /* 967 * Attach table-defined devices 968 */ 969 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 970 struct acpi_attach_args aaa; 971 972 memset(&aaa, 0, sizeof(aaa)); 973 aaa.aaa_iot = sc->sc_iot; 974 aaa.aaa_memt = sc->sc_memt; 975 #if 0 976 aaa.aaa_pcit = sc->sc_pcit; 977 aaa.aaa_smbust = sc->sc_smbust; 978 #endif 979 aaa.aaa_table = entry->q_table; 980 config_found_sm(self, &aaa, acpi_print, acpi_submatch); 981 } 982 983 /* initialize runtime environment */ 984 aml_find_node(&aml_root, "_INI", acpi_inidev, sc); 985 986 /* Get PCI mapping */ 987 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_getpci, sc); 988 989 /* attach pci interrupt routing tables */ 990 aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc); 991 992#ifndef SMALL_KERNEL 993 aml_find_node(&aml_root, "_HID", acpi_foundec, sc); 994 995 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc); 996 997 /* attach battery, power supply and button devices */ 998 aml_find_node(&aml_root, "_HID", acpi_foundhid, sc); 999 1000#if NWD > 0 1001 /* Attach IDE bay */ 1002 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_foundide, sc); 1003#endif 1004 1005 /* attach docks */ 1006 aml_find_node(&aml_root, "_DCK", acpi_founddock, sc); 1007 1008 /* check if we're running on a sony */ 1009 aml_find_node(&aml_root, "GBRT", acpi_foundsony, sc); 1010 1011 /* attach video only if this is not a stinkpad or toshiba */ 1012 if (!acpi_thinkpad_enabled && !acpi_toshiba_enabled && 1013 !acpi_asus_enabled) 1014 aml_find_node(&aml_root, "_DOS", acpi_foundvideo, sc); 1015 1016 /* create list of devices we want to query when APM come in */ 1017 SLIST_INIT(&sc->sc_ac); 1018 SLIST_INIT(&sc->sc_bat); 1019 TAILQ_FOREACH(dev, &alldevs, dv_list) { 1020 if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpiac")) { 1021 ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO); 1022 ac->aac_softc = (struct acpiac_softc *)dev; 1023 SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link); 1024 } else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpibat")) { 1025 bat = malloc(sizeof(*bat), M_DEVBUF, M_WAITOK | M_ZERO); 1026 bat->aba_softc = (struct acpibat_softc *)dev; 1027 SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link); 1028 } 1029 } 1030 1031 /* Setup threads */ 1032 sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK); 1033 sc->sc_thread->sc = sc; 1034 sc->sc_thread->running = 1; 1035 1036 /* Enable PCI Power Management. */ 1037 pci_dopm = 1; 1038 1039 acpi_attach_machdep(sc); 1040 1041 kthread_create_deferred(acpi_create_thread, sc); 1042#endif /* SMALL_KERNEL */ 1043} 1044 1045int 1046acpi_submatch(struct device *parent, void *match, void *aux) 1047{ 1048 struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux; 1049 struct cfdata *cf = match; 1050 1051 if (aaa->aaa_table == NULL) 1052 return (0); 1053 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 1054} 1055 1056int 1057acpi_print(void *aux, const char *pnp) 1058{ 1059 struct acpi_attach_args *aa = aux; 1060 1061 if (pnp) { 1062 if (aa->aaa_name) 1063 printf("%s at %s", aa->aaa_name, pnp); 1064 else 1065 return (QUIET); 1066 } 1067 1068 return (UNCONF); 1069} 1070 1071struct acpi_q * 1072acpi_maptable(struct acpi_softc *sc, paddr_t addr, const char *sig, 1073 const char *oem, const char *tbl, int flag) 1074{ 1075 static int tblid; 1076 struct acpi_mem_map handle; 1077 struct acpi_table_header *hdr; 1078 struct acpi_q *entry; 1079 size_t len; 1080 1081 /* Check if we can map address */ 1082 if (addr == 0) 1083 return NULL; 1084 if (acpi_map(addr, sizeof(*hdr), &handle)) 1085 return NULL; 1086 hdr = (struct acpi_table_header *)handle.va; 1087 len = hdr->length; 1088 acpi_unmap(&handle); 1089 1090 /* Validate length/checksum */ 1091 if (acpi_map(addr, len, &handle)) 1092 return NULL; 1093 hdr = (struct acpi_table_header *)handle.va; 1094 if (acpi_checksum(hdr, len)) 1095 printf("\n%s: %.4s checksum error", 1096 DEVNAME(sc), hdr->signature); 1097 1098 if ((sig && memcmp(sig, hdr->signature, 4)) || 1099 (oem && memcmp(oem, hdr->oemid, 6)) || 1100 (tbl && memcmp(tbl, hdr->oemtableid, 8))) { 1101 acpi_unmap(&handle); 1102 return NULL; 1103 } 1104 1105 /* Allocate copy */ 1106 entry = malloc(len + sizeof(*entry), M_DEVBUF, M_NOWAIT); 1107 if (entry != NULL) { 1108 memcpy(entry->q_data, handle.va, len); 1109 entry->q_table = entry->q_data; 1110 entry->q_id = ++tblid; 1111 1112 if (flag < 0) 1113 SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, 1114 q_next); 1115 else if (flag > 0) 1116 SIMPLEQ_INSERT_TAIL(&sc->sc_tables, entry, 1117 q_next); 1118 } 1119 acpi_unmap(&handle); 1120 return entry; 1121} 1122 1123int 1124acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp) 1125{ 1126 struct acpi_q *sdt; 1127 int i, ntables; 1128 size_t len; 1129 1130 if (rsdp->rsdp_revision == 2 && rsdp->rsdp_xsdt) { 1131 struct acpi_xsdt *xsdt; 1132 1133 sdt = acpi_maptable(sc, rsdp->rsdp_xsdt, NULL, NULL, NULL, 0); 1134 if (sdt == NULL) { 1135 printf("couldn't map rsdt\n"); 1136 return (ENOMEM); 1137 } 1138 1139 xsdt = (struct acpi_xsdt *)sdt->q_data; 1140 len = xsdt->hdr.length; 1141 ntables = (len - sizeof(struct acpi_table_header)) / 1142 sizeof(xsdt->table_offsets[0]); 1143 1144 for (i = 0; i < ntables; i++) 1145 acpi_maptable(sc, xsdt->table_offsets[i], NULL, NULL, 1146 NULL, 1); 1147 1148 free(sdt, M_DEVBUF, 0); 1149 } else { 1150 struct acpi_rsdt *rsdt; 1151 1152 sdt = acpi_maptable(sc, rsdp->rsdp_rsdt, NULL, NULL, NULL, 0); 1153 if (sdt == NULL) { 1154 printf("couldn't map rsdt\n"); 1155 return (ENOMEM); 1156 } 1157 1158 rsdt = (struct acpi_rsdt *)sdt->q_data; 1159 len = rsdt->hdr.length; 1160 ntables = (len - sizeof(struct acpi_table_header)) / 1161 sizeof(rsdt->table_offsets[0]); 1162 1163 for (i = 0; i < ntables; i++) 1164 acpi_maptable(sc, rsdt->table_offsets[i], NULL, NULL, 1165 NULL, 1); 1166 1167 free(sdt, M_DEVBUF, 0); 1168 } 1169 1170 return (0); 1171} 1172 1173/* Read from power management register */ 1174int 1175acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset) 1176{ 1177 bus_space_handle_t ioh; 1178 bus_size_t size; 1179 int regval; 1180 1181 /* Special cases: 1A/1B blocks can be OR'ed together */ 1182 switch (reg) { 1183 case ACPIREG_PM1_EN: 1184 return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) | 1185 acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset)); 1186 case ACPIREG_PM1_STS: 1187 return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) | 1188 acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset)); 1189 case ACPIREG_PM1_CNT: 1190 return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) | 1191 acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset)); 1192 case ACPIREG_GPE_STS: 1193 dnprintf(50, "read GPE_STS offset: %.2x %.2x %.2x\n", offset, 1194 sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1); 1195 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1196 reg = ACPIREG_GPE0_STS; 1197 } 1198 break; 1199 case ACPIREG_GPE_EN: 1200 dnprintf(50, "read GPE_EN offset: %.2x %.2x %.2x\n", 1201 offset, sc->sc_fadt->gpe0_blk_len>>1, 1202 sc->sc_fadt->gpe1_blk_len>>1); 1203 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1204 reg = ACPIREG_GPE0_EN; 1205 } 1206 break; 1207 } 1208 1209 if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0) 1210 return (0); 1211 1212 regval = 0; 1213 ioh = sc->sc_pmregs[reg].ioh; 1214 size = sc->sc_pmregs[reg].size; 1215 if (size > sc->sc_pmregs[reg].access) 1216 size = sc->sc_pmregs[reg].access; 1217 1218 switch (size) { 1219 case 1: 1220 regval = bus_space_read_1(sc->sc_iot, ioh, offset); 1221 break; 1222 case 2: 1223 regval = bus_space_read_2(sc->sc_iot, ioh, offset); 1224 break; 1225 case 4: 1226 regval = bus_space_read_4(sc->sc_iot, ioh, offset); 1227 break; 1228 } 1229 1230 dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n", 1231 sc->sc_pmregs[reg].name, 1232 sc->sc_pmregs[reg].addr, offset, regval); 1233 return (regval); 1234} 1235 1236/* Write to power management register */ 1237void 1238acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval) 1239{ 1240 bus_space_handle_t ioh; 1241 bus_size_t size; 1242 1243 /* Special cases: 1A/1B blocks can be written with same value */ 1244 switch (reg) { 1245 case ACPIREG_PM1_EN: 1246 acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval); 1247 acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval); 1248 break; 1249 case ACPIREG_PM1_STS: 1250 acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval); 1251 acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval); 1252 break; 1253 case ACPIREG_PM1_CNT: 1254 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval); 1255 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval); 1256 break; 1257 case ACPIREG_GPE_STS: 1258 dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n", 1259 offset, sc->sc_fadt->gpe0_blk_len>>1, 1260 sc->sc_fadt->gpe1_blk_len>>1, regval); 1261 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1262 reg = ACPIREG_GPE0_STS; 1263 } 1264 break; 1265 case ACPIREG_GPE_EN: 1266 dnprintf(50, "write GPE_EN offset: %.2x %.2x %.2x %.2x\n", 1267 offset, sc->sc_fadt->gpe0_blk_len>>1, 1268 sc->sc_fadt->gpe1_blk_len>>1, regval); 1269 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1270 reg = ACPIREG_GPE0_EN; 1271 } 1272 break; 1273 } 1274 1275 /* All special case return here */ 1276 if (reg >= ACPIREG_MAXREG) 1277 return; 1278 1279 ioh = sc->sc_pmregs[reg].ioh; 1280 size = sc->sc_pmregs[reg].size; 1281 if (size > sc->sc_pmregs[reg].access) 1282 size = sc->sc_pmregs[reg].access; 1283 1284 switch (size) { 1285 case 1: 1286 bus_space_write_1(sc->sc_iot, ioh, offset, regval); 1287 break; 1288 case 2: 1289 bus_space_write_2(sc->sc_iot, ioh, offset, regval); 1290 break; 1291 case 4: 1292 bus_space_write_4(sc->sc_iot, ioh, offset, regval); 1293 break; 1294 } 1295 1296 dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n", 1297 sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval); 1298} 1299 1300/* Map Power Management registers */ 1301void 1302acpi_map_pmregs(struct acpi_softc *sc) 1303{ 1304 bus_addr_t addr; 1305 bus_size_t size, access; 1306 const char *name; 1307 int reg; 1308 1309 for (reg = 0; reg < ACPIREG_MAXREG; reg++) { 1310 size = 0; 1311 access = 0; 1312 switch (reg) { 1313 case ACPIREG_SMICMD: 1314 name = "smi"; 1315 size = access = 1; 1316 addr = sc->sc_fadt->smi_cmd; 1317 break; 1318 case ACPIREG_PM1A_STS: 1319 case ACPIREG_PM1A_EN: 1320 name = "pm1a_sts"; 1321 size = sc->sc_fadt->pm1_evt_len >> 1; 1322 addr = sc->sc_fadt->pm1a_evt_blk; 1323 access = 2; 1324 if (reg == ACPIREG_PM1A_EN && addr) { 1325 addr += size; 1326 name = "pm1a_en"; 1327 } 1328 break; 1329 case ACPIREG_PM1A_CNT: 1330 name = "pm1a_cnt"; 1331 size = sc->sc_fadt->pm1_cnt_len; 1332 addr = sc->sc_fadt->pm1a_cnt_blk; 1333 access = 2; 1334 break; 1335 case ACPIREG_PM1B_STS: 1336 case ACPIREG_PM1B_EN: 1337 name = "pm1b_sts"; 1338 size = sc->sc_fadt->pm1_evt_len >> 1; 1339 addr = sc->sc_fadt->pm1b_evt_blk; 1340 access = 2; 1341 if (reg == ACPIREG_PM1B_EN && addr) { 1342 addr += size; 1343 name = "pm1b_en"; 1344 } 1345 break; 1346 case ACPIREG_PM1B_CNT: 1347 name = "pm1b_cnt"; 1348 size = sc->sc_fadt->pm1_cnt_len; 1349 addr = sc->sc_fadt->pm1b_cnt_blk; 1350 access = 2; 1351 break; 1352 case ACPIREG_PM2_CNT: 1353 name = "pm2_cnt"; 1354 size = sc->sc_fadt->pm2_cnt_len; 1355 addr = sc->sc_fadt->pm2_cnt_blk; 1356 access = size; 1357 break; 1358#if 0 1359 case ACPIREG_PM_TMR: 1360 /* Allocated in acpitimer */ 1361 name = "pm_tmr"; 1362 size = sc->sc_fadt->pm_tmr_len; 1363 addr = sc->sc_fadt->pm_tmr_blk; 1364 access = 4; 1365 break; 1366#endif 1367 case ACPIREG_GPE0_STS: 1368 case ACPIREG_GPE0_EN: 1369 name = "gpe0_sts"; 1370 size = sc->sc_fadt->gpe0_blk_len >> 1; 1371 addr = sc->sc_fadt->gpe0_blk; 1372 access = 1; 1373 1374 dnprintf(20, "gpe0 block len : %x\n", 1375 sc->sc_fadt->gpe0_blk_len >> 1); 1376 dnprintf(20, "gpe0 block addr: %x\n", 1377 sc->sc_fadt->gpe0_blk); 1378 if (reg == ACPIREG_GPE0_EN && addr) { 1379 addr += size; 1380 name = "gpe0_en"; 1381 } 1382 break; 1383 case ACPIREG_GPE1_STS: 1384 case ACPIREG_GPE1_EN: 1385 name = "gpe1_sts"; 1386 size = sc->sc_fadt->gpe1_blk_len >> 1; 1387 addr = sc->sc_fadt->gpe1_blk; 1388 access = 1; 1389 1390 dnprintf(20, "gpe1 block len : %x\n", 1391 sc->sc_fadt->gpe1_blk_len >> 1); 1392 dnprintf(20, "gpe1 block addr: %x\n", 1393 sc->sc_fadt->gpe1_blk); 1394 if (reg == ACPIREG_GPE1_EN && addr) { 1395 addr += size; 1396 name = "gpe1_en"; 1397 } 1398 break; 1399 } 1400 if (size && addr) { 1401 dnprintf(50, "mapping: %.4lx %.4lx %s\n", 1402 addr, size, name); 1403 1404 /* Size and address exist; map register space */ 1405 bus_space_map(sc->sc_iot, addr, size, 0, 1406 &sc->sc_pmregs[reg].ioh); 1407 1408 sc->sc_pmregs[reg].name = name; 1409 sc->sc_pmregs[reg].size = size; 1410 sc->sc_pmregs[reg].addr = addr; 1411 sc->sc_pmregs[reg].access = min(access, 4); 1412 } 1413 } 1414} 1415 1416int 1417acpi_enable(struct acpi_softc *sc) 1418{ 1419 int idx; 1420 1421 acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable); 1422 idx = 0; 1423 do { 1424 if (idx++ > ACPIEN_RETRIES) { 1425 return ETIMEDOUT; 1426 } 1427 } while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN)); 1428 1429 return 0; 1430} 1431 1432void 1433acpi_init_states(struct acpi_softc *sc) 1434{ 1435 struct aml_value res; 1436 char name[8]; 1437 int i; 1438 1439 printf("\n%s: sleep states", DEVNAME(sc)); 1440 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) { 1441 snprintf(name, sizeof(name), "_S%d_", i); 1442 sc->sc_sleeptype[i].slp_typa = -1; 1443 sc->sc_sleeptype[i].slp_typb = -1; 1444 if (aml_evalname(sc, &aml_root, name, 0, NULL, &res) == 0) { 1445 if (res.type == AML_OBJTYPE_PACKAGE) { 1446 sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]); 1447 sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]); 1448 printf(" S%d", i); 1449 } 1450 aml_freevalue(&res); 1451 } 1452 } 1453} 1454 1455/* ACPI Workqueue support */ 1456SIMPLEQ_HEAD(,acpi_taskq) acpi_taskq = 1457 SIMPLEQ_HEAD_INITIALIZER(acpi_taskq); 1458 1459void 1460acpi_addtask(struct acpi_softc *sc, void (*handler)(void *, int), 1461 void *arg0, int arg1) 1462{ 1463 struct acpi_taskq *wq; 1464 int s; 1465 1466 wq = malloc(sizeof(*wq), M_DEVBUF, M_ZERO | M_NOWAIT); 1467 if (wq == NULL) 1468 return; 1469 wq->handler = handler; 1470 wq->arg0 = arg0; 1471 wq->arg1 = arg1; 1472 1473 s = spltty(); 1474 SIMPLEQ_INSERT_TAIL(&acpi_taskq, wq, next); 1475 splx(s); 1476} 1477 1478int 1479acpi_dotask(struct acpi_softc *sc) 1480{ 1481 struct acpi_taskq *wq; 1482 int s; 1483 1484 s = spltty(); 1485 if (SIMPLEQ_EMPTY(&acpi_taskq)) { 1486 splx(s); 1487 1488 /* we don't have anything to do */ 1489 return (0); 1490 } 1491 wq = SIMPLEQ_FIRST(&acpi_taskq); 1492 SIMPLEQ_REMOVE_HEAD(&acpi_taskq, next); 1493 splx(s); 1494 1495 wq->handler(wq->arg0, wq->arg1); 1496 1497 free(wq, M_DEVBUF, 0); 1498 1499 /* We did something */ 1500 return (1); 1501} 1502 1503#ifndef SMALL_KERNEL 1504int 1505is_ata(struct aml_node *node) 1506{ 1507 return (aml_searchname(node, "_GTM") != NULL || 1508 aml_searchname(node, "_GTF") != NULL || 1509 aml_searchname(node, "_STM") != NULL || 1510 aml_searchname(node, "_SDD") != NULL); 1511} 1512 1513int 1514is_ejectable(struct aml_node *node) 1515{ 1516 return (aml_searchname(node, "_EJ0") != NULL); 1517} 1518 1519int 1520is_ejectable_bay(struct aml_node *node) 1521{ 1522 return ((is_ata(node) || is_ata(node->parent)) && is_ejectable(node)); 1523} 1524 1525#if NWD > 0 1526int 1527acpiide_notify(struct aml_node *node, int ntype, void *arg) 1528{ 1529 struct idechnl *ide = arg; 1530 struct acpi_softc *sc = ide->sc; 1531 struct pciide_softc *wsc; 1532 struct device *dev; 1533 int b,d,f; 1534 int64_t sta; 1535 1536 if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta) != 0) 1537 return (0); 1538 1539 dnprintf(10, "IDE notify! %s %d status:%llx\n", aml_nodename(node), 1540 ntype, sta); 1541 1542 /* Walk device list looking for IDE device match */ 1543 TAILQ_FOREACH(dev, &alldevs, dv_list) { 1544 if (strcmp(dev->dv_cfdata->cf_driver->cd_name, "pciide")) 1545 continue; 1546 1547 wsc = (struct pciide_softc *)dev; 1548 pci_decompose_tag(NULL, wsc->sc_tag, &b, &d, &f); 1549 if (b != ACPI_PCI_BUS(ide->addr) || 1550 d != ACPI_PCI_DEV(ide->addr) || 1551 f != ACPI_PCI_FN(ide->addr)) 1552 continue; 1553 dnprintf(10, "Found pciide: %s %x.%x.%x channel:%llx\n", 1554 dev->dv_xname, b,d,f, ide->chnl); 1555 1556 if (sta == 0 && ide->sta) 1557 wdcdetach( 1558 &wsc->pciide_channels[ide->chnl].wdc_channel, 0); 1559 else if (sta && !ide->sta) 1560 wdcattach( 1561 &wsc->pciide_channels[ide->chnl].wdc_channel); 1562 ide->sta = sta; 1563 } 1564 return (0); 1565} 1566 1567int 1568acpi_foundide(struct aml_node *node, void *arg) 1569{ 1570 struct acpi_softc *sc = arg; 1571 struct aml_node *pp; 1572 struct idechnl *ide; 1573 union amlpci_t pi; 1574 int lvl; 1575 1576 /* Check if this is an ejectable bay */ 1577 if (!is_ejectable_bay(node)) 1578 return (0); 1579 1580 ide = malloc(sizeof(struct idechnl), M_DEVBUF, M_NOWAIT | M_ZERO); 1581 ide->sc = sc; 1582 1583 /* GTM/GTF can be at 2/3 levels: pciX.ideX.channelX[.driveX] */ 1584 lvl = 0; 1585 for (pp=node->parent; pp; pp=pp->parent) { 1586 lvl++; 1587 if (aml_searchname(pp, "_HID")) 1588 break; 1589 } 1590 1591 /* Get PCI address and channel */ 1592 if (lvl == 3) { 1593 aml_evalinteger(sc, node->parent, "_ADR", 0, NULL, 1594 &ide->chnl); 1595 aml_rdpciaddr(node->parent->parent, &pi); 1596 ide->addr = pi.addr; 1597 } else if (lvl == 4) { 1598 aml_evalinteger(sc, node->parent->parent, "_ADR", 0, NULL, 1599 &ide->chnl); 1600 aml_rdpciaddr(node->parent->parent->parent, &pi); 1601 ide->addr = pi.addr; 1602 } 1603 dnprintf(10, "%s %llx channel:%llx\n", 1604 aml_nodename(node), ide->addr, ide->chnl); 1605 1606 aml_evalinteger(sc, node, "_STA", 0, NULL, &ide->sta); 1607 dnprintf(10, "Got Initial STA: %llx\n", ide->sta); 1608 1609 aml_register_notify(node, "acpiide", acpiide_notify, ide, 0); 1610 return (0); 1611} 1612#endif /* NWD > 0 */ 1613 1614void 1615acpi_reset(void) 1616{ 1617 u_int32_t reset_as, reset_len; 1618 u_int32_t value; 1619 struct acpi_softc *sc = acpi_softc; 1620 struct acpi_fadt *fadt = sc->sc_fadt; 1621 1622 if (acpi_enabled == 0) 1623 return; 1624 1625 /* 1626 * RESET_REG_SUP is not properly set in some implementations, 1627 * but not testing against it breaks more machines than it fixes 1628 */ 1629 if (fadt->hdr_revision <= 1 || 1630 !(fadt->flags & FADT_RESET_REG_SUP) || fadt->reset_reg.address == 0) 1631 return; 1632 1633 value = fadt->reset_value; 1634 1635 reset_as = fadt->reset_reg.register_bit_width / 8; 1636 if (reset_as == 0) 1637 reset_as = 1; 1638 1639 reset_len = fadt->reset_reg.access_size; 1640 if (reset_len == 0) 1641 reset_len = reset_as; 1642 1643 acpi_gasio(sc, ACPI_IOWRITE, 1644 fadt->reset_reg.address_space_id, 1645 fadt->reset_reg.address, reset_as, reset_len, &value); 1646 1647 delay(100000); 1648} 1649 1650void 1651acpi_gpe_task(void *arg0, int gpe) 1652{ 1653 struct acpi_softc *sc = acpi_softc; 1654 struct gpe_block *pgpe = &sc->gpe_table[gpe]; 1655 1656 dnprintf(10, "handle gpe: %x\n", gpe); 1657 if (pgpe->handler && pgpe->active) { 1658 pgpe->active = 0; 1659 pgpe->handler(sc, gpe, pgpe->arg); 1660 } 1661} 1662 1663void 1664acpi_pbtn_task(void *arg0, int dummy) 1665{ 1666 struct acpi_softc *sc = arg0; 1667 uint16_t en; 1668 int s; 1669 1670 dnprintf(1,"power button pressed\n"); 1671 1672 /* Reset the latch and re-enable the GPE */ 1673 s = spltty(); 1674 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1675 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, 1676 en | ACPI_PM1_PWRBTN_EN); 1677 splx(s); 1678 1679 acpi_addtask(sc, acpi_powerdown_task, sc, 0); 1680} 1681 1682void 1683acpi_sbtn_task(void *arg0, int dummy) 1684{ 1685 struct acpi_softc *sc = arg0; 1686 uint16_t en; 1687 int s; 1688 1689 dnprintf(1,"sleep button pressed\n"); 1690 aml_notify_dev(ACPI_DEV_SBD, 0x80); 1691 1692 /* Reset the latch and re-enable the GPE */ 1693 s = spltty(); 1694 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1695 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, 1696 en | ACPI_PM1_SLPBTN_EN); 1697 splx(s); 1698} 1699 1700void 1701acpi_powerdown_task(void *arg0, int dummy) 1702{ 1703 extern int allowpowerdown; 1704 1705 if (allowpowerdown == 1) { 1706 allowpowerdown = 0; 1707 prsignal(initprocess, SIGUSR2); 1708 } 1709} 1710 1711void 1712acpi_sleep_task(void *arg0, int sleepmode) 1713{ 1714 struct acpi_softc *sc = arg0; 1715 struct acpi_ac *ac; 1716 struct acpi_bat *bat; 1717 1718 /* System goes to sleep here.. */ 1719 acpi_sleep_state(sc, sleepmode); 1720 1721 /* AC and battery information needs refreshing */ 1722 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) 1723 aml_notify(ac->aac_softc->sc_devnode, 1724 0x80); 1725 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) 1726 aml_notify(bat->aba_softc->sc_devnode, 1727 0x80); 1728} 1729 1730int 1731acpi_interrupt(void *arg) 1732{ 1733 struct acpi_softc *sc = (struct acpi_softc *)arg; 1734 u_int32_t processed = 0, idx, jdx; 1735 u_int16_t sts, en; 1736 1737 dnprintf(40, "ACPI Interrupt\n"); 1738 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 1739 sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3); 1740 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, idx>>3); 1741 if (en & sts) { 1742 dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts, 1743 en); 1744 /* Mask the GPE until it is serviced */ 1745 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts); 1746 for (jdx = 0; jdx < 8; jdx++) { 1747 if (en & sts & (1L << jdx)) { 1748 /* Signal this GPE */ 1749 sc->gpe_table[idx+jdx].active = 1; 1750 dnprintf(10, "queue gpe: %x\n", idx+jdx); 1751 acpi_addtask(sc, acpi_gpe_task, NULL, idx+jdx); 1752 1753 /* 1754 * Edge interrupts need their STS bits 1755 * cleared now. Level interrupts will 1756 * have their STS bits cleared just 1757 * before they are re-enabled. 1758 */ 1759 if (sc->gpe_table[idx+jdx].edge) 1760 acpi_write_pmreg(sc, 1761 ACPIREG_GPE_STS, idx>>3, 1762 1L << jdx); 1763 processed = 1; 1764 } 1765 } 1766 } 1767 } 1768 1769 sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0); 1770 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1771 if (sts & en) { 1772 dnprintf(10,"GEN interrupt: %.4x\n", sts & en); 1773 sts &= en; 1774 if (sts & ACPI_PM1_PWRBTN_STS) { 1775 /* Mask and acknowledge */ 1776 en &= ~ACPI_PM1_PWRBTN_EN; 1777 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 1778 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, 1779 ACPI_PM1_PWRBTN_STS); 1780 sts &= ~ACPI_PM1_PWRBTN_STS; 1781 1782 acpi_addtask(sc, acpi_pbtn_task, sc, 0); 1783 } 1784 if (sts & ACPI_PM1_SLPBTN_STS) { 1785 /* Mask and acknowledge */ 1786 en &= ~ACPI_PM1_SLPBTN_EN; 1787 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 1788 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, 1789 ACPI_PM1_SLPBTN_STS); 1790 sts &= ~ACPI_PM1_SLPBTN_STS; 1791 1792 acpi_addtask(sc, acpi_sbtn_task, sc, 0); 1793 } 1794 if (sts) { 1795 printf("%s: PM1 stuck (en 0x%x st 0x%x), clearing\n", 1796 sc->sc_dev.dv_xname, en, sts); 1797 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts); 1798 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, sts); 1799 } 1800 processed = 1; 1801 } 1802 1803 if (processed) { 1804 acpi_wakeup(sc); 1805 } 1806 1807 return (processed); 1808} 1809 1810int 1811acpi_add_device(struct aml_node *node, void *arg) 1812{ 1813 static int nacpicpus = 0; 1814 struct device *self = arg; 1815 struct acpi_softc *sc = arg; 1816 struct acpi_attach_args aaa; 1817#ifdef MULTIPROCESSOR 1818 struct aml_value res; 1819 int proc_id = -1; 1820#endif 1821 1822 memset(&aaa, 0, sizeof(aaa)); 1823 aaa.aaa_node = node; 1824 aaa.aaa_iot = sc->sc_iot; 1825 aaa.aaa_memt = sc->sc_memt; 1826 if (node == NULL || node->value == NULL) 1827 return 0; 1828 1829 switch (node->value->type) { 1830 case AML_OBJTYPE_PROCESSOR: 1831 if (nacpicpus >= ncpus) 1832 return 0; 1833#ifdef MULTIPROCESSOR 1834 if (aml_evalnode(sc, aaa.aaa_node, 0, NULL, &res) == 0) { 1835 if (res.type == AML_OBJTYPE_PROCESSOR) 1836 proc_id = res.v_processor.proc_id; 1837 aml_freevalue(&res); 1838 } 1839 if (proc_id < -1 || proc_id >= LAPIC_MAP_SIZE || 1840 (acpi_lapic_flags[proc_id] & ACPI_PROC_ENABLE) == 0) 1841 return 0; 1842#endif 1843 nacpicpus++; 1844 1845 aaa.aaa_name = "acpicpu"; 1846 break; 1847 case AML_OBJTYPE_THERMZONE: 1848 aaa.aaa_name = "acpitz"; 1849 break; 1850 case AML_OBJTYPE_POWERRSRC: 1851 aaa.aaa_name = "acpipwrres"; 1852 break; 1853 default: 1854 return 0; 1855 } 1856 config_found(self, &aaa, acpi_print); 1857 return 0; 1858} 1859 1860void 1861acpi_enable_onegpe(struct acpi_softc *sc, int gpe) 1862{ 1863 uint8_t mask, en; 1864 1865 /* Read enabled register */ 1866 mask = (1L << (gpe & 7)); 1867 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); 1868 dnprintf(50, "enabling GPE %.2x (current: %sabled) %.2x\n", 1869 gpe, (en & mask) ? "en" : "dis", en); 1870 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask); 1871} 1872 1873/* Clear all GPEs */ 1874void 1875acpi_disable_allgpes(struct acpi_softc *sc) 1876{ 1877 int idx; 1878 1879 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 1880 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx >> 3, 0); 1881 acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx >> 3, -1); 1882 } 1883} 1884 1885/* Enable runtime GPEs */ 1886void 1887acpi_enable_rungpes(struct acpi_softc *sc) 1888{ 1889 int idx; 1890 1891 for (idx = 0; idx < sc->sc_lastgpe; idx++) 1892 if (sc->gpe_table[idx].handler) 1893 acpi_enable_onegpe(sc, idx); 1894} 1895 1896/* Enable wakeup GPEs */ 1897void 1898acpi_enable_wakegpes(struct acpi_softc *sc, int state) 1899{ 1900 struct acpi_wakeq *wentry; 1901 1902 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { 1903 dnprintf(10, "%.4s(S%d) gpe %.2x\n", wentry->q_node->name, 1904 wentry->q_state, 1905 wentry->q_gpe); 1906 if (state <= wentry->q_state) 1907 acpi_enable_onegpe(sc, wentry->q_gpe); 1908 } 1909} 1910 1911int 1912acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler) 1913 (struct acpi_softc *, int, void *), void *arg, int edge) 1914{ 1915 struct gpe_block *ptbl; 1916 1917 ptbl = acpi_find_gpe(sc, gpe); 1918 if (ptbl == NULL || handler == NULL) 1919 return -EINVAL; 1920 if (ptbl->handler != NULL) { 1921 dnprintf(10, "error: GPE %.2x already enabled\n", gpe); 1922 return -EBUSY; 1923 } 1924 dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, edge ? "edge" : "level"); 1925 ptbl->handler = handler; 1926 ptbl->arg = arg; 1927 ptbl->edge = edge; 1928 1929 return (0); 1930} 1931 1932int 1933acpi_gpe(struct acpi_softc *sc, int gpe, void *arg) 1934{ 1935 struct aml_node *node = arg; 1936 uint8_t mask, en; 1937 1938 dnprintf(10, "handling GPE %.2x\n", gpe); 1939 aml_evalnode(sc, node, 0, NULL, NULL); 1940 1941 mask = (1L << (gpe & 7)); 1942 if (!sc->gpe_table[gpe].edge) 1943 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); 1944 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); 1945 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask); 1946 return (0); 1947} 1948 1949/* Discover Devices that can wakeup the system 1950 * _PRW returns a package 1951 * pkg[0] = integer (FADT gpe bit) or package (gpe block,gpe bit) 1952 * pkg[1] = lowest sleep state 1953 * pkg[2+] = power resource devices (optional) 1954 * 1955 * To enable wakeup devices: 1956 * Evaluate _ON method in each power resource device 1957 * Evaluate _PSW method 1958 */ 1959int 1960acpi_foundprw(struct aml_node *node, void *arg) 1961{ 1962 struct acpi_softc *sc = arg; 1963 struct acpi_wakeq *wq; 1964 1965 wq = malloc(sizeof(struct acpi_wakeq), M_DEVBUF, M_NOWAIT | M_ZERO); 1966 if (wq == NULL) 1967 return 0; 1968 1969 wq->q_wakepkg = malloc(sizeof(struct aml_value), M_DEVBUF, 1970 M_NOWAIT | M_ZERO); 1971 if (wq->q_wakepkg == NULL) { 1972 free(wq, M_DEVBUF, 0); 1973 return 0; 1974 } 1975 dnprintf(10, "Found _PRW (%s)\n", node->parent->name); 1976 aml_evalnode(sc, node, 0, NULL, wq->q_wakepkg); 1977 wq->q_node = node->parent; 1978 wq->q_gpe = -1; 1979 1980 /* Get GPE of wakeup device, and lowest sleep level */ 1981 if (wq->q_wakepkg->type == AML_OBJTYPE_PACKAGE && 1982 wq->q_wakepkg->length >= 2) { 1983 if (wq->q_wakepkg->v_package[0]->type == AML_OBJTYPE_INTEGER) 1984 wq->q_gpe = wq->q_wakepkg->v_package[0]->v_integer; 1985 if (wq->q_wakepkg->v_package[1]->type == AML_OBJTYPE_INTEGER) 1986 wq->q_state = wq->q_wakepkg->v_package[1]->v_integer; 1987 } 1988 SIMPLEQ_INSERT_TAIL(&sc->sc_wakedevs, wq, q_next); 1989 return 0; 1990} 1991 1992struct gpe_block * 1993acpi_find_gpe(struct acpi_softc *sc, int gpe) 1994{ 1995 if (gpe >= sc->sc_lastgpe) 1996 return NULL; 1997 return &sc->gpe_table[gpe]; 1998} 1999 2000void 2001acpi_init_gpes(struct acpi_softc *sc) 2002{ 2003 struct aml_node *gpe; 2004 char name[12]; 2005 int idx, ngpe; 2006 2007 sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2; 2008 if (sc->sc_fadt->gpe1_blk_len) { 2009 } 2010 dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe); 2011 2012 /* Allocate GPE table */ 2013 sc->gpe_table = mallocarray(sc->sc_lastgpe, sizeof(struct gpe_block), 2014 M_DEVBUF, M_WAITOK | M_ZERO); 2015 2016 ngpe = 0; 2017 2018 /* Clear GPE status */ 2019 acpi_disable_allgpes(sc); 2020 for (idx = 0; idx < sc->sc_lastgpe; idx++) { 2021 /* Search Level-sensitive GPES */ 2022 snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx); 2023 gpe = aml_searchname(&aml_root, name); 2024 if (gpe != NULL) 2025 acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, 0); 2026 if (gpe == NULL) { 2027 /* Search Edge-sensitive GPES */ 2028 snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx); 2029 gpe = aml_searchname(&aml_root, name); 2030 if (gpe != NULL) 2031 acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, 1); 2032 } 2033 } 2034 aml_find_node(&aml_root, "_PRW", acpi_foundprw, sc); 2035 sc->sc_maxgpe = ngpe; 2036} 2037 2038void 2039acpi_init_pm(struct acpi_softc *sc) 2040{ 2041 sc->sc_tts = aml_searchname(&aml_root, "_TTS"); 2042 sc->sc_pts = aml_searchname(&aml_root, "_PTS"); 2043 sc->sc_wak = aml_searchname(&aml_root, "_WAK"); 2044 sc->sc_bfs = aml_searchname(&aml_root, "_BFS"); 2045 sc->sc_gts = aml_searchname(&aml_root, "_GTS"); 2046 sc->sc_sst = aml_searchname(&aml_root, "_SI_._SST"); 2047} 2048 2049void 2050acpi_sleep_pm(struct acpi_softc *sc, int state) 2051{ 2052 uint16_t rega, regb, regra, regrb; 2053 int retry = 0; 2054 2055 disable_intr(); 2056 2057 /* Clear WAK_STS bit */ 2058 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); 2059 2060 /* Disable BM arbitration at deep sleep and beyond */ 2061 if (state >= ACPI_STATE_S3 && 2062 sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) 2063 acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, ACPI_PM2_ARB_DIS); 2064 2065 /* Write SLP_TYPx values */ 2066 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); 2067 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); 2068 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2069 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2070 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa); 2071 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb); 2072 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 2073 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 2074 2075 /* Loop on WAK_STS, setting the SLP_EN bits once in a while */ 2076 rega |= ACPI_PM1_SLP_EN; 2077 regb |= ACPI_PM1_SLP_EN; 2078 while (1) { 2079 if (retry == 0) { 2080 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 2081 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 2082 } 2083 retry = (retry + 1) % 100000; 2084 2085 regra = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0); 2086 regrb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0); 2087 if ((regra & ACPI_PM1_WAK_STS) || 2088 (regrb & ACPI_PM1_WAK_STS)) 2089 break; 2090 } 2091} 2092 2093void 2094acpi_resume_pm(struct acpi_softc *sc, int fromstate) 2095{ 2096 uint16_t rega, regb, en; 2097 2098 /* Write SLP_TYPx values */ 2099 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); 2100 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); 2101 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2102 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2103 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typa); 2104 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typb); 2105 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 2106 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 2107 2108 /* Force SCI_EN on resume to fix horribly broken machines */ 2109 acpi_write_pmreg(sc, ACPIREG_PM1_CNT, 0, ACPI_PM1_SCI_EN); 2110 2111 /* Clear fixed event status */ 2112 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS); 2113 2114 /* acpica-reference.pdf page 148 says do not call _BFS */ 2115 /* 1st resume AML step: _BFS(fromstate) */ 2116 aml_node_setval(sc, sc->sc_bfs, fromstate); 2117 2118 /* Enable runtime GPEs */ 2119 acpi_disable_allgpes(sc); 2120 acpi_enable_rungpes(sc); 2121 2122 acpi_indicator(sc, ACPI_SST_WAKING); 2123 2124 /* 2nd resume AML step: _WAK(fromstate) */ 2125 aml_node_setval(sc, sc->sc_wak, fromstate); 2126 2127 /* Clear WAK_STS bit */ 2128 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); 2129 2130 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 2131 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) 2132 en |= ACPI_PM1_PWRBTN_EN; 2133 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) 2134 en |= ACPI_PM1_SLPBTN_EN; 2135 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 2136 2137 /* 2138 * If PM2 exists, re-enable BM arbitration (reportedly some 2139 * BIOS forget to) 2140 */ 2141 if (sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) { 2142 rega = acpi_read_pmreg(sc, ACPIREG_PM2_CNT, 0); 2143 rega &= ~ACPI_PM2_ARB_DIS; 2144 acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, rega); 2145 } 2146} 2147 2148/* Set the indicator light to some state */ 2149void 2150acpi_indicator(struct acpi_softc *sc, int led_state) 2151{ 2152 static int save_led_state = -1; 2153 2154 if (save_led_state != led_state) { 2155 aml_node_setval(sc, sc->sc_sst, led_state); 2156 save_led_state = led_state; 2157 } 2158} 2159 2160int 2161acpi_sleep_state(struct acpi_softc *sc, int state) 2162{ 2163 extern int perflevel; 2164 extern int lid_suspend; 2165 int error = ENXIO; 2166 int s; 2167 2168 switch (state) { 2169 case ACPI_STATE_S0: 2170 return (0); 2171 case ACPI_STATE_S1: 2172 return (EOPNOTSUPP); 2173 case ACPI_STATE_S5: /* only sleep states handled here */ 2174 return (EOPNOTSUPP); 2175 } 2176 2177 if (sc->sc_sleeptype[state].slp_typa == -1 || 2178 sc->sc_sleeptype[state].slp_typb == -1) { 2179 printf("%s: state S%d unavailable\n", 2180 sc->sc_dev.dv_xname, state); 2181 return (EOPNOTSUPP); 2182 } 2183 2184 /* 1st suspend AML step: _TTS(tostate) */ 2185 if (aml_node_setval(sc, sc->sc_tts, state) != 0) 2186 goto fail_tts; 2187 acpi_indicator(sc, ACPI_SST_WAKING); /* blink */ 2188 2189#if NWSDISPLAY > 0 2190 /* 2191 * Temporarily release the lock to prevent the X server from 2192 * blocking on setting the display brightness. 2193 */ 2194 rw_exit_write(&sc->sc_lck); 2195 wsdisplay_suspend(); 2196 rw_enter_write(&sc->sc_lck); 2197#endif /* NWSDISPLAY > 0 */ 2198 2199#ifdef HIBERNATE 2200 if (state == ACPI_STATE_S4) { 2201 uvmpd_hibernate(); 2202 hibernate_suspend_bufcache(); 2203 if (hibernate_alloc()) 2204 goto fail_alloc; 2205 } 2206#endif /* HIBERNATE */ 2207 2208 if (config_suspend_all(DVACT_QUIESCE)) 2209 goto fail_quiesce; 2210 2211 bufq_quiesce(); 2212 2213#ifdef MULTIPROCESSOR 2214 acpi_sleep_mp(); 2215#endif 2216 2217 resettodr(); 2218 2219 s = splhigh(); 2220 disable_intr(); /* PSL_I for resume; PIC/APIC broken until repair */ 2221 cold = 1; /* Force other code to delay() instead of tsleep() */ 2222 2223 if (config_suspend_all(DVACT_SUSPEND) != 0) 2224 goto fail_suspend; 2225 acpi_sleep_clocks(sc, state); 2226 2227 suspend_randomness(); 2228 2229 /* 2nd suspend AML step: _PTS(tostate) */ 2230 if (aml_node_setval(sc, sc->sc_pts, state) != 0) 2231 goto fail_pts; 2232 2233 acpibtn_enable_psw(); /* enable _LID for wakeup */ 2234 acpi_indicator(sc, ACPI_SST_SLEEPING); 2235 2236 /* 3rd suspend AML step: _GTS(tostate) */ 2237 aml_node_setval(sc, sc->sc_gts, state); 2238 2239 /* Clear fixed event status */ 2240 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS); 2241 2242 /* Enable wake GPEs */ 2243 acpi_disable_allgpes(sc); 2244 acpi_enable_wakegpes(sc, state); 2245 2246 /* Sleep */ 2247 sc->sc_state = state; 2248 error = acpi_sleep_cpu(sc, state); 2249 sc->sc_state = ACPI_STATE_S0; 2250 /* Resume */ 2251 2252#ifdef HIBERNATE 2253 if (state == ACPI_STATE_S4) { 2254 uvm_pmr_dirty_everything(); 2255 uvm_pmr_zero_everything(); 2256 } 2257#endif /* HIBERNATE */ 2258 2259 acpi_resume_clocks(sc); /* AML may need clocks */ 2260 acpi_resume_pm(sc, state); 2261 acpi_resume_cpu(sc); 2262 2263fail_pts: 2264 config_suspend_all(DVACT_RESUME); 2265 2266fail_suspend: 2267 cold = 0; 2268 enable_intr(); 2269 splx(s); 2270 2271 acpibtn_disable_psw(); /* disable _LID for wakeup */ 2272 inittodr(time_second); 2273 2274 /* 3rd resume AML step: _TTS(runstate) */ 2275 aml_node_setval(sc, sc->sc_tts, sc->sc_state); 2276 2277 resume_randomness(); /* force RNG upper level reseed */ 2278 2279#ifdef MULTIPROCESSOR 2280 acpi_resume_mp(); 2281#endif 2282 2283 bufq_restart(); 2284 2285fail_quiesce: 2286 config_suspend_all(DVACT_WAKEUP); 2287 2288#ifdef HIBERNATE 2289fail_alloc: 2290 if (state == ACPI_STATE_S4) { 2291 hibernate_free(); 2292 hibernate_resume_bufcache(); 2293 } 2294#endif /* HIBERNATE */ 2295 2296#if NWSDISPLAY > 0 2297 rw_exit_write(&sc->sc_lck); 2298 wsdisplay_resume(); 2299 rw_enter_write(&sc->sc_lck); 2300#endif /* NWSDISPLAY > 0 */ 2301 2302 /* Restore hw.setperf */ 2303 if (cpu_setperf != NULL) 2304 cpu_setperf(perflevel); 2305 2306 acpi_record_event(sc, APM_NORMAL_RESUME); 2307 acpi_indicator(sc, ACPI_SST_WORKING); 2308 2309 /* If we woke up but all the lids are closed, go back to sleep */ 2310 if (acpibtn_numopenlids() == 0 && lid_suspend != 0) 2311 acpi_addtask(sc, acpi_sleep_task, sc, state); 2312 2313fail_tts: 2314 return (error); 2315} 2316 2317void 2318acpi_wakeup(void *arg) 2319{ 2320 struct acpi_softc *sc = (struct acpi_softc *)arg; 2321 2322 sc->sc_threadwaiting = 0; 2323 wakeup(sc); 2324} 2325 2326/* XXX 2327 * We are going to do AML execution but are not in the acpi thread. 2328 * We do not know if the acpi thread is sleeping on acpiec in some 2329 * intermediate context. Wish us luck. 2330 */ 2331void 2332acpi_powerdown(void) 2333{ 2334 int state = ACPI_STATE_S5, s; 2335 struct acpi_softc *sc = acpi_softc; 2336 2337 if (acpi_enabled == 0) 2338 return; 2339 2340 s = splhigh(); 2341 disable_intr(); 2342 cold = 1; 2343 2344 /* 1st powerdown AML step: _PTS(tostate) */ 2345 aml_node_setval(sc, sc->sc_pts, state); 2346 2347 acpi_disable_allgpes(sc); 2348 acpi_enable_wakegpes(sc, state); 2349 2350 /* 2nd powerdown AML step: _GTS(tostate) */ 2351 aml_node_setval(sc, sc->sc_gts, state); 2352 2353 acpi_sleep_pm(sc, state); 2354 panic("acpi S5 transition did not happen"); 2355 while (1) 2356 ; 2357} 2358 2359void 2360acpi_thread(void *arg) 2361{ 2362 struct acpi_thread *thread = arg; 2363 struct acpi_softc *sc = thread->sc; 2364 extern int aml_busy; 2365 int s; 2366 2367 /* AML/SMI cannot be trusted -- only run on the BSP */ 2368 sched_peg_curproc(&cpu_info_primary); 2369 2370 rw_enter_write(&sc->sc_lck); 2371 2372 /* 2373 * If we have an interrupt handler, we can get notification 2374 * when certain status bits changes in the ACPI registers, 2375 * so let us enable some events we can forward to userland 2376 */ 2377 if (sc->sc_interrupt) { 2378 int16_t en; 2379 2380 dnprintf(1,"slpbtn:%c pwrbtn:%c\n", 2381 sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y', 2382 sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y'); 2383 dnprintf(10, "Enabling acpi interrupts...\n"); 2384 sc->sc_threadwaiting = 1; 2385 2386 /* Enable Sleep/Power buttons if they exist */ 2387 s = spltty(); 2388 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 2389 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) 2390 en |= ACPI_PM1_PWRBTN_EN; 2391 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) 2392 en |= ACPI_PM1_SLPBTN_EN; 2393 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 2394 2395 /* Enable handled GPEs here */ 2396 acpi_enable_rungpes(sc); 2397 splx(s); 2398 } 2399 2400 while (thread->running) { 2401 s = spltty(); 2402 while (sc->sc_threadwaiting) { 2403 dnprintf(10, "acpi thread going to sleep...\n"); 2404 rw_exit_write(&sc->sc_lck); 2405 tsleep(sc, PWAIT, "acpi0", 0); 2406 rw_enter_write(&sc->sc_lck); 2407 } 2408 sc->sc_threadwaiting = 1; 2409 splx(s); 2410 if (aml_busy) { 2411 panic("thread woke up to find aml was busy"); 2412 continue; 2413 } 2414 2415 /* Run ACPI taskqueue */ 2416 while(acpi_dotask(acpi_softc)) 2417 ; 2418 } 2419 free(thread, M_DEVBUF, 0); 2420 2421 kthread_exit(0); 2422} 2423 2424void 2425acpi_create_thread(void *arg) 2426{ 2427 struct acpi_softc *sc = arg; 2428 2429 if (kthread_create(acpi_thread, sc->sc_thread, NULL, DEVNAME(sc)) 2430 != 0) 2431 printf("%s: unable to create isr thread, GPEs disabled\n", 2432 DEVNAME(sc)); 2433} 2434 2435int 2436acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas, bus_addr_t base, 2437 bus_size_t size, bus_space_handle_t *pioh, bus_space_tag_t *piot) 2438{ 2439 int iospace = GAS_SYSTEM_IOSPACE; 2440 2441 /* No GAS structure, default to I/O space */ 2442 if (gas != NULL) { 2443 base += gas->address; 2444 iospace = gas->address_space_id; 2445 } 2446 switch (iospace) { 2447 case GAS_SYSTEM_MEMORY: 2448 *piot = sc->sc_memt; 2449 break; 2450 case GAS_SYSTEM_IOSPACE: 2451 *piot = sc->sc_iot; 2452 break; 2453 default: 2454 return -1; 2455 } 2456 if (bus_space_map(*piot, base, size, 0, pioh)) 2457 return -1; 2458 2459 return 0; 2460} 2461 2462int 2463acpi_foundec(struct aml_node *node, void *arg) 2464{ 2465 struct acpi_softc *sc = (struct acpi_softc *)arg; 2466 struct device *self = (struct device *)arg; 2467 const char *dev; 2468 struct aml_value res; 2469 struct acpi_attach_args aaa; 2470 2471 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 2472 return 0; 2473 2474 switch (res.type) { 2475 case AML_OBJTYPE_STRING: 2476 dev = res.v_string; 2477 break; 2478 case AML_OBJTYPE_INTEGER: 2479 dev = aml_eisaid(aml_val2int(&res)); 2480 break; 2481 default: 2482 dev = "unknown"; 2483 break; 2484 } 2485 2486 if (strcmp(dev, ACPI_DEV_ECD)) 2487 return 0; 2488 2489 /* Check if we're already attached */ 2490 if (sc->sc_ec && sc->sc_ec->sc_devnode == node->parent) 2491 return 0; 2492 2493 memset(&aaa, 0, sizeof(aaa)); 2494 aaa.aaa_iot = sc->sc_iot; 2495 aaa.aaa_memt = sc->sc_memt; 2496 aaa.aaa_node = node->parent; 2497 aaa.aaa_dev = dev; 2498 aaa.aaa_name = "acpiec"; 2499 config_found(self, &aaa, acpi_print); 2500 aml_freevalue(&res); 2501 2502 return 0; 2503} 2504 2505int 2506acpi_foundhid(struct aml_node *node, void *arg) 2507{ 2508 struct acpi_softc *sc = (struct acpi_softc *)arg; 2509 struct device *self = (struct device *)arg; 2510 const char *dev; 2511 char cdev[16]; 2512 struct aml_value res; 2513 struct acpi_attach_args aaa; 2514 int i; 2515 2516 /* NB aml_eisaid returns a static buffer, this must come first */ 2517 if (aml_evalname(acpi_softc, node->parent, "_CID", 0, NULL, &res) == 0) { 2518 switch (res.type) { 2519 case AML_OBJTYPE_STRING: 2520 dev = res.v_string; 2521 break; 2522 case AML_OBJTYPE_INTEGER: 2523 dev = aml_eisaid(aml_val2int(&res)); 2524 break; 2525 default: 2526 dev = "unknown"; 2527 break; 2528 } 2529 strlcpy(cdev, dev, sizeof(cdev)); 2530 aml_freevalue(&res); 2531 2532 dnprintf(10, "compatible with device: %s\n", cdev); 2533 } else { 2534 cdev[0] = '\0'; 2535 } 2536 2537 dnprintf(10, "found hid device: %s ", node->parent->name); 2538 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 2539 return 0; 2540 2541 switch (res.type) { 2542 case AML_OBJTYPE_STRING: 2543 dev = res.v_string; 2544 break; 2545 case AML_OBJTYPE_INTEGER: 2546 dev = aml_eisaid(aml_val2int(&res)); 2547 break; 2548 default: 2549 dev = "unknown"; 2550 break; 2551 } 2552 dnprintf(10, " device: %s\n", dev); 2553 2554 memset(&aaa, 0, sizeof(aaa)); 2555 aaa.aaa_iot = sc->sc_iot; 2556 aaa.aaa_memt = sc->sc_memt; 2557 aaa.aaa_node = node->parent; 2558 aaa.aaa_dev = dev; 2559 2560 if (!strcmp(dev, ACPI_DEV_AC)) 2561 aaa.aaa_name = "acpiac"; 2562 else if (!strcmp(dev, ACPI_DEV_CMB)) 2563 aaa.aaa_name = "acpibat"; 2564 else if (!strcmp(dev, ACPI_DEV_LD) || 2565 !strcmp(dev, ACPI_DEV_PBD) || 2566 !strcmp(dev, ACPI_DEV_SBD)) 2567 aaa.aaa_name = "acpibtn"; 2568 else if (!strcmp(dev, ACPI_DEV_ASUS) || !strcmp(dev, ACPI_DEV_ASUS1)) { 2569 aaa.aaa_name = "acpiasus"; 2570 acpi_asus_enabled = 1; 2571 } else if (!strcmp(dev, ACPI_DEV_IBM) || 2572 !strcmp(dev, ACPI_DEV_LENOVO)) { 2573 aaa.aaa_name = "acpithinkpad"; 2574 acpi_thinkpad_enabled = 1; 2575 } else if (!strcmp(dev, ACPI_DEV_ASUSAIBOOSTER)) 2576 aaa.aaa_name = "aibs"; 2577 else if (!strcmp(dev, ACPI_DEV_TOSHIBA_LIBRETTO) || 2578 !strcmp(dev, ACPI_DEV_TOSHIBA_DYNABOOK) || 2579 !strcmp(dev, ACPI_DEV_TOSHIBA_SPA40)) { 2580 aaa.aaa_name = "acpitoshiba"; 2581 acpi_toshiba_enabled = 1; 2582 } 2583 2584 if (!strcmp(cdev, ACPI_DEV_MOUSE)) { 2585 for (i = 0; i < nitems(sbtn_pnp); i++) { 2586 if (!strcmp(dev, sbtn_pnp[i])) { 2587 mouse_has_softbtn = 1; 2588 break; 2589 } 2590 } 2591 } 2592 2593 if (aaa.aaa_name) 2594 config_found(self, &aaa, acpi_print); 2595 2596 aml_freevalue(&res); 2597 2598 return 0; 2599} 2600 2601int 2602acpi_founddock(struct aml_node *node, void *arg) 2603{ 2604 struct acpi_softc *sc = (struct acpi_softc *)arg; 2605 struct device *self = (struct device *)arg; 2606 struct acpi_attach_args aaa; 2607 2608 dnprintf(10, "found dock entry: %s\n", node->parent->name); 2609 2610 memset(&aaa, 0, sizeof(aaa)); 2611 aaa.aaa_iot = sc->sc_iot; 2612 aaa.aaa_memt = sc->sc_memt; 2613 aaa.aaa_node = node->parent; 2614 aaa.aaa_name = "acpidock"; 2615 2616 config_found(self, &aaa, acpi_print); 2617 2618 return 0; 2619} 2620 2621int 2622acpi_foundvideo(struct aml_node *node, void *arg) 2623{ 2624 struct acpi_softc *sc = (struct acpi_softc *)arg; 2625 struct device *self = (struct device *)arg; 2626 struct acpi_attach_args aaa; 2627 2628 memset(&aaa, 0, sizeof(aaa)); 2629 aaa.aaa_iot = sc->sc_iot; 2630 aaa.aaa_memt = sc->sc_memt; 2631 aaa.aaa_node = node->parent; 2632 aaa.aaa_name = "acpivideo"; 2633 2634 config_found(self, &aaa, acpi_print); 2635 2636 return (0); 2637} 2638 2639int 2640acpi_foundsony(struct aml_node *node, void *arg) 2641{ 2642 struct acpi_softc *sc = (struct acpi_softc *)arg; 2643 struct device *self = (struct device *)arg; 2644 struct acpi_attach_args aaa; 2645 2646 memset(&aaa, 0, sizeof(aaa)); 2647 aaa.aaa_iot = sc->sc_iot; 2648 aaa.aaa_memt = sc->sc_memt; 2649 aaa.aaa_node = node->parent; 2650 aaa.aaa_name = "acpisony"; 2651 2652 config_found(self, &aaa, acpi_print); 2653 2654 return 0; 2655} 2656 2657int 2658acpiopen(dev_t dev, int flag, int mode, struct proc *p) 2659{ 2660 int error = 0; 2661 struct acpi_softc *sc; 2662 int s; 2663 2664 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 2665 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 2666 return (ENXIO); 2667 2668 s = spltty(); 2669 switch (APMDEV(dev)) { 2670 case APMDEV_CTL: 2671 if (!(flag & FWRITE)) { 2672 error = EINVAL; 2673 break; 2674 } 2675 if (sc->sc_flags & SCFLAG_OWRITE) { 2676 error = EBUSY; 2677 break; 2678 } 2679 sc->sc_flags |= SCFLAG_OWRITE; 2680 break; 2681 case APMDEV_NORMAL: 2682 if (!(flag & FREAD) || (flag & FWRITE)) { 2683 error = EINVAL; 2684 break; 2685 } 2686 sc->sc_flags |= SCFLAG_OREAD; 2687 break; 2688 default: 2689 error = ENXIO; 2690 break; 2691 } 2692 splx(s); 2693 return (error); 2694} 2695 2696int 2697acpiclose(dev_t dev, int flag, int mode, struct proc *p) 2698{ 2699 int error = 0; 2700 struct acpi_softc *sc; 2701 int s; 2702 2703 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 2704 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 2705 return (ENXIO); 2706 2707 s = spltty(); 2708 switch (APMDEV(dev)) { 2709 case APMDEV_CTL: 2710 sc->sc_flags &= ~SCFLAG_OWRITE; 2711 break; 2712 case APMDEV_NORMAL: 2713 sc->sc_flags &= ~SCFLAG_OREAD; 2714 break; 2715 default: 2716 error = ENXIO; 2717 break; 2718 } 2719 splx(s); 2720 return (error); 2721} 2722 2723int 2724acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 2725{ 2726 int error = 0; 2727 struct acpi_softc *sc; 2728 struct acpi_ac *ac; 2729 struct acpi_bat *bat; 2730 struct apm_power_info *pi = (struct apm_power_info *)data; 2731 int bats; 2732 unsigned int remaining, rem, minutes, rate; 2733 int s; 2734 2735 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 2736 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 2737 return (ENXIO); 2738 2739 s = spltty(); 2740 /* fake APM */ 2741 switch (cmd) { 2742 case APM_IOC_SUSPEND: 2743 case APM_IOC_STANDBY: 2744 if ((flag & FWRITE) == 0) { 2745 error = EBADF; 2746 break; 2747 } 2748 acpi_addtask(sc, acpi_sleep_task, sc, ACPI_STATE_S3); 2749 acpi_wakeup(sc); 2750 break; 2751#ifdef HIBERNATE 2752 case APM_IOC_HIBERNATE: 2753 if ((error = suser(p, 0)) != 0) 2754 break; 2755 if ((flag & FWRITE) == 0) { 2756 error = EBADF; 2757 break; 2758 } 2759 if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL) { 2760 error = EOPNOTSUPP; 2761 break; 2762 } 2763 acpi_addtask(sc, acpi_sleep_task, sc, ACPI_STATE_S4); 2764 acpi_wakeup(sc); 2765 break; 2766#endif 2767 case APM_IOC_GETPOWER: 2768 /* A/C */ 2769 pi->ac_state = APM_AC_UNKNOWN; 2770 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) { 2771 if (ac->aac_softc->sc_ac_stat == PSR_ONLINE) 2772 pi->ac_state = APM_AC_ON; 2773 else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE) 2774 if (pi->ac_state == APM_AC_UNKNOWN) 2775 pi->ac_state = APM_AC_OFF; 2776 } 2777 2778 /* battery */ 2779 pi->battery_state = APM_BATT_UNKNOWN; 2780 pi->battery_life = 0; 2781 pi->minutes_left = 0; 2782 bats = 0; 2783 remaining = rem = 0; 2784 minutes = 0; 2785 rate = 0; 2786 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) { 2787 if (bat->aba_softc->sc_bat_present == 0) 2788 continue; 2789 2790 if (bat->aba_softc->sc_bif.bif_last_capacity == 0) 2791 continue; 2792 2793 bats++; 2794 rem = (bat->aba_softc->sc_bst.bst_capacity * 100) / 2795 bat->aba_softc->sc_bif.bif_last_capacity; 2796 if (rem > 100) 2797 rem = 100; 2798 remaining += rem; 2799 2800 if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN) 2801 continue; 2802 else if (bat->aba_softc->sc_bst.bst_rate > 1) 2803 rate = bat->aba_softc->sc_bst.bst_rate; 2804 2805 minutes += bat->aba_softc->sc_bst.bst_capacity; 2806 } 2807 2808 if (bats == 0) { 2809 pi->battery_state = APM_BATTERY_ABSENT; 2810 pi->battery_life = 0; 2811 pi->minutes_left = (unsigned int)-1; 2812 break; 2813 } 2814 2815 if (pi->ac_state == APM_AC_ON || rate == 0) 2816 pi->minutes_left = (unsigned int)-1; 2817 else 2818 pi->minutes_left = 60 * minutes / rate; 2819 2820 /* running on battery */ 2821 pi->battery_life = remaining / bats; 2822 if (pi->battery_life > 50) 2823 pi->battery_state = APM_BATT_HIGH; 2824 else if (pi->battery_life > 25) 2825 pi->battery_state = APM_BATT_LOW; 2826 else 2827 pi->battery_state = APM_BATT_CRITICAL; 2828 2829 break; 2830 2831 default: 2832 error = ENOTTY; 2833 } 2834 2835 splx(s); 2836 return (error); 2837} 2838 2839void acpi_filtdetach(struct knote *); 2840int acpi_filtread(struct knote *, long); 2841 2842struct filterops acpiread_filtops = { 2843 1, NULL, acpi_filtdetach, acpi_filtread 2844}; 2845 2846int acpi_evindex; 2847 2848int 2849acpi_record_event(struct acpi_softc *sc, u_int type) 2850{ 2851 if ((sc->sc_flags & SCFLAG_OPEN) == 0) 2852 return (1); 2853 2854 acpi_evindex++; 2855 KNOTE(sc->sc_note, APM_EVENT_COMPOSE(type, acpi_evindex)); 2856 return (0); 2857} 2858 2859void 2860acpi_filtdetach(struct knote *kn) 2861{ 2862 struct acpi_softc *sc = kn->kn_hook; 2863 int s; 2864 2865 s = spltty(); 2866 SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext); 2867 splx(s); 2868} 2869 2870int 2871acpi_filtread(struct knote *kn, long hint) 2872{ 2873 /* XXX weird kqueue_scan() semantics */ 2874 if (hint && !kn->kn_data) 2875 kn->kn_data = hint; 2876 return (1); 2877} 2878 2879int 2880acpikqfilter(dev_t dev, struct knote *kn) 2881{ 2882 struct acpi_softc *sc; 2883 int s; 2884 2885 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 2886 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 2887 return (ENXIO); 2888 2889 switch (kn->kn_filter) { 2890 case EVFILT_READ: 2891 kn->kn_fop = &acpiread_filtops; 2892 break; 2893 default: 2894 return (EINVAL); 2895 } 2896 2897 kn->kn_hook = sc; 2898 2899 s = spltty(); 2900 SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext); 2901 splx(s); 2902 2903 return (0); 2904} 2905 2906#else /* SMALL_KERNEL */ 2907 2908int 2909acpiopen(dev_t dev, int flag, int mode, struct proc *p) 2910{ 2911 return (ENXIO); 2912} 2913 2914int 2915acpiclose(dev_t dev, int flag, int mode, struct proc *p) 2916{ 2917 return (ENXIO); 2918} 2919 2920int 2921acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 2922{ 2923 return (ENXIO); 2924} 2925 2926int 2927acpikqfilter(dev_t dev, struct knote *kn) 2928{ 2929 return (ENXIO); 2930} 2931#endif /* SMALL_KERNEL */ 2932