acpi.c revision 1.115
1/* $OpenBSD: acpi.c,v 1.115 2008/04/24 13:57:49 jsing 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/device.h> 22#include <sys/malloc.h> 23#include <sys/fcntl.h> 24#include <sys/ioccom.h> 25#include <sys/event.h> 26#include <sys/signalvar.h> 27#include <sys/proc.h> 28#include <sys/kthread.h> 29 30#include <machine/conf.h> 31#include <machine/cpufunc.h> 32#include <machine/bus.h> 33 34#include <dev/pci/pcivar.h> 35#include <dev/acpi/acpireg.h> 36#include <dev/acpi/acpivar.h> 37#include <dev/acpi/amltypes.h> 38#include <dev/acpi/acpidev.h> 39#include <dev/acpi/dsdt.h> 40 41#include <machine/apmvar.h> 42#define APMUNIT(dev) (minor(dev)&0xf0) 43#define APMDEV(dev) (minor(dev)&0x0f) 44#define APMDEV_NORMAL 0 45#define APMDEV_CTL 8 46 47#ifdef ACPI_DEBUG 48int acpi_debug = 16; 49#endif 50int acpi_enabled; 51int acpi_poll_enabled; 52int acpi_hasprocfvs; 53 54#define ACPIEN_RETRIES 15 55 56void acpi_isr_thread(void *); 57void acpi_create_thread(void *); 58 59int acpi_match(struct device *, void *, void *); 60void acpi_attach(struct device *, struct device *, void *); 61int acpi_submatch(struct device *, void *, void *); 62int acpi_print(void *, const char *); 63 64void acpi_map_pmregs(struct acpi_softc *); 65 66int acpi_founddock(struct aml_node *, void *); 67int acpi_foundpss(struct aml_node *, void *); 68int acpi_foundhid(struct aml_node *, void *); 69int acpi_foundec(struct aml_node *, void *); 70int acpi_foundtmp(struct aml_node *, void *); 71int acpi_foundprt(struct aml_node *, void *); 72int acpi_foundprw(struct aml_node *, void *); 73int acpi_inidev(struct aml_node *, void *); 74 75int acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *); 76void acpi_load_table(paddr_t, size_t, acpi_qhead_t *); 77void acpi_load_dsdt(paddr_t, struct acpi_q **); 78 79void acpi_init_states(struct acpi_softc *); 80void acpi_init_gpes(struct acpi_softc *); 81void acpi_init_pm(struct acpi_softc *); 82 83void acpi_filtdetach(struct knote *); 84int acpi_filtread(struct knote *, long); 85 86void acpi_enable_onegpe(struct acpi_softc *, int, int); 87int acpi_gpe_level(struct acpi_softc *, int, void *); 88int acpi_gpe_edge(struct acpi_softc *, int, void *); 89 90#define ACPI_LOCK(sc) 91#define ACPI_UNLOCK(sc) 92 93/* XXX move this into dsdt softc at some point */ 94extern struct aml_node aml_root; 95 96struct filterops acpiread_filtops = { 97 1, NULL, acpi_filtdetach, acpi_filtread 98}; 99 100struct cfattach acpi_ca = { 101 sizeof(struct acpi_softc), acpi_match, acpi_attach 102}; 103 104struct cfdriver acpi_cd = { 105 NULL, "acpi", DV_DULL 106}; 107 108struct acpi_softc *acpi_softc; 109int acpi_evindex; 110 111#define acpi_bus_space_map _bus_space_map 112#define acpi_bus_space_unmap _bus_space_unmap 113 114#define pch(x) (((x)>=' ' && (x)<='z') ? (x) : ' ') 115 116void 117acpi_delay(struct acpi_softc *sc, int64_t uSecs) 118{ 119 /* XXX this needs to become a tsleep later */ 120 delay(uSecs); 121} 122 123int 124acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, 125 int access_size, int len, void *buffer) 126{ 127 u_int8_t *pb; 128 bus_space_handle_t ioh; 129 struct acpi_mem_map mh; 130 pci_chipset_tag_t pc; 131 pcitag_t tag; 132 bus_addr_t ioaddr; 133 int reg, idx, ival, sval; 134 135 dnprintf(50, "gasio: %.2x 0x%.8llx %s\n", 136 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); 137 138 pb = (u_int8_t *)buffer; 139 switch (iospace) { 140 case GAS_SYSTEM_MEMORY: 141 /* copy to/from system memory */ 142 acpi_map(address, len, &mh); 143 if (iodir == ACPI_IOREAD) 144 memcpy(buffer, mh.va, len); 145 else 146 memcpy(mh.va, buffer, len); 147 acpi_unmap(&mh); 148 break; 149 150 case GAS_SYSTEM_IOSPACE: 151 /* read/write from I/O registers */ 152 ioaddr = address; 153 if (acpi_bus_space_map(sc->sc_iot, ioaddr, len, 0, &ioh) != 0) { 154 printf("unable to map iospace\n"); 155 return (-1); 156 } 157 for (reg = 0; reg < len; reg += access_size) { 158 if (iodir == ACPI_IOREAD) { 159 switch (access_size) { 160 case 1: 161 *(uint8_t *)(pb+reg) = bus_space_read_1( 162 sc->sc_iot, ioh, reg); 163 dnprintf(80, "os_in8(%llx) = %x\n", 164 reg+address, *(uint8_t *)(pb+reg)); 165 break; 166 case 2: 167 *(uint16_t *)(pb+reg) = bus_space_read_2( 168 sc->sc_iot, ioh, reg); 169 dnprintf(80, "os_in16(%llx) = %x\n", 170 reg+address, *(uint16_t *)(pb+reg)); 171 break; 172 case 4: 173 *(uint32_t *)(pb+reg) = bus_space_read_4( 174 sc->sc_iot, ioh, reg); 175 break; 176 } 177 } else { 178 switch (access_size) { 179 case 1: 180 bus_space_write_1(sc->sc_iot, ioh, reg, 181 *(uint8_t *)(pb+reg)); 182 dnprintf(80, "os_out8(%llx,%x)\n", 183 reg+address, *(uint8_t *)(pb+reg)); 184 break; 185 case 2: 186 bus_space_write_2(sc->sc_iot, ioh, reg, 187 *(uint16_t *)(pb+reg)); 188 dnprintf(80, "os_out16(%llx,%x)\n", 189 reg+address, *(uint16_t *)(pb+reg)); 190 break; 191 case 4: 192 bus_space_write_4(sc->sc_iot, ioh, reg, 193 *(uint32_t *)(pb+reg)); 194 break; 195 } 196 } 197 198 /* During autoconf some devices are still gathering 199 * information. Delay here to give them an opportunity 200 * to finish. During runtime we simply need to ignore 201 * transient values. 202 */ 203 if (cold) 204 delay(10000); 205 } 206 acpi_bus_space_unmap(sc->sc_iot, ioh, len, &ioaddr); 207 break; 208 209 case GAS_PCI_CFG_SPACE: 210 /* format of address: 211 * bits 00..15 = register 212 * bits 16..31 = function 213 * bits 32..47 = device 214 * bits 48..63 = bus 215 */ 216 pc = NULL; 217 tag = pci_make_tag(pc, 218 ACPI_PCI_BUS(address), ACPI_PCI_DEV(address), 219 ACPI_PCI_FN(address)); 220 221 /* XXX: This is ugly. read-modify-write does a byte at a time */ 222 reg = ACPI_PCI_REG(address); 223 for (idx = reg; idx < reg+len; idx++) { 224 ival = pci_conf_read(pc, tag, idx & ~0x3); 225 if (iodir == ACPI_IOREAD) { 226 *pb = ival >> (8 * (idx & 0x3)); 227 } else { 228 sval = *pb; 229 ival &= ~(0xFF << (8* (idx & 0x3))); 230 ival |= sval << (8* (idx & 0x3)); 231 pci_conf_write(pc, tag, idx & ~0x3, ival); 232 } 233 pb++; 234 } 235 break; 236 case GAS_EMBEDDED: 237 if (sc->sc_ec == NULL) 238 break; 239#ifndef SMALL_KERNEL 240 if (iodir == ACPI_IOREAD) 241 acpiec_read(sc->sc_ec, (u_int8_t)address, len, buffer); 242 else 243 acpiec_write(sc->sc_ec, (u_int8_t)address, len, buffer); 244#endif 245 break; 246 } 247 return (0); 248} 249 250int 251acpi_inidev(struct aml_node *node, void *arg) 252{ 253 struct acpi_softc *sc = (struct acpi_softc *)arg; 254 struct aml_value res; 255 int st = 0; 256 257 /* Default value */ 258 st = STA_PRESENT|STA_ENABLED; 259 st |= STA_SHOW_UI|STA_DEV_OK; 260 st |= STA_BATTERY; 261 262 /* 263 * Per the ACPI spec 6.5.1, only run _INI when device is there or 264 * when there is no _STA. We terminate the tree walk (with return 1) 265 * early if necessary. 266 */ 267 268 /* Evaluate _STA to decide _INI fate and walk fate */ 269 if (!aml_evalname(sc, node, "_STA", 0, NULL, &res)) 270 st = (int)aml_val2int(&res); 271 aml_freevalue(&res); 272 273 /* Evaluate _INI if we are present */ 274 if (st & STA_PRESENT) 275 aml_evalnode(sc, node, 0, NULL, NULL); 276 277 /* If we are functioning, we walk/search our children */ 278 if(st & STA_DEV_OK) 279 return 0; 280 281 /* If we are not enabled, or not present, terminate search */ 282 if (!(st & (STA_PRESENT|STA_ENABLED))) 283 return 1; 284 285 /* Default just continue search */ 286 return 0; 287} 288 289int 290acpi_foundprt(struct aml_node *node, void *arg) 291{ 292 struct acpi_softc *sc = (struct acpi_softc *)arg; 293 struct device *self = (struct device *)arg; 294 const char *dev; 295 struct acpi_attach_args aaa; 296 struct aml_value res; 297 int st = 0; 298 299 dnprintf(10, "found prt entry: %s\n", node->parent->name); 300 301 /* Default value */ 302 st = STA_PRESENT|STA_ENABLED; 303 st |= STA_SHOW_UI|STA_DEV_OK; 304 st |= STA_BATTERY; 305 306 /* Evaluate _STA to decide _PRT fate and walk fate */ 307 if (!aml_evalname(sc, node, "_STA", 0, NULL, &res)) 308 st = (int)aml_val2int(&res); 309 aml_freevalue(&res); 310 311 if (st & STA_PRESENT) { 312 memset(&aaa, 0, sizeof(aaa)); 313 aaa.aaa_iot = sc->sc_iot; 314 aaa.aaa_memt = sc->sc_memt; 315 aaa.aaa_node = node; 316 aaa.aaa_dev = dev; 317 aaa.aaa_name = "acpiprt"; 318 319 config_found(self, &aaa, acpi_print); 320 } 321 322 /* If we are functioning, we walk/search our children */ 323 if(st & STA_DEV_OK) 324 return 0; 325 326 /* If we are not enabled, or not present, terminate search */ 327 if (!(st & (STA_PRESENT|STA_ENABLED))) 328 return 1; 329 330 /* Default just continue search */ 331 return 0; 332} 333 334int 335acpi_match(struct device *parent, void *match, void *aux) 336{ 337 struct bios_attach_args *ba = aux; 338 struct cfdata *cf = match; 339 340 /* sanity */ 341 if (strcmp(ba->ba_name, cf->cf_driver->cd_name)) 342 return (0); 343 344 if (!acpi_probe(parent, cf, ba)) 345 return (0); 346 347 return (1); 348} 349 350int acpi_add_device(struct aml_node *node, void *arg); 351 352int 353acpi_add_device(struct aml_node *node, void *arg) 354{ 355 static int nacpicpus = 0; 356 struct device *self = arg; 357 struct acpi_softc *sc = arg; 358 struct acpi_attach_args aaa; 359#ifdef MULTIPROCESSOR 360 struct aml_value res; 361 int proc_id = -1; 362#endif 363 364 memset(&aaa, 0, sizeof(aaa)); 365 aaa.aaa_node = node; 366 aaa.aaa_dev = ""; 367 aaa.aaa_iot = sc->sc_iot; 368 aaa.aaa_memt = sc->sc_memt; 369 if (node == NULL || node->value == NULL) 370 return 0; 371 372 switch (node->value->type) { 373 case AML_OBJTYPE_PROCESSOR: 374 if (nacpicpus >= ncpus) 375 return 0; 376#ifdef MULTIPROCESSOR 377 if (aml_evalnode(sc, aaa.aaa_node, 0, NULL, &res) == 0) { 378 if (res.type == AML_OBJTYPE_PROCESSOR) 379 proc_id = res.v_processor.proc_id; 380 aml_freevalue(&res); 381 } 382 if (proc_id < -1 || proc_id >= LAPIC_MAP_SIZE || 383 (acpi_lapic_flags[proc_id] & ACPI_PROC_ENABLE) == 0) 384 return 0; 385#endif 386 nacpicpus++; 387 388 aaa.aaa_name = "acpicpu"; 389 break; 390 case AML_OBJTYPE_THERMZONE: 391 aaa.aaa_name = "acpitz"; 392 break; 393 default: 394 return 0; 395 } 396 config_found(self, &aaa, acpi_print); 397 return 0; 398} 399 400void 401acpi_attach(struct device *parent, struct device *self, void *aux) 402{ 403 struct bios_attach_args *ba = aux; 404 struct acpi_softc *sc = (struct acpi_softc *)self; 405 struct acpi_mem_map handle; 406 struct acpi_rsdp *rsdp; 407 struct acpi_q *entry; 408 struct acpi_wakeq *wentry; 409 struct acpi_dsdt *p_dsdt; 410#ifndef SMALL_KERNEL 411 struct device *dev; 412 struct acpi_ac *ac; 413 struct acpi_bat *bat; 414#endif 415 paddr_t facspa; 416 417 sc->sc_iot = ba->ba_iot; 418 sc->sc_memt = ba->ba_memt; 419 420 if (acpi_map(ba->ba_acpipbase, sizeof(struct acpi_rsdp), &handle)) { 421 printf(": can't map memory\n"); 422 return; 423 } 424 425 rsdp = (struct acpi_rsdp *)handle.va; 426 sc->sc_revision = (int)rsdp->rsdp_revision; 427 printf(": rev %d", sc->sc_revision); 428 429 SIMPLEQ_INIT(&sc->sc_tables); 430 SIMPLEQ_INIT(&sc->sc_wakedevs); 431 432 sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT | M_ZERO); 433 if (sc->sc_note == NULL) { 434 printf(", can't allocate memory\n"); 435 acpi_unmap(&handle); 436 return; 437 } 438 439 if (acpi_loadtables(sc, rsdp)) { 440 printf(", can't load tables\n"); 441 acpi_unmap(&handle); 442 return; 443 } 444 445 acpi_unmap(&handle); 446 447 /* 448 * Find the FADT 449 */ 450 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 451 if (memcmp(entry->q_table, FADT_SIG, 452 sizeof(FADT_SIG) - 1) == 0) { 453 sc->sc_fadt = entry->q_table; 454 break; 455 } 456 } 457 if (sc->sc_fadt == NULL) { 458 printf(", no FADT\n"); 459 return; 460 } 461 462 /* 463 * Check if we are able to enable ACPI control 464 */ 465 if (!sc->sc_fadt->smi_cmd || 466 (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) { 467 printf(", ACPI control unavailable\n"); 468 return; 469 } 470 471 /* 472 * Set up a pointer to the firmware control structure 473 */ 474 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0) 475 facspa = sc->sc_fadt->firmware_ctl; 476 else 477 facspa = sc->sc_fadt->x_firmware_ctl; 478 479 if (acpi_map(facspa, sizeof(struct acpi_facs), &handle)) 480 printf(" !FACS"); 481 else 482 sc->sc_facs = (struct acpi_facs *)handle.va; 483 484 acpi_enabled = 1; 485 486 /* Create opcode hashtable */ 487 aml_hashopcodes(); 488 489 /* Create Default AML objects */ 490 aml_create_defaultobjects(); 491 492 /* 493 * Load the DSDT from the FADT pointer -- use the 494 * extended (64-bit) pointer if it exists 495 */ 496 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0) 497 acpi_load_dsdt(sc->sc_fadt->dsdt, &entry); 498 else 499 acpi_load_dsdt(sc->sc_fadt->x_dsdt, &entry); 500 501 if (entry == NULL) 502 printf(" !DSDT"); 503 SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, q_next); 504 505 p_dsdt = entry->q_table; 506 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 507 sizeof(p_dsdt->hdr)); 508 509 /* Load SSDT's */ 510 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 511 if (memcmp(entry->q_table, SSDT_SIG, 512 sizeof(SSDT_SIG) - 1) == 0) { 513 p_dsdt = entry->q_table; 514 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 515 sizeof(p_dsdt->hdr)); 516 } 517 } 518 519 /* Perform post-parsing fixups */ 520 aml_postparse(); 521 522#ifndef SMALL_KERNEL 523 /* Find available sleeping states */ 524 acpi_init_states(sc); 525 526 /* Find available sleep/resume related methods. */ 527 acpi_init_pm(sc); 528 529 /* Map Power Management registers */ 530 acpi_map_pmregs(sc); 531 532 /* Initialize GPE handlers */ 533 acpi_init_gpes(sc); 534 535 /* some devices require periodic polling */ 536 timeout_set(&sc->sc_dev_timeout, acpi_poll, sc); 537#endif /* SMALL_KERNEL */ 538 539 /* 540 * Take over ACPI control. Note that once we do this, we 541 * effectively tell the system that we have ownership of 542 * the ACPI hardware registers, and that SMI should leave 543 * them alone 544 * 545 * This may prevent thermal control on some systems where 546 * that actually does work 547 */ 548 int idx; 549 550 acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable); 551 idx = 0; 552 do { 553 if (idx++ > ACPIEN_RETRIES) { 554 printf(", can't enable ACPI\n"); 555 return; 556 } 557 } while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN)); 558 559 printf("\n"); 560 561 printf("%s: tables", DEVNAME(sc)); 562 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 563 printf(" %.4s", entry->q_table); 564 } 565 printf("\n"); 566 567 /* Display wakeup devices and lowest S-state */ 568 printf("%s: wakeup devices", DEVNAME(sc)); 569 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { 570 printf(" %.4s(S%d)", wentry->q_node->name, 571 wentry->q_state); 572 } 573 printf("\n"); 574 575 576#ifndef SMALL_KERNEL 577 /* 578 * ACPI is enabled now -- attach timer 579 */ 580 { 581 struct acpi_attach_args aaa; 582 583 memset(&aaa, 0, sizeof(aaa)); 584 aaa.aaa_name = "acpitimer"; 585 aaa.aaa_iot = sc->sc_iot; 586 aaa.aaa_memt = sc->sc_memt; 587#if 0 588 aaa.aaa_pcit = sc->sc_pcit; 589 aaa.aaa_smbust = sc->sc_smbust; 590#endif 591 config_found(self, &aaa, acpi_print); 592 } 593#endif /* SMALL_KERNEL */ 594 595 /* 596 * Attach table-defined devices 597 */ 598 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 599 struct acpi_attach_args aaa; 600 601 memset(&aaa, 0, sizeof(aaa)); 602 aaa.aaa_iot = sc->sc_iot; 603 aaa.aaa_memt = sc->sc_memt; 604 #if 0 605 aaa.aaa_pcit = sc->sc_pcit; 606 aaa.aaa_smbust = sc->sc_smbust; 607 #endif 608 aaa.aaa_table = entry->q_table; 609 config_found_sm(self, &aaa, acpi_print, acpi_submatch); 610 } 611 612 acpi_softc = sc; 613 614 /* initialize runtime environment */ 615 aml_find_node(aml_root.child, "_INI", acpi_inidev, sc); 616 617 /* attach pci interrupt routing tables */ 618 aml_find_node(aml_root.child, "_PRT", acpi_foundprt, sc); 619 620#ifndef SMALL_KERNEL 621 /* XXX EC needs to be attached first on some systems */ 622 aml_find_node(aml_root.child, "_HID", acpi_foundec, sc); 623 624 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc); 625 626 /* attach battery, power supply and button devices */ 627 aml_find_node(aml_root.child, "_HID", acpi_foundhid, sc); 628 629 /* attach docks */ 630 aml_find_node(aml_root.child, "_DCK", acpi_founddock, sc); 631 632 /* create list of devices we want to query when APM come in */ 633 SLIST_INIT(&sc->sc_ac); 634 SLIST_INIT(&sc->sc_bat); 635 TAILQ_FOREACH(dev, &alldevs, dv_list) { 636 if (!strncmp(dev->dv_xname, "acpiac", strlen("acpiac"))) { 637 ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO); 638 ac->aac_softc = (struct acpiac_softc *)dev; 639 SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link); 640 } 641 if (!strncmp(dev->dv_xname, "acpibat", strlen("acpibat"))) { 642 bat = malloc(sizeof(*bat), M_DEVBUF, M_WAITOK | M_ZERO); 643 bat->aba_softc = (struct acpibat_softc *)dev; 644 SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link); 645 } 646 } 647 648 /* Setup threads */ 649 sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK); 650 sc->sc_thread->sc = sc; 651 sc->sc_thread->running = 1; 652 653 acpi_attach_machdep(sc); 654 655 kthread_create_deferred(acpi_create_thread, sc); 656#endif /* SMALL_KERNEL */ 657} 658 659int 660acpi_submatch(struct device *parent, void *match, void *aux) 661{ 662 struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux; 663 struct cfdata *cf = match; 664 665 if (aaa->aaa_table == NULL) 666 return (0); 667 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 668} 669 670int 671acpi_print(void *aux, const char *pnp) 672{ 673 /* XXX ACPIVERBOSE should be replaced with dnprintf */ 674 struct acpi_attach_args *aa = aux; 675#ifdef ACPIVERBOSE 676 struct acpi_table_header *hdr = 677 (struct acpi_table_header *)aa->aaa_table; 678#endif 679 680 if (pnp) { 681 if (aa->aaa_name) 682 printf("%s at %s", aa->aaa_name, pnp); 683#ifdef ACPIVERBOSE 684 else 685 printf("acpi device at %s from", pnp); 686#else 687 else 688 return (QUIET); 689#endif 690 } 691#ifdef ACPIVERBOSE 692 if (hdr) 693 printf(" table %c%c%c%c", 694 hdr->signature[0], hdr->signature[1], 695 hdr->signature[2], hdr->signature[3]); 696#endif 697 698 return (UNCONF); 699} 700 701int 702acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp) 703{ 704 struct acpi_mem_map hrsdt, handle; 705 struct acpi_table_header *hdr; 706 int i, ntables; 707 size_t len; 708 709 if (rsdp->rsdp_revision == 2) { 710 struct acpi_xsdt *xsdt; 711 712 if (acpi_map(rsdp->rsdp_xsdt, sizeof(*hdr), &handle)) { 713 printf("couldn't map rsdt\n"); 714 return (ENOMEM); 715 } 716 717 hdr = (struct acpi_table_header *)handle.va; 718 len = hdr->length; 719 acpi_unmap(&handle); 720 hdr = NULL; 721 722 acpi_map(rsdp->rsdp_xsdt, len, &hrsdt); 723 xsdt = (struct acpi_xsdt *)hrsdt.va; 724 725 ntables = (len - sizeof(struct acpi_table_header)) / 726 sizeof(xsdt->table_offsets[0]); 727 728 for (i = 0; i < ntables; i++) { 729 acpi_map(xsdt->table_offsets[i], sizeof(*hdr), &handle); 730 hdr = (struct acpi_table_header *)handle.va; 731 acpi_load_table(xsdt->table_offsets[i], hdr->length, 732 &sc->sc_tables); 733 acpi_unmap(&handle); 734 } 735 acpi_unmap(&hrsdt); 736 } else { 737 struct acpi_rsdt *rsdt; 738 739 if (acpi_map(rsdp->rsdp_rsdt, sizeof(*hdr), &handle)) { 740 printf("couldn't map rsdt\n"); 741 return (ENOMEM); 742 } 743 744 hdr = (struct acpi_table_header *)handle.va; 745 len = hdr->length; 746 acpi_unmap(&handle); 747 hdr = NULL; 748 749 acpi_map(rsdp->rsdp_rsdt, len, &hrsdt); 750 rsdt = (struct acpi_rsdt *)hrsdt.va; 751 752 ntables = (len - sizeof(struct acpi_table_header)) / 753 sizeof(rsdt->table_offsets[0]); 754 755 for (i = 0; i < ntables; i++) { 756 acpi_map(rsdt->table_offsets[i], sizeof(*hdr), &handle); 757 hdr = (struct acpi_table_header *)handle.va; 758 acpi_load_table(rsdt->table_offsets[i], hdr->length, 759 &sc->sc_tables); 760 acpi_unmap(&handle); 761 } 762 acpi_unmap(&hrsdt); 763 } 764 765 return (0); 766} 767 768void 769acpi_load_table(paddr_t pa, size_t len, acpi_qhead_t *queue) 770{ 771 struct acpi_mem_map handle; 772 struct acpi_q *entry; 773 774 entry = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT); 775 776 if (entry != NULL) { 777 if (acpi_map(pa, len, &handle)) { 778 free(entry, M_DEVBUF); 779 return; 780 } 781 memcpy(entry->q_data, handle.va, len); 782 entry->q_table = entry->q_data; 783 acpi_unmap(&handle); 784 SIMPLEQ_INSERT_TAIL(queue, entry, q_next); 785 } 786} 787 788void 789acpi_load_dsdt(paddr_t pa, struct acpi_q **dsdt) 790{ 791 struct acpi_mem_map handle; 792 struct acpi_table_header *hdr; 793 size_t len; 794 795 if (acpi_map(pa, sizeof(*hdr), &handle)) 796 return; 797 hdr = (struct acpi_table_header *)handle.va; 798 len = hdr->length; 799 acpi_unmap(&handle); 800 801 *dsdt = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT); 802 803 if (*dsdt != NULL) { 804 if (acpi_map(pa, len, &handle)) { 805 free(*dsdt, M_DEVBUF); 806 *dsdt = NULL; 807 return; 808 } 809 memcpy((*dsdt)->q_data, handle.va, len); 810 (*dsdt)->q_table = (*dsdt)->q_data; 811 acpi_unmap(&handle); 812 } 813} 814 815int 816acpiopen(dev_t dev, int flag, int mode, struct proc *p) 817{ 818 struct acpi_softc *sc; 819 int error = 0; 820 821 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 822 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 823 return (ENXIO); 824 825 switch (APMDEV(dev)) { 826 case APMDEV_CTL: 827 if (!(flag & FWRITE)) { 828 error = EINVAL; 829 break; 830 } 831 break; 832 case APMDEV_NORMAL: 833 if (!(flag & FREAD) || (flag & FWRITE)) { 834 error = EINVAL; 835 break; 836 } 837 break; 838 default: 839 error = ENXIO; 840 break; 841 } 842 return (error); 843} 844 845int 846acpiclose(dev_t dev, int flag, int mode, struct proc *p) 847{ 848 struct acpi_softc *sc; 849 int error = 0; 850 851 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 852 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 853 return (ENXIO); 854 switch (APMDEV(dev)) { 855 case APMDEV_CTL: 856 case APMDEV_NORMAL: 857 break; 858 default: 859 error = ENXIO; 860 break; 861 } 862 return (error); 863} 864 865int 866acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 867{ 868 int error = 0; 869#ifndef SMALL_KERNEL 870 struct acpi_softc *sc; 871 struct acpi_ac *ac; 872 struct acpi_bat *bat; 873 struct apm_power_info *pi = (struct apm_power_info *)data; 874 int bats; 875 unsigned int remaining, rem, minutes, rate; 876 877 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 878 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 879 return (ENXIO); 880 881 ACPI_LOCK(sc); 882 /* fake APM */ 883 switch (cmd) { 884 case APM_IOC_GETPOWER: 885 /* A/C */ 886 pi->ac_state = APM_AC_UNKNOWN; 887 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) { 888 if (ac->aac_softc->sc_ac_stat == PSR_ONLINE) 889 pi->ac_state = APM_AC_ON; 890 else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE) 891 if (pi->ac_state == APM_AC_UNKNOWN) 892 pi->ac_state = APM_AC_OFF; 893 } 894 895 /* battery */ 896 pi->battery_state = APM_BATT_UNKNOWN; 897 pi->battery_life = 0; 898 pi->minutes_left = 0; 899 bats = 0; 900 remaining = rem = 0; 901 minutes = 0; 902 rate = 0; 903 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) { 904 if (bat->aba_softc->sc_bat_present == 0) 905 continue; 906 907 if (bat->aba_softc->sc_bif.bif_last_capacity == 0) 908 continue; 909 910 bats++; 911 rem = (bat->aba_softc->sc_bst.bst_capacity * 100) / 912 bat->aba_softc->sc_bif.bif_last_capacity; 913 if (rem > 100) 914 rem = 100; 915 remaining += rem; 916 917 if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN) 918 continue; 919 else if (bat->aba_softc->sc_bst.bst_rate > 1) 920 rate = bat->aba_softc->sc_bst.bst_rate; 921 922 minutes += bat->aba_softc->sc_bst.bst_capacity; 923 } 924 925 if (bats == 0) { 926 pi->battery_state = APM_BATTERY_ABSENT; 927 pi->battery_life = 0; 928 pi->minutes_left = (unsigned int)-1; 929 break; 930 } 931 932 if (pi->ac_state == APM_AC_ON || rate == 0) 933 pi->minutes_left = (unsigned int)-1; 934 else 935 pi->minutes_left = 100 * minutes / rate; 936 937 /* running on battery */ 938 pi->battery_life = remaining / bats; 939 if (pi->battery_life > 50) 940 pi->battery_state = APM_BATT_HIGH; 941 else if (pi->battery_life > 25) 942 pi->battery_state = APM_BATT_LOW; 943 else 944 pi->battery_state = APM_BATT_CRITICAL; 945 946 break; 947 948 default: 949 error = ENOTTY; 950 } 951 952 ACPI_UNLOCK(sc); 953#else 954 error = ENXIO; 955#endif /* SMALL_KERNEL */ 956 return (error); 957} 958 959void 960acpi_filtdetach(struct knote *kn) 961{ 962 struct acpi_softc *sc = kn->kn_hook; 963 964 ACPI_LOCK(sc); 965 SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext); 966 ACPI_UNLOCK(sc); 967} 968 969int 970acpi_filtread(struct knote *kn, long hint) 971{ 972 /* XXX weird kqueue_scan() semantics */ 973 if (hint & !kn->kn_data) 974 kn->kn_data = hint; 975 976 return (1); 977} 978 979int 980acpikqfilter(dev_t dev, struct knote *kn) 981{ 982 struct acpi_softc *sc; 983 984 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 985 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 986 return (ENXIO); 987 988 switch (kn->kn_filter) { 989 case EVFILT_READ: 990 kn->kn_fop = &acpiread_filtops; 991 break; 992 default: 993 return (1); 994 } 995 996 kn->kn_hook = sc; 997 998 ACPI_LOCK(sc); 999 SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext); 1000 ACPI_UNLOCK(sc); 1001 1002 return (0); 1003} 1004 1005/* Read from power management register */ 1006int 1007acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset) 1008{ 1009 bus_space_handle_t ioh; 1010 bus_size_t size, __size; 1011 int regval; 1012 1013 __size = 0; 1014 /* Special cases: 1A/1B blocks can be OR'ed together */ 1015 switch (reg) { 1016 case ACPIREG_PM1_EN: 1017 return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) | 1018 acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset)); 1019 case ACPIREG_PM1_STS: 1020 return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) | 1021 acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset)); 1022 case ACPIREG_PM1_CNT: 1023 return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) | 1024 acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset)); 1025 case ACPIREG_GPE_STS: 1026 __size = 1; 1027 dnprintf(50, "read GPE_STS offset: %.2x %.2x %.2x\n", offset, 1028 sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1); 1029 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1030 reg = ACPIREG_GPE0_STS; 1031 } 1032 break; 1033 case ACPIREG_GPE_EN: 1034 __size = 1; 1035 dnprintf(50, "read GPE_EN offset: %.2x %.2x %.2x\n", 1036 offset, sc->sc_fadt->gpe0_blk_len>>1, 1037 sc->sc_fadt->gpe1_blk_len>>1); 1038 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1039 reg = ACPIREG_GPE0_EN; 1040 } 1041 break; 1042 } 1043 1044 if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0) 1045 return (0); 1046 1047 regval = 0; 1048 ioh = sc->sc_pmregs[reg].ioh; 1049 size = sc->sc_pmregs[reg].size; 1050 if (__size) 1051 size = __size; 1052 if (size > 4) 1053 size = 4; 1054 1055 switch (size) { 1056 case 1: 1057 regval = bus_space_read_1(sc->sc_iot, ioh, offset); 1058 break; 1059 case 2: 1060 regval = bus_space_read_2(sc->sc_iot, ioh, offset); 1061 break; 1062 case 4: 1063 regval = bus_space_read_4(sc->sc_iot, ioh, offset); 1064 break; 1065 } 1066 1067 dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n", 1068 sc->sc_pmregs[reg].name, 1069 sc->sc_pmregs[reg].addr, offset, regval); 1070 return (regval); 1071} 1072 1073/* Write to power management register */ 1074void 1075acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval) 1076{ 1077 bus_space_handle_t ioh; 1078 bus_size_t size, __size; 1079 1080 __size = 0; 1081 /* Special cases: 1A/1B blocks can be written with same value */ 1082 switch (reg) { 1083 case ACPIREG_PM1_EN: 1084 acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval); 1085 acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval); 1086 break; 1087 case ACPIREG_PM1_STS: 1088 acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval); 1089 acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval); 1090 break; 1091 case ACPIREG_PM1_CNT: 1092 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval); 1093 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval); 1094 break; 1095 case ACPIREG_GPE_STS: 1096 __size = 1; 1097 dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n", 1098 offset, sc->sc_fadt->gpe0_blk_len>>1, 1099 sc->sc_fadt->gpe1_blk_len>>1, regval); 1100 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1101 reg = ACPIREG_GPE0_STS; 1102 } 1103 break; 1104 case ACPIREG_GPE_EN: 1105 __size = 1; 1106 dnprintf(50, "write GPE_EN offset: %.2x %.2x %.2x %.2x\n", 1107 offset, sc->sc_fadt->gpe0_blk_len>>1, 1108 sc->sc_fadt->gpe1_blk_len>>1, regval); 1109 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1110 reg = ACPIREG_GPE0_EN; 1111 } 1112 break; 1113 } 1114 1115 /* All special case return here */ 1116 if (reg >= ACPIREG_MAXREG) 1117 return; 1118 1119 ioh = sc->sc_pmregs[reg].ioh; 1120 size = sc->sc_pmregs[reg].size; 1121 if (__size) 1122 size = __size; 1123 if (size > 4) 1124 size = 4; 1125 switch (size) { 1126 case 1: 1127 bus_space_write_1(sc->sc_iot, ioh, offset, regval); 1128 break; 1129 case 2: 1130 bus_space_write_2(sc->sc_iot, ioh, offset, regval); 1131 break; 1132 case 4: 1133 bus_space_write_4(sc->sc_iot, ioh, offset, regval); 1134 break; 1135 } 1136 1137 dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n", 1138 sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval); 1139} 1140 1141int 1142acpi_interrupt(void *arg) 1143{ 1144 struct acpi_softc *sc = (struct acpi_softc *)arg; 1145 u_int32_t processed, sts, en, idx, jdx; 1146 1147 processed = 0; 1148 1149 dnprintf(40, "ACPI Interrupt\n"); 1150 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 1151 sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3); 1152 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, idx>>3); 1153 if (en & sts) { 1154 dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts, 1155 en); 1156 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts); 1157 for (jdx = 0; jdx < 8; jdx++) { 1158 if (en & sts & (1L << jdx)) { 1159 /* Signal this GPE */ 1160 sc->gpe_table[idx+jdx].active = 1; 1161 processed = 1; 1162 } 1163 } 1164 } 1165 } 1166 1167 sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0); 1168 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1169 if (sts & en) { 1170 dnprintf(10,"GEN interrupt: %.4x\n", sts & en); 1171 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts); 1172 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, en); 1173 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 1174 if (sts & ACPI_PM1_PWRBTN_STS) 1175 sc->sc_powerbtn = 1; 1176 if (sts & ACPI_PM1_SLPBTN_STS) 1177 sc->sc_sleepbtn = 1; 1178 processed = 1; 1179 } 1180 1181 if (processed) { 1182 sc->sc_wakeup = 0; 1183 wakeup(sc); 1184 } 1185 1186 return (processed); 1187} 1188 1189void 1190acpi_reset(void) 1191{ 1192 struct acpi_fadt *fadt; 1193 u_int32_t reset_as, reset_len; 1194 u_int32_t value; 1195 1196 fadt = acpi_softc->sc_fadt; 1197 1198 /* 1199 * RESET_REG_SUP is not properly set in some implementations, 1200 * but not testing against it breaks more machines than it fixes 1201 */ 1202 if (acpi_softc->sc_revision <= 1 || 1203 !(fadt->flags & FADT_RESET_REG_SUP) || fadt->reset_reg.address == 0) 1204 return; 1205 1206 value = fadt->reset_value; 1207 1208 reset_as = fadt->reset_reg.register_bit_width / 8; 1209 if (reset_as == 0) 1210 reset_as = 1; 1211 1212 reset_len = fadt->reset_reg.access_size; 1213 if (reset_len == 0) 1214 reset_len = reset_as; 1215 1216 acpi_gasio(acpi_softc, ACPI_IOWRITE, 1217 fadt->reset_reg.address_space_id, 1218 fadt->reset_reg.address, reset_as, reset_len, &value); 1219 1220 delay(100000); 1221} 1222 1223/* move all stuff that doesn't go on the boot media in here */ 1224#ifndef SMALL_KERNEL 1225 1226void 1227acpi_enable_onegpe(struct acpi_softc *sc, int gpe, int enable) 1228{ 1229 uint8_t mask = (1L << (gpe & 7)); 1230 uint8_t en; 1231 1232 /* Read enabled register */ 1233 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); 1234 dnprintf(50, "%sabling GPE %.2x (current: %sabled) %.2x\n", 1235 enable ? "en" : "dis", gpe, (en & mask) ? "en" : "dis", en); 1236 if (enable) 1237 en |= mask; 1238 else 1239 en &= ~mask; 1240 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en); 1241} 1242 1243int 1244acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler) 1245 (struct acpi_softc *, int, void *), void *arg, const char *label) 1246{ 1247 if (gpe >= sc->sc_lastgpe || handler == NULL) 1248 return -EINVAL; 1249 1250 if (sc->gpe_table[gpe].handler != NULL) { 1251 dnprintf(10, "error: GPE %.2x already enabled\n", gpe); 1252 return -EBUSY; 1253 } 1254 1255 dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, label); 1256 sc->gpe_table[gpe].handler = handler; 1257 sc->gpe_table[gpe].arg = arg; 1258 1259 /* Defer enabling GPEs */ 1260 1261 return (0); 1262} 1263 1264int 1265acpi_gpe_level(struct acpi_softc *sc, int gpe, void *arg) 1266{ 1267 struct aml_node *node = arg; 1268 uint8_t mask; 1269 1270 dnprintf(10, "handling Level-sensitive GPE %.2x\n", gpe); 1271 mask = (1L << (gpe & 7)); 1272 1273 aml_evalnode(sc, node, 0, NULL, NULL); 1274 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); 1275 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, mask); 1276 1277 return (0); 1278} 1279 1280int 1281acpi_gpe_edge(struct acpi_softc *sc, int gpe, void *arg) 1282{ 1283 1284 struct aml_node *node = arg; 1285 uint8_t mask; 1286 1287 dnprintf(10, "handling Edge-sensitive GPE %.2x\n", gpe); 1288 mask = (1L << (gpe & 7)); 1289 1290 aml_evalnode(sc, node, 0, NULL, NULL); 1291 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); 1292 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, mask); 1293 1294 return (0); 1295} 1296 1297/* Discover Devices that can wakeup the system 1298 * _PRW returns a package 1299 * pkg[0] = integer (FADT gpe bit) or package (gpe block,gpe bit) 1300 * pkg[1] = lowest sleep state 1301 * pkg[2+] = power resource devices (optional) 1302 * 1303 * To enable wakeup devices: 1304 * Evaluate _ON method in each power resource device 1305 * Evaluate _PSW method 1306 */ 1307int 1308acpi_foundprw(struct aml_node *node, void *arg) 1309{ 1310 struct acpi_softc *sc = arg; 1311 struct acpi_wakeq *wq; 1312 1313 wq = (struct acpi_wakeq *)malloc(sizeof(struct acpi_wakeq), M_DEVBUF, M_NOWAIT); 1314 if (wq == NULL) { 1315 return 0; 1316 } 1317 memset(wq, 0, sizeof(struct acpi_wakeq)); 1318 1319 wq->q_wakepkg = (struct aml_value *)malloc(sizeof(struct aml_value), 1320 M_DEVBUF, M_NOWAIT); 1321 if (wq->q_wakepkg == NULL) { 1322 free(wq, M_DEVBUF); 1323 return 0; 1324 } 1325 memset(wq->q_wakepkg, 0, sizeof(struct aml_value)); 1326 dnprintf(10, "Found _PRW (%s)\n", node->parent->name); 1327 aml_evalnode(sc, node, 0, NULL, wq->q_wakepkg); 1328 wq->q_node = node->parent; 1329 wq->q_gpe = -1; 1330 1331 /* Get GPE of wakeup device, and lowest sleep level */ 1332 if (wq->q_wakepkg->type == AML_OBJTYPE_PACKAGE && wq->q_wakepkg->length >= 2) { 1333 if (wq->q_wakepkg->v_package[0]->type == AML_OBJTYPE_INTEGER) { 1334 wq->q_gpe = wq->q_wakepkg->v_package[0]->v_integer; 1335 } 1336 if (wq->q_wakepkg->v_package[1]->type == AML_OBJTYPE_INTEGER) { 1337 wq->q_state = wq->q_wakepkg->v_package[1]->v_integer; 1338 } 1339 } 1340 SIMPLEQ_INSERT_TAIL(&sc->sc_wakedevs, wq, q_next); 1341 return 0; 1342} 1343 1344void 1345acpi_init_gpes(struct acpi_softc *sc) 1346{ 1347 struct aml_node *gpe; 1348 char name[12]; 1349 int idx, ngpe; 1350 1351 sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2; 1352 if (sc->sc_fadt->gpe1_blk_len) { 1353 } 1354 dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe); 1355 1356 /* Allocate GPE table */ 1357 sc->gpe_table = malloc(sc->sc_lastgpe * sizeof(struct gpe_block), 1358 M_DEVBUF, M_WAITOK | M_ZERO); 1359 1360 ngpe = 0; 1361 1362 /* Clear GPE status */ 1363 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 1364 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, 0); 1365 acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx>>3, -1); 1366 } 1367 for (idx = 0; idx < sc->sc_lastgpe; idx++) { 1368 /* Search Level-sensitive GPES */ 1369 snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx); 1370 gpe = aml_searchname(&aml_root, name); 1371 if (gpe != NULL) 1372 acpi_set_gpehandler(sc, idx, acpi_gpe_level, gpe, 1373 "level"); 1374 if (gpe == NULL) { 1375 /* Search Edge-sensitive GPES */ 1376 snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx); 1377 gpe = aml_searchname(&aml_root, name); 1378 if (gpe != NULL) 1379 acpi_set_gpehandler(sc, idx, acpi_gpe_edge, gpe, 1380 "edge"); 1381 } 1382 } 1383 aml_find_node(aml_root.child, "_PRW", acpi_foundprw, sc); 1384 sc->sc_maxgpe = ngpe; 1385} 1386 1387void 1388acpi_init_states(struct acpi_softc *sc) 1389{ 1390 struct aml_value res; 1391 char name[8]; 1392 int i; 1393 1394 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) { 1395 snprintf(name, sizeof(name), "_S%d_", i); 1396 sc->sc_sleeptype[i].slp_typa = -1; 1397 sc->sc_sleeptype[i].slp_typb = -1; 1398 if (aml_evalname(sc, aml_root.child, name, 0, NULL, &res) == 0) { 1399 if (res.type == AML_OBJTYPE_PACKAGE) { 1400 sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]); 1401 sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]); 1402 } 1403 aml_freevalue(&res); 1404 } 1405 } 1406} 1407 1408void 1409acpi_init_pm(struct acpi_softc *sc) 1410{ 1411 sc->sc_tts = aml_searchname(aml_root.child, "_TTS"); 1412 sc->sc_pts = aml_searchname(aml_root.child, "_PTS"); 1413 sc->sc_wak = aml_searchname(aml_root.child, "_WAK"); 1414 sc->sc_bfs = aml_searchname(aml_root.child, "_BFS"); 1415 sc->sc_gts = aml_searchname(aml_root.child, "_GTS"); 1416} 1417 1418void 1419acpi_enter_sleep_state(struct acpi_softc *sc, int state) 1420{ 1421 struct aml_value env; 1422 u_int16_t rega, regb; 1423 int retries; 1424 1425 if (state == ACPI_STATE_S0) 1426 return; 1427 if (sc->sc_sleeptype[state].slp_typa == -1 || 1428 sc->sc_sleeptype[state].slp_typb == -1) { 1429 printf("%s: state S%d unavailable\n", 1430 sc->sc_dev.dv_xname, state); 1431 return; 1432 } 1433 1434 env.type = AML_OBJTYPE_INTEGER; 1435 env.v_integer = state; 1436 /* _TTS(state) */ 1437 if (sc->sc_tts) { 1438 if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) { 1439 dnprintf(10, "%s evaluating method _TTS failed.\n", 1440 DEVNAME(sc)); 1441 return; 1442 } 1443 } 1444 switch (state) { 1445 case ACPI_STATE_S1: 1446 case ACPI_STATE_S2: 1447 resettodr(); 1448 dopowerhooks(PWR_SUSPEND); 1449 break; 1450 case ACPI_STATE_S3: 1451 resettodr(); 1452 dopowerhooks(PWR_STANDBY); 1453 break; 1454 } 1455 /* _PTS(state) */ 1456 if (sc->sc_pts) { 1457 if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) { 1458 dnprintf(10, "%s evaluating method _PTS failed.\n", 1459 DEVNAME(sc)); 1460 return; 1461 } 1462 } 1463 sc->sc_state = state; 1464 /* _GTS(state) */ 1465 if (sc->sc_gts) { 1466 if (aml_evalnode(sc, sc->sc_gts, 1, &env, NULL) != 0) { 1467 dnprintf(10, "%s evaluating method _GTS failed.\n", 1468 DEVNAME(sc)); 1469 return; 1470 } 1471 } 1472 disable_intr(); 1473 1474 /* Clear WAK_STS bit */ 1475 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); 1476 1477 /* Write SLP_TYPx values */ 1478 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); 1479 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); 1480 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 1481 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 1482 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa); 1483 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb); 1484 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 1485 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 1486 1487 /* Set SLP_EN bit */ 1488 rega |= ACPI_PM1_SLP_EN; 1489 regb |= ACPI_PM1_SLP_EN; 1490 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 1491 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 1492 1493 /* Loop on WAK_STS */ 1494 for (retries = 1000; retries > 0; retries--) { 1495 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0); 1496 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0); 1497 if (rega & ACPI_PM1_WAK_STS || 1498 regb & ACPI_PM1_WAK_STS) 1499 break; 1500 DELAY(10); 1501 } 1502 1503 enable_intr(); 1504} 1505 1506void 1507acpi_resume(struct acpi_softc *sc) 1508{ 1509 struct aml_value env; 1510 1511 env.type = AML_OBJTYPE_INTEGER; 1512 env.v_integer = sc->sc_state; 1513 1514 if (sc->sc_bfs) { 1515 if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) { 1516 dnprintf(10, "%s evaluating method _BFS failed.\n", 1517 DEVNAME(sc)); 1518 } 1519 } 1520 dopowerhooks(PWR_RESUME); 1521 inittodr(0); 1522 if (sc->sc_wak) { 1523 if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) { 1524 dnprintf(10, "%s evaluating method _WAK failed.\n", 1525 DEVNAME(sc)); 1526 } 1527 } 1528 sc->sc_state = ACPI_STATE_S0; 1529 if (sc->sc_tts) { 1530 env.v_integer = sc->sc_state; 1531 if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) { 1532 dnprintf(10, "%s evaluating method _TTS failed.\n", 1533 DEVNAME(sc)); 1534 } 1535 } 1536} 1537 1538void 1539acpi_powerdown(void) 1540{ 1541 acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5); 1542} 1543 1544void 1545acpi_isr_thread(void *arg) 1546{ 1547 struct acpi_thread *thread = arg; 1548 struct acpi_softc *sc = thread->sc; 1549 u_int32_t gpe; 1550 1551 /* 1552 * If we have an interrupt handler, we can get notification 1553 * when certain status bits changes in the ACPI registers, 1554 * so let us enable some events we can forward to userland 1555 */ 1556 if (sc->sc_interrupt) { 1557 int16_t flag; 1558 1559 dnprintf(1,"slpbtn:%c pwrbtn:%c\n", 1560 sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y', 1561 sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y'); 1562 dnprintf(10, "Enabling acpi interrupts...\n"); 1563 sc->sc_wakeup = 1; 1564 1565 /* Enable Sleep/Power buttons if they exist */ 1566 flag = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1567 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) { 1568 flag |= ACPI_PM1_PWRBTN_EN; 1569 } 1570 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) { 1571 flag |= ACPI_PM1_SLPBTN_EN; 1572 } 1573 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, flag); 1574 1575 /* Enable handled GPEs here */ 1576 for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) { 1577 if (sc->gpe_table[gpe].handler) 1578 acpi_enable_onegpe(sc, gpe, 1); 1579 } 1580 } 1581 1582 while (thread->running) { 1583 dnprintf(10, "sleep... %d\n", sc->sc_wakeup); 1584 while (sc->sc_wakeup) 1585 tsleep(sc, PWAIT, "acpi_idle", 0); 1586 sc->sc_wakeup = 1; 1587 dnprintf(10, "wakeup..\n"); 1588 1589 for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) { 1590 struct gpe_block *pgpe = &sc->gpe_table[gpe]; 1591 1592 if (pgpe->active) { 1593 pgpe->active = 0; 1594 dnprintf(50, "softgpe: %.2x\n", gpe); 1595 if (pgpe->handler) 1596 pgpe->handler(sc, gpe, pgpe->arg); 1597 } 1598 } 1599 if (sc->sc_powerbtn) { 1600 sc->sc_powerbtn = 0; 1601 1602 aml_notify_dev(ACPI_DEV_PBD, 0x80); 1603 1604 acpi_evindex++; 1605 dnprintf(1,"power button pressed\n"); 1606 KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_PWRBTN, 1607 acpi_evindex)); 1608 } 1609 if (sc->sc_sleepbtn) { 1610 sc->sc_sleepbtn = 0; 1611 1612 aml_notify_dev(ACPI_DEV_SBD, 0x80); 1613 1614 acpi_evindex++; 1615 dnprintf(1,"sleep button pressed\n"); 1616 KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_SLPBTN, 1617 acpi_evindex)); 1618 } 1619 1620 /* handle polling here to keep code non-concurrent*/ 1621 if (sc->sc_poll) { 1622 sc->sc_poll = 0; 1623 acpi_poll_notify(); 1624 } 1625 } 1626 free(thread, M_DEVBUF); 1627 1628 kthread_exit(0); 1629} 1630 1631void 1632acpi_create_thread(void *arg) 1633{ 1634 struct acpi_softc *sc = arg; 1635 1636 if (kthread_create(acpi_isr_thread, sc->sc_thread, NULL, DEVNAME(sc)) 1637 != 0) { 1638 printf("%s: unable to create isr thread, GPEs disabled\n", 1639 DEVNAME(sc)); 1640 return; 1641 } 1642} 1643 1644int 1645acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas, bus_addr_t base, 1646 bus_size_t size, bus_space_handle_t *pioh, bus_space_tag_t *piot) 1647{ 1648 int iospace = GAS_SYSTEM_IOSPACE; 1649 1650 /* No GAS structure, default to I/O space */ 1651 if (gas != NULL) { 1652 base += gas->address; 1653 iospace = gas->address_space_id; 1654 } 1655 switch (iospace) { 1656 case GAS_SYSTEM_MEMORY: 1657 *piot = sc->sc_memt; 1658 break; 1659 case GAS_SYSTEM_IOSPACE: 1660 *piot = sc->sc_iot; 1661 break; 1662 default: 1663 return -1; 1664 } 1665 if (bus_space_map(*piot, base, size, 0, pioh)) 1666 return -1; 1667 1668 return 0; 1669} 1670 1671/* Map Power Management registers */ 1672void 1673acpi_map_pmregs(struct acpi_softc *sc) 1674{ 1675 bus_addr_t addr; 1676 bus_size_t size; 1677 const char *name; 1678 int reg; 1679 1680 for (reg = 0; reg < ACPIREG_MAXREG; reg++) { 1681 size = 0; 1682 switch (reg) { 1683 case ACPIREG_SMICMD: 1684 name = "smi"; 1685 size = 1; 1686 addr = sc->sc_fadt->smi_cmd; 1687 break; 1688 case ACPIREG_PM1A_STS: 1689 case ACPIREG_PM1A_EN: 1690 name = "pm1a_sts"; 1691 size = sc->sc_fadt->pm1_evt_len >> 1; 1692 addr = sc->sc_fadt->pm1a_evt_blk; 1693 if (reg == ACPIREG_PM1A_EN && addr) { 1694 addr += size; 1695 name = "pm1a_en"; 1696 } 1697 break; 1698 case ACPIREG_PM1A_CNT: 1699 name = "pm1a_cnt"; 1700 size = sc->sc_fadt->pm1_cnt_len; 1701 addr = sc->sc_fadt->pm1a_cnt_blk; 1702 break; 1703 case ACPIREG_PM1B_STS: 1704 case ACPIREG_PM1B_EN: 1705 name = "pm1b_sts"; 1706 size = sc->sc_fadt->pm1_evt_len >> 1; 1707 addr = sc->sc_fadt->pm1b_evt_blk; 1708 if (reg == ACPIREG_PM1B_EN && addr) { 1709 addr += size; 1710 name = "pm1b_en"; 1711 } 1712 break; 1713 case ACPIREG_PM1B_CNT: 1714 name = "pm1b_cnt"; 1715 size = sc->sc_fadt->pm1_cnt_len; 1716 addr = sc->sc_fadt->pm1b_cnt_blk; 1717 break; 1718 case ACPIREG_PM2_CNT: 1719 name = "pm2_cnt"; 1720 size = sc->sc_fadt->pm2_cnt_len; 1721 addr = sc->sc_fadt->pm2_cnt_blk; 1722 break; 1723#if 0 1724 case ACPIREG_PM_TMR: 1725 /* Allocated in acpitimer */ 1726 name = "pm_tmr"; 1727 size = sc->sc_fadt->pm_tmr_len; 1728 addr = sc->sc_fadt->pm_tmr_blk; 1729 break; 1730#endif 1731 case ACPIREG_GPE0_STS: 1732 case ACPIREG_GPE0_EN: 1733 name = "gpe0_sts"; 1734 size = sc->sc_fadt->gpe0_blk_len >> 1; 1735 addr = sc->sc_fadt->gpe0_blk; 1736 1737 dnprintf(20, "gpe0 block len : %x\n", 1738 sc->sc_fadt->gpe0_blk_len >> 1); 1739 dnprintf(20, "gpe0 block addr: %x\n", 1740 sc->sc_fadt->gpe0_blk); 1741 if (reg == ACPIREG_GPE0_EN && addr) { 1742 addr += size; 1743 name = "gpe0_en"; 1744 } 1745 break; 1746 case ACPIREG_GPE1_STS: 1747 case ACPIREG_GPE1_EN: 1748 name = "gpe1_sts"; 1749 size = sc->sc_fadt->gpe1_blk_len >> 1; 1750 addr = sc->sc_fadt->gpe1_blk; 1751 1752 dnprintf(20, "gpe1 block len : %x\n", 1753 sc->sc_fadt->gpe1_blk_len >> 1); 1754 dnprintf(20, "gpe1 block addr: %x\n", 1755 sc->sc_fadt->gpe1_blk); 1756 if (reg == ACPIREG_GPE1_EN && addr) { 1757 addr += size; 1758 name = "gpe1_en"; 1759 } 1760 break; 1761 } 1762 if (size && addr) { 1763 dnprintf(50, "mapping: %.4x %.4x %s\n", 1764 addr, size, name); 1765 1766 /* Size and address exist; map register space */ 1767 bus_space_map(sc->sc_iot, addr, size, 0, 1768 &sc->sc_pmregs[reg].ioh); 1769 1770 sc->sc_pmregs[reg].name = name; 1771 sc->sc_pmregs[reg].size = size; 1772 sc->sc_pmregs[reg].addr = addr; 1773 } 1774 } 1775} 1776 1777int 1778acpi_foundec(struct aml_node *node, void *arg) 1779{ 1780 struct acpi_softc *sc = (struct acpi_softc *)arg; 1781 struct device *self = (struct device *)arg; 1782 const char *dev; 1783 struct aml_value res; 1784 struct acpi_attach_args aaa; 1785 1786 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 1787 return 0; 1788 1789 switch (res.type) { 1790 case AML_OBJTYPE_STRING: 1791 dev = res.v_string; 1792 break; 1793 case AML_OBJTYPE_INTEGER: 1794 dev = aml_eisaid(aml_val2int(&res)); 1795 break; 1796 default: 1797 dev = "unknown"; 1798 break; 1799 } 1800 1801 if (strcmp(dev, ACPI_DEV_ECD)) 1802 return 0; 1803 1804 memset(&aaa, 0, sizeof(aaa)); 1805 aaa.aaa_iot = sc->sc_iot; 1806 aaa.aaa_memt = sc->sc_memt; 1807 aaa.aaa_node = node->parent; 1808 aaa.aaa_dev = dev; 1809 aaa.aaa_name = "acpiec"; 1810 config_found(self, &aaa, acpi_print); 1811 aml_freevalue(&res); 1812 1813 return 0; 1814} 1815 1816int 1817acpi_foundhid(struct aml_node *node, void *arg) 1818{ 1819 struct acpi_softc *sc = (struct acpi_softc *)arg; 1820 struct device *self = (struct device *)arg; 1821 const char *dev; 1822 struct aml_value res; 1823 struct acpi_attach_args aaa; 1824 1825 dnprintf(10, "found hid device: %s ", node->parent->name); 1826 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 1827 return 0; 1828 1829 switch (res.type) { 1830 case AML_OBJTYPE_STRING: 1831 dev = res.v_string; 1832 break; 1833 case AML_OBJTYPE_INTEGER: 1834 dev = aml_eisaid(aml_val2int(&res)); 1835 break; 1836 default: 1837 dev = "unknown"; 1838 break; 1839 } 1840 dnprintf(10, " device: %s\n", dev); 1841 1842 memset(&aaa, 0, sizeof(aaa)); 1843 aaa.aaa_iot = sc->sc_iot; 1844 aaa.aaa_memt = sc->sc_memt; 1845 aaa.aaa_node = node->parent; 1846 aaa.aaa_dev = dev; 1847 1848 if (!strcmp(dev, ACPI_DEV_AC)) 1849 aaa.aaa_name = "acpiac"; 1850 else if (!strcmp(dev, ACPI_DEV_CMB)) 1851 aaa.aaa_name = "acpibat"; 1852 else if (!strcmp(dev, ACPI_DEV_LD) || 1853 !strcmp(dev, ACPI_DEV_PBD) || 1854 !strcmp(dev, ACPI_DEV_SBD)) 1855 aaa.aaa_name = "acpibtn"; 1856 else if (!strcmp(dev, ACPI_DEV_ASUS)) 1857 aaa.aaa_name = "acpiasus"; 1858 1859 if (aaa.aaa_name) 1860 config_found(self, &aaa, acpi_print); 1861 aml_freevalue(&res); 1862 1863 return 0; 1864} 1865 1866int 1867acpi_founddock(struct aml_node *node, void *arg) 1868{ 1869 struct acpi_softc *sc = (struct acpi_softc *)arg; 1870 struct device *self = (struct device *)arg; 1871 const char *dev; 1872 struct acpi_attach_args aaa; 1873 1874 dnprintf(10, "found dock entry: %s\n", node->parent->name); 1875 1876 memset(&aaa, 0, sizeof(aaa)); 1877 aaa.aaa_iot = sc->sc_iot; 1878 aaa.aaa_memt = sc->sc_memt; 1879 aaa.aaa_node = node->parent; 1880 aaa.aaa_dev = dev; 1881 aaa.aaa_name = "acpidock"; 1882 1883 config_found(self, &aaa, acpi_print); 1884 1885 return 0; 1886} 1887#endif /* SMALL_KERNEL */ 1888