17c478bd9Sstevel@tonic-gate /* 28e56767dSsmall * CDDL HEADER START 38e56767dSsmall * 48e56767dSsmall * The contents of this file are subject to the terms of the 53d50435fSmyers * Common Development and Distribution License (the "License"). 63d50435fSmyers * You may not use this file except in compliance with the License. 78e56767dSsmall * 88e56767dSsmall * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98e56767dSsmall * or http://www.opensolaris.org/os/licensing. 108e56767dSsmall * See the License for the specific language governing permissions 118e56767dSsmall * and limitations under the License. 128e56767dSsmall * 138e56767dSsmall * When distributing Covered Code, include this CDDL HEADER in each 148e56767dSsmall * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158e56767dSsmall * If applicable, add the following below this CDDL HEADER, with the 168e56767dSsmall * fields enclosed by brackets "[]" replaced with your own identifying 178e56767dSsmall * information: Portions Copyright [yyyy] [name of copyright owner] 188e56767dSsmall * 198e56767dSsmall * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 220f1b305eSSeth Goldberg * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 25fa96bd91SMichael Corcoran /* 26fa96bd91SMichael Corcoran * Copyright (c) 2009, Intel Corporation. 27fa96bd91SMichael Corcoran * All rights reserved. 28fa96bd91SMichael Corcoran */ 298e56767dSsmall /* 308e56767dSsmall * Solaris x86 ACPI CA services 318e56767dSsmall */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <sys/file.h> 347c478bd9Sstevel@tonic-gate #include <sys/errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/conf.h> 367c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 377c478bd9Sstevel@tonic-gate #include <sys/open.h> 387c478bd9Sstevel@tonic-gate #include <sys/stat.h> 39*a3114836SGerry Liu #include <sys/spl.h> 407c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 417c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 427c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 432df1fe9cSrandyf #include <sys/kstat.h> 44b9bfdccdSStuart Maybee #include <sys/x86_archext.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <sys/acpi/acpi.h> 477c478bd9Sstevel@tonic-gate #include <sys/acpica.h> 484cf02d40SSaurabh Misra #include <sys/archsystm.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 547c478bd9Sstevel@tonic-gate &mod_miscops, 5587bb58d6Smyers "ACPI interpreter", 567c478bd9Sstevel@tonic-gate }; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 597c478bd9Sstevel@tonic-gate MODREV_1, /* MODREV_1 manual */ 607c478bd9Sstevel@tonic-gate (void *)&modlmisc, /* module linkage */ 617c478bd9Sstevel@tonic-gate NULL, /* list terminator */ 627c478bd9Sstevel@tonic-gate }; 637c478bd9Sstevel@tonic-gate 642df1fe9cSrandyf /* 652df1fe9cSrandyf * Local prototypes 662df1fe9cSrandyf */ 672df1fe9cSrandyf 682df1fe9cSrandyf static void acpica_init_kstats(void); 692df1fe9cSrandyf 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * Local data 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static kmutex_t acpica_module_lock; 752df1fe9cSrandyf static kstat_t *acpica_ksp; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * State of acpica subsystem 797c478bd9Sstevel@tonic-gate * After successful initialization, will be ACPICA_INITIALIZED 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate int acpica_init_state = ACPICA_NOT_INITIALIZED; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * Following are set by acpica_process_user_options() 857c478bd9Sstevel@tonic-gate * 867c478bd9Sstevel@tonic-gate * acpica_enable = FALSE prevents initialization of ACPI CA 877c478bd9Sstevel@tonic-gate * completely 887c478bd9Sstevel@tonic-gate * 897c478bd9Sstevel@tonic-gate * acpi_init_level determines level of ACPI CA functionality 907c478bd9Sstevel@tonic-gate * enabled in acpica_init() 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate int acpica_enable; 937c478bd9Sstevel@tonic-gate UINT32 acpi_init_level; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * Non-zero enables lax behavior with respect to some 977c478bd9Sstevel@tonic-gate * common ACPI BIOS issues; see ACPI CA documentation 987c478bd9Sstevel@tonic-gate * Setting this to zero causes ACPI CA to enforce strict 997c478bd9Sstevel@tonic-gate * compliance with ACPI specification 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate int acpica_enable_interpreter_slack = 1; 1027c478bd9Sstevel@tonic-gate 1033d50435fSmyers /* 1043d50435fSmyers * For non-DEBUG builds, set the ACPI CA debug level to 0 1053d50435fSmyers * to quiet chatty BIOS output into /var/adm/messages 1063d50435fSmyers * Field-patchable for diagnostic use. 1073d50435fSmyers */ 1083d50435fSmyers #ifdef DEBUG 1093d50435fSmyers int acpica_muzzle_debug_output = 0; 1103d50435fSmyers #else 1113d50435fSmyers int acpica_muzzle_debug_output = 1; 1123d50435fSmyers #endif 1133d50435fSmyers 1142df1fe9cSrandyf /* 1152df1fe9cSrandyf * ACPI DDI hooks 1162df1fe9cSrandyf */ 1172df1fe9cSrandyf static int acpica_ddi_setwake(dev_info_t *dip, int level); 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate int 1207c478bd9Sstevel@tonic-gate _init(void) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate int error = EBUSY; 1237c478bd9Sstevel@tonic-gate int status; 1242df1fe9cSrandyf extern int (*acpi_fp_setwake)(); 125*a3114836SGerry Liu extern kmutex_t cpu_map_lock; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate mutex_init(&acpica_module_lock, NULL, MUTEX_DRIVER, NULL); 128*a3114836SGerry Liu mutex_init(&cpu_map_lock, NULL, MUTEX_SPIN, 129*a3114836SGerry Liu (ddi_iblock_cookie_t)ipltospl(DISP_LEVEL)); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate if ((error = mod_install(&modlinkage)) != 0) { 1327c478bd9Sstevel@tonic-gate mutex_destroy(&acpica_module_lock); 1332df1fe9cSrandyf goto load_error; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate AcpiGbl_EnableInterpreterSlack = (acpica_enable_interpreter_slack != 0); 1377c478bd9Sstevel@tonic-gate 138c1381f44SDana Myers /* global ACPI CA initialization */ 139c1381f44SDana Myers if (ACPI_FAILURE(status = AcpiInitializeSubsystem())) 140c1381f44SDana Myers cmn_err(CE_WARN, "!AcpiInitializeSubsystem failed: %d", status); 141c1381f44SDana Myers 142c1381f44SDana Myers /* initialize table manager */ 143c1381f44SDana Myers if (ACPI_FAILURE(status = AcpiInitializeTables(NULL, 0, 0))) 144c1381f44SDana Myers cmn_err(CE_WARN, "!AcpiInitializeTables failed: %d", status); 1457c478bd9Sstevel@tonic-gate 1462df1fe9cSrandyf acpi_fp_setwake = acpica_ddi_setwake; 1472df1fe9cSrandyf 1482df1fe9cSrandyf load_error: 1497c478bd9Sstevel@tonic-gate return (error); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate int 1537c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate int 1597c478bd9Sstevel@tonic-gate _fini(void) 1607c478bd9Sstevel@tonic-gate { 161186507a7Smyers /* 162186507a7Smyers * acpica module is never unloaded at run-time; there's always 163186507a7Smyers * a PSM depending on it, at the very least 164186507a7Smyers */ 165186507a7Smyers return (EBUSY); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * Install acpica-provided address-space handlers 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate static int 1727c478bd9Sstevel@tonic-gate acpica_install_handlers() 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate ACPI_STATUS rv = AE_OK; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* 1777c478bd9Sstevel@tonic-gate * Install ACPI CA default handlers 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 1807c478bd9Sstevel@tonic-gate ACPI_ADR_SPACE_SYSTEM_MEMORY, 1817c478bd9Sstevel@tonic-gate ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 1827c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!acpica: no default handler for" 1837c478bd9Sstevel@tonic-gate " system memory"); 1847c478bd9Sstevel@tonic-gate rv = AE_ERROR; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 1887c478bd9Sstevel@tonic-gate ACPI_ADR_SPACE_SYSTEM_IO, 1897c478bd9Sstevel@tonic-gate ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 1907c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!acpica: no default handler for" 1917c478bd9Sstevel@tonic-gate " system I/O"); 1927c478bd9Sstevel@tonic-gate rv = AE_ERROR; 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 1967c478bd9Sstevel@tonic-gate ACPI_ADR_SPACE_PCI_CONFIG, 1977c478bd9Sstevel@tonic-gate ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) { 1987c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!acpica: no default handler for" 1997c478bd9Sstevel@tonic-gate " PCI Config"); 2007c478bd9Sstevel@tonic-gate rv = AE_ERROR; 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate return (rv); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Find the BIOS date, and return TRUE if supplied 2097c478bd9Sstevel@tonic-gate * date is same or later than the BIOS date, or FALSE 2107c478bd9Sstevel@tonic-gate * if the BIOS date can't be fetched for any reason 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate static int 2137c478bd9Sstevel@tonic-gate acpica_check_bios_date(int yy, int mm, int dd) 2147c478bd9Sstevel@tonic-gate { 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate char *datep; 2177c478bd9Sstevel@tonic-gate int bios_year, bios_month, bios_day; 2187c478bd9Sstevel@tonic-gate 219f2be5148Sszhou /* If firmware has no bios, skip the check */ 220fa96bd91SMichael Corcoran if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, 221fa96bd91SMichael Corcoran "bios-free")) 222f2be5148Sszhou return (TRUE); 223f2be5148Sszhou 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * PC BIOSes contain a string in the form of 2267c478bd9Sstevel@tonic-gate * "mm/dd/yy" at absolute address 0xffff5, 2277c478bd9Sstevel@tonic-gate * where mm, dd and yy are all ASCII digits. 2287c478bd9Sstevel@tonic-gate * We map the string, pluck out the values, 2297c478bd9Sstevel@tonic-gate * and accept all BIOSes from 1 Jan 1999 on 2307c478bd9Sstevel@tonic-gate * as valid. 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate 233db2bae30SDana Myers if ((datep = (char *)AcpiOsMapMemory(0xffff5, 8)) == NULL) 2347c478bd9Sstevel@tonic-gate return (FALSE); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* year */ 2377c478bd9Sstevel@tonic-gate bios_year = ((int)(*(datep + 6) - '0') * 10) + (*(datep + 7) - '0'); 2387c478bd9Sstevel@tonic-gate /* month */ 2397c478bd9Sstevel@tonic-gate bios_month = ((int)(*datep - '0') * 10) + (*(datep + 1) - '0'); 2407c478bd9Sstevel@tonic-gate /* day */ 2417c478bd9Sstevel@tonic-gate bios_day = ((int)(*(datep + 3) - '0') * 10) + (*(datep + 4) - '0'); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate AcpiOsUnmapMemory((void *) datep, 8); 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate if (bios_year < 0 || bios_year > 99 || bios_month < 0 || 2467c478bd9Sstevel@tonic-gate bios_month > 99 || bios_day < 0 || bios_day > 99) { 2477c478bd9Sstevel@tonic-gate /* non-digit chars in BIOS date */ 2487c478bd9Sstevel@tonic-gate return (FALSE); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * Adjust for 2-digit year; note to grand-children: 2537c478bd9Sstevel@tonic-gate * need a new scheme before 2080 rolls around 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate bios_year += (bios_year >= 80 && bios_year <= 99) ? 2567c478bd9Sstevel@tonic-gate 1900 : 2000; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (bios_year < yy) 2597c478bd9Sstevel@tonic-gate return (FALSE); 2607c478bd9Sstevel@tonic-gate else if (bios_year > yy) 2617c478bd9Sstevel@tonic-gate return (TRUE); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (bios_month < mm) 2647c478bd9Sstevel@tonic-gate return (FALSE); 2657c478bd9Sstevel@tonic-gate else if (bios_month > mm) 2667c478bd9Sstevel@tonic-gate return (TRUE); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate if (bios_day < dd) 2697c478bd9Sstevel@tonic-gate return (FALSE); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate return (TRUE); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Check for Metropolis systems with BIOSes older than 10/12/04 2767c478bd9Sstevel@tonic-gate * return TRUE if BIOS requires legacy mode, FALSE otherwise 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate static int 2797c478bd9Sstevel@tonic-gate acpica_metro_old_bios() 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate ACPI_TABLE_HEADER *fadt; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* get the FADT */ 284db2bae30SDana Myers if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) != 285db2bae30SDana Myers AE_OK) 2867c478bd9Sstevel@tonic-gate return (FALSE); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* compare OEM Table ID to "SUNmetro" - no match, return false */ 2897c478bd9Sstevel@tonic-gate if (strncmp("SUNmetro", fadt->OemTableId, 8)) 2907c478bd9Sstevel@tonic-gate return (FALSE); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* On a Metro - return FALSE if later than 10/12/04 */ 2937c478bd9Sstevel@tonic-gate return (!acpica_check_bios_date(2004, 10, 12)); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * Process acpi-user-options property if present 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate static void 3017c478bd9Sstevel@tonic-gate acpica_process_user_options() 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate static int processed = 0; 3047c478bd9Sstevel@tonic-gate int acpi_user_options; 3057c478bd9Sstevel@tonic-gate char *acpi_prop; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * return if acpi-user-options has already been processed 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate if (processed) 3117c478bd9Sstevel@tonic-gate return; 3127c478bd9Sstevel@tonic-gate else 3137c478bd9Sstevel@tonic-gate processed = 1; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* converts acpi-user-options from type string to int, if any */ 3167c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 3177c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) == 3187c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 3197c478bd9Sstevel@tonic-gate long data; 3207c478bd9Sstevel@tonic-gate int ret; 3217c478bd9Sstevel@tonic-gate ret = ddi_strtol(acpi_prop, NULL, 0, &data); 3227c478bd9Sstevel@tonic-gate if (ret == 0) { 3237c478bd9Sstevel@tonic-gate e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(), 3247c478bd9Sstevel@tonic-gate "acpi-user-options"); 325f7534bc1Ssmall e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), 326f7534bc1Ssmall "acpi-user-options", data); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate ddi_prop_free(acpi_prop); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * fetch the optional options property 3337c478bd9Sstevel@tonic-gate */ 334fa96bd91SMichael Corcoran acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 335fa96bd91SMichael Corcoran DDI_PROP_DONTPASS, "acpi-user-options", 0); 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * Note that 'off' has precedence over 'on' 3397c478bd9Sstevel@tonic-gate * Also note - all cases of ACPI_OUSER_MASK 3407c478bd9Sstevel@tonic-gate * provided here, no default: case is present 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate switch (acpi_user_options & ACPI_OUSER_MASK) { 3437c478bd9Sstevel@tonic-gate case ACPI_OUSER_DFLT: 3447c478bd9Sstevel@tonic-gate acpica_enable = acpica_check_bios_date(1999, 1, 1); 3457c478bd9Sstevel@tonic-gate break; 3467c478bd9Sstevel@tonic-gate case ACPI_OUSER_ON: 3477c478bd9Sstevel@tonic-gate acpica_enable = TRUE; 3487c478bd9Sstevel@tonic-gate break; 3497c478bd9Sstevel@tonic-gate case ACPI_OUSER_OFF: 3507c478bd9Sstevel@tonic-gate case ACPI_OUSER_OFF | ACPI_OUSER_ON: 3517c478bd9Sstevel@tonic-gate acpica_enable = FALSE; 3527c478bd9Sstevel@tonic-gate break; 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate acpi_init_level = ACPI_FULL_INITIALIZATION; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* 3587c478bd9Sstevel@tonic-gate * special test here; may be generalized in the 3597c478bd9Sstevel@tonic-gate * future - test for a machines that are known to 3607c478bd9Sstevel@tonic-gate * work only in legacy mode, and set OUSER_LEGACY if 3617c478bd9Sstevel@tonic-gate * we're on one 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate if (acpica_metro_old_bios()) 3647c478bd9Sstevel@tonic-gate acpi_user_options |= ACPI_OUSER_LEGACY; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * If legacy mode is specified, set initialization 3687c478bd9Sstevel@tonic-gate * options to avoid entering ACPI mode and hooking SCI 3697c478bd9Sstevel@tonic-gate * - basically try to act like legacy acpi_intp 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0) 3727c478bd9Sstevel@tonic-gate acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT); 3733d50435fSmyers 3743d50435fSmyers /* 3753d50435fSmyers * modify default ACPI CA debug output level for non-DEBUG builds 3763d50435fSmyers * (to avoid BIOS debug chatter in /var/adm/messages) 3773d50435fSmyers */ 3783d50435fSmyers if (acpica_muzzle_debug_output) 3793d50435fSmyers AcpiDbgLevel = 0; 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate /* 3837c478bd9Sstevel@tonic-gate * Initialize the CA subsystem if it hasn't been done already 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate int 3867c478bd9Sstevel@tonic-gate acpica_init() 3877c478bd9Sstevel@tonic-gate { 388b9bfdccdSStuart Maybee extern void acpica_find_ioapics(void); 3897c478bd9Sstevel@tonic-gate ACPI_STATUS status; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate /* 3927c478bd9Sstevel@tonic-gate * Make sure user options are processed, 3937c478bd9Sstevel@tonic-gate * then fail to initialize if ACPI CA has been 3947c478bd9Sstevel@tonic-gate * disabled 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate acpica_process_user_options(); 3977c478bd9Sstevel@tonic-gate if (!acpica_enable) 3987c478bd9Sstevel@tonic-gate return (AE_ERROR); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate mutex_enter(&acpica_module_lock); 401fa96bd91SMichael Corcoran if (acpica_init_state == ACPICA_INITIALIZED) { 402fa96bd91SMichael Corcoran mutex_exit(&acpica_module_lock); 403fa96bd91SMichael Corcoran return (AE_OK); 404fa96bd91SMichael Corcoran } 4057c478bd9Sstevel@tonic-gate 406fa96bd91SMichael Corcoran if (ACPI_FAILURE(status = AcpiLoadTables())) 407fa96bd91SMichael Corcoran goto error; 408db2bae30SDana Myers 409fa96bd91SMichael Corcoran if (ACPI_FAILURE(status = acpica_install_handlers())) 410fa96bd91SMichael Corcoran goto error; 411db2bae30SDana Myers 4125f68fde5SDana Myers /* 4135f68fde5SDana Myers * Create ACPI-to-devinfo mapping now so _INI and _STA 4145f68fde5SDana Myers * methods can access PCI config space when needed 4155f68fde5SDana Myers */ 4165f68fde5SDana Myers scan_d2a_map(); 4175f68fde5SDana Myers 418fa96bd91SMichael Corcoran if (ACPI_FAILURE(status = AcpiEnableSubsystem(acpi_init_level))) 419fa96bd91SMichael Corcoran goto error; 420db2bae30SDana Myers 421fa96bd91SMichael Corcoran /* do after AcpiEnableSubsystem() so GPEs are initialized */ 422fa96bd91SMichael Corcoran acpica_ec_init(); /* initialize EC if present */ 423c1381f44SDana Myers 424fa96bd91SMichael Corcoran if (ACPI_FAILURE(status = AcpiInitializeObjects(0))) 425fa96bd91SMichael Corcoran goto error; 426db2bae30SDana Myers 427fa96bd91SMichael Corcoran acpica_init_state = ACPICA_INITIALIZED; 428fa96bd91SMichael Corcoran 429fa96bd91SMichael Corcoran /* 430fa96bd91SMichael Corcoran * If we are running on the Xen hypervisor as dom0 we need to 431fa96bd91SMichael Corcoran * find the ioapics so we can prevent ACPI from trying to 432fa96bd91SMichael Corcoran * access them. 433fa96bd91SMichael Corcoran */ 434fa96bd91SMichael Corcoran if (get_hwenv() == HW_XEN_PV && is_controldom()) 435fa96bd91SMichael Corcoran acpica_find_ioapics(); 436fa96bd91SMichael Corcoran acpica_init_kstats(); 4377c478bd9Sstevel@tonic-gate error: 438fa96bd91SMichael Corcoran if (acpica_init_state != ACPICA_INITIALIZED) { 439fa96bd91SMichael Corcoran cmn_err(CE_NOTE, "!failed to initialize ACPI services"); 440fa96bd91SMichael Corcoran } 4417c478bd9Sstevel@tonic-gate 442f7534bc1Ssmall /* 443f7534bc1Ssmall * Set acpi-status to 13 if acpica has been initialized successfully. 444f7534bc1Ssmall * This indicates that acpica is up and running. This variable name 445f7534bc1Ssmall * and value were chosen in order to remain compatible with acpi_intp. 446f7534bc1Ssmall */ 447f7534bc1Ssmall e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "acpi-status", 448fa96bd91SMichael Corcoran (ACPI_SUCCESS(status)) ? (ACPI_BOOT_INIT | ACPI_BOOT_ENABLE | 44987bb58d6Smyers ACPI_BOOT_BOOTCONF) : 0); 450f7534bc1Ssmall 451fa96bd91SMichael Corcoran /* Mark acpica subsystem as fully initialized. */ 452fa96bd91SMichael Corcoran if (ACPI_SUCCESS(status) && 453fa96bd91SMichael Corcoran acpi_init_level == ACPI_FULL_INITIALIZATION) { 454fa96bd91SMichael Corcoran acpica_set_core_feature(ACPI_FEATURE_FULL_INIT); 455fa96bd91SMichael Corcoran } 456fa96bd91SMichael Corcoran 4577c478bd9Sstevel@tonic-gate mutex_exit(&acpica_module_lock); 4587c478bd9Sstevel@tonic-gate return (status); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * SCI handling 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate ACPI_STATUS 4667c478bd9Sstevel@tonic-gate acpica_get_sci(int *sci_irq, iflag_t *sci_flags) 4677c478bd9Sstevel@tonic-gate { 468db2bae30SDana Myers ACPI_SUBTABLE_HEADER *ap; 469db2bae30SDana Myers ACPI_TABLE_MADT *mat; 470db2bae30SDana Myers ACPI_MADT_INTERRUPT_OVERRIDE *mio; 471db2bae30SDana Myers ACPI_TABLE_FADT *fadt; 4727c478bd9Sstevel@tonic-gate int madt_seen, madt_size; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate /* 4767c478bd9Sstevel@tonic-gate * Make sure user options are processed, 4777c478bd9Sstevel@tonic-gate * then return error if ACPI CA has been 4787c478bd9Sstevel@tonic-gate * disabled or system is not running in ACPI 4797c478bd9Sstevel@tonic-gate * and won't need/understand SCI 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate acpica_process_user_options(); 4827c478bd9Sstevel@tonic-gate if ((!acpica_enable) || (acpi_init_level & ACPI_NO_ACPI_ENABLE)) 4837c478bd9Sstevel@tonic-gate return (AE_ERROR); 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate /* 4867c478bd9Sstevel@tonic-gate * according to Intel ACPI developers, SCI 4877c478bd9Sstevel@tonic-gate * conforms to PCI bus conventions; level/low 4887c478bd9Sstevel@tonic-gate * unless otherwise directed by overrides. 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate sci_flags->intr_el = INTR_EL_LEVEL; 4917c478bd9Sstevel@tonic-gate sci_flags->intr_po = INTR_PO_ACTIVE_LOW; 4927c478bd9Sstevel@tonic-gate sci_flags->bustype = BUS_PCI; /* we *do* conform to PCI */ 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate /* get the SCI from the FADT */ 495db2bae30SDana Myers if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) != 496db2bae30SDana Myers AE_OK) 4977c478bd9Sstevel@tonic-gate return (AE_ERROR); 4987c478bd9Sstevel@tonic-gate 499db2bae30SDana Myers *sci_irq = fadt->SciInterrupt; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate /* search for ISOs that modify it */ 5027c478bd9Sstevel@tonic-gate /* if we don't find a MADT, that's OK; no ISOs then */ 503db2bae30SDana Myers if (AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **) &mat) != 504db2bae30SDana Myers AE_OK) 5057c478bd9Sstevel@tonic-gate return (AE_OK); 5067c478bd9Sstevel@tonic-gate 507db2bae30SDana Myers ap = (ACPI_SUBTABLE_HEADER *) (mat + 1); 508db2bae30SDana Myers madt_size = mat->Header.Length; 5097c478bd9Sstevel@tonic-gate madt_seen = sizeof (*mat); 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate while (madt_seen < madt_size) { 5127c478bd9Sstevel@tonic-gate switch (ap->Type) { 513db2bae30SDana Myers case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 514db2bae30SDana Myers mio = (ACPI_MADT_INTERRUPT_OVERRIDE *) ap; 515db2bae30SDana Myers if (mio->SourceIrq == *sci_irq) { 516db2bae30SDana Myers *sci_irq = mio->GlobalIrq; 517db2bae30SDana Myers sci_flags->intr_el = (mio->IntiFlags & 518db2bae30SDana Myers ACPI_MADT_TRIGGER_MASK) >> 2; 519db2bae30SDana Myers sci_flags->intr_po = mio->IntiFlags & 520db2bae30SDana Myers ACPI_MADT_POLARITY_MASK; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate break; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* advance to next entry */ 5267c478bd9Sstevel@tonic-gate madt_seen += ap->Length; 527db2bae30SDana Myers ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * One more check; if ISO said "conform", revert to default 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate if (sci_flags->intr_el == INTR_EL_CONFORM) 5347c478bd9Sstevel@tonic-gate sci_flags->intr_el = INTR_EL_LEVEL; 5357c478bd9Sstevel@tonic-gate if (sci_flags->intr_po == INTR_PO_CONFORM) 5367c478bd9Sstevel@tonic-gate sci_flags->intr_po = INTR_PO_ACTIVE_LOW; 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate return (AE_OK); 5397c478bd9Sstevel@tonic-gate } 5402df1fe9cSrandyf 5412df1fe9cSrandyf /* 5422df1fe9cSrandyf * Sets ACPI wake state for device referenced by dip. 5432df1fe9cSrandyf * If level is S0 (0), disables wake event; otherwise, 5442df1fe9cSrandyf * enables wake event which will wake system from level. 5452df1fe9cSrandyf */ 5462df1fe9cSrandyf static int 5472df1fe9cSrandyf acpica_ddi_setwake(dev_info_t *dip, int level) 5482df1fe9cSrandyf { 5492df1fe9cSrandyf ACPI_STATUS status; 5502df1fe9cSrandyf ACPI_HANDLE devobj, gpeobj; 5512df1fe9cSrandyf ACPI_OBJECT *prw, *gpe; 5522df1fe9cSrandyf ACPI_BUFFER prw_buf; 5532df1fe9cSrandyf int gpebit, pwr_res_count, prw_level, rv; 5542df1fe9cSrandyf 5552df1fe9cSrandyf /* 5562df1fe9cSrandyf * initialize these early so we can use a common 5572df1fe9cSrandyf * exit point below 5582df1fe9cSrandyf */ 5592df1fe9cSrandyf prw_buf.Pointer = NULL; 5602df1fe9cSrandyf prw_buf.Length = ACPI_ALLOCATE_BUFFER; 5612df1fe9cSrandyf rv = 0; 5622df1fe9cSrandyf 5632df1fe9cSrandyf /* 5642df1fe9cSrandyf * Attempt to get a handle to a corresponding ACPI object. 5652df1fe9cSrandyf * If no object is found, return quietly, since not all 5662df1fe9cSrandyf * devices have corresponding ACPI objects. 5672df1fe9cSrandyf */ 5682df1fe9cSrandyf status = acpica_get_handle(dip, &devobj); 5692df1fe9cSrandyf if (ACPI_FAILURE(status)) { 5702df1fe9cSrandyf char pathbuf[MAXPATHLEN]; 5712df1fe9cSrandyf ddi_pathname(dip, pathbuf); 5722df1fe9cSrandyf #ifdef DEBUG 5732df1fe9cSrandyf cmn_err(CE_NOTE, "!acpica_ddi_setwake: could not get" 5742df1fe9cSrandyf " handle for %s, %s:%d", pathbuf, ddi_driver_name(dip), 5752df1fe9cSrandyf ddi_get_instance(dip)); 5762df1fe9cSrandyf #endif 5772df1fe9cSrandyf goto done; 5782df1fe9cSrandyf } 5792df1fe9cSrandyf 5802df1fe9cSrandyf /* 5812df1fe9cSrandyf * Attempt to evaluate _PRW object. 5822df1fe9cSrandyf * If no valid object is found, return quietly, since not all 5832df1fe9cSrandyf * devices have _PRW objects. 5842df1fe9cSrandyf */ 5852df1fe9cSrandyf status = AcpiEvaluateObject(devobj, "_PRW", NULL, &prw_buf); 5862df1fe9cSrandyf prw = prw_buf.Pointer; 587db2bae30SDana Myers if (ACPI_FAILURE(status) || prw_buf.Length == 0 || prw == NULL || 5882df1fe9cSrandyf prw->Type != ACPI_TYPE_PACKAGE || prw->Package.Count < 2 || 5892df1fe9cSrandyf prw->Package.Elements[1].Type != ACPI_TYPE_INTEGER) { 5902df1fe9cSrandyf cmn_err(CE_NOTE, "acpica_ddi_setwake: could not " 5912df1fe9cSrandyf " evaluate _PRW"); 5922df1fe9cSrandyf goto done; 5932df1fe9cSrandyf } 5942df1fe9cSrandyf 5952df1fe9cSrandyf /* fetch the lowest wake level from the _PRW */ 5962df1fe9cSrandyf prw_level = prw->Package.Elements[1].Integer.Value; 5972df1fe9cSrandyf 5982df1fe9cSrandyf /* 5992df1fe9cSrandyf * process the GPE description 6002df1fe9cSrandyf */ 6012df1fe9cSrandyf switch (prw->Package.Elements[0].Type) { 6022df1fe9cSrandyf case ACPI_TYPE_INTEGER: 6032df1fe9cSrandyf gpeobj = NULL; 6042df1fe9cSrandyf gpebit = prw->Package.Elements[0].Integer.Value; 6052df1fe9cSrandyf break; 6062df1fe9cSrandyf case ACPI_TYPE_PACKAGE: 6072df1fe9cSrandyf gpe = &prw->Package.Elements[0]; 6082df1fe9cSrandyf if (gpe->Package.Count != 2 || 6092df1fe9cSrandyf gpe->Package.Elements[1].Type != ACPI_TYPE_INTEGER) 6102df1fe9cSrandyf goto done; 6112df1fe9cSrandyf gpeobj = gpe->Package.Elements[0].Reference.Handle; 6122df1fe9cSrandyf gpebit = gpe->Package.Elements[1].Integer.Value; 6132df1fe9cSrandyf if (gpeobj == NULL) 6142df1fe9cSrandyf goto done; 6152df1fe9cSrandyf default: 6162df1fe9cSrandyf goto done; 6172df1fe9cSrandyf } 6182df1fe9cSrandyf 6192df1fe9cSrandyf rv = -1; 6202df1fe9cSrandyf if (level == 0) { 6212df1fe9cSrandyf if (ACPI_FAILURE(AcpiDisableGpe(gpeobj, gpebit, ACPI_NOT_ISR))) 6222df1fe9cSrandyf goto done; 6232df1fe9cSrandyf } else if (prw_level <= level) { 6242df1fe9cSrandyf if (ACPI_SUCCESS( 6252df1fe9cSrandyf AcpiSetGpeType(gpeobj, gpebit, ACPI_GPE_TYPE_WAKE))) 6262df1fe9cSrandyf if (ACPI_FAILURE( 6272df1fe9cSrandyf AcpiEnableGpe(gpeobj, gpebit, ACPI_NOT_ISR))) 6282df1fe9cSrandyf goto done; 6292df1fe9cSrandyf } 6302df1fe9cSrandyf rv = 0; 6312df1fe9cSrandyf done: 6322df1fe9cSrandyf if (prw_buf.Pointer != NULL) 6332df1fe9cSrandyf AcpiOsFree(prw_buf.Pointer); 6342df1fe9cSrandyf return (rv); 6352df1fe9cSrandyf } 6362df1fe9cSrandyf 6372df1fe9cSrandyf /* 6382df1fe9cSrandyf * kstat access to a limited set of ACPI propertis 6392df1fe9cSrandyf */ 6402df1fe9cSrandyf static void 6412df1fe9cSrandyf acpica_init_kstats() 6422df1fe9cSrandyf { 6432df1fe9cSrandyf ACPI_HANDLE s3handle; 6442df1fe9cSrandyf ACPI_STATUS status; 645db2bae30SDana Myers ACPI_TABLE_FADT *fadt; 6462df1fe9cSrandyf kstat_named_t *knp; 6472df1fe9cSrandyf 6482df1fe9cSrandyf /* 6492df1fe9cSrandyf * Create a small set of named kstats; just return in the rare 6502df1fe9cSrandyf * case of a failure, * in which case, the kstats won't be present. 6512df1fe9cSrandyf */ 6522df1fe9cSrandyf if ((acpica_ksp = kstat_create("acpi", 0, "acpi", "misc", 6532df1fe9cSrandyf KSTAT_TYPE_NAMED, 2, 0)) == NULL) 6542df1fe9cSrandyf return; 6552df1fe9cSrandyf 6562df1fe9cSrandyf /* 6572df1fe9cSrandyf * initialize kstat 'S3' to reflect the presence of \_S3 in 6582df1fe9cSrandyf * the ACPI namespace (1 = present, 0 = not present) 6592df1fe9cSrandyf */ 6602df1fe9cSrandyf knp = acpica_ksp->ks_data; 6612df1fe9cSrandyf knp->value.l = (AcpiGetHandle(NULL, "\\_S3", &s3handle) == AE_OK); 6622df1fe9cSrandyf kstat_named_init(knp, "S3", KSTAT_DATA_LONG); 6632df1fe9cSrandyf knp++; /* advance to next named kstat */ 6642df1fe9cSrandyf 6652df1fe9cSrandyf /* 6662df1fe9cSrandyf * initialize kstat 'preferred_pm_profile' to the value 6672df1fe9cSrandyf * contained in the (always present) FADT 6682df1fe9cSrandyf */ 669db2bae30SDana Myers status = AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt); 670db2bae30SDana Myers knp->value.l = (status == AE_OK) ? fadt->PreferredProfile : -1; 6712df1fe9cSrandyf kstat_named_init(knp, "preferred_pm_profile", KSTAT_DATA_LONG); 6722df1fe9cSrandyf 6732df1fe9cSrandyf /* 6742df1fe9cSrandyf * install the named kstats 6752df1fe9cSrandyf */ 6762df1fe9cSrandyf kstat_install(acpica_ksp); 6772df1fe9cSrandyf } 6782df1fe9cSrandyf 6792df1fe9cSrandyf /* 6802df1fe9cSrandyf * Attempt to save the current ACPI settings (_CRS) for the device 6812df1fe9cSrandyf * which corresponds to the supplied devinfo node. The settings are 6822df1fe9cSrandyf * saved as a property on the dip. If no ACPI object is found to be 6832df1fe9cSrandyf * associated with the devinfo node, no action is taken and no error 6842df1fe9cSrandyf * is reported. 6852df1fe9cSrandyf */ 6862df1fe9cSrandyf void 6872df1fe9cSrandyf acpica_ddi_save_resources(dev_info_t *dip) 6882df1fe9cSrandyf { 6892df1fe9cSrandyf ACPI_HANDLE devobj; 6902df1fe9cSrandyf ACPI_BUFFER resbuf; 6912df1fe9cSrandyf int ret; 6922df1fe9cSrandyf 6932df1fe9cSrandyf resbuf.Length = ACPI_ALLOCATE_BUFFER; 6942df1fe9cSrandyf if (ACPI_FAILURE(acpica_get_handle(dip, &devobj)) || 6952df1fe9cSrandyf ACPI_FAILURE(AcpiGetCurrentResources(devobj, &resbuf))) 6962df1fe9cSrandyf return; 6972df1fe9cSrandyf 6982df1fe9cSrandyf ret = ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 6992df1fe9cSrandyf "acpi-crs", resbuf.Pointer, resbuf.Length); 7002df1fe9cSrandyf 7012df1fe9cSrandyf ASSERT(ret == DDI_PROP_SUCCESS); 7022df1fe9cSrandyf 7032df1fe9cSrandyf AcpiOsFree(resbuf.Pointer); 7042df1fe9cSrandyf } 7052df1fe9cSrandyf 7062df1fe9cSrandyf /* 7072df1fe9cSrandyf * If the supplied devinfo node has an ACPI settings property attached, 7082df1fe9cSrandyf * restore them to the associated ACPI device using _SRS. The property 7092df1fe9cSrandyf * is deleted from the devinfo node afterward. 7102df1fe9cSrandyf */ 7112df1fe9cSrandyf void 7122df1fe9cSrandyf acpica_ddi_restore_resources(dev_info_t *dip) 7132df1fe9cSrandyf { 7142df1fe9cSrandyf ACPI_HANDLE devobj; 7152df1fe9cSrandyf ACPI_BUFFER resbuf; 7162df1fe9cSrandyf uchar_t *propdata; 7172df1fe9cSrandyf uint_t proplen; 7182df1fe9cSrandyf 7192df1fe9cSrandyf if (ACPI_FAILURE(acpica_get_handle(dip, &devobj))) 7202df1fe9cSrandyf return; 7212df1fe9cSrandyf 7222df1fe9cSrandyf if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 7232df1fe9cSrandyf "acpi-crs", &propdata, &proplen) != DDI_PROP_SUCCESS) 7242df1fe9cSrandyf return; 7252df1fe9cSrandyf 7262df1fe9cSrandyf resbuf.Pointer = propdata; 7272df1fe9cSrandyf resbuf.Length = proplen; 7282df1fe9cSrandyf (void) AcpiSetCurrentResources(devobj, &resbuf); 7292df1fe9cSrandyf ddi_prop_free(propdata); 7300f1b305eSSeth Goldberg (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "acpi-crs"); 7312df1fe9cSrandyf } 7324cf02d40SSaurabh Misra 7334cf02d40SSaurabh Misra void 7344cf02d40SSaurabh Misra acpi_reset_system(void) 7354cf02d40SSaurabh Misra { 7364cf02d40SSaurabh Misra ACPI_STATUS status; 7374cf02d40SSaurabh Misra int ten; 7384cf02d40SSaurabh Misra 7394cf02d40SSaurabh Misra status = AcpiReset(); 7404cf02d40SSaurabh Misra if (status == AE_OK) { 7414cf02d40SSaurabh Misra /* 7424cf02d40SSaurabh Misra * Wait up to 500 milliseconds for AcpiReset() to make its 7434cf02d40SSaurabh Misra * way. 7444cf02d40SSaurabh Misra */ 7454cf02d40SSaurabh Misra ten = 50000; 7464cf02d40SSaurabh Misra while (ten-- > 0) 7474cf02d40SSaurabh Misra tenmicrosec(); 7484cf02d40SSaurabh Misra } 7494cf02d40SSaurabh Misra } 750