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