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