1 /* $NetBSD: acpi.c,v 1.121 2008/12/07 10:53:57 mlelstv 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.121 2008/12/07 10:53:57 mlelstv 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 ACPI_BUFFER buf; 812 813 aprint_normal("%s (%s) ", aa->aa_node->ad_name, 814 pnpstr); 815 816 buf.Pointer = NULL; 817 buf.Length = ACPI_ALLOCATE_BUFFER; 818 rv = AcpiEvaluateObject(aa->aa_node->ad_handle, 819 "_STR", NULL, &buf); 820 if (ACPI_SUCCESS(rv)) { 821 ACPI_OBJECT *obj = buf.Pointer; 822 switch (obj->Type) { 823 case ACPI_TYPE_STRING: 824 aprint_normal("[%s] ", obj->String.Pointer); 825 break; 826 case ACPI_TYPE_BUFFER: 827 aprint_normal("buffer %p ", obj->Buffer.Pointer); 828 break; 829 default: 830 aprint_normal("type %d ",obj->Type); 831 break; 832 } 833 AcpiOsFree(buf.Pointer); 834 } 835 #ifdef ACPIVERBOSE 836 else { 837 int i; 838 839 for (i = 0; i < sizeof(acpi_knowndevs) / 840 sizeof(acpi_knowndevs[0]); i++) { 841 if (strcmp(acpi_knowndevs[i].pnp, 842 pnpstr) == 0) { 843 aprint_normal("[%s] ", 844 acpi_knowndevs[i].str); 845 } 846 } 847 } 848 849 #endif 850 aprint_normal("at %s", pnp); 851 } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) { 852 aprint_normal("%s (ACPI Object Type '%s' " 853 "[0x%02x]) ", aa->aa_node->ad_name, 854 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type), 855 aa->aa_node->ad_devinfo->Type); 856 aprint_normal("at %s", pnp); 857 } else 858 return 0; 859 } else { 860 aprint_normal(" (%s", aa->aa_node->ad_name); 861 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) { 862 aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.Value); 863 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) { 864 const char *uid; 865 866 uid = aa->aa_node->ad_devinfo->UniqueId.Value; 867 if (uid[0] == '\0') 868 uid = "<null>"; 869 aprint_normal("-%s", uid); 870 } 871 } 872 aprint_normal(")"); 873 } 874 875 return UNCONF; 876 } 877 878 /***************************************************************************** 879 * ACPI fixed-hardware feature handlers 880 *****************************************************************************/ 881 882 static UINT32 acpi_fixed_button_handler(void *); 883 static void acpi_fixed_button_pressed(void *); 884 885 /* 886 * acpi_enable_fixed_events: 887 * 888 * Enable any fixed-hardware feature handlers. 889 */ 890 static void 891 acpi_enable_fixed_events(struct acpi_softc *sc) 892 { 893 static int beenhere; 894 ACPI_STATUS rv; 895 896 KASSERT(beenhere == 0); 897 beenhere = 1; 898 899 /* 900 * Check for fixed-hardware buttons. 901 */ 902 903 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 904 aprint_verbose_dev(sc->sc_dev, 905 "fixed-feature power button present\n"); 906 sc->sc_smpsw_power.smpsw_name = device_xname(sc->sc_dev); 907 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER; 908 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 909 aprint_error_dev(sc->sc_dev, 910 "unable to register fixed power " 911 "button with sysmon\n"); 912 } else { 913 rv = AcpiInstallFixedEventHandler( 914 ACPI_EVENT_POWER_BUTTON, 915 acpi_fixed_button_handler, &sc->sc_smpsw_power); 916 if (ACPI_FAILURE(rv)) { 917 aprint_error_dev(sc->sc_dev, 918 "unable to install handler " 919 "for fixed power button: %s\n", 920 AcpiFormatException(rv)); 921 } 922 } 923 } 924 925 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 926 aprint_verbose_dev(sc->sc_dev, 927 "fixed-feature sleep button present\n"); 928 sc->sc_smpsw_sleep.smpsw_name = device_xname(sc->sc_dev); 929 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP; 930 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 931 aprint_error_dev(sc->sc_dev, 932 "unable to register fixed sleep " 933 "button with sysmon\n"); 934 } else { 935 rv = AcpiInstallFixedEventHandler( 936 ACPI_EVENT_SLEEP_BUTTON, 937 acpi_fixed_button_handler, &sc->sc_smpsw_sleep); 938 if (ACPI_FAILURE(rv)) { 939 aprint_error_dev(sc->sc_dev, 940 "unable to install handler " 941 "for fixed sleep button: %s\n", 942 AcpiFormatException(rv)); 943 } 944 } 945 } 946 } 947 948 /* 949 * acpi_fixed_button_handler: 950 * 951 * Event handler for the fixed buttons. 952 */ 953 static UINT32 954 acpi_fixed_button_handler(void *context) 955 { 956 struct sysmon_pswitch *smpsw = context; 957 int rv; 958 959 #ifdef ACPI_BUT_DEBUG 960 printf("%s: fixed button handler\n", smpsw->smpsw_name); 961 #endif 962 963 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, 964 acpi_fixed_button_pressed, smpsw); 965 if (ACPI_FAILURE(rv)) 966 printf("%s: WARNING: unable to queue fixed button pressed " 967 "callback: %s\n", smpsw->smpsw_name, 968 AcpiFormatException(rv)); 969 970 return ACPI_INTERRUPT_HANDLED; 971 } 972 973 /* 974 * acpi_fixed_button_pressed: 975 * 976 * Deal with a fixed button being pressed. 977 */ 978 static void 979 acpi_fixed_button_pressed(void *context) 980 { 981 struct sysmon_pswitch *smpsw = context; 982 983 #ifdef ACPI_BUT_DEBUG 984 printf("%s: fixed button pressed, calling sysmon\n", 985 smpsw->smpsw_name); 986 #endif 987 988 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED); 989 } 990 991 /***************************************************************************** 992 * ACPI utility routines. 993 *****************************************************************************/ 994 995 /* 996 * acpi_eval_integer: 997 * 998 * Evaluate an integer object. 999 */ 1000 ACPI_STATUS 1001 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) 1002 { 1003 ACPI_STATUS rv; 1004 ACPI_BUFFER buf; 1005 ACPI_OBJECT param; 1006 1007 if (handle == NULL) 1008 handle = ACPI_ROOT_OBJECT; 1009 1010 buf.Pointer = ¶m; 1011 buf.Length = sizeof(param); 1012 1013 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_INTEGER); 1014 if (ACPI_SUCCESS(rv)) 1015 *valp = param.Integer.Value; 1016 1017 return rv; 1018 } 1019 1020 /* 1021 * acpi_eval_string: 1022 * 1023 * Evaluate a (Unicode) string object. 1024 */ 1025 ACPI_STATUS 1026 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 1027 { 1028 ACPI_STATUS rv; 1029 ACPI_BUFFER buf; 1030 1031 if (handle == NULL) 1032 handle = ACPI_ROOT_OBJECT; 1033 1034 buf.Pointer = NULL; 1035 buf.Length = ACPI_ALLOCATE_BUFFER; 1036 1037 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING); 1038 if (ACPI_SUCCESS(rv)) { 1039 ACPI_OBJECT *param = buf.Pointer; 1040 const char *ptr = param->String.Pointer; 1041 size_t len = param->String.Length; 1042 if ((*stringp = AcpiOsAllocate(len)) == NULL) 1043 rv = AE_NO_MEMORY; 1044 else 1045 (void)memcpy(*stringp, ptr, len); 1046 AcpiOsFree(param); 1047 } 1048 1049 return rv; 1050 } 1051 1052 1053 /* 1054 * acpi_eval_struct: 1055 * 1056 * Evaluate a more complex structure. 1057 * Caller must free buf.Pointer by AcpiOsFree(). 1058 */ 1059 ACPI_STATUS 1060 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp) 1061 { 1062 ACPI_STATUS rv; 1063 1064 if (handle == NULL) 1065 handle = ACPI_ROOT_OBJECT; 1066 1067 bufp->Pointer = NULL; 1068 bufp->Length = ACPI_ALLOCATE_BUFFER; 1069 1070 rv = AcpiEvaluateObject(handle, path, NULL, bufp); 1071 1072 return rv; 1073 } 1074 1075 /* 1076 * acpi_foreach_package_object: 1077 * 1078 * Iterate over all objects in a in a packages and pass then all 1079 * to a function. If the called function returns non AE_OK, the 1080 * iteration is stopped and that value is returned. 1081 */ 1082 1083 ACPI_STATUS 1084 acpi_foreach_package_object(ACPI_OBJECT *pkg, 1085 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), 1086 void *arg) 1087 { 1088 ACPI_STATUS rv = AE_OK; 1089 int i; 1090 1091 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE) 1092 return AE_BAD_PARAMETER; 1093 1094 for (i = 0; i < pkg->Package.Count; i++) { 1095 rv = (*func)(&pkg->Package.Elements[i], arg); 1096 if (ACPI_FAILURE(rv)) 1097 break; 1098 } 1099 1100 return rv; 1101 } 1102 1103 const char * 1104 acpi_name(ACPI_HANDLE handle) 1105 { 1106 static char buffer[80]; 1107 ACPI_BUFFER buf; 1108 ACPI_STATUS rv; 1109 1110 buf.Length = sizeof(buffer); 1111 buf.Pointer = buffer; 1112 1113 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 1114 if (ACPI_FAILURE(rv)) 1115 return "(unknown acpi path)"; 1116 return buffer; 1117 } 1118 1119 /* 1120 * acpi_get: 1121 * 1122 * Fetch data info the specified (empty) ACPI buffer. 1123 * Caller must free buf.Pointer by AcpiOsFree(). 1124 */ 1125 ACPI_STATUS 1126 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 1127 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 1128 { 1129 buf->Pointer = NULL; 1130 buf->Length = ACPI_ALLOCATE_BUFFER; 1131 1132 return (*getit)(handle, buf); 1133 } 1134 1135 1136 /* 1137 * acpi_match_hid 1138 * 1139 * Match given ids against _HID and _CIDs 1140 */ 1141 int 1142 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 1143 { 1144 int i; 1145 1146 while (*ids) { 1147 if (ad->Valid & ACPI_VALID_HID) { 1148 if (pmatch(ad->HardwareId.Value, *ids, NULL) == 2) 1149 return 1; 1150 } 1151 1152 if (ad->Valid & ACPI_VALID_CID) { 1153 for (i = 0; i < ad->CompatibilityId.Count; i++) { 1154 if (pmatch(ad->CompatibilityId.Id[i].Value, *ids, NULL) == 2) 1155 return 1; 1156 } 1157 } 1158 ids++; 1159 } 1160 1161 return 0; 1162 } 1163 1164 /* 1165 * acpi_wake_gpe_helper 1166 * 1167 * Set/unset GPE as both Runtime and Wake 1168 */ 1169 static void 1170 acpi_wake_gpe_helper(ACPI_HANDLE handle, bool enable) 1171 { 1172 ACPI_BUFFER buf; 1173 ACPI_STATUS rv; 1174 ACPI_OBJECT *p, *elt; 1175 1176 rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf); 1177 if (ACPI_FAILURE(rv)) 1178 return; /* just ignore */ 1179 1180 p = buf.Pointer; 1181 if (p->Type != ACPI_TYPE_PACKAGE || p->Package.Count < 2) 1182 goto out; /* just ignore */ 1183 1184 elt = p->Package.Elements; 1185 1186 /* TBD: package support */ 1187 if (enable) { 1188 AcpiSetGpeType(NULL, elt[0].Integer.Value, 1189 ACPI_GPE_TYPE_WAKE_RUN); 1190 AcpiEnableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR); 1191 } else 1192 AcpiDisableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR); 1193 1194 out: 1195 AcpiOsFree(buf.Pointer); 1196 } 1197 1198 /* 1199 * acpi_clear_wake_gpe 1200 * 1201 * Clear GPE as both Runtime and Wake 1202 */ 1203 void 1204 acpi_clear_wake_gpe(ACPI_HANDLE handle) 1205 { 1206 acpi_wake_gpe_helper(handle, false); 1207 } 1208 1209 /* 1210 * acpi_set_wake_gpe 1211 * 1212 * Set GPE as both Runtime and Wake 1213 */ 1214 void 1215 acpi_set_wake_gpe(ACPI_HANDLE handle) 1216 { 1217 acpi_wake_gpe_helper(handle, true); 1218 } 1219 1220 1221 /***************************************************************************** 1222 * ACPI sleep support. 1223 *****************************************************************************/ 1224 1225 static int 1226 is_available_state(struct acpi_softc *sc, int state) 1227 { 1228 UINT8 type_a, type_b; 1229 1230 return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state, 1231 &type_a, &type_b)); 1232 } 1233 1234 /* 1235 * acpi_enter_sleep_state: 1236 * 1237 * enter to the specified sleep state. 1238 */ 1239 1240 ACPI_STATUS 1241 acpi_enter_sleep_state(struct acpi_softc *sc, int state) 1242 { 1243 int err; 1244 ACPI_STATUS ret = AE_OK; 1245 1246 if (state == acpi_sleepstate) 1247 return AE_OK; 1248 1249 aprint_normal_dev(sc->sc_dev, "entering state %d\n", state); 1250 1251 switch (state) { 1252 case ACPI_STATE_S0: 1253 break; 1254 case ACPI_STATE_S1: 1255 case ACPI_STATE_S2: 1256 case ACPI_STATE_S3: 1257 case ACPI_STATE_S4: 1258 if (!is_available_state(sc, state)) { 1259 aprint_error_dev(sc->sc_dev, 1260 "ACPI S%d not available on this platform\n", state); 1261 break; 1262 } 1263 1264 if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_F_NONE)) { 1265 aprint_error_dev(sc->sc_dev, "aborting suspend\n"); 1266 break; 1267 } 1268 1269 ret = AcpiEnterSleepStatePrep(state); 1270 if (ACPI_FAILURE(ret)) { 1271 aprint_error_dev(sc->sc_dev, 1272 "failed preparing to sleep (%s)\n", 1273 AcpiFormatException(ret)); 1274 break; 1275 } 1276 1277 acpi_sleepstate = state; 1278 if (state == ACPI_STATE_S1) { 1279 /* just enter the state */ 1280 acpi_md_OsDisableInterrupt(); 1281 ret = AcpiEnterSleepState((UINT8)state); 1282 if (ACPI_FAILURE(ret)) 1283 aprint_error_dev(sc->sc_dev, 1284 "failed to enter sleep state S1: %s\n", 1285 AcpiFormatException(ret)); 1286 AcpiLeaveSleepState((UINT8)state); 1287 } else { 1288 err = acpi_md_sleep(state); 1289 if (state == ACPI_STATE_S4) 1290 AcpiEnable(); 1291 pmf_system_bus_resume(PMF_F_NONE); 1292 AcpiLeaveSleepState((UINT8)state); 1293 pmf_system_resume(PMF_F_NONE); 1294 } 1295 1296 break; 1297 case ACPI_STATE_S5: 1298 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5); 1299 if (ACPI_FAILURE(ret)) { 1300 aprint_error_dev(sc->sc_dev, 1301 "failed preparing to sleep (%s)\n", 1302 AcpiFormatException(ret)); 1303 break; 1304 } 1305 DELAY(1000000); 1306 acpi_sleepstate = state; 1307 acpi_md_OsDisableInterrupt(); 1308 AcpiEnterSleepState(ACPI_STATE_S5); 1309 aprint_error_dev(sc->sc_dev, "WARNING powerdown failed!\n"); 1310 break; 1311 } 1312 1313 acpi_sleepstate = ACPI_STATE_S0; 1314 return ret; 1315 } 1316 1317 #if defined(ACPI_ACTIVATE_DEV) 1318 /* XXX This very incomplete */ 1319 ACPI_STATUS 1320 acpi_allocate_resources(ACPI_HANDLE handle) 1321 { 1322 ACPI_BUFFER bufp, bufc, bufn; 1323 ACPI_RESOURCE *resp, *resc, *resn; 1324 ACPI_RESOURCE_IRQ *irq; 1325 ACPI_RESOURCE_EXTENDED_IRQ *xirq; 1326 ACPI_STATUS rv; 1327 uint delta; 1328 1329 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources); 1330 if (ACPI_FAILURE(rv)) 1331 goto out; 1332 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources); 1333 if (ACPI_FAILURE(rv)) { 1334 goto out1; 1335 } 1336 1337 bufn.Length = 1000; 1338 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK); 1339 resp = bufp.Pointer; 1340 resc = bufc.Pointer; 1341 while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG && 1342 resp->Type != ACPI_RESOURCE_TYPE_END_TAG) { 1343 while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG) 1344 resp = ACPI_NEXT_RESOURCE(resp); 1345 if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG) 1346 break; 1347 /* Found identical Id */ 1348 resn->Type = resc->Type; 1349 switch (resc->Type) { 1350 case ACPI_RESOURCE_TYPE_IRQ: 1351 memcpy(&resn->Data, &resp->Data, 1352 sizeof(ACPI_RESOURCE_IRQ)); 1353 irq = (ACPI_RESOURCE_IRQ *)&resn->Data; 1354 irq->Interrupts[0] = 1355 ((ACPI_RESOURCE_IRQ *)&resp->Data)-> 1356 Interrupts[irq->InterruptCount-1]; 1357 irq->InterruptCount = 1; 1358 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ); 1359 break; 1360 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 1361 memcpy(&resn->Data, &resp->Data, 1362 sizeof(ACPI_RESOURCE_EXTENDED_IRQ)); 1363 xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data; 1364 #if 0 1365 /* 1366 * XXX not duplicating the interrupt logic above 1367 * because its not clear what it accomplishes. 1368 */ 1369 xirq->Interrupts[0] = 1370 ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)-> 1371 Interrupts[irq->NumberOfInterrupts-1]; 1372 xirq->NumberOfInterrupts = 1; 1373 #endif 1374 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ); 1375 break; 1376 case ACPI_RESOURCE_TYPE_IO: 1377 memcpy(&resn->Data, &resp->Data, 1378 sizeof(ACPI_RESOURCE_IO)); 1379 resn->Length = resp->Length; 1380 break; 1381 default: 1382 printf("acpi_allocate_resources: res=%d\n", resc->Type); 1383 rv = AE_BAD_DATA; 1384 goto out2; 1385 } 1386 resc = ACPI_NEXT_RESOURCE(resc); 1387 resn = ACPI_NEXT_RESOURCE(resn); 1388 resp = ACPI_NEXT_RESOURCE(resp); 1389 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer; 1390 if (delta >= 1391 bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) { 1392 bufn.Length *= 2; 1393 bufn.Pointer = realloc(bufn.Pointer, bufn.Length, 1394 M_ACPI, M_WAITOK); 1395 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta); 1396 } 1397 } 1398 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) { 1399 printf("acpi_allocate_resources: resc not exhausted\n"); 1400 rv = AE_BAD_DATA; 1401 goto out3; 1402 } 1403 1404 resn->Type = ACPI_RESOURCE_TYPE_END_TAG; 1405 rv = AcpiSetCurrentResources(handle, &bufn); 1406 if (ACPI_FAILURE(rv)) { 1407 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n", 1408 AcpiFormatException(rv)); 1409 } 1410 1411 out3: 1412 free(bufn.Pointer, M_ACPI); 1413 out2: 1414 AcpiOsFree(bufc.Pointer); 1415 out1: 1416 AcpiOsFree(bufp.Pointer); 1417 out: 1418 return rv; 1419 } 1420 #endif /* ACPI_ACTIVATE_DEV */ 1421 1422 SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup") 1423 { 1424 const struct sysctlnode *node; 1425 const struct sysctlnode *ssnode; 1426 1427 if (sysctl_createv(clog, 0, NULL, NULL, 1428 CTLFLAG_PERMANENT, 1429 CTLTYPE_NODE, "hw", NULL, 1430 NULL, 0, NULL, 0, 1431 CTL_HW, CTL_EOL) != 0) 1432 return; 1433 1434 if (sysctl_createv(clog, 0, NULL, &node, 1435 CTLFLAG_PERMANENT, 1436 CTLTYPE_NODE, "acpi", NULL, 1437 NULL, 0, NULL, 0, 1438 CTL_HW, CTL_CREATE, CTL_EOL) != 0) 1439 return; 1440 1441 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY, 1442 CTLTYPE_QUAD, "root", 1443 SYSCTL_DESCR("ACPI root pointer"), 1444 NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer), 1445 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 1446 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY, 1447 CTLTYPE_STRING, "supported_states", 1448 SYSCTL_DESCR("Supported ACPI system states"), 1449 NULL, 0, acpi_supported_states, 0, 1450 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 1451 1452 /* ACPI sleepstate sysctl */ 1453 if (sysctl_createv(NULL, 0, NULL, &node, 1454 CTLFLAG_PERMANENT, 1455 CTLTYPE_NODE, "machdep", NULL, 1456 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0) 1457 return; 1458 if (sysctl_createv(NULL, 0, &node, &ssnode, 1459 CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state", 1460 NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE, 1461 CTL_EOL) != 0) 1462 return; 1463 } 1464 1465 static int 1466 sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS) 1467 { 1468 int error, t; 1469 struct sysctlnode node; 1470 1471 node = *rnode; 1472 t = acpi_sleepstate; 1473 node.sysctl_data = &t; 1474 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1475 if (error || newp == NULL) 1476 return error; 1477 1478 if (acpi_softc == NULL) 1479 return ENOSYS; 1480 1481 acpi_enter_sleep_state(acpi_softc, t); 1482 1483 return 0; 1484 } 1485 1486 static ACPI_TABLE_HEADER * 1487 acpi_map_rsdt(void) 1488 { 1489 ACPI_PHYSICAL_ADDRESS paddr; 1490 ACPI_TABLE_RSDP *rsdp; 1491 1492 paddr = AcpiOsGetRootPointer(); 1493 if (paddr == 0) { 1494 printf("ACPI: couldn't get root pointer\n"); 1495 return NULL; 1496 } 1497 rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP)); 1498 if (rsdp == NULL) { 1499 printf("ACPI: couldn't map RSDP\n"); 1500 return NULL; 1501 } 1502 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress) 1503 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress; 1504 else 1505 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress; 1506 AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP)); 1507 1508 return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER)); 1509 } 1510 1511 static void 1512 acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt) 1513 { 1514 if (rsdt == NULL) 1515 return; 1516 1517 AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER)); 1518 } 1519