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