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