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