acpi.c revision 1.124
1/* $NetBSD: acpi.c,v 1.124 2009/04/08 00:23:30 dyoung 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.124 2009/04/08 00:23:30 dyoung 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, struct cfdata *, 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, struct cfdata *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 sprintf(acpi_supported_states, "%s%s%s%s%s%s", 523 is_available_state(sc, ACPI_STATE_S0) ? "S0 " : "", 524 is_available_state(sc, ACPI_STATE_S1) ? "S1 " : "", 525 is_available_state(sc, ACPI_STATE_S2) ? "S2 " : "", 526 is_available_state(sc, ACPI_STATE_S3) ? "S3 " : "", 527 is_available_state(sc, ACPI_STATE_S4) ? "S4 " : "", 528 is_available_state(sc, ACPI_STATE_S5) ? "S5 " : ""); 529 530#ifdef ACPI_DEBUGGER 531 if (acpi_dbgr & ACPI_DBGR_RUNNING) 532 acpi_osd_debugger(); 533#endif 534} 535 536static int 537acpi_detach(device_t self, int flags) 538{ 539 int rc; 540 541#ifdef ACPI_DEBUGGER 542 if (acpi_dbgr & ACPI_DBGR_RUNNING) 543 acpi_osd_debugger(); 544#endif 545 546 if ((rc = config_detach_children(self, flags)) != 0) 547 return rc; 548 549#ifdef ACPI_DEBUGGER 550 if (acpi_dbgr & ACPI_DBGR_PROBE) 551 acpi_osd_debugger(); 552#endif 553 554 if ((rc = acpitimer_detach()) != 0) 555 return rc; 556 557#if 0 558 /* 559 * Bring ACPI on-line. 560 */ 561#ifdef ACPI_DEBUGGER 562 if (acpi_dbgr & ACPI_DBGR_ENABLE) 563 acpi_osd_debugger(); 564#endif 565 566#define ACPI_ENABLE_PHASE1 \ 567 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT) 568#define ACPI_ENABLE_PHASE2 \ 569 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \ 570 ACPI_NO_ADDRESS_SPACE_INIT) 571 572 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1); 573 if (ACPI_FAILURE(rv)) { 574 aprint_error_dev(self, "unable to enable ACPI: %s\n", 575 AcpiFormatException(rv)); 576 return; 577 } 578 579 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2); 580 if (ACPI_FAILURE(rv)) { 581 aprint_error_dev(self, "unable to enable ACPI: %s\n", 582 AcpiFormatException(rv)); 583 return; 584 } 585 586 /* early EC handler initialization if ECDT table is available */ 587 config_found_ia(self, "acpiecdtbus", NULL, NULL); 588 589 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); 590 if (ACPI_FAILURE(rv)) { 591 aprint_error_dev(self, 592 "unable to initialize ACPI objects: %s\n", 593 AcpiFormatException(rv)); 594 return; 595 } 596 acpi_active = 1; 597 598 acpi_enable_fixed_events(sc); 599#endif 600 601 pmf_device_deregister(self); 602 603#if 0 604 sysmon_power_settype("acpi"); 605#endif 606 acpi_softc = NULL; 607 608 return 0; 609} 610 611static bool 612acpi_suspend(device_t dv PMF_FN_ARGS) 613{ 614 acpi_suspended = 1; 615 return true; 616} 617 618static bool 619acpi_resume(device_t dv PMF_FN_ARGS) 620{ 621 acpi_suspended = 0; 622 return true; 623} 624 625#if 0 626/* 627 * acpi_disable: 628 * 629 * Disable ACPI. 630 */ 631static ACPI_STATUS 632acpi_disable(struct acpi_softc *sc) 633{ 634 ACPI_STATUS rv = AE_OK; 635 636 if (acpi_active) { 637 rv = AcpiDisable(); 638 if (ACPI_SUCCESS(rv)) 639 acpi_active = 0; 640 } 641 return rv; 642} 643#endif 644 645struct acpi_make_devnode_state { 646 struct acpi_softc *softc; 647 struct acpi_scope *scope; 648}; 649 650/* 651 * acpi_build_tree: 652 * 653 * Scan relevant portions of the ACPI namespace and attach 654 * child devices. 655 */ 656static void 657acpi_build_tree(struct acpi_softc *sc) 658{ 659 static const char *scopes[] = { 660 "\\_PR_", /* ACPI 1.0 processor namespace */ 661 "\\_SB_", /* system bus namespace */ 662 "\\_SI_", /* system indicator namespace */ 663 "\\_TZ_", /* ACPI 1.0 thermal zone namespace */ 664 NULL, 665 }; 666 struct acpi_make_devnode_state state; 667 struct acpi_scope *as; 668 ACPI_HANDLE parent; 669 ACPI_STATUS rv; 670 int i; 671 672 TAILQ_INIT(&sc->sc_scopes); 673 674 state.softc = sc; 675 676 /* 677 * Scan the namespace and build our tree. 678 */ 679 for (i = 0; scopes[i] != NULL; i++) { 680 as = malloc(sizeof(*as), M_ACPI, M_WAITOK); 681 as->as_name = scopes[i]; 682 TAILQ_INIT(&as->as_devnodes); 683 684 TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list); 685 686 state.scope = as; 687 688 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], 689 &parent); 690 if (ACPI_SUCCESS(rv)) { 691 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, 692 acpi_make_devnode, &state, NULL); 693 } 694 } 695 696 acpi_rescan1(sc, NULL, NULL); 697} 698 699static int 700acpi_rescan(device_t self, const char *ifattr, const int *locators) 701{ 702 struct acpi_softc *sc = device_private(self); 703 704 acpi_rescan1(sc, ifattr, locators); 705 return 0; 706} 707 708/* XXX share this with sys/arch/i386/pci/elan520.c */ 709static bool 710ifattr_match(const char *snull, const char *t) 711{ 712 return (snull == NULL) || strcmp(snull, t) == 0; 713} 714 715static void 716acpi_rescan1(struct acpi_softc *sc, const char *ifattr, const int *locators) 717{ 718 if (ifattr_match(ifattr, "acpinodebus")) 719 acpi_rescan_nodes(sc); 720 721 if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) { 722 sc->sc_apmbus = config_found_ia(sc->sc_dev, "acpiapmbus", NULL, 723 NULL); 724 } 725} 726 727static void 728acpi_rescan_nodes(struct acpi_softc *sc) 729{ 730 struct acpi_scope *as; 731 732 TAILQ_FOREACH(as, &sc->sc_scopes, as_list) { 733 struct acpi_devnode *ad; 734 735 /* Now, for this namespace, try to attach the devices. */ 736 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) { 737 struct acpi_attach_args aa; 738 739 if (ad->ad_device != NULL) 740 continue; 741 742 aa.aa_node = ad; 743 aa.aa_iot = sc->sc_iot; 744 aa.aa_memt = sc->sc_memt; 745 aa.aa_pc = sc->sc_pc; 746 aa.aa_pciflags = sc->sc_pciflags; 747 aa.aa_ic = sc->sc_ic; 748 749 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) { 750 /* 751 * XXX We only attach devices which are: 752 * 753 * - present 754 * - enabled 755 * - functioning properly 756 * 757 * However, if enabled, it's decoding resources, 758 * so we should claim them, if possible. 759 * Requires changes to bus_space(9). 760 */ 761 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) == 762 ACPI_VALID_STA && 763 (ad->ad_devinfo->CurrentStatus & 764 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| 765 ACPI_STA_DEV_OK)) != 766 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| 767 ACPI_STA_DEV_OK)) 768 continue; 769 } 770 771 /* 772 * XXX Same problem as above... 773 * 774 * Do this check only for devices, as e.g. 775 * a Thermal Zone doesn't have a HID. 776 */ 777 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE && 778 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) 779 continue; 780 781 /* 782 * Handled internally 783 */ 784 if (ad->ad_devinfo->Type == ACPI_TYPE_PROCESSOR || 785 ad->ad_devinfo->Type == ACPI_TYPE_POWER) 786 continue; 787 788 /* 789 * Skip ignored HIDs 790 */ 791 if (acpi_match_hid(ad->ad_devinfo, acpi_ignored_ids)) 792 continue; 793 794 ad->ad_device = config_found_ia(sc->sc_dev, 795 "acpinodebus", &aa, acpi_print); 796 } 797 } 798} 799 800#ifdef ACPI_ACTIVATE_DEV 801static void 802acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di) 803{ 804 ACPI_STATUS rv; 805 ACPI_BUFFER buf; 806 807 buf.Pointer = NULL; 808 buf.Length = ACPI_ALLOCATE_BUFFER; 809 810#ifdef ACPI_DEBUG 811 aprint_normal("acpi_activate_device: %s, old status=%x\n", 812 (*di)->HardwareId.Value, (*di)->CurrentStatus); 813#endif 814 815 rv = acpi_allocate_resources(handle); 816 if (ACPI_FAILURE(rv)) { 817 aprint_error("acpi: activate failed for %s\n", 818 (*di)->HardwareId.Value); 819 } else { 820 aprint_verbose("acpi: activated %s\n", 821 (*di)->HardwareId.Value); 822 } 823 824 (void)AcpiGetObjectInfo(handle, &buf); 825 AcpiOsFree(*di); 826 *di = buf.Pointer; 827 828#ifdef ACPI_DEBUG 829 aprint_normal("acpi_activate_device: %s, new status=%x\n", 830 (*di)->HardwareId.Value, (*di)->CurrentStatus); 831#endif 832} 833#endif /* ACPI_ACTIVATE_DEV */ 834 835/* 836 * acpi_make_devnode: 837 * 838 * Make an ACPI devnode. 839 */ 840static ACPI_STATUS 841acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context, 842 void **status) 843{ 844 struct acpi_make_devnode_state *state = context; 845#if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG) 846 struct acpi_softc *sc = state->softc; 847#endif 848 struct acpi_scope *as = state->scope; 849 struct acpi_devnode *ad; 850 ACPI_OBJECT_TYPE type; 851 ACPI_BUFFER buf; 852 ACPI_DEVICE_INFO *devinfo; 853 ACPI_STATUS rv; 854 ACPI_NAME_UNION *anu; 855 int i, clear = 0; 856 857 rv = AcpiGetType(handle, &type); 858 if (ACPI_SUCCESS(rv)) { 859 buf.Pointer = NULL; 860 buf.Length = ACPI_ALLOCATE_BUFFER; 861 rv = AcpiGetObjectInfo(handle, &buf); 862 if (ACPI_FAILURE(rv)) { 863#ifdef ACPI_DEBUG 864 aprint_normal_dev(sc->sc_dev, 865 "AcpiGetObjectInfo failed: %s\n", 866 AcpiFormatException(rv)); 867#endif 868 goto out; /* XXX why return OK */ 869 } 870 871 devinfo = buf.Pointer; 872 873 switch (type) { 874 case ACPI_TYPE_DEVICE: 875#ifdef ACPI_ACTIVATE_DEV 876 if ((devinfo->Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) == 877 (ACPI_VALID_STA|ACPI_VALID_HID) && 878 (devinfo->CurrentStatus & 879 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) == 880 ACPI_STA_DEV_PRESENT) 881 acpi_activate_device(handle, &devinfo); 882 883 /* FALLTHROUGH */ 884#endif 885 886 case ACPI_TYPE_PROCESSOR: 887 case ACPI_TYPE_THERMAL: 888 case ACPI_TYPE_POWER: 889 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO); 890 if (ad == NULL) 891 return AE_NO_MEMORY; 892 893 ad->ad_devinfo = devinfo; 894 ad->ad_handle = handle; 895 ad->ad_level = level; 896 ad->ad_scope = as; 897 ad->ad_type = type; 898 899 anu = (ACPI_NAME_UNION *)&devinfo->Name; 900 ad->ad_name[4] = '\0'; 901 for (i = 3, clear = 0; i >= 0; i--) { 902 if (!clear && anu->Ascii[i] == '_') 903 ad->ad_name[i] = '\0'; 904 else { 905 ad->ad_name[i] = anu->Ascii[i]; 906 clear = 1; 907 } 908 } 909 if (ad->ad_name[0] == '\0') 910 ad->ad_name[0] = '_'; 911 912 TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list); 913 914 if (type == ACPI_TYPE_DEVICE && 915 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) 916 goto out; 917 918#ifdef ACPI_EXTRA_DEBUG 919 aprint_normal_dev(sc->sc_dev, 920 "HID %s found in scope %s level %d\n", 921 ad->ad_devinfo->HardwareId.Value, 922 as->as_name, ad->ad_level); 923 if (ad->ad_devinfo->Valid & ACPI_VALID_UID) 924 aprint_normal(" UID %s\n", 925 ad->ad_devinfo->UniqueId.Value); 926 if (ad->ad_devinfo->Valid & ACPI_VALID_ADR) 927 aprint_normal(" ADR 0x%016" PRIx64 "\n", 928 ad->ad_devinfo->Address); 929 if (ad->ad_devinfo->Valid & ACPI_VALID_STA) 930 aprint_normal(" STA 0x%08x\n", 931 ad->ad_devinfo->CurrentStatus); 932#endif 933 } 934 } 935 out: 936 return AE_OK; 937} 938 939/* 940 * acpi_print: 941 * 942 * Autoconfiguration print routine for ACPI node bus. 943 */ 944static int 945acpi_print(void *aux, const char *pnp) 946{ 947 struct acpi_attach_args *aa = aux; 948 ACPI_STATUS rv; 949 950 if (pnp) { 951 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) { 952 char *pnpstr = 953 aa->aa_node->ad_devinfo->HardwareId.Value; 954 ACPI_BUFFER buf; 955 956 aprint_normal("%s (%s) ", aa->aa_node->ad_name, 957 pnpstr); 958 959 buf.Pointer = NULL; 960 buf.Length = ACPI_ALLOCATE_BUFFER; 961 rv = AcpiEvaluateObject(aa->aa_node->ad_handle, 962 "_STR", NULL, &buf); 963 if (ACPI_SUCCESS(rv)) { 964 ACPI_OBJECT *obj = buf.Pointer; 965 switch (obj->Type) { 966 case ACPI_TYPE_STRING: 967 aprint_normal("[%s] ", obj->String.Pointer); 968 break; 969 case ACPI_TYPE_BUFFER: 970 aprint_normal("buffer %p ", obj->Buffer.Pointer); 971 break; 972 default: 973 aprint_normal("type %d ",obj->Type); 974 break; 975 } 976 AcpiOsFree(buf.Pointer); 977 } 978#ifdef ACPIVERBOSE 979 else { 980 int i; 981 982 for (i = 0; i < sizeof(acpi_knowndevs) / 983 sizeof(acpi_knowndevs[0]); i++) { 984 if (strcmp(acpi_knowndevs[i].pnp, 985 pnpstr) == 0) { 986 aprint_normal("[%s] ", 987 acpi_knowndevs[i].str); 988 } 989 } 990 } 991 992#endif 993 aprint_normal("at %s", pnp); 994 } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) { 995 aprint_normal("%s (ACPI Object Type '%s' " 996 "[0x%02x]) ", aa->aa_node->ad_name, 997 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type), 998 aa->aa_node->ad_devinfo->Type); 999 aprint_normal("at %s", pnp); 1000 } else 1001 return 0; 1002 } else { 1003 aprint_normal(" (%s", aa->aa_node->ad_name); 1004 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) { 1005 aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.Value); 1006 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) { 1007 const char *uid; 1008 1009 uid = aa->aa_node->ad_devinfo->UniqueId.Value; 1010 if (uid[0] == '\0') 1011 uid = "<null>"; 1012 aprint_normal("-%s", uid); 1013 } 1014 } 1015 aprint_normal(")"); 1016 } 1017 1018 return UNCONF; 1019} 1020 1021/***************************************************************************** 1022 * ACPI fixed-hardware feature handlers 1023 *****************************************************************************/ 1024 1025static UINT32 acpi_fixed_button_handler(void *); 1026static void acpi_fixed_button_pressed(void *); 1027 1028/* 1029 * acpi_enable_fixed_events: 1030 * 1031 * Enable any fixed-hardware feature handlers. 1032 */ 1033static void 1034acpi_enable_fixed_events(struct acpi_softc *sc) 1035{ 1036 static int beenhere; 1037 ACPI_STATUS rv; 1038 1039 KASSERT(beenhere == 0); 1040 beenhere = 1; 1041 1042 /* 1043 * Check for fixed-hardware buttons. 1044 */ 1045 1046 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 1047 aprint_verbose_dev(sc->sc_dev, 1048 "fixed-feature power button present\n"); 1049 sc->sc_smpsw_power.smpsw_name = device_xname(sc->sc_dev); 1050 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER; 1051 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 1052 aprint_error_dev(sc->sc_dev, 1053 "unable to register fixed power " 1054 "button with sysmon\n"); 1055 } else { 1056 rv = AcpiInstallFixedEventHandler( 1057 ACPI_EVENT_POWER_BUTTON, 1058 acpi_fixed_button_handler, &sc->sc_smpsw_power); 1059 if (ACPI_FAILURE(rv)) { 1060 aprint_error_dev(sc->sc_dev, 1061 "unable to install handler " 1062 "for fixed power button: %s\n", 1063 AcpiFormatException(rv)); 1064 } 1065 } 1066 } 1067 1068 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 1069 aprint_verbose_dev(sc->sc_dev, 1070 "fixed-feature sleep button present\n"); 1071 sc->sc_smpsw_sleep.smpsw_name = device_xname(sc->sc_dev); 1072 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP; 1073 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 1074 aprint_error_dev(sc->sc_dev, 1075 "unable to register fixed sleep " 1076 "button with sysmon\n"); 1077 } else { 1078 rv = AcpiInstallFixedEventHandler( 1079 ACPI_EVENT_SLEEP_BUTTON, 1080 acpi_fixed_button_handler, &sc->sc_smpsw_sleep); 1081 if (ACPI_FAILURE(rv)) { 1082 aprint_error_dev(sc->sc_dev, 1083 "unable to install handler " 1084 "for fixed sleep button: %s\n", 1085 AcpiFormatException(rv)); 1086 } 1087 } 1088 } 1089} 1090 1091/* 1092 * acpi_fixed_button_handler: 1093 * 1094 * Event handler for the fixed buttons. 1095 */ 1096static UINT32 1097acpi_fixed_button_handler(void *context) 1098{ 1099 struct sysmon_pswitch *smpsw = context; 1100 int rv; 1101 1102#ifdef ACPI_BUT_DEBUG 1103 printf("%s: fixed button handler\n", smpsw->smpsw_name); 1104#endif 1105 1106 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, 1107 acpi_fixed_button_pressed, smpsw); 1108 if (ACPI_FAILURE(rv)) 1109 printf("%s: WARNING: unable to queue fixed button pressed " 1110 "callback: %s\n", smpsw->smpsw_name, 1111 AcpiFormatException(rv)); 1112 1113 return ACPI_INTERRUPT_HANDLED; 1114} 1115 1116/* 1117 * acpi_fixed_button_pressed: 1118 * 1119 * Deal with a fixed button being pressed. 1120 */ 1121static void 1122acpi_fixed_button_pressed(void *context) 1123{ 1124 struct sysmon_pswitch *smpsw = context; 1125 1126#ifdef ACPI_BUT_DEBUG 1127 printf("%s: fixed button pressed, calling sysmon\n", 1128 smpsw->smpsw_name); 1129#endif 1130 1131 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED); 1132} 1133 1134/***************************************************************************** 1135 * ACPI utility routines. 1136 *****************************************************************************/ 1137 1138/* 1139 * acpi_eval_integer: 1140 * 1141 * Evaluate an integer object. 1142 */ 1143ACPI_STATUS 1144acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) 1145{ 1146 ACPI_STATUS rv; 1147 ACPI_BUFFER buf; 1148 ACPI_OBJECT param; 1149 1150 if (handle == NULL) 1151 handle = ACPI_ROOT_OBJECT; 1152 1153 buf.Pointer = ¶m; 1154 buf.Length = sizeof(param); 1155 1156 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_INTEGER); 1157 if (ACPI_SUCCESS(rv)) 1158 *valp = param.Integer.Value; 1159 1160 return rv; 1161} 1162 1163/* 1164 * acpi_eval_string: 1165 * 1166 * Evaluate a (Unicode) string object. 1167 */ 1168ACPI_STATUS 1169acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 1170{ 1171 ACPI_STATUS rv; 1172 ACPI_BUFFER buf; 1173 1174 if (handle == NULL) 1175 handle = ACPI_ROOT_OBJECT; 1176 1177 buf.Pointer = NULL; 1178 buf.Length = ACPI_ALLOCATE_BUFFER; 1179 1180 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING); 1181 if (ACPI_SUCCESS(rv)) { 1182 ACPI_OBJECT *param = buf.Pointer; 1183 const char *ptr = param->String.Pointer; 1184 size_t len = param->String.Length; 1185 if ((*stringp = AcpiOsAllocate(len)) == NULL) 1186 rv = AE_NO_MEMORY; 1187 else 1188 (void)memcpy(*stringp, ptr, len); 1189 AcpiOsFree(param); 1190 } 1191 1192 return rv; 1193} 1194 1195 1196/* 1197 * acpi_eval_struct: 1198 * 1199 * Evaluate a more complex structure. 1200 * Caller must free buf.Pointer by AcpiOsFree(). 1201 */ 1202ACPI_STATUS 1203acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp) 1204{ 1205 ACPI_STATUS rv; 1206 1207 if (handle == NULL) 1208 handle = ACPI_ROOT_OBJECT; 1209 1210 bufp->Pointer = NULL; 1211 bufp->Length = ACPI_ALLOCATE_BUFFER; 1212 1213 rv = AcpiEvaluateObject(handle, path, NULL, bufp); 1214 1215 return rv; 1216} 1217 1218/* 1219 * acpi_foreach_package_object: 1220 * 1221 * Iterate over all objects in a in a packages and pass then all 1222 * to a function. If the called function returns non AE_OK, the 1223 * iteration is stopped and that value is returned. 1224 */ 1225 1226ACPI_STATUS 1227acpi_foreach_package_object(ACPI_OBJECT *pkg, 1228 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), 1229 void *arg) 1230{ 1231 ACPI_STATUS rv = AE_OK; 1232 int i; 1233 1234 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE) 1235 return AE_BAD_PARAMETER; 1236 1237 for (i = 0; i < pkg->Package.Count; i++) { 1238 rv = (*func)(&pkg->Package.Elements[i], arg); 1239 if (ACPI_FAILURE(rv)) 1240 break; 1241 } 1242 1243 return rv; 1244} 1245 1246const char * 1247acpi_name(ACPI_HANDLE handle) 1248{ 1249 static char buffer[80]; 1250 ACPI_BUFFER buf; 1251 ACPI_STATUS rv; 1252 1253 buf.Length = sizeof(buffer); 1254 buf.Pointer = buffer; 1255 1256 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 1257 if (ACPI_FAILURE(rv)) 1258 return "(unknown acpi path)"; 1259 return buffer; 1260} 1261 1262/* 1263 * acpi_get: 1264 * 1265 * Fetch data info the specified (empty) ACPI buffer. 1266 * Caller must free buf.Pointer by AcpiOsFree(). 1267 */ 1268ACPI_STATUS 1269acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 1270 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 1271{ 1272 buf->Pointer = NULL; 1273 buf->Length = ACPI_ALLOCATE_BUFFER; 1274 1275 return (*getit)(handle, buf); 1276} 1277 1278 1279/* 1280 * acpi_match_hid 1281 * 1282 * Match given ids against _HID and _CIDs 1283 */ 1284int 1285acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 1286{ 1287 int i; 1288 1289 while (*ids) { 1290 if (ad->Valid & ACPI_VALID_HID) { 1291 if (pmatch(ad->HardwareId.Value, *ids, NULL) == 2) 1292 return 1; 1293 } 1294 1295 if (ad->Valid & ACPI_VALID_CID) { 1296 for (i = 0; i < ad->CompatibilityId.Count; i++) { 1297 if (pmatch(ad->CompatibilityId.Id[i].Value, *ids, NULL) == 2) 1298 return 1; 1299 } 1300 } 1301 ids++; 1302 } 1303 1304 return 0; 1305} 1306 1307/* 1308 * acpi_wake_gpe_helper 1309 * 1310 * Set/unset GPE as both Runtime and Wake 1311 */ 1312static void 1313acpi_wake_gpe_helper(ACPI_HANDLE handle, bool enable) 1314{ 1315 ACPI_BUFFER buf; 1316 ACPI_STATUS rv; 1317 ACPI_OBJECT *p, *elt; 1318 1319 rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf); 1320 if (ACPI_FAILURE(rv)) 1321 return; /* just ignore */ 1322 1323 p = buf.Pointer; 1324 if (p->Type != ACPI_TYPE_PACKAGE || p->Package.Count < 2) 1325 goto out; /* just ignore */ 1326 1327 elt = p->Package.Elements; 1328 1329 /* TBD: package support */ 1330 if (enable) { 1331 AcpiSetGpeType(NULL, elt[0].Integer.Value, 1332 ACPI_GPE_TYPE_WAKE_RUN); 1333 AcpiEnableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR); 1334 } else 1335 AcpiDisableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR); 1336 1337 out: 1338 AcpiOsFree(buf.Pointer); 1339} 1340 1341/* 1342 * acpi_clear_wake_gpe 1343 * 1344 * Clear GPE as both Runtime and Wake 1345 */ 1346void 1347acpi_clear_wake_gpe(ACPI_HANDLE handle) 1348{ 1349 acpi_wake_gpe_helper(handle, false); 1350} 1351 1352/* 1353 * acpi_set_wake_gpe 1354 * 1355 * Set GPE as both Runtime and Wake 1356 */ 1357void 1358acpi_set_wake_gpe(ACPI_HANDLE handle) 1359{ 1360 acpi_wake_gpe_helper(handle, true); 1361} 1362 1363 1364/***************************************************************************** 1365 * ACPI sleep support. 1366 *****************************************************************************/ 1367 1368static int 1369is_available_state(struct acpi_softc *sc, int state) 1370{ 1371 UINT8 type_a, type_b; 1372 1373 return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state, 1374 &type_a, &type_b)); 1375} 1376 1377/* 1378 * acpi_enter_sleep_state: 1379 * 1380 * enter to the specified sleep state. 1381 */ 1382 1383ACPI_STATUS 1384acpi_enter_sleep_state(struct acpi_softc *sc, int state) 1385{ 1386 int err; 1387 ACPI_STATUS ret = AE_OK; 1388 1389 if (state == acpi_sleepstate) 1390 return AE_OK; 1391 1392 aprint_normal_dev(sc->sc_dev, "entering state %d\n", state); 1393 1394 switch (state) { 1395 case ACPI_STATE_S0: 1396 break; 1397 case ACPI_STATE_S1: 1398 case ACPI_STATE_S2: 1399 case ACPI_STATE_S3: 1400 case ACPI_STATE_S4: 1401 if (!is_available_state(sc, state)) { 1402 aprint_error_dev(sc->sc_dev, 1403 "ACPI S%d not available on this platform\n", state); 1404 break; 1405 } 1406 1407 if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_F_NONE)) { 1408 aprint_error_dev(sc->sc_dev, "aborting suspend\n"); 1409 break; 1410 } 1411 1412 ret = AcpiEnterSleepStatePrep(state); 1413 if (ACPI_FAILURE(ret)) { 1414 aprint_error_dev(sc->sc_dev, 1415 "failed preparing to sleep (%s)\n", 1416 AcpiFormatException(ret)); 1417 break; 1418 } 1419 1420 acpi_sleepstate = state; 1421 if (state == ACPI_STATE_S1) { 1422 /* just enter the state */ 1423 acpi_md_OsDisableInterrupt(); 1424 ret = AcpiEnterSleepState((UINT8)state); 1425 if (ACPI_FAILURE(ret)) 1426 aprint_error_dev(sc->sc_dev, 1427 "failed to enter sleep state S1: %s\n", 1428 AcpiFormatException(ret)); 1429 AcpiLeaveSleepState((UINT8)state); 1430 } else { 1431 err = acpi_md_sleep(state); 1432 if (state == ACPI_STATE_S4) 1433 AcpiEnable(); 1434 pmf_system_bus_resume(PMF_F_NONE); 1435 AcpiLeaveSleepState((UINT8)state); 1436 pmf_system_resume(PMF_F_NONE); 1437 } 1438 1439 break; 1440 case ACPI_STATE_S5: 1441 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5); 1442 if (ACPI_FAILURE(ret)) { 1443 aprint_error_dev(sc->sc_dev, 1444 "failed preparing to sleep (%s)\n", 1445 AcpiFormatException(ret)); 1446 break; 1447 } 1448 DELAY(1000000); 1449 acpi_sleepstate = state; 1450 acpi_md_OsDisableInterrupt(); 1451 AcpiEnterSleepState(ACPI_STATE_S5); 1452 aprint_error_dev(sc->sc_dev, "WARNING powerdown failed!\n"); 1453 break; 1454 } 1455 1456 acpi_sleepstate = ACPI_STATE_S0; 1457 return ret; 1458} 1459 1460#if defined(ACPI_ACTIVATE_DEV) 1461/* XXX This very incomplete */ 1462ACPI_STATUS 1463acpi_allocate_resources(ACPI_HANDLE handle) 1464{ 1465 ACPI_BUFFER bufp, bufc, bufn; 1466 ACPI_RESOURCE *resp, *resc, *resn; 1467 ACPI_RESOURCE_IRQ *irq; 1468 ACPI_RESOURCE_EXTENDED_IRQ *xirq; 1469 ACPI_STATUS rv; 1470 uint delta; 1471 1472 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources); 1473 if (ACPI_FAILURE(rv)) 1474 goto out; 1475 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources); 1476 if (ACPI_FAILURE(rv)) { 1477 goto out1; 1478 } 1479 1480 bufn.Length = 1000; 1481 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK); 1482 resp = bufp.Pointer; 1483 resc = bufc.Pointer; 1484 while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG && 1485 resp->Type != ACPI_RESOURCE_TYPE_END_TAG) { 1486 while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG) 1487 resp = ACPI_NEXT_RESOURCE(resp); 1488 if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG) 1489 break; 1490 /* Found identical Id */ 1491 resn->Type = resc->Type; 1492 switch (resc->Type) { 1493 case ACPI_RESOURCE_TYPE_IRQ: 1494 memcpy(&resn->Data, &resp->Data, 1495 sizeof(ACPI_RESOURCE_IRQ)); 1496 irq = (ACPI_RESOURCE_IRQ *)&resn->Data; 1497 irq->Interrupts[0] = 1498 ((ACPI_RESOURCE_IRQ *)&resp->Data)-> 1499 Interrupts[irq->InterruptCount-1]; 1500 irq->InterruptCount = 1; 1501 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ); 1502 break; 1503 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 1504 memcpy(&resn->Data, &resp->Data, 1505 sizeof(ACPI_RESOURCE_EXTENDED_IRQ)); 1506 xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data; 1507#if 0 1508 /* 1509 * XXX not duplicating the interrupt logic above 1510 * because its not clear what it accomplishes. 1511 */ 1512 xirq->Interrupts[0] = 1513 ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)-> 1514 Interrupts[irq->NumberOfInterrupts-1]; 1515 xirq->NumberOfInterrupts = 1; 1516#endif 1517 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ); 1518 break; 1519 case ACPI_RESOURCE_TYPE_IO: 1520 memcpy(&resn->Data, &resp->Data, 1521 sizeof(ACPI_RESOURCE_IO)); 1522 resn->Length = resp->Length; 1523 break; 1524 default: 1525 printf("acpi_allocate_resources: res=%d\n", resc->Type); 1526 rv = AE_BAD_DATA; 1527 goto out2; 1528 } 1529 resc = ACPI_NEXT_RESOURCE(resc); 1530 resn = ACPI_NEXT_RESOURCE(resn); 1531 resp = ACPI_NEXT_RESOURCE(resp); 1532 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer; 1533 if (delta >= 1534 bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) { 1535 bufn.Length *= 2; 1536 bufn.Pointer = realloc(bufn.Pointer, bufn.Length, 1537 M_ACPI, M_WAITOK); 1538 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta); 1539 } 1540 } 1541 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) { 1542 printf("acpi_allocate_resources: resc not exhausted\n"); 1543 rv = AE_BAD_DATA; 1544 goto out3; 1545 } 1546 1547 resn->Type = ACPI_RESOURCE_TYPE_END_TAG; 1548 rv = AcpiSetCurrentResources(handle, &bufn); 1549 if (ACPI_FAILURE(rv)) { 1550 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n", 1551 AcpiFormatException(rv)); 1552 } 1553 1554out3: 1555 free(bufn.Pointer, M_ACPI); 1556out2: 1557 AcpiOsFree(bufc.Pointer); 1558out1: 1559 AcpiOsFree(bufp.Pointer); 1560out: 1561 return rv; 1562} 1563#endif /* ACPI_ACTIVATE_DEV */ 1564 1565SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup") 1566{ 1567 const struct sysctlnode *node; 1568 const struct sysctlnode *ssnode; 1569 1570 if (sysctl_createv(clog, 0, NULL, NULL, 1571 CTLFLAG_PERMANENT, 1572 CTLTYPE_NODE, "hw", NULL, 1573 NULL, 0, NULL, 0, 1574 CTL_HW, CTL_EOL) != 0) 1575 return; 1576 1577 if (sysctl_createv(clog, 0, NULL, &node, 1578 CTLFLAG_PERMANENT, 1579 CTLTYPE_NODE, "acpi", NULL, 1580 NULL, 0, NULL, 0, 1581 CTL_HW, CTL_CREATE, CTL_EOL) != 0) 1582 return; 1583 1584 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY, 1585 CTLTYPE_QUAD, "root", 1586 SYSCTL_DESCR("ACPI root pointer"), 1587 NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer), 1588 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 1589 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY, 1590 CTLTYPE_STRING, "supported_states", 1591 SYSCTL_DESCR("Supported ACPI system states"), 1592 NULL, 0, acpi_supported_states, 0, 1593 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 1594 1595 /* ACPI sleepstate sysctl */ 1596 if (sysctl_createv(NULL, 0, NULL, &node, 1597 CTLFLAG_PERMANENT, 1598 CTLTYPE_NODE, "machdep", NULL, 1599 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0) 1600 return; 1601 if (sysctl_createv(NULL, 0, &node, &ssnode, 1602 CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state", 1603 NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE, 1604 CTL_EOL) != 0) 1605 return; 1606} 1607 1608static int 1609sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS) 1610{ 1611 int error, t; 1612 struct sysctlnode node; 1613 1614 node = *rnode; 1615 t = acpi_sleepstate; 1616 node.sysctl_data = &t; 1617 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1618 if (error || newp == NULL) 1619 return error; 1620 1621 if (acpi_softc == NULL) 1622 return ENOSYS; 1623 1624 acpi_enter_sleep_state(acpi_softc, t); 1625 1626 return 0; 1627} 1628 1629static ACPI_TABLE_HEADER * 1630acpi_map_rsdt(void) 1631{ 1632 ACPI_PHYSICAL_ADDRESS paddr; 1633 ACPI_TABLE_RSDP *rsdp; 1634 1635 paddr = AcpiOsGetRootPointer(); 1636 if (paddr == 0) { 1637 printf("ACPI: couldn't get root pointer\n"); 1638 return NULL; 1639 } 1640 rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP)); 1641 if (rsdp == NULL) { 1642 printf("ACPI: couldn't map RSDP\n"); 1643 return NULL; 1644 } 1645 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress) 1646 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress; 1647 else 1648 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress; 1649 AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP)); 1650 1651 return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER)); 1652} 1653 1654static void 1655acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt) 1656{ 1657 if (rsdt == NULL) 1658 return; 1659 1660 AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER)); 1661} 1662