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