1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2011, Joyent, Inc. All rights reserved. 24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 25 */ 26 /* 27 * Copyright (c) 2009, Intel Corporation. 28 * All rights reserved. 29 */ 30 /* 31 * Solaris x86 ACPI CA services 32 */ 33 34 #include <sys/file.h> 35 #include <sys/errno.h> 36 #include <sys/conf.h> 37 #include <sys/modctl.h> 38 #include <sys/open.h> 39 #include <sys/stat.h> 40 #include <sys/spl.h> 41 #include <sys/ddi.h> 42 #include <sys/sunddi.h> 43 #include <sys/esunddi.h> 44 #include <sys/kstat.h> 45 #include <sys/x86_archext.h> 46 47 #include <sys/acpi/acpi.h> 48 #include <sys/acpica.h> 49 #include <sys/archsystm.h> 50 51 /* 52 * 53 */ 54 static struct modlmisc modlmisc = { 55 &mod_miscops, 56 "ACPI interpreter", 57 }; 58 59 static struct modlinkage modlinkage = { 60 MODREV_1, /* MODREV_1 manual */ 61 { (void *)&modlmisc, NULL } /* module linkage */ 62 }; 63 64 /* 65 * Local prototypes 66 */ 67 68 struct parsed_prw { 69 ACPI_HANDLE prw_gpeobj; 70 int prw_gpebit; 71 int prw_level; 72 }; 73 74 static void acpica_init_kstats(void); 75 static ACPI_STATUS acpica_init_PRW( 76 ACPI_HANDLE hdl, 77 UINT32 lvl, 78 void *ctxp, 79 void **rvpp); 80 81 static ACPI_STATUS acpica_parse_PRW( 82 ACPI_BUFFER *prw_buf, 83 struct parsed_prw *prw); 84 85 /* 86 * Local data 87 */ 88 89 static kmutex_t acpica_module_lock; 90 static kstat_t *acpica_ksp; 91 92 /* 93 * State of acpica subsystem 94 * After successful initialization, will be ACPICA_INITIALIZED 95 */ 96 int acpica_init_state = ACPICA_NOT_INITIALIZED; 97 98 /* 99 * Following are set by acpica_process_user_options() 100 * 101 * acpica_enable = FALSE prevents initialization of ACPI CA 102 * completely 103 * 104 * acpi_init_level determines level of ACPI CA functionality 105 * enabled in acpica_init() 106 */ 107 int acpica_enable; 108 UINT32 acpi_init_level; 109 110 /* 111 * Non-zero enables lax behavior with respect to some 112 * common ACPI BIOS issues; see ACPI CA documentation 113 * Setting this to zero causes ACPI CA to enforce strict 114 * compliance with ACPI specification 115 */ 116 int acpica_enable_interpreter_slack = 1; 117 118 /* 119 * For non-DEBUG builds, set the ACPI CA debug level to 0 120 * to quiet chatty BIOS output into /var/adm/messages 121 * Field-patchable for diagnostic use. 122 */ 123 #ifdef DEBUG 124 int acpica_muzzle_debug_output = 0; 125 #else 126 int acpica_muzzle_debug_output = 1; 127 #endif 128 129 /* 130 * ACPI DDI hooks 131 */ 132 static int acpica_ddi_setwake(dev_info_t *dip, int level); 133 134 int 135 _init(void) 136 { 137 int error = EBUSY; 138 int status; 139 extern int (*acpi_fp_setwake)(); 140 extern kmutex_t cpu_map_lock; 141 142 mutex_init(&acpica_module_lock, NULL, MUTEX_DRIVER, NULL); 143 mutex_init(&cpu_map_lock, NULL, MUTEX_SPIN, 144 (ddi_iblock_cookie_t)ipltospl(DISP_LEVEL)); 145 146 if ((error = mod_install(&modlinkage)) != 0) { 147 mutex_destroy(&acpica_module_lock); 148 goto load_error; 149 } 150 151 AcpiGbl_EnableInterpreterSlack = (acpica_enable_interpreter_slack != 0); 152 153 /* global ACPI CA initialization */ 154 if (ACPI_FAILURE(status = AcpiInitializeSubsystem())) 155 cmn_err(CE_WARN, "!AcpiInitializeSubsystem failed: %d", status); 156 157 /* initialize table manager */ 158 if (ACPI_FAILURE(status = AcpiInitializeTables(NULL, 0, 0))) 159 cmn_err(CE_WARN, "!AcpiInitializeTables failed: %d", status); 160 161 acpi_fp_setwake = acpica_ddi_setwake; 162 163 load_error: 164 return (error); 165 } 166 167 int 168 _info(struct modinfo *modinfop) 169 { 170 return (mod_info(&modlinkage, modinfop)); 171 } 172 173 int 174 _fini(void) 175 { 176 /* 177 * acpica module is never unloaded at run-time; there's always 178 * a PSM depending on it, at the very least 179 */ 180 return (EBUSY); 181 } 182 183 /* 184 * Install acpica-provided (default) address-space handlers 185 * that may be needed before AcpiEnableSubsystem() runs. 186 * See the comment in AcpiInstallAddressSpaceHandler(). 187 * Default handlers for remaining address spaces are 188 * installed later, in AcpiEnableSubsystem. 189 */ 190 static int 191 acpica_install_handlers() 192 { 193 ACPI_STATUS rv = AE_OK; 194 195 /* 196 * Install ACPI CA default handlers 197 */ 198 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 199 ACPI_ADR_SPACE_SYSTEM_MEMORY, 200 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 201 cmn_err(CE_WARN, "!acpica: no default handler for" 202 " system memory"); 203 rv = AE_ERROR; 204 } 205 206 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 207 ACPI_ADR_SPACE_SYSTEM_IO, 208 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 209 cmn_err(CE_WARN, "!acpica: no default handler for" 210 " system I/O"); 211 rv = AE_ERROR; 212 } 213 214 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 215 ACPI_ADR_SPACE_PCI_CONFIG, 216 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 217 cmn_err(CE_WARN, "!acpica: no default handler for" 218 " PCI Config"); 219 rv = AE_ERROR; 220 } 221 222 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 223 ACPI_ADR_SPACE_DATA_TABLE, 224 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 225 cmn_err(CE_WARN, "!acpica: no default handler for" 226 " Data Table"); 227 rv = AE_ERROR; 228 } 229 230 return (rv); 231 } 232 233 /* 234 * Find the BIOS date, and return TRUE if supplied 235 * date is same or later than the BIOS date, or FALSE 236 * if the BIOS date can't be fetched for any reason 237 */ 238 static int 239 acpica_check_bios_date(int yy, int mm, int dd) 240 { 241 242 char *datep; 243 int bios_year, bios_month, bios_day; 244 245 /* If firmware has no bios, skip the check */ 246 if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, 247 "bios-free")) 248 return (TRUE); 249 250 /* 251 * PC BIOSes contain a string in the form of 252 * "mm/dd/yy" at absolute address 0xffff5, 253 * where mm, dd and yy are all ASCII digits. 254 * We map the string, pluck out the values, 255 * and accept all BIOSes from 1 Jan 1999 on 256 * as valid. 257 */ 258 259 if ((datep = (char *)AcpiOsMapMemory(0xffff5, 8)) == NULL) 260 return (FALSE); 261 262 /* year */ 263 bios_year = ((int)(*(datep + 6) - '0') * 10) + (*(datep + 7) - '0'); 264 /* month */ 265 bios_month = ((int)(*datep - '0') * 10) + (*(datep + 1) - '0'); 266 /* day */ 267 bios_day = ((int)(*(datep + 3) - '0') * 10) + (*(datep + 4) - '0'); 268 269 AcpiOsUnmapMemory((void *) datep, 8); 270 271 if (bios_year < 0 || bios_year > 99 || bios_month < 0 || 272 bios_month > 99 || bios_day < 0 || bios_day > 99) { 273 /* non-digit chars in BIOS date */ 274 return (FALSE); 275 } 276 277 /* 278 * Adjust for 2-digit year; note to grand-children: 279 * need a new scheme before 2080 rolls around 280 */ 281 bios_year += (bios_year >= 80 && bios_year <= 99) ? 282 1900 : 2000; 283 284 if (bios_year < yy) 285 return (FALSE); 286 else if (bios_year > yy) 287 return (TRUE); 288 289 if (bios_month < mm) 290 return (FALSE); 291 else if (bios_month > mm) 292 return (TRUE); 293 294 if (bios_day < dd) 295 return (FALSE); 296 297 return (TRUE); 298 } 299 300 /* 301 * Check for Metropolis systems with BIOSes older than 10/12/04 302 * return TRUE if BIOS requires legacy mode, FALSE otherwise 303 */ 304 static int 305 acpica_metro_old_bios() 306 { 307 ACPI_TABLE_HEADER *fadt; 308 309 /* get the FADT */ 310 if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) != 311 AE_OK) 312 return (FALSE); 313 314 /* compare OEM Table ID to "SUNmetro" - no match, return false */ 315 if (strncmp("SUNmetro", fadt->OemTableId, 8)) 316 return (FALSE); 317 318 /* On a Metro - return FALSE if later than 10/12/04 */ 319 return (!acpica_check_bios_date(2004, 10, 12)); 320 } 321 322 323 /* 324 * Process acpi-user-options property if present 325 */ 326 static void 327 acpica_process_user_options() 328 { 329 static int processed = 0; 330 int acpi_user_options; 331 char *acpi_prop; 332 333 /* 334 * return if acpi-user-options has already been processed 335 */ 336 if (processed) 337 return; 338 else 339 processed = 1; 340 341 /* converts acpi-user-options from type string to int, if any */ 342 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 343 DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) == 344 DDI_PROP_SUCCESS) { 345 long data; 346 int ret; 347 ret = ddi_strtol(acpi_prop, NULL, 0, &data); 348 if (ret == 0) { 349 e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(), 350 "acpi-user-options"); 351 e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), 352 "acpi-user-options", data); 353 } 354 ddi_prop_free(acpi_prop); 355 } 356 357 /* 358 * fetch the optional options property 359 */ 360 acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 361 DDI_PROP_DONTPASS, "acpi-user-options", 0); 362 363 /* 364 * Note that 'off' has precedence over 'on' 365 * Also note - all cases of ACPI_OUSER_MASK 366 * provided here, no default: case is present 367 */ 368 switch (acpi_user_options & ACPI_OUSER_MASK) { 369 case ACPI_OUSER_DFLT: 370 acpica_enable = acpica_check_bios_date(1999, 1, 1); 371 break; 372 case ACPI_OUSER_ON: 373 acpica_enable = TRUE; 374 break; 375 case ACPI_OUSER_OFF: 376 case ACPI_OUSER_OFF | ACPI_OUSER_ON: 377 acpica_enable = FALSE; 378 break; 379 } 380 381 acpi_init_level = ACPI_FULL_INITIALIZATION; 382 383 /* 384 * special test here; may be generalized in the 385 * future - test for a machines that are known to 386 * work only in legacy mode, and set OUSER_LEGACY if 387 * we're on one 388 */ 389 if (acpica_metro_old_bios()) 390 acpi_user_options |= ACPI_OUSER_LEGACY; 391 392 /* 393 * If legacy mode is specified, set initialization 394 * options to avoid entering ACPI mode and hooking SCI 395 * - basically try to act like legacy acpi_intp 396 */ 397 if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0) 398 acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT); 399 400 /* 401 * modify default ACPI CA debug output level for non-DEBUG builds 402 * (to avoid BIOS debug chatter in /var/adm/messages) 403 */ 404 if (acpica_muzzle_debug_output) 405 AcpiDbgLevel = 0; 406 } 407 408 /* 409 * Initialize the CA subsystem if it hasn't been done already 410 */ 411 int 412 acpica_init() 413 { 414 extern void acpica_find_ioapics(void); 415 ACPI_STATUS status; 416 417 /* 418 * Make sure user options are processed, 419 * then fail to initialize if ACPI CA has been 420 * disabled 421 */ 422 acpica_process_user_options(); 423 if (!acpica_enable) 424 return (AE_ERROR); 425 426 mutex_enter(&acpica_module_lock); 427 if (acpica_init_state == ACPICA_INITIALIZED) { 428 mutex_exit(&acpica_module_lock); 429 return (AE_OK); 430 } 431 432 if (ACPI_FAILURE(status = AcpiLoadTables())) 433 goto error; 434 435 if (ACPI_FAILURE(status = acpica_install_handlers())) 436 goto error; 437 438 /* 439 * Create ACPI-to-devinfo mapping now so _INI and _STA 440 * methods can access PCI config space when needed 441 */ 442 scan_d2a_map(); 443 444 if (ACPI_FAILURE(status = AcpiEnableSubsystem(acpi_init_level))) 445 goto error; 446 447 /* do after AcpiEnableSubsystem() so GPEs are initialized */ 448 acpica_ec_init(); /* initialize EC if present */ 449 450 /* This runs all device _STA and _INI methods. */ 451 if (ACPI_FAILURE(status = AcpiInitializeObjects(0))) 452 goto error; 453 454 acpica_init_state = ACPICA_INITIALIZED; 455 456 /* 457 * [ACPI, sec. 4.4.1.1] 458 * As of ACPICA version 20101217 (December 2010), the _PRW methods 459 * (Power Resources for Wake) are no longer automatically executed 460 * as part of the ACPICA initialization. The OS must do this. 461 */ 462 (void) AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 463 UINT32_MAX, acpica_init_PRW, NULL, NULL, NULL); 464 (void) AcpiUpdateAllGpes(); 465 466 /* 467 * If we are running on the Xen hypervisor as dom0 we need to 468 * find the ioapics so we can prevent ACPI from trying to 469 * access them. 470 */ 471 if (get_hwenv() == HW_XEN_PV && is_controldom()) 472 acpica_find_ioapics(); 473 acpica_init_kstats(); 474 error: 475 if (acpica_init_state != ACPICA_INITIALIZED) { 476 cmn_err(CE_NOTE, "!failed to initialize ACPI services"); 477 } 478 479 /* 480 * Set acpi-status to 13 if acpica has been initialized successfully. 481 * This indicates that acpica is up and running. This variable name 482 * and value were chosen in order to remain compatible with acpi_intp. 483 */ 484 e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "acpi-status", 485 (ACPI_SUCCESS(status)) ? (ACPI_BOOT_INIT | ACPI_BOOT_ENABLE | 486 ACPI_BOOT_BOOTCONF) : 0); 487 488 /* Mark acpica subsystem as fully initialized. */ 489 if (ACPI_SUCCESS(status) && 490 acpi_init_level == ACPI_FULL_INITIALIZATION) { 491 acpica_set_core_feature(ACPI_FEATURE_FULL_INIT); 492 } 493 494 mutex_exit(&acpica_module_lock); 495 return (status); 496 } 497 498 /* 499 * SCI handling 500 */ 501 502 ACPI_STATUS 503 acpica_get_sci(int *sci_irq, iflag_t *sci_flags) 504 { 505 ACPI_SUBTABLE_HEADER *ap; 506 ACPI_TABLE_MADT *mat; 507 ACPI_MADT_INTERRUPT_OVERRIDE *mio; 508 ACPI_TABLE_FADT *fadt; 509 int madt_seen, madt_size; 510 511 512 /* 513 * Make sure user options are processed, 514 * then return error if ACPI CA has been 515 * disabled or system is not running in ACPI 516 * and won't need/understand SCI 517 */ 518 acpica_process_user_options(); 519 if ((!acpica_enable) || (acpi_init_level & ACPI_NO_ACPI_ENABLE)) 520 return (AE_ERROR); 521 522 /* 523 * according to Intel ACPI developers, SCI 524 * conforms to PCI bus conventions; level/low 525 * unless otherwise directed by overrides. 526 */ 527 sci_flags->intr_el = INTR_EL_LEVEL; 528 sci_flags->intr_po = INTR_PO_ACTIVE_LOW; 529 sci_flags->bustype = BUS_PCI; /* we *do* conform to PCI */ 530 531 /* get the SCI from the FADT */ 532 if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) != 533 AE_OK) 534 return (AE_ERROR); 535 536 *sci_irq = fadt->SciInterrupt; 537 538 /* search for ISOs that modify it */ 539 /* if we don't find a MADT, that's OK; no ISOs then */ 540 if (AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **) &mat) != 541 AE_OK) 542 return (AE_OK); 543 544 ap = (ACPI_SUBTABLE_HEADER *) (mat + 1); 545 madt_size = mat->Header.Length; 546 madt_seen = sizeof (*mat); 547 548 while (madt_seen < madt_size) { 549 switch (ap->Type) { 550 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 551 mio = (ACPI_MADT_INTERRUPT_OVERRIDE *) ap; 552 if (mio->SourceIrq == *sci_irq) { 553 *sci_irq = mio->GlobalIrq; 554 sci_flags->intr_el = (mio->IntiFlags & 555 ACPI_MADT_TRIGGER_MASK) >> 2; 556 sci_flags->intr_po = mio->IntiFlags & 557 ACPI_MADT_POLARITY_MASK; 558 } 559 break; 560 } 561 562 /* advance to next entry */ 563 madt_seen += ap->Length; 564 ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length); 565 } 566 567 /* 568 * One more check; if ISO said "conform", revert to default 569 */ 570 if (sci_flags->intr_el == INTR_EL_CONFORM) 571 sci_flags->intr_el = INTR_EL_LEVEL; 572 if (sci_flags->intr_po == INTR_PO_CONFORM) 573 sci_flags->intr_po = INTR_PO_ACTIVE_LOW; 574 575 return (AE_OK); 576 } 577 578 /* 579 * Call-back function used for _PRW initialization. For every 580 * device node that has a _PRW method, evaluate, parse, and do 581 * AcpiSetupGpeForWake(). 582 */ 583 static ACPI_STATUS 584 acpica_init_PRW( 585 ACPI_HANDLE devhdl, 586 UINT32 depth, 587 void *ctxp, 588 void **rvpp) 589 { 590 ACPI_STATUS status; 591 ACPI_BUFFER prw_buf; 592 struct parsed_prw prw; 593 594 prw_buf.Pointer = NULL; 595 prw_buf.Length = ACPI_ALLOCATE_BUFFER; 596 597 /* 598 * Attempt to evaluate _PRW object. 599 * If no valid object is found, return quietly, since not all 600 * devices have _PRW objects. 601 */ 602 status = AcpiEvaluateObject(devhdl, "_PRW", NULL, &prw_buf); 603 if (ACPI_FAILURE(status)) 604 goto done; 605 status = acpica_parse_PRW(&prw_buf, &prw); 606 if (ACPI_FAILURE(status)) 607 goto done; 608 609 (void) AcpiSetupGpeForWake(devhdl, 610 prw.prw_gpeobj, prw.prw_gpebit); 611 612 done: 613 if (prw_buf.Pointer != NULL) 614 AcpiOsFree(prw_buf.Pointer); 615 616 return (AE_OK); 617 } 618 619 /* 620 * Sets ACPI wake state for device referenced by dip. 621 * If level is S0 (0), disables wake event; otherwise, 622 * enables wake event which will wake system from level. 623 */ 624 static int 625 acpica_ddi_setwake(dev_info_t *dip, int level) 626 { 627 ACPI_STATUS status; 628 ACPI_HANDLE devobj; 629 ACPI_BUFFER prw_buf; 630 ACPI_OBJECT_LIST arglist; 631 ACPI_OBJECT args[3]; 632 struct parsed_prw prw; 633 int rv; 634 635 /* 636 * initialize these early so we can use a common 637 * exit point below 638 */ 639 prw_buf.Pointer = NULL; 640 prw_buf.Length = ACPI_ALLOCATE_BUFFER; 641 rv = 0; 642 643 /* 644 * Attempt to get a handle to a corresponding ACPI object. 645 * If no object is found, return quietly, since not all 646 * devices have corresponding ACPI objects. 647 */ 648 status = acpica_get_handle(dip, &devobj); 649 if (ACPI_FAILURE(status)) { 650 char pathbuf[MAXPATHLEN]; 651 ddi_pathname(dip, pathbuf); 652 #ifdef DEBUG 653 cmn_err(CE_NOTE, "!acpica_ddi_setwake: could not get" 654 " handle for %s, %s:%d", pathbuf, ddi_driver_name(dip), 655 ddi_get_instance(dip)); 656 #endif 657 goto done; 658 } 659 660 /* 661 * ACPI3.0 7.2.1: only use the _PSW method if OSPM does not support 662 * _DSW or if the _DSW method is not present. 663 * 664 * _DSW arguments: 665 * args[0] - Enable/Disable 666 * args[1] - Target system state 667 * args[2] - Target device state 668 */ 669 670 arglist.Count = 3; 671 arglist.Pointer = args; 672 args[0].Type = ACPI_TYPE_INTEGER; 673 args[0].Integer.Value = level ? 1 : 0; 674 args[1].Type = ACPI_TYPE_INTEGER; 675 args[1].Integer.Value = level; 676 args[2].Type = ACPI_TYPE_INTEGER; 677 args[2].Integer.Value = level; 678 if (ACPI_FAILURE(status = AcpiEvaluateObject(devobj, "_DSW", 679 &arglist, NULL))) { 680 681 if (status == AE_NOT_FOUND) { 682 arglist.Count = 1; 683 args[0].Type = ACPI_TYPE_INTEGER; 684 args[0].Integer.Value = level ? 1 : 0; 685 686 if (ACPI_FAILURE(status = AcpiEvaluateObject(devobj, 687 "_PSW", &arglist, NULL))) { 688 689 if (status != AE_NOT_FOUND) { 690 cmn_err(CE_NOTE, 691 "!_PSW failure %d for device %s", 692 status, ddi_driver_name(dip)); 693 } 694 } 695 696 } else { 697 cmn_err(CE_NOTE, "!_DSW failure %d for device %s", 698 status, ddi_driver_name(dip)); 699 } 700 } 701 702 /* 703 * Attempt to evaluate _PRW object. 704 * If no valid object is found, return quietly, since not all 705 * devices have _PRW objects. 706 */ 707 status = AcpiEvaluateObject(devobj, "_PRW", NULL, &prw_buf); 708 if (ACPI_FAILURE(status)) 709 goto done; 710 status = acpica_parse_PRW(&prw_buf, &prw); 711 if (ACPI_FAILURE(status)) 712 goto done; 713 714 rv = -1; 715 if (level == 0) { 716 status = AcpiDisableGpe(prw.prw_gpeobj, prw.prw_gpebit); 717 if (ACPI_FAILURE(status)) 718 goto done; 719 } else if (prw.prw_level >= level) { 720 status = AcpiSetGpeWakeMask(prw.prw_gpeobj, prw.prw_gpebit, 721 ACPI_GPE_ENABLE); 722 if (ACPI_SUCCESS(status)) { 723 status = AcpiEnableGpe(prw.prw_gpeobj, prw.prw_gpebit); 724 if (ACPI_FAILURE(status)) 725 goto done; 726 } 727 } 728 rv = 0; 729 done: 730 if (prw_buf.Pointer != NULL) 731 AcpiOsFree(prw_buf.Pointer); 732 return (rv); 733 } 734 735 static ACPI_STATUS 736 acpica_parse_PRW( 737 ACPI_BUFFER *prw_buf, 738 struct parsed_prw *p_prw) 739 { 740 ACPI_HANDLE gpeobj; 741 ACPI_OBJECT *prw, *gpe; 742 int gpebit, prw_level; 743 744 if (prw_buf->Length == 0 || prw_buf->Pointer == NULL) 745 return (AE_NULL_OBJECT); 746 747 prw = prw_buf->Pointer; 748 if (prw->Type != ACPI_TYPE_PACKAGE || prw->Package.Count < 2 || 749 prw->Package.Elements[1].Type != ACPI_TYPE_INTEGER) 750 return (AE_TYPE); 751 752 /* fetch the lowest wake level from the _PRW */ 753 prw_level = prw->Package.Elements[1].Integer.Value; 754 755 /* 756 * process the GPE description 757 */ 758 switch (prw->Package.Elements[0].Type) { 759 case ACPI_TYPE_INTEGER: 760 gpeobj = NULL; 761 gpebit = prw->Package.Elements[0].Integer.Value; 762 break; 763 case ACPI_TYPE_PACKAGE: 764 gpe = &prw->Package.Elements[0]; 765 if (gpe->Package.Count != 2 || 766 gpe->Package.Elements[1].Type != ACPI_TYPE_INTEGER) 767 return (AE_TYPE); 768 gpeobj = gpe->Package.Elements[0].Reference.Handle; 769 gpebit = gpe->Package.Elements[1].Integer.Value; 770 if (gpeobj == NULL) 771 return (AE_NULL_OBJECT); 772 break; 773 default: 774 return (AE_TYPE); 775 } 776 777 p_prw->prw_gpeobj = gpeobj; 778 p_prw->prw_gpebit = gpebit; 779 p_prw->prw_level = prw_level; 780 781 return (AE_OK); 782 } 783 784 /* 785 * kstat access to a limited set of ACPI propertis 786 */ 787 static void 788 acpica_init_kstats() 789 { 790 ACPI_HANDLE s3handle; 791 ACPI_STATUS status; 792 ACPI_TABLE_FADT *fadt; 793 kstat_named_t *knp; 794 795 /* 796 * Create a small set of named kstats; just return in the rare 797 * case of a failure, * in which case, the kstats won't be present. 798 */ 799 if ((acpica_ksp = kstat_create("acpi", 0, "acpi", "misc", 800 KSTAT_TYPE_NAMED, 2, 0)) == NULL) 801 return; 802 803 /* 804 * initialize kstat 'S3' to reflect the presence of \_S3 in 805 * the ACPI namespace (1 = present, 0 = not present) 806 */ 807 knp = acpica_ksp->ks_data; 808 knp->value.l = (AcpiGetHandle(NULL, "\\_S3", &s3handle) == AE_OK); 809 kstat_named_init(knp, "S3", KSTAT_DATA_LONG); 810 knp++; /* advance to next named kstat */ 811 812 /* 813 * initialize kstat 'preferred_pm_profile' to the value 814 * contained in the (always present) FADT 815 */ 816 status = AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt); 817 knp->value.l = (status == AE_OK) ? fadt->PreferredProfile : -1; 818 kstat_named_init(knp, "preferred_pm_profile", KSTAT_DATA_LONG); 819 820 /* 821 * install the named kstats 822 */ 823 kstat_install(acpica_ksp); 824 } 825 826 /* 827 * Attempt to save the current ACPI settings (_CRS) for the device 828 * which corresponds to the supplied devinfo node. The settings are 829 * saved as a property on the dip. If no ACPI object is found to be 830 * associated with the devinfo node, no action is taken and no error 831 * is reported. 832 */ 833 void 834 acpica_ddi_save_resources(dev_info_t *dip) 835 { 836 ACPI_HANDLE devobj; 837 ACPI_BUFFER resbuf; 838 int ret; 839 840 resbuf.Length = ACPI_ALLOCATE_BUFFER; 841 if (ACPI_FAILURE(acpica_get_handle(dip, &devobj)) || 842 ACPI_FAILURE(AcpiGetCurrentResources(devobj, &resbuf))) 843 return; 844 845 ret = ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 846 "acpi-crs", resbuf.Pointer, resbuf.Length); 847 848 ASSERT(ret == DDI_PROP_SUCCESS); 849 850 AcpiOsFree(resbuf.Pointer); 851 } 852 853 /* 854 * If the supplied devinfo node has an ACPI settings property attached, 855 * restore them to the associated ACPI device using _SRS. The property 856 * is deleted from the devinfo node afterward. 857 */ 858 void 859 acpica_ddi_restore_resources(dev_info_t *dip) 860 { 861 ACPI_HANDLE devobj; 862 ACPI_BUFFER resbuf; 863 uchar_t *propdata; 864 uint_t proplen; 865 866 if (ACPI_FAILURE(acpica_get_handle(dip, &devobj))) 867 return; 868 869 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 870 "acpi-crs", &propdata, &proplen) != DDI_PROP_SUCCESS) 871 return; 872 873 resbuf.Pointer = propdata; 874 resbuf.Length = proplen; 875 (void) AcpiSetCurrentResources(devobj, &resbuf); 876 ddi_prop_free(propdata); 877 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "acpi-crs"); 878 } 879 880 void 881 acpi_reset_system(void) 882 { 883 ACPI_STATUS status; 884 int ten; 885 886 status = AcpiReset(); 887 if (status == AE_OK) { 888 /* 889 * Wait up to 500 milliseconds for AcpiReset() to make its 890 * way. 891 */ 892 ten = 50000; 893 while (ten-- > 0) 894 tenmicrosec(); 895 } 896 }