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