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