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