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