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