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