acpi.c revision 1.159
1/* $NetBSD: acpi.c,v 1.159 2010/03/10 09:42:46 jruoho Exp $ */ 2 3/*- 4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum of By Noon Software, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Copyright 2001, 2003 Wasabi Systems, Inc. 34 * All rights reserved. 35 * 36 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed for the NetBSD Project by 49 * Wasabi Systems, Inc. 50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 51 * or promote products derived from this software without specific prior 52 * written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67/* 68 * Autoconfiguration support for the Intel ACPI Component Architecture 69 * ACPI reference implementation. 70 */ 71 72#include <sys/cdefs.h> 73__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.159 2010/03/10 09:42:46 jruoho Exp $"); 74 75#include "opt_acpi.h" 76#include "opt_pcifixup.h" 77 78#include <sys/param.h> 79#include <sys/device.h> 80#include <sys/kernel.h> 81#include <sys/malloc.h> 82#include <sys/mutex.h> 83#include <sys/sysctl.h> 84#include <sys/systm.h> 85 86#include <dev/acpi/acpireg.h> 87#include <dev/acpi/acpivar.h> 88#include <dev/acpi/acpi_osd.h> 89#include <dev/acpi/acpi_pci.h> 90#include <dev/acpi/acpi_timer.h> 91#include <dev/acpi/acpi_wakedev.h> 92 93#ifdef ACPIVERBOSE 94#include <dev/acpi/acpidevs_data.h> 95#endif 96 97#define _COMPONENT ACPI_TOOLS 98ACPI_MODULE_NAME ("acpi") 99 100#if defined(ACPI_PCI_FIXUP) 101#error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED. Please adjust your kernel configuration file. 102#endif 103 104#ifdef PCI_INTR_FIXUP_DISABLED 105#include <dev/pci/pcidevs.h> 106#endif 107 108MALLOC_DECLARE(M_ACPI); 109 110#include <machine/acpi_machdep.h> 111 112#ifdef ACPI_DEBUGGER 113#define ACPI_DBGR_INIT 0x01 114#define ACPI_DBGR_TABLES 0x02 115#define ACPI_DBGR_ENABLE 0x04 116#define ACPI_DBGR_PROBE 0x08 117#define ACPI_DBGR_RUNNING 0x10 118 119static int acpi_dbgr = 0x00; 120#endif 121 122static ACPI_TABLE_DESC acpi_initial_tables[128]; 123 124static int acpi_match(device_t, cfdata_t, void *); 125static void acpi_attach(device_t, device_t, void *); 126static void acpi_childdet(device_t, device_t); 127static int acpi_detach(device_t, int); 128 129static int acpi_rescan(device_t, const char *, const int *); 130static void acpi_rescan1(struct acpi_softc *, const char *, const int *); 131static void acpi_rescan_nodes(struct acpi_softc *); 132 133static int acpi_print(void *aux, const char *); 134 135static int sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS); 136 137extern struct cfdriver acpi_cd; 138 139CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc), 140 acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet); 141 142/* 143 * This is a flag we set when the ACPI subsystem is active. Machine 144 * dependent code may wish to skip other steps (such as attaching 145 * subsystems that ACPI supercedes) when ACPI is active. 146 */ 147int acpi_active; 148int acpi_force_load; 149int acpi_suspended = 0; 150 151/* 152 * Pointer to the ACPI subsystem's state. There can be only 153 * one ACPI instance. 154 */ 155struct acpi_softc *acpi_softc; 156 157/* 158 * Locking stuff. 159 */ 160extern kmutex_t acpi_interrupt_list_mtx; 161 162/* 163 * Ignored HIDs. 164 */ 165static const char * const acpi_ignored_ids[] = { 166#if defined(i386) || defined(x86_64) 167 "PNP0000", /* AT interrupt controller is handled internally */ 168 "PNP0200", /* AT DMA controller is handled internally */ 169 "PNP0A??", /* PCI Busses are handled internally */ 170 "PNP0B00", /* AT RTC is handled internally */ 171 "PNP0C01", /* No "System Board" driver */ 172 "PNP0C02", /* No "PnP motherboard register resources" driver */ 173 "PNP0C0B", /* No need for "ACPI fan" driver */ 174 "PNP0C0F", /* ACPI PCI link devices are handled internally */ 175 "INT0800", /* Intel HW RNG is handled internally */ 176#endif 177#if defined(x86_64) 178 "PNP0C04", /* FPU is handled internally */ 179#endif 180 NULL 181}; 182 183/* 184 * sysctl-related information 185 */ 186 187static uint64_t acpi_root_pointer; /* found as hw.acpi.root */ 188static int acpi_sleepstate = ACPI_STATE_S0; 189static char acpi_supported_states[3 * 6 + 1] = ""; 190 191/* 192 * Prototypes. 193 */ 194static void acpi_build_tree(struct acpi_softc *); 195static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, uint32_t, 196 void *, void **); 197 198static void acpi_enable_fixed_events(struct acpi_softc *); 199 200static ACPI_TABLE_HEADER *acpi_map_rsdt(void); 201static void acpi_unmap_rsdt(ACPI_TABLE_HEADER *); 202static int is_available_state(struct acpi_softc *, int); 203 204static bool acpi_suspend(device_t, const pmf_qual_t *); 205static bool acpi_resume(device_t, const pmf_qual_t *); 206 207#ifdef ACPI_ACTIVATE_DEV 208static void acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **); 209static ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE); 210#endif 211 212/* 213 * acpi_probe: 214 * 215 * Probe for ACPI support. This is called by the 216 * machine-dependent ACPI front-end. All of the 217 * actual work is done by ACPICA. 218 * 219 * NOTE: This is not an autoconfiguration interface function. 220 */ 221int 222acpi_probe(void) 223{ 224 static int beenhere; 225 ACPI_TABLE_HEADER *rsdt; 226 ACPI_STATUS rv; 227 228 if (beenhere != 0) 229 panic("acpi_probe: ACPI has already been probed"); 230 beenhere = 1; 231 232 mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE); 233 234 /* 235 * Start up ACPICA. 236 */ 237#ifdef ACPI_DEBUGGER 238 if (acpi_dbgr & ACPI_DBGR_INIT) 239 acpi_osd_debugger(); 240#endif 241 242 AcpiGbl_AllMethodsSerialized = FALSE; 243 AcpiGbl_EnableInterpreterSlack = TRUE; 244 245 rv = AcpiInitializeSubsystem(); 246 if (ACPI_FAILURE(rv)) { 247 printf("ACPI: unable to initialize ACPICA: %s\n", 248 AcpiFormatException(rv)); 249 return 0; 250 } 251 252 rv = AcpiInitializeTables(acpi_initial_tables, 128, 0); 253 if (ACPI_FAILURE(rv)) { 254#ifdef ACPI_DEBUG 255 printf("ACPI: unable to initialize ACPI tables: %s\n", 256 AcpiFormatException(rv)); 257#endif 258 AcpiTerminate(); 259 return 0; 260 } 261 262 rv = AcpiReallocateRootTable(); 263 if (ACPI_FAILURE(rv)) { 264 printf("ACPI: unable to reallocate root table: %s\n", 265 AcpiFormatException(rv)); 266 AcpiTerminate(); 267 return 0; 268 } 269 270#ifdef ACPI_DEBUGGER 271 if (acpi_dbgr & ACPI_DBGR_TABLES) 272 acpi_osd_debugger(); 273#endif 274 275 rv = AcpiLoadTables(); 276 if (ACPI_FAILURE(rv)) { 277 printf("ACPI: unable to load tables: %s\n", 278 AcpiFormatException(rv)); 279 AcpiTerminate(); 280 return 0; 281 } 282 283 rsdt = acpi_map_rsdt(); 284 if (rsdt == NULL) { 285 printf("ACPI: unable to map RSDT\n"); 286 AcpiTerminate(); 287 return 0; 288 } 289 290 if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) { 291 printf("ACPI: BIOS implementation in listed as broken:\n"); 292 printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, " 293 "AslId <%4.4s,%08x>\n", 294 rsdt->OemId, rsdt->OemTableId, 295 rsdt->OemRevision, 296 rsdt->AslCompilerId, 297 rsdt->AslCompilerRevision); 298 printf("ACPI: not used. set acpi_force_load to use anyway.\n"); 299 acpi_unmap_rsdt(rsdt); 300 AcpiTerminate(); 301 return 0; 302 } 303 304 acpi_unmap_rsdt(rsdt); 305 306#if notyet 307 /* Install the default address space handlers. */ 308 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 309 ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); 310 if (ACPI_FAILURE(rv)) { 311 printf("ACPI: unable to initialize SystemMemory handler: %s\n", 312 AcpiFormatException(rv)); 313 AcpiTerminate(); 314 return 0; 315 } 316 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 317 ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); 318 if (ACPI_FAILURE(rv)) { 319 printf("ACPI: unable to initialize SystemIO handler: %s\n", 320 AcpiFormatException(rv)); 321 AcpiTerminate(); 322 return 0; 323 } 324 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 325 ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); 326 if (ACPI_FAILURE(rv)) { 327 printf("ACPI: unable to initialize PciConfig handler: %s\n", 328 AcpiFormatException(rv)); 329 AcpiTerminate(); 330 return 0; 331 } 332#endif 333 334 rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE)); 335 if (ACPI_FAILURE(rv)) { 336 printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv)); 337 AcpiTerminate(); 338 return 0; 339 } 340 341 /* 342 * Looks like we have ACPI! 343 */ 344 345 return 1; 346} 347 348static int 349acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux) 350{ 351 struct cfattach *ca; 352 353 ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname); 354 return (ca == &acpi_ca); 355} 356 357int 358acpi_check(device_t parent, const char *ifattr) 359{ 360 return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL); 361} 362 363ACPI_PHYSICAL_ADDRESS 364acpi_OsGetRootPointer(void) 365{ 366 ACPI_PHYSICAL_ADDRESS PhysicalAddress; 367 368 /* 369 * IA-32: Use AcpiFindRootPointer() to locate the RSDP. 370 * 371 * IA-64: Use the EFI. 372 * 373 * We let MD code handle this since there are multiple 374 * ways to do it. 375 */ 376 377 PhysicalAddress = acpi_md_OsGetRootPointer(); 378 379 if (acpi_root_pointer == 0) 380 acpi_root_pointer = PhysicalAddress; 381 382 return PhysicalAddress; 383} 384 385/* 386 * acpi_match: 387 * 388 * Autoconfiguration `match' routine. 389 */ 390static int 391acpi_match(device_t parent, cfdata_t match, void *aux) 392{ 393 /* 394 * XXX Check other locators? Hard to know -- machine 395 * dependent code has already checked for the presence 396 * of ACPI by calling acpi_probe(), so I suppose we 397 * don't really have to do anything else. 398 */ 399 return 1; 400} 401 402/* Remove references to child devices. 403 * 404 * XXX Need to reclaim any resources? 405 */ 406static void 407acpi_childdet(device_t self, device_t child) 408{ 409 struct acpi_softc *sc = device_private(self); 410 struct acpi_devnode *ad; 411 412 if (sc->sc_apmbus == child) 413 sc->sc_apmbus = NULL; 414 415 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) { 416 417 if (ad->ad_device == child) 418 ad->ad_device = NULL; 419 } 420} 421 422/* 423 * acpi_attach: 424 * 425 * Autoconfiguration `attach' routine. Finish initializing 426 * ACPICA (some initialization was done in acpi_probe(), 427 * which was required to check for the presence of ACPI), 428 * and enable the ACPI subsystem. 429 */ 430static void 431acpi_attach(device_t parent, device_t self, void *aux) 432{ 433 struct acpi_softc *sc = device_private(self); 434 struct acpibus_attach_args *aa = aux; 435 ACPI_STATUS rv; 436 ACPI_TABLE_HEADER *rsdt; 437 438 aprint_naive("\n"); 439 aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION); 440 441 if (acpi_softc != NULL) 442 panic("acpi_attach: ACPI has already been attached"); 443 444 sysmon_power_settype("acpi"); 445 446 rsdt = acpi_map_rsdt(); 447 if (rsdt) { 448 aprint_verbose_dev( 449 self, 450 "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n", 451 rsdt->OemId, rsdt->OemTableId, 452 rsdt->OemRevision, 453 rsdt->AslCompilerId, rsdt->AslCompilerRevision); 454 } else 455 aprint_error_dev(self, "X/RSDT: Not found\n"); 456 457 acpi_unmap_rsdt(rsdt); 458 459 sc->sc_dev = self; 460 sc->sc_quirks = acpi_find_quirks(); 461 462 sc->sc_iot = aa->aa_iot; 463 sc->sc_memt = aa->aa_memt; 464 sc->sc_pc = aa->aa_pc; 465 sc->sc_pciflags = aa->aa_pciflags; 466 sc->sc_ic = aa->aa_ic; 467 468 SIMPLEQ_INIT(&sc->sc_devnodes); 469 470 acpi_softc = sc; 471 472 /* 473 * Register null power management handler. 474 */ 475 if (!pmf_device_register(self, acpi_suspend, acpi_resume)) 476 aprint_error_dev(self, "couldn't establish power handler\n"); 477 478 /* 479 * Bring ACPI on-line. 480 */ 481#ifdef ACPI_DEBUGGER 482 if (acpi_dbgr & ACPI_DBGR_ENABLE) 483 acpi_osd_debugger(); 484#endif 485 486#define ACPI_ENABLE_PHASE1 \ 487 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT) 488#define ACPI_ENABLE_PHASE2 \ 489 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \ 490 ACPI_NO_ADDRESS_SPACE_INIT) 491 492 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1); 493 if (ACPI_FAILURE(rv)) { 494 aprint_error_dev(self, "unable to enable ACPI: %s\n", 495 AcpiFormatException(rv)); 496 return; 497 } 498 499 acpi_md_callback(); 500 501 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2); 502 if (ACPI_FAILURE(rv)) { 503 aprint_error_dev(self, "unable to enable ACPI: %s\n", 504 AcpiFormatException(rv)); 505 return; 506 } 507 508 /* Early EC handler initialization if ECDT table is available. */ 509 config_found_ia(self, "acpiecdtbus", NULL, NULL); 510 511 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); 512 if (ACPI_FAILURE(rv)) { 513 aprint_error_dev(self, 514 "unable to initialize ACPI objects: %s\n", 515 AcpiFormatException(rv)); 516 return; 517 } 518 acpi_active = 1; 519 520 /* Our current state is "awake". */ 521 sc->sc_sleepstate = ACPI_STATE_S0; 522 523 /* Show SCI interrupt. */ 524 aprint_verbose_dev(self, "SCI interrupting at int %u\n", 525 AcpiGbl_FADT.SciInterrupt); 526 527 /* 528 * Check for fixed-hardware features. 529 */ 530 acpi_enable_fixed_events(sc); 531 acpitimer_init(); 532 533 /* 534 * Scan the namespace and build our device tree. 535 */ 536#ifdef ACPI_DEBUGGER 537 if (acpi_dbgr & ACPI_DBGR_PROBE) 538 acpi_osd_debugger(); 539#endif 540 acpi_build_tree(sc); 541 542 snprintf(acpi_supported_states, sizeof(acpi_supported_states), 543 "%s%s%s%s%s%s", 544 is_available_state(sc, ACPI_STATE_S0) ? "S0 " : "", 545 is_available_state(sc, ACPI_STATE_S1) ? "S1 " : "", 546 is_available_state(sc, ACPI_STATE_S2) ? "S2 " : "", 547 is_available_state(sc, ACPI_STATE_S3) ? "S3 " : "", 548 is_available_state(sc, ACPI_STATE_S4) ? "S4 " : "", 549 is_available_state(sc, ACPI_STATE_S5) ? "S5 " : ""); 550 551#ifdef ACPI_DEBUGGER 552 if (acpi_dbgr & ACPI_DBGR_RUNNING) 553 acpi_osd_debugger(); 554#endif 555 556#ifdef ACPI_DEBUG 557 acpi_debug_init(); 558#endif 559} 560 561static int 562acpi_detach(device_t self, int flags) 563{ 564 int rc; 565 566#ifdef ACPI_DEBUGGER 567 if (acpi_dbgr & ACPI_DBGR_RUNNING) 568 acpi_osd_debugger(); 569#endif 570 571 if ((rc = config_detach_children(self, flags)) != 0) 572 return rc; 573 574#ifdef ACPI_DEBUGGER 575 if (acpi_dbgr & ACPI_DBGR_PROBE) 576 acpi_osd_debugger(); 577#endif 578 579 if ((rc = acpitimer_detach()) != 0) 580 return rc; 581 582#if 0 583 /* 584 * Bring ACPI on-line. 585 */ 586#ifdef ACPI_DEBUGGER 587 if (acpi_dbgr & ACPI_DBGR_ENABLE) 588 acpi_osd_debugger(); 589#endif 590 591#define ACPI_ENABLE_PHASE1 \ 592 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT) 593#define ACPI_ENABLE_PHASE2 \ 594 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \ 595 ACPI_NO_ADDRESS_SPACE_INIT) 596 597 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1); 598 if (ACPI_FAILURE(rv)) { 599 aprint_error_dev(self, "unable to enable ACPI: %s\n", 600 AcpiFormatException(rv)); 601 return; 602 } 603 604 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2); 605 if (ACPI_FAILURE(rv)) { 606 aprint_error_dev(self, "unable to enable ACPI: %s\n", 607 AcpiFormatException(rv)); 608 return; 609 } 610 611 /* Early EC handler initialization if ECDT table is available. */ 612 config_found_ia(self, "acpiecdtbus", NULL, NULL); 613 614 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); 615 if (ACPI_FAILURE(rv)) { 616 aprint_error_dev(self, 617 "unable to initialize ACPI objects: %s\n", 618 AcpiFormatException(rv)); 619 return; 620 } 621 acpi_active = 1; 622 623 acpi_enable_fixed_events(sc); 624#endif 625 626 pmf_device_deregister(self); 627 628#if 0 629 sysmon_power_settype("acpi"); 630#endif 631 acpi_softc = NULL; 632 633 return 0; 634} 635 636static bool 637acpi_suspend(device_t dv, const pmf_qual_t *qual) 638{ 639 acpi_suspended = 1; 640 return true; 641} 642 643static bool 644acpi_resume(device_t dv, const pmf_qual_t *qual) 645{ 646 acpi_suspended = 0; 647 return true; 648} 649 650#if 0 651/* 652 * acpi_disable: 653 * 654 * Disable ACPI. 655 */ 656static ACPI_STATUS 657acpi_disable(struct acpi_softc *sc) 658{ 659 ACPI_STATUS rv = AE_OK; 660 661 if (acpi_active) { 662 rv = AcpiDisable(); 663 if (ACPI_SUCCESS(rv)) 664 acpi_active = 0; 665 } 666 return rv; 667} 668#endif 669 670/* 671 * acpi_build_tree: 672 * 673 * Scan relevant portions of the ACPI namespace and attach 674 * child devices. 675 */ 676static void 677acpi_build_tree(struct acpi_softc *sc) 678{ 679 static const char *scopes[] = { 680 "\\_PR_", "\\_SB_", "\\_SI_", "\\_TZ_", NULL 681 }; 682 683 ACPI_HANDLE parent; 684 ACPI_STATUS rv; 685 int i; 686 687 /* 688 * Scan the namespace and build our device tree. 689 */ 690 for (i = 0; scopes[i] != NULL; i++) { 691 692 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent); 693 694 if (ACPI_SUCCESS(rv)) 695 (void)AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, 696 acpi_make_devnode, sc, NULL); 697 } 698 699 acpi_rescan1(sc, NULL, NULL); 700 acpi_wakedev_scan(sc); 701 acpi_pcidev_scan(sc); 702} 703 704static int 705acpi_rescan(device_t self, const char *ifattr, const int *locators) 706{ 707 struct acpi_softc *sc = device_private(self); 708 709 acpi_rescan1(sc, ifattr, locators); 710 return 0; 711} 712 713static void 714acpi_rescan1(struct acpi_softc *sc, const char *ifattr, const int *locators) 715{ 716 if (ifattr_match(ifattr, "acpinodebus")) 717 acpi_rescan_nodes(sc); 718 719 if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) { 720 sc->sc_apmbus = config_found_ia(sc->sc_dev, "acpiapmbus", NULL, 721 NULL); 722 } 723} 724 725static void 726acpi_rescan_nodes(struct acpi_softc *sc) 727{ 728 struct acpi_attach_args aa; 729 struct acpi_devnode *ad; 730 731 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) { 732 733 if (ad->ad_device != NULL) 734 continue; 735 736 aa.aa_node = ad; 737 aa.aa_iot = sc->sc_iot; 738 aa.aa_memt = sc->sc_memt; 739 aa.aa_pc = sc->sc_pc; 740 aa.aa_pciflags = sc->sc_pciflags; 741 aa.aa_ic = sc->sc_ic; 742 743 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) { 744 /* 745 * XXX We only attach devices which are: 746 * 747 * - present 748 * - enabled 749 * - functioning properly 750 * 751 * However, if enabled, it's decoding resources, 752 * so we should claim them, if possible. 753 * Requires changes to bus_space(9). 754 */ 755 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) == 756 ACPI_VALID_STA && 757 (ad->ad_devinfo->CurrentStatus & 758 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| 759 ACPI_STA_DEV_OK)) != 760 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| 761 ACPI_STA_DEV_OK)) 762 continue; 763 } 764 765 /* 766 * XXX Same problem as above... 767 * 768 * Do this check only for devices, as e.g. 769 * a Thermal Zone doesn't have a HID. 770 */ 771 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE && 772 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) 773 continue; 774 775 /* 776 * Handled internally. 777 */ 778 if (ad->ad_devinfo->Type == ACPI_TYPE_PROCESSOR || 779 ad->ad_devinfo->Type == ACPI_TYPE_POWER) 780 continue; 781 782 /* 783 * Skip ignored HIDs. 784 */ 785 if (acpi_match_hid(ad->ad_devinfo, acpi_ignored_ids)) 786 continue; 787 788 ad->ad_device = config_found_ia(sc->sc_dev, 789 "acpinodebus", &aa, acpi_print); 790 } 791} 792 793/* 794 * acpi_make_devnode: 795 * 796 * Make an ACPI devnode. 797 */ 798static ACPI_STATUS 799acpi_make_devnode(ACPI_HANDLE handle, uint32_t level, 800 void *context, void **status) 801{ 802 struct acpi_softc *sc = context; 803 struct acpi_devnode *ad; 804 ACPI_DEVICE_INFO *devinfo; 805 ACPI_OBJECT_TYPE type; 806 ACPI_NAME_UNION *anu; 807 ACPI_STATUS rv; 808 int clear, i; 809 810 rv = AcpiGetType(handle, &type); 811 812 if (ACPI_FAILURE(rv)) 813 return AE_OK; /* Do not terminate the walk. */ 814 815 rv = AcpiGetObjectInfo(handle, &devinfo); 816 817 if (ACPI_FAILURE(rv)) { 818 aprint_debug_dev(sc->sc_dev, "failed to get object " 819 "information: %s\n", AcpiFormatException(rv)); 820 return AE_OK; 821 } 822 823 switch (type) { 824 825 case ACPI_TYPE_DEVICE: 826 827#ifdef ACPI_ACTIVATE_DEV 828 acpi_activate_device(handle, &devinfo); 829#endif 830 831 case ACPI_TYPE_PROCESSOR: 832 case ACPI_TYPE_THERMAL: 833 case ACPI_TYPE_POWER: 834 835 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT | M_ZERO); 836 837 if (ad == NULL) 838 return AE_NO_MEMORY; 839 840 ad->ad_parent = sc->sc_dev; 841 ad->ad_devinfo = devinfo; 842 ad->ad_handle = handle; 843 ad->ad_type = type; 844 845 anu = (ACPI_NAME_UNION *)&devinfo->Name; 846 ad->ad_name[4] = '\0'; 847 848 for (i = 3, clear = 0; i >= 0; i--) { 849 850 if (clear == 0 && anu->Ascii[i] == '_') 851 ad->ad_name[i] = '\0'; 852 else { 853 ad->ad_name[i] = anu->Ascii[i]; 854 clear = 1; 855 } 856 } 857 858 if (ad->ad_name[0] == '\0') 859 ad->ad_name[0] = '_'; 860 861 SIMPLEQ_INSERT_TAIL(&sc->sc_devnodes, ad, ad_list); 862 863#ifdef ACPIVERBOSE 864 865 if (type != ACPI_TYPE_DEVICE) 866 return AE_OK; 867 868 aprint_normal_dev(sc->sc_dev, "%-5s ", ad->ad_name); 869 870 aprint_normal("HID %-10s ", 871 ((devinfo->Valid & ACPI_VALID_HID) != 0) ? 872 devinfo->HardwareId.String: "-"); 873 874 aprint_normal("UID %-4s ", 875 ((devinfo->Valid & ACPI_VALID_UID) != 0) ? 876 devinfo->UniqueId.String : "-"); 877 878 if ((devinfo->Valid & ACPI_VALID_STA) != 0) 879 aprint_normal("STA 0x%08X ", devinfo->CurrentStatus); 880 else 881 aprint_normal("STA %10s ", "-"); 882 883 if ((devinfo->Valid & ACPI_VALID_ADR) != 0) 884 aprint_normal("ADR 0x%016" PRIX64"", 885 devinfo->Address); 886 887 aprint_normal("\n"); 888#endif 889 } 890 891 return AE_OK; 892} 893 894/* 895 * acpi_print: 896 * 897 * Autoconfiguration print routine for ACPI node bus. 898 */ 899static int 900acpi_print(void *aux, const char *pnp) 901{ 902 struct acpi_attach_args *aa = aux; 903 ACPI_STATUS rv; 904 905 if (pnp) { 906 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) { 907 char *pnpstr = 908 aa->aa_node->ad_devinfo->HardwareId.String; 909 ACPI_BUFFER buf; 910 911 aprint_normal("%s (%s) ", aa->aa_node->ad_name, 912 pnpstr); 913 914 rv = acpi_eval_struct(aa->aa_node->ad_handle, 915 "_STR", &buf); 916 if (ACPI_SUCCESS(rv)) { 917 ACPI_OBJECT *obj = buf.Pointer; 918 switch (obj->Type) { 919 case ACPI_TYPE_STRING: 920 aprint_normal("[%s] ", obj->String.Pointer); 921 break; 922 case ACPI_TYPE_BUFFER: 923 aprint_normal("buffer %p ", obj->Buffer.Pointer); 924 break; 925 default: 926 aprint_normal("type %u ",obj->Type); 927 break; 928 } 929 ACPI_FREE(buf.Pointer); 930 } 931#ifdef ACPIVERBOSE 932 else { 933 int i; 934 935 for (i = 0; i < __arraycount(acpi_knowndevs); 936 i++) { 937 if (strcmp(acpi_knowndevs[i].pnp, 938 pnpstr) == 0) { 939 aprint_normal("[%s] ", 940 acpi_knowndevs[i].str); 941 } 942 } 943 } 944 945#endif 946 aprint_normal("at %s", pnp); 947 } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) { 948 aprint_normal("%s (ACPI Object Type '%s' " 949 "[0x%02x]) ", aa->aa_node->ad_name, 950 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type), 951 aa->aa_node->ad_devinfo->Type); 952 aprint_normal("at %s", pnp); 953 } else 954 return 0; 955 } else { 956 aprint_normal(" (%s", aa->aa_node->ad_name); 957 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) { 958 aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.String); 959 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) { 960 const char *uid; 961 962 uid = aa->aa_node->ad_devinfo->UniqueId.String; 963 if (uid[0] == '\0') 964 uid = "<null>"; 965 aprint_normal("-%s", uid); 966 } 967 } 968 aprint_normal(")"); 969 } 970 971 return UNCONF; 972} 973 974/***************************************************************************** 975 * ACPI fixed-hardware feature handlers 976 *****************************************************************************/ 977 978static UINT32 acpi_fixed_button_handler(void *); 979static void acpi_fixed_button_pressed(void *); 980 981/* 982 * acpi_enable_fixed_events: 983 * 984 * Enable any fixed-hardware feature handlers. 985 */ 986static void 987acpi_enable_fixed_events(struct acpi_softc *sc) 988{ 989 static int beenhere; 990 ACPI_STATUS rv; 991 992 KASSERT(beenhere == 0); 993 beenhere = 1; 994 995 /* 996 * Check for fixed-hardware buttons. 997 */ 998 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 999 aprint_verbose_dev(sc->sc_dev, 1000 "fixed-feature power button present\n"); 1001 sc->sc_smpsw_power.smpsw_name = device_xname(sc->sc_dev); 1002 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER; 1003 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 1004 aprint_error_dev(sc->sc_dev, 1005 "unable to register fixed power " 1006 "button with sysmon\n"); 1007 } else { 1008 rv = AcpiInstallFixedEventHandler( 1009 ACPI_EVENT_POWER_BUTTON, 1010 acpi_fixed_button_handler, &sc->sc_smpsw_power); 1011 if (ACPI_FAILURE(rv)) { 1012 aprint_error_dev(sc->sc_dev, 1013 "unable to install handler " 1014 "for fixed power button: %s\n", 1015 AcpiFormatException(rv)); 1016 } 1017 } 1018 } 1019 1020 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 1021 aprint_verbose_dev(sc->sc_dev, 1022 "fixed-feature sleep button present\n"); 1023 sc->sc_smpsw_sleep.smpsw_name = device_xname(sc->sc_dev); 1024 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP; 1025 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 1026 aprint_error_dev(sc->sc_dev, 1027 "unable to register fixed sleep " 1028 "button with sysmon\n"); 1029 } else { 1030 rv = AcpiInstallFixedEventHandler( 1031 ACPI_EVENT_SLEEP_BUTTON, 1032 acpi_fixed_button_handler, &sc->sc_smpsw_sleep); 1033 if (ACPI_FAILURE(rv)) { 1034 aprint_error_dev(sc->sc_dev, 1035 "unable to install handler " 1036 "for fixed sleep button: %s\n", 1037 AcpiFormatException(rv)); 1038 } 1039 } 1040 } 1041} 1042 1043/* 1044 * acpi_fixed_button_handler: 1045 * 1046 * Event handler for the fixed buttons. 1047 */ 1048static UINT32 1049acpi_fixed_button_handler(void *context) 1050{ 1051 static const int handler = OSL_NOTIFY_HANDLER; 1052 struct sysmon_pswitch *smpsw = context; 1053 1054 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s\n", __func__)); 1055 1056 (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw); 1057 1058 return ACPI_INTERRUPT_HANDLED; 1059} 1060 1061/* 1062 * acpi_fixed_button_pressed: 1063 * 1064 * Deal with a fixed button being pressed. 1065 */ 1066static void 1067acpi_fixed_button_pressed(void *context) 1068{ 1069 struct sysmon_pswitch *smpsw = context; 1070 1071 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: %s fixed button pressed\n", 1072 __func__, smpsw->smpsw_name)); 1073 1074 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED); 1075} 1076 1077/***************************************************************************** 1078 * ACPI utility routines. 1079 *****************************************************************************/ 1080 1081/* 1082 * acpi_eval_integer: 1083 * 1084 * Evaluate an integer object. 1085 */ 1086ACPI_STATUS 1087acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) 1088{ 1089 ACPI_STATUS rv; 1090 ACPI_BUFFER buf; 1091 ACPI_OBJECT param; 1092 1093 if (handle == NULL) 1094 handle = ACPI_ROOT_OBJECT; 1095 1096 buf.Pointer = ¶m; 1097 buf.Length = sizeof(param); 1098 1099 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, 1100 ACPI_TYPE_INTEGER); 1101 if (ACPI_SUCCESS(rv)) 1102 *valp = param.Integer.Value; 1103 1104 return rv; 1105} 1106 1107/* 1108 * acpi_eval_set_integer: 1109 * 1110 * Evaluate an integer object with a single integer input parameter. 1111 */ 1112ACPI_STATUS 1113acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER arg) 1114{ 1115 ACPI_OBJECT param_arg; 1116 ACPI_OBJECT_LIST param_args; 1117 1118 if (handle == NULL) 1119 handle = ACPI_ROOT_OBJECT; 1120 1121 param_arg.Type = ACPI_TYPE_INTEGER; 1122 param_arg.Integer.Value = arg; 1123 1124 param_args.Count = 1; 1125 param_args.Pointer = ¶m_arg; 1126 1127 return AcpiEvaluateObject(handle, path, ¶m_args, NULL); 1128} 1129 1130/* 1131 * acpi_eval_string: 1132 * 1133 * Evaluate a (Unicode) string object. 1134 */ 1135ACPI_STATUS 1136acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 1137{ 1138 ACPI_OBJECT *obj; 1139 ACPI_BUFFER buf; 1140 ACPI_STATUS rv; 1141 1142 rv = acpi_eval_struct(handle, path, &buf); 1143 1144 if (ACPI_FAILURE(rv)) 1145 return rv; 1146 1147 obj = buf.Pointer; 1148 1149 if (obj->Type != ACPI_TYPE_STRING) { 1150 rv = AE_TYPE; 1151 goto out; 1152 } 1153 1154 if (obj->String.Length == 0) { 1155 rv = AE_BAD_DATA; 1156 goto out; 1157 } 1158 1159 *stringp = ACPI_ALLOCATE(obj->String.Length + 1); 1160 1161 if (*stringp == NULL) { 1162 rv = AE_NO_MEMORY; 1163 goto out; 1164 } 1165 1166 (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); 1167 1168 (*stringp)[obj->String.Length] = '\0'; 1169 1170out: 1171 ACPI_FREE(buf.Pointer); 1172 1173 return rv; 1174} 1175 1176/* 1177 * acpi_eval_struct: 1178 * 1179 * Evaluate a more complex structure. 1180 * Caller must free buf.Pointer by ACPI_FREE(). 1181 */ 1182ACPI_STATUS 1183acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp) 1184{ 1185 ACPI_STATUS rv; 1186 1187 if (handle == NULL) 1188 handle = ACPI_ROOT_OBJECT; 1189 1190 bufp->Pointer = NULL; 1191 bufp->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1192 1193 rv = AcpiEvaluateObject(handle, path, NULL, bufp); 1194 1195 return rv; 1196} 1197 1198/* 1199 * acpi_eval_reference_handle: 1200 * 1201 * Evaluate a reference handle from an element in a package. 1202 */ 1203ACPI_STATUS 1204acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) 1205{ 1206 1207 if (elm == NULL || handle == NULL) 1208 return AE_BAD_PARAMETER; 1209 1210 switch (elm->Type) { 1211 1212 case ACPI_TYPE_ANY: 1213 case ACPI_TYPE_LOCAL_REFERENCE: 1214 1215 if (elm->Reference.Handle == NULL) 1216 return AE_NULL_ENTRY; 1217 1218 *handle = elm->Reference.Handle; 1219 1220 return AE_OK; 1221 1222 case ACPI_TYPE_STRING: 1223 return AcpiGetHandle(NULL, elm->String.Pointer, handle); 1224 1225 default: 1226 return AE_TYPE; 1227 } 1228} 1229 1230/* 1231 * acpi_foreach_package_object: 1232 * 1233 * Iterate over all objects in a package, and pass them all 1234 * to a function. If the called function returns non AE_OK, the 1235 * iteration is stopped and that value is returned. 1236 */ 1237ACPI_STATUS 1238acpi_foreach_package_object(ACPI_OBJECT *pkg, 1239 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), 1240 void *arg) 1241{ 1242 ACPI_STATUS rv = AE_OK; 1243 int i; 1244 1245 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE) 1246 return AE_BAD_PARAMETER; 1247 1248 for (i = 0; i < pkg->Package.Count; i++) { 1249 rv = (*func)(&pkg->Package.Elements[i], arg); 1250 if (ACPI_FAILURE(rv)) 1251 break; 1252 } 1253 1254 return rv; 1255} 1256 1257/* 1258 * acpi_name: 1259 * 1260 * Return a complete pathname from a handle. 1261 * 1262 * Note that the function uses static data storage; 1263 * if the data is needed for future use, it should be 1264 * copied before any subsequent calls overwrite it. 1265 */ 1266const char * 1267acpi_name(ACPI_HANDLE handle) 1268{ 1269 static char buffer[80]; 1270 ACPI_BUFFER buf; 1271 ACPI_STATUS rv; 1272 1273 buf.Length = sizeof(buffer); 1274 buf.Pointer = buffer; 1275 1276 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 1277 if (ACPI_FAILURE(rv)) 1278 return "(unknown acpi path)"; 1279 return buffer; 1280} 1281 1282/* 1283 * acpi_get: 1284 * 1285 * Fetch data info the specified (empty) ACPI buffer. 1286 * Caller must free buf.Pointer by ACPI_FREE(). 1287 */ 1288ACPI_STATUS 1289acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 1290 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 1291{ 1292 buf->Pointer = NULL; 1293 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1294 1295 return (*getit)(handle, buf); 1296} 1297 1298 1299/* 1300 * acpi_match_hid 1301 * 1302 * Match given ids against _HID and _CIDs. 1303 */ 1304int 1305acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 1306{ 1307 int i; 1308 1309 while (*ids) { 1310 if (ad->Valid & ACPI_VALID_HID) { 1311 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) 1312 return 1; 1313 } 1314 1315 if (ad->Valid & ACPI_VALID_CID) { 1316 for (i = 0; i < ad->CompatibleIdList.Count; i++) { 1317 if (pmatch(ad->CompatibleIdList.Ids[i].String, *ids, NULL) == 2) 1318 return 1; 1319 } 1320 } 1321 ids++; 1322 } 1323 1324 return 0; 1325} 1326 1327/* 1328 * acpi_wake_gpe_helper 1329 * 1330 * Set/unset GPE as both Runtime and Wake. 1331 */ 1332static void 1333acpi_wake_gpe_helper(ACPI_HANDLE handle, bool enable) 1334{ 1335 ACPI_OBJECT *elm, *obj; 1336 ACPI_INTEGER val; 1337 ACPI_BUFFER buf; 1338 ACPI_STATUS rv; 1339 1340 rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf); 1341 1342 if (ACPI_FAILURE(rv)) 1343 return; 1344 1345 obj = buf.Pointer; 1346 1347 if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count < 2) 1348 goto out; 1349 1350 /* 1351 * As noted in ACPI 3.0 (section 7.2.10), the _PRW object is 1352 * a package in which the first element is either an integer 1353 * or again a package. In the latter case the package inside 1354 * the package element has two elements, a reference handle 1355 * and the GPE number. 1356 */ 1357 elm = &obj->Package.Elements[0]; 1358 1359 switch (elm->Type) { 1360 1361 case ACPI_TYPE_INTEGER: 1362 val = elm->Integer.Value; 1363 break; 1364 1365 case ACPI_TYPE_PACKAGE: 1366 1367 if (elm->Package.Count < 2) 1368 goto out; 1369 1370 if (elm->Package.Elements[0].Type != ACPI_TYPE_LOCAL_REFERENCE) 1371 goto out; 1372 1373 if (elm->Package.Elements[1].Type != ACPI_TYPE_INTEGER) 1374 goto out; 1375 1376 val = elm->Package.Elements[1].Integer.Value; 1377 break; 1378 1379 default: 1380 goto out; 1381 } 1382 1383 if (enable) { 1384 (void)AcpiSetGpeType(NULL, val, ACPI_GPE_TYPE_WAKE_RUN); 1385 (void)AcpiEnableGpe(NULL, val, ACPI_NOT_ISR); 1386 } else 1387 (void)AcpiDisableGpe(NULL, val, ACPI_NOT_ISR); 1388 1389out: 1390 ACPI_FREE(buf.Pointer); 1391} 1392 1393/* 1394 * acpi_clear_wake_gpe 1395 * 1396 * Clear GPE as both Runtime and Wake. 1397 */ 1398void 1399acpi_clear_wake_gpe(ACPI_HANDLE handle) 1400{ 1401 acpi_wake_gpe_helper(handle, false); 1402} 1403 1404/* 1405 * acpi_set_wake_gpe 1406 * 1407 * Set GPE as both Runtime and Wake. 1408 */ 1409void 1410acpi_set_wake_gpe(ACPI_HANDLE handle) 1411{ 1412 acpi_wake_gpe_helper(handle, true); 1413} 1414 1415 1416/***************************************************************************** 1417 * ACPI sleep support. 1418 *****************************************************************************/ 1419 1420static int 1421is_available_state(struct acpi_softc *sc, int state) 1422{ 1423 UINT8 type_a, type_b; 1424 1425 return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state, 1426 &type_a, &type_b)); 1427} 1428 1429/* 1430 * acpi_enter_sleep_state: 1431 * 1432 * Enter to the specified sleep state. 1433 */ 1434 1435ACPI_STATUS 1436acpi_enter_sleep_state(struct acpi_softc *sc, int state) 1437{ 1438 int err; 1439 ACPI_STATUS ret = AE_OK; 1440 1441 if (state == acpi_sleepstate) 1442 return AE_OK; 1443 1444 aprint_normal_dev(sc->sc_dev, "entering state %d\n", state); 1445 1446 switch (state) { 1447 case ACPI_STATE_S0: 1448 break; 1449 case ACPI_STATE_S1: 1450 case ACPI_STATE_S2: 1451 case ACPI_STATE_S3: 1452 case ACPI_STATE_S4: 1453 if (!is_available_state(sc, state)) { 1454 aprint_error_dev(sc->sc_dev, 1455 "ACPI S%d not available on this platform\n", state); 1456 break; 1457 } 1458 1459 acpi_wakedev_commit(sc, state); 1460 1461 if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_Q_NONE)) { 1462 aprint_error_dev(sc->sc_dev, "aborting suspend\n"); 1463 break; 1464 } 1465 1466 ret = AcpiEnterSleepStatePrep(state); 1467 if (ACPI_FAILURE(ret)) { 1468 aprint_error_dev(sc->sc_dev, 1469 "failed preparing to sleep (%s)\n", 1470 AcpiFormatException(ret)); 1471 break; 1472 } 1473 1474 acpi_sleepstate = state; 1475 if (state == ACPI_STATE_S1) { 1476 /* just enter the state */ 1477 acpi_md_OsDisableInterrupt(); 1478 ret = AcpiEnterSleepState((UINT8)state); 1479 if (ACPI_FAILURE(ret)) 1480 aprint_error_dev(sc->sc_dev, 1481 "failed to enter sleep state S1: %s\n", 1482 AcpiFormatException(ret)); 1483 AcpiLeaveSleepState((UINT8)state); 1484 } else { 1485 err = acpi_md_sleep(state); 1486 if (state == ACPI_STATE_S4) 1487 AcpiEnable(); 1488 pmf_system_bus_resume(PMF_Q_NONE); 1489 AcpiLeaveSleepState((UINT8)state); 1490 pmf_system_resume(PMF_Q_NONE); 1491 } 1492 1493 break; 1494 case ACPI_STATE_S5: 1495 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5); 1496 if (ACPI_FAILURE(ret)) { 1497 aprint_error_dev(sc->sc_dev, 1498 "failed preparing to sleep (%s)\n", 1499 AcpiFormatException(ret)); 1500 break; 1501 } 1502 DELAY(1000000); 1503 acpi_sleepstate = state; 1504 acpi_md_OsDisableInterrupt(); 1505 AcpiEnterSleepState(ACPI_STATE_S5); 1506 aprint_error_dev(sc->sc_dev, "WARNING powerdown failed!\n"); 1507 break; 1508 } 1509 1510 acpi_sleepstate = ACPI_STATE_S0; 1511 return ret; 1512} 1513 1514#ifdef ACPI_ACTIVATE_DEV 1515 1516#define ACPI_DEV_VALID (ACPI_VALID_STA | ACPI_VALID_HID) 1517#define ACPI_DEV_STATUS (ACPI_STA_DEV_PRESENT | ACPI_STA_DEV_ENABLED) 1518 1519static void 1520acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di) 1521{ 1522 ACPI_DEVICE_INFO *newdi; 1523 ACPI_STATUS rv; 1524 uint32_t old; 1525 1526 /* 1527 * If the device is valid and present, 1528 * but not enabled, try to activate it. 1529 */ 1530 if (((*di)->Valid & ACPI_DEV_VALID) != ACPI_DEV_VALID) 1531 return; 1532 1533 old = (*di)->CurrentStatus; 1534 1535 if ((old & ACPI_DEV_STATUS) != ACPI_STA_DEV_PRESENT) 1536 return; 1537 1538 rv = acpi_allocate_resources(handle); 1539 1540 if (ACPI_FAILURE(rv)) 1541 goto fail; 1542 1543 rv = AcpiGetObjectInfo(handle, &newdi); 1544 1545 if (ACPI_FAILURE(rv)) 1546 goto fail; 1547 1548 ACPI_FREE(*di); 1549 *di = newdi; 1550 1551 aprint_verbose_dev(acpi_softc->sc_dev, 1552 "%s activated, STA 0x%08X -> STA 0x%08X\n", 1553 (*di)->HardwareId.String, old, (*di)->CurrentStatus); 1554 1555 return; 1556 1557fail: 1558 aprint_error_dev(acpi_softc->sc_dev, "failed to " 1559 "activate %s\n", (*di)->HardwareId.String); 1560} 1561 1562/* 1563 * XXX: This very incomplete. 1564 */ 1565ACPI_STATUS 1566acpi_allocate_resources(ACPI_HANDLE handle) 1567{ 1568 ACPI_BUFFER bufp, bufc, bufn; 1569 ACPI_RESOURCE *resp, *resc, *resn; 1570 ACPI_RESOURCE_IRQ *irq; 1571 ACPI_RESOURCE_EXTENDED_IRQ *xirq; 1572 ACPI_STATUS rv; 1573 uint delta; 1574 1575 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources); 1576 if (ACPI_FAILURE(rv)) 1577 goto out; 1578 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources); 1579 if (ACPI_FAILURE(rv)) { 1580 goto out1; 1581 } 1582 1583 bufn.Length = 1000; 1584 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK); 1585 resp = bufp.Pointer; 1586 resc = bufc.Pointer; 1587 while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG && 1588 resp->Type != ACPI_RESOURCE_TYPE_END_TAG) { 1589 while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG) 1590 resp = ACPI_NEXT_RESOURCE(resp); 1591 if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG) 1592 break; 1593 /* Found identical Id */ 1594 resn->Type = resc->Type; 1595 switch (resc->Type) { 1596 case ACPI_RESOURCE_TYPE_IRQ: 1597 memcpy(&resn->Data, &resp->Data, 1598 sizeof(ACPI_RESOURCE_IRQ)); 1599 irq = (ACPI_RESOURCE_IRQ *)&resn->Data; 1600 irq->Interrupts[0] = 1601 ((ACPI_RESOURCE_IRQ *)&resp->Data)-> 1602 Interrupts[irq->InterruptCount-1]; 1603 irq->InterruptCount = 1; 1604 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ); 1605 break; 1606 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 1607 memcpy(&resn->Data, &resp->Data, 1608 sizeof(ACPI_RESOURCE_EXTENDED_IRQ)); 1609 xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data; 1610#if 0 1611 /* 1612 * XXX not duplicating the interrupt logic above 1613 * because its not clear what it accomplishes. 1614 */ 1615 xirq->Interrupts[0] = 1616 ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)-> 1617 Interrupts[irq->NumberOfInterrupts-1]; 1618 xirq->NumberOfInterrupts = 1; 1619#endif 1620 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ); 1621 break; 1622 case ACPI_RESOURCE_TYPE_IO: 1623 memcpy(&resn->Data, &resp->Data, 1624 sizeof(ACPI_RESOURCE_IO)); 1625 resn->Length = resp->Length; 1626 break; 1627 default: 1628 aprint_error_dev(acpi_softc->sc_dev, 1629 "%s: invalid type %u\n", __func__, resc->Type); 1630 rv = AE_BAD_DATA; 1631 goto out2; 1632 } 1633 resc = ACPI_NEXT_RESOURCE(resc); 1634 resn = ACPI_NEXT_RESOURCE(resn); 1635 resp = ACPI_NEXT_RESOURCE(resp); 1636 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer; 1637 if (delta >= 1638 bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) { 1639 bufn.Length *= 2; 1640 bufn.Pointer = realloc(bufn.Pointer, bufn.Length, 1641 M_ACPI, M_WAITOK); 1642 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta); 1643 } 1644 } 1645 1646 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) { 1647 aprint_error_dev(acpi_softc->sc_dev, 1648 "%s: resc not exhausted\n", __func__); 1649 rv = AE_BAD_DATA; 1650 goto out3; 1651 } 1652 1653 resn->Type = ACPI_RESOURCE_TYPE_END_TAG; 1654 rv = AcpiSetCurrentResources(handle, &bufn); 1655 1656 if (ACPI_FAILURE(rv)) 1657 aprint_error_dev(acpi_softc->sc_dev, "%s: failed to set " 1658 "resources: %s\n", __func__, AcpiFormatException(rv)); 1659 1660out3: 1661 free(bufn.Pointer, M_ACPI); 1662out2: 1663 ACPI_FREE(bufc.Pointer); 1664out1: 1665 ACPI_FREE(bufp.Pointer); 1666out: 1667 return rv; 1668} 1669 1670#undef ACPI_DEV_VALID 1671#undef ACPI_DEV_STATUS 1672 1673#endif /* ACPI_ACTIVATE_DEV */ 1674 1675SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup") 1676{ 1677 const struct sysctlnode *node; 1678 const struct sysctlnode *ssnode; 1679 1680 if (sysctl_createv(clog, 0, NULL, NULL, 1681 CTLFLAG_PERMANENT, 1682 CTLTYPE_NODE, "hw", NULL, 1683 NULL, 0, NULL, 0, 1684 CTL_HW, CTL_EOL) != 0) 1685 return; 1686 1687 if (sysctl_createv(clog, 0, NULL, &node, 1688 CTLFLAG_PERMANENT, 1689 CTLTYPE_NODE, "acpi", NULL, 1690 NULL, 0, NULL, 0, 1691 CTL_HW, CTL_CREATE, CTL_EOL) != 0) 1692 return; 1693 1694 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY, 1695 CTLTYPE_QUAD, "root", 1696 SYSCTL_DESCR("ACPI root pointer"), 1697 NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer), 1698 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 1699 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY, 1700 CTLTYPE_STRING, "supported_states", 1701 SYSCTL_DESCR("Supported ACPI system states"), 1702 NULL, 0, acpi_supported_states, 0, 1703 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 1704 1705 /* ACPI sleepstate sysctl */ 1706 if (sysctl_createv(NULL, 0, NULL, &node, 1707 CTLFLAG_PERMANENT, 1708 CTLTYPE_NODE, "machdep", NULL, 1709 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0) 1710 return; 1711 if (sysctl_createv(NULL, 0, &node, &ssnode, 1712 CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state", 1713 NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE, 1714 CTL_EOL) != 0) 1715 return; 1716} 1717 1718static int 1719sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS) 1720{ 1721 int error, t; 1722 struct sysctlnode node; 1723 1724 node = *rnode; 1725 t = acpi_sleepstate; 1726 node.sysctl_data = &t; 1727 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1728 if (error || newp == NULL) 1729 return error; 1730 1731 if (acpi_softc == NULL) 1732 return ENOSYS; 1733 1734 acpi_enter_sleep_state(acpi_softc, t); 1735 1736 return 0; 1737} 1738 1739static ACPI_TABLE_HEADER * 1740acpi_map_rsdt(void) 1741{ 1742 ACPI_PHYSICAL_ADDRESS paddr; 1743 ACPI_TABLE_RSDP *rsdp; 1744 1745 paddr = AcpiOsGetRootPointer(); 1746 if (paddr == 0) { 1747 printf("ACPI: couldn't get root pointer\n"); 1748 return NULL; 1749 } 1750 rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP)); 1751 if (rsdp == NULL) { 1752 printf("ACPI: couldn't map RSDP\n"); 1753 return NULL; 1754 } 1755 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress) 1756 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress; 1757 else 1758 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress; 1759 AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP)); 1760 1761 return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER)); 1762} 1763 1764static void 1765acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt) 1766{ 1767 if (rsdt == NULL) 1768 return; 1769 1770 AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER)); 1771} 1772