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