evmisc.c revision 99146
129088Smarkm/****************************************************************************** 229088Smarkm * 329088Smarkm * Module Name: evmisc - Miscellaneous event manager support functions 429088Smarkm * $Revision: 48 $ 529088Smarkm * 629088Smarkm *****************************************************************************/ 729088Smarkm 829088Smarkm/****************************************************************************** 929088Smarkm * 1029088Smarkm * 1. Copyright Notice 1129088Smarkm * 1229088Smarkm * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp. 1329088Smarkm * All rights reserved. 1429088Smarkm * 1529088Smarkm * 2. License 1629088Smarkm * 1729088Smarkm * 2.1. This is your license from Intel Corp. under its intellectual property 1829088Smarkm * rights. You may have additional license terms from the party that provided 1929088Smarkm * you this software, covering your right to use that party's intellectual 2029088Smarkm * property rights. 2129088Smarkm * 2229088Smarkm * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 2329088Smarkm * copy of the source code appearing in this file ("Covered Code") an 2429088Smarkm * irrevocable, perpetual, worldwide license under Intel's copyrights in the 2529088Smarkm * base code distributed originally by Intel ("Original Intel Code") to copy, 2629088Smarkm * make derivatives, distribute, use and display any portion of the Covered 2729088Smarkm * Code in any form, with the right to sublicense such rights; and 2829088Smarkm * 2929088Smarkm * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 3029088Smarkm * license (with the right to sublicense), under only those claims of Intel 3129088Smarkm * patents that are infringed by the Original Intel Code, to make, use, sell, 3229088Smarkm * offer to sell, and import the Covered Code and derivative works thereof 3329088Smarkm * solely to the minimum extent necessary to exercise the above copyright 3429088Smarkm * license, and in no event shall the patent license extend to any additions 3563248Speter * to or modifications of the Original Intel Code. No other license or right 3629181Smarkm * is granted directly or by implication, estoppel or otherwise; 3763248Speter * 3863248Speter * The above copyright and patent license is granted only if the following 3963248Speter * conditions are met: 4063248Speter * 4129088Smarkm * 3. Conditions 4229088Smarkm * 4329088Smarkm * 3.1. Redistribution of Source with Rights to Further Distribute Source. 4429088Smarkm * Redistribution of source code of any substantial portion of the Covered 4529088Smarkm * Code or modification with rights to further distribute source must include 4629088Smarkm * the above Copyright Notice, the above License, this list of Conditions, 4729088Smarkm * and the following Disclaimer and Export Compliance provision. In addition, 4829088Smarkm * Licensee must cause all Covered Code to which Licensee contributes to 4929088Smarkm * contain a file documenting the changes Licensee made to create that Covered 5029088Smarkm * Code and the date of any change. Licensee must include in that file the 5129088Smarkm * documentation of any changes made by any predecessor Licensee. Licensee 5229088Smarkm * must include a prominent statement that the modification is derived, 5329088Smarkm * directly or indirectly, from Original Intel Code. 5429088Smarkm * 5529088Smarkm * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 5629088Smarkm * Redistribution of source code of any substantial portion of the Covered 5729181Smarkm * Code or modification without rights to further distribute source must 5829181Smarkm * include the following Disclaimer and Export Compliance provision in the 5929181Smarkm * documentation and/or other materials provided with distribution. In 6029088Smarkm * addition, Licensee may not authorize further sublicense of source of any 6129088Smarkm * portion of the Covered Code, and must include terms to the effect that the 6229088Smarkm * license from Licensee to its licensee is limited to the intellectual 6329088Smarkm * property embodied in the software Licensee provides to its licensee, and 6429088Smarkm * not to intellectual property embodied in modifications its licensee may 6529088Smarkm * make. 6629088Smarkm * 6729181Smarkm * 3.3. Redistribution of Executable. Redistribution in executable form of any 6829181Smarkm * substantial portion of the Covered Code or modification must reproduce the 6929181Smarkm * above Copyright Notice, and the following Disclaimer and Export Compliance 7029181Smarkm * provision in the documentation and/or other materials provided with the 7129181Smarkm * distribution. 7229181Smarkm * 7329181Smarkm * 3.4. Intel retains all right, title, and interest in and to the Original 7429088Smarkm * Intel Code. 7529088Smarkm * 7629088Smarkm * 3.5. Neither the name Intel nor any other trademark owned or controlled by 7729088Smarkm * Intel shall be used in advertising or otherwise to promote the sale, use or 7829088Smarkm * other dealings in products derived from or relating to the Covered Code 7929088Smarkm * without prior written authorization from Intel. 8029088Smarkm * 8129088Smarkm * 4. Disclaimer and Export Compliance 8229088Smarkm * 8329088Smarkm * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 8429088Smarkm * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 8529088Smarkm * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 8629088Smarkm * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 8729088Smarkm * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 8829088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 8929088Smarkm * PARTICULAR PURPOSE. 9029088Smarkm * 9129088Smarkm * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 9229088Smarkm * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 9329088Smarkm * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 9429088Smarkm * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 9529088Smarkm * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 9629088Smarkm * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 9729088Smarkm * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 9829088Smarkm * LIMITED REMEDY. 9929088Smarkm * 10029088Smarkm * 4.3. Licensee shall not export, either directly or indirectly, any of this 10129088Smarkm * software or system incorporating such software without first obtaining any 10229088Smarkm * required license or other approval from the U. S. Department of Commerce or 10329088Smarkm * any other agency or department of the United States Government. In the 10429088Smarkm * event Licensee exports any such software from the United States or 10529088Smarkm * re-exports any such software from a foreign destination, Licensee shall 10629088Smarkm * ensure that the distribution and export/re-export of the software is in 10729088Smarkm * compliance with all laws, regulations, orders, or other restrictions of the 10829088Smarkm * U.S. Export Administration Regulations. Licensee agrees that neither it nor 10929088Smarkm * any of its subsidiaries will export/re-export any technical data, process, 11029088Smarkm * software, or service, directly or indirectly, to any country for which the 11129088Smarkm * United States government or any agency thereof requires an export license, 11229088Smarkm * other governmental approval, or letter of assurance, without first obtaining 11329088Smarkm * such license, approval or letter. 11429088Smarkm * 11529088Smarkm *****************************************************************************/ 11629088Smarkm 11729088Smarkm#include "acpi.h" 11829088Smarkm#include "acevents.h" 11929088Smarkm#include "acnamesp.h" 12029088Smarkm#include "acinterp.h" 12129088Smarkm#include "achware.h" 12229181Smarkm 12347973Sru#define _COMPONENT ACPI_EVENTS 12429181Smarkm ACPI_MODULE_NAME ("evmisc") 12529088Smarkm 12629088Smarkm 12729088Smarkm/******************************************************************************* 12829088Smarkm * 12929088Smarkm * FUNCTION: AcpiEvIsNotifyObject 13029088Smarkm * 13129088Smarkm * PARAMETERS: Node - Node to check 13229088Smarkm * 13329088Smarkm * RETURN: TRUE if notifies allowed on this object 13429088Smarkm * 13529088Smarkm * DESCRIPTION: Check type of node for a object that supports notifies. 13629088Smarkm * 13729088Smarkm * TBD: This could be replaced by a flag bit in the node. 13829088Smarkm * 13929088Smarkm ******************************************************************************/ 14029088Smarkm 14129088SmarkmBOOLEAN 14229088SmarkmAcpiEvIsNotifyObject ( 14329088Smarkm ACPI_NAMESPACE_NODE *Node) 14429088Smarkm{ 14529088Smarkm switch (Node->Type) 14629088Smarkm { 14729088Smarkm case ACPI_TYPE_DEVICE: 14829088Smarkm case ACPI_TYPE_PROCESSOR: 14929088Smarkm case ACPI_TYPE_POWER: 15029088Smarkm case ACPI_TYPE_THERMAL: 15129088Smarkm /* 15229088Smarkm * These are the ONLY objects that can receive ACPI notifications 15329088Smarkm */ 15429088Smarkm return (TRUE); 15529088Smarkm 15629088Smarkm default: 15729088Smarkm return (FALSE); 15829088Smarkm } 15929088Smarkm} 16029088Smarkm 16129088Smarkm 16229088Smarkm/******************************************************************************* 16329088Smarkm * 16429088Smarkm * FUNCTION: AcpiEvGetGpeRegisterIndex 16529088Smarkm * 16629088Smarkm * PARAMETERS: GpeNumber - Raw GPE number 16729088Smarkm * 16829088Smarkm * RETURN: None. 16929088Smarkm * 17029088Smarkm * DESCRIPTION: Returns the register index (index into the GPE register info 17129088Smarkm * table) associated with this GPE. 17229088Smarkm * 17329088Smarkm ******************************************************************************/ 17429088Smarkm 17529088SmarkmUINT32 17629088SmarkmAcpiEvGetGpeRegisterIndex ( 17729088Smarkm UINT32 GpeNumber) 17829088Smarkm{ 17929088Smarkm 18029088Smarkm if (GpeNumber > AcpiGbl_GpeNumberMax) 18129088Smarkm { 18229088Smarkm return (ACPI_GPE_INVALID); 18329088Smarkm } 18429088Smarkm 18529088Smarkm return (ACPI_DIV_8 (AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex)); 18629088Smarkm} 18729088Smarkm 18829088Smarkm 18929088Smarkm/******************************************************************************* 19029088Smarkm * 19129088Smarkm * FUNCTION: AcpiEvGetGpeNumberIndex 19229088Smarkm * 19329088Smarkm * PARAMETERS: GpeNumber - Raw GPE number 19429088Smarkm * 19529088Smarkm * RETURN: None. 19629088Smarkm * 19729088Smarkm * DESCRIPTION: Returns the number index (index into the GPE number info table) 19829088Smarkm * associated with this GPE. 19929088Smarkm * 20029088Smarkm ******************************************************************************/ 20129088Smarkm 20229088SmarkmUINT32 20329088SmarkmAcpiEvGetGpeNumberIndex ( 20429088Smarkm UINT32 GpeNumber) 20529088Smarkm{ 20629088Smarkm 20729088Smarkm if (GpeNumber > AcpiGbl_GpeNumberMax) 20829088Smarkm { 20929088Smarkm return (ACPI_GPE_INVALID); 21029088Smarkm } 21129088Smarkm 21229088Smarkm return (AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex); 21329088Smarkm} 21429088Smarkm 21529088Smarkm 21629088Smarkm/******************************************************************************* 21729088Smarkm * 21829088Smarkm * FUNCTION: AcpiEvQueueNotifyRequest 21929088Smarkm * 22029088Smarkm * PARAMETERS: 22129088Smarkm * 22229088Smarkm * RETURN: None. 22329088Smarkm * 22429088Smarkm * DESCRIPTION: Dispatch a device notification event to a previously 22529088Smarkm * installed handler. 22629088Smarkm * 22729088Smarkm ******************************************************************************/ 22829088Smarkm 22929088SmarkmACPI_STATUS 23029088SmarkmAcpiEvQueueNotifyRequest ( 23129088Smarkm ACPI_NAMESPACE_NODE *Node, 23229088Smarkm UINT32 NotifyValue) 23329088Smarkm{ 23429088Smarkm ACPI_OPERAND_OBJECT *ObjDesc; 23529088Smarkm ACPI_OPERAND_OBJECT *HandlerObj = NULL; 23629088Smarkm ACPI_GENERIC_STATE *NotifyInfo; 23729088Smarkm ACPI_STATUS Status = AE_OK; 23829088Smarkm 23929088Smarkm 24029088Smarkm ACPI_FUNCTION_NAME ("EvQueueNotifyRequest"); 24129088Smarkm 24229088Smarkm 24329088Smarkm /* 24429088Smarkm * For value 1 (Ejection Request), some device method may need to be run. 24529088Smarkm * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run. 24629088Smarkm * For value 0x80 (Status Change) on the power button or sleep button, 24729088Smarkm * initiate soft-off or sleep operation? 24829088Smarkm */ 24929088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 25029088Smarkm "Dispatching Notify(%X) on node %p\n", NotifyValue, Node)); 25129088Smarkm 25229088Smarkm switch (NotifyValue) 25329088Smarkm { 25429088Smarkm case 0: 25529088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Re-enumerate Devices\n")); 25629088Smarkm break; 25729088Smarkm 25829088Smarkm case 1: 25929088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Ejection Request\n")); 26029088Smarkm break; 26129088Smarkm 26229088Smarkm case 2: 26329088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Device Wake\n")); 26429088Smarkm break; 26529088Smarkm 26629088Smarkm case 0x80: 26729088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Status Change\n")); 26829088Smarkm break; 26929088Smarkm 27029088Smarkm default: 27129088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unknown Notify Value: %X \n", NotifyValue)); 27229088Smarkm break; 27329088Smarkm } 27429088Smarkm 27529088Smarkm /* 27629088Smarkm * Get the notify object attached to the device Node 27729088Smarkm */ 27829088Smarkm ObjDesc = AcpiNsGetAttachedObject (Node); 27929088Smarkm if (ObjDesc) 28029088Smarkm { 28129088Smarkm /* We have the notify object, Get the right handler */ 28229088Smarkm 28329088Smarkm switch (Node->Type) 28429088Smarkm { 28529088Smarkm case ACPI_TYPE_DEVICE: 28629088Smarkm 28729088Smarkm if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) 28829088Smarkm { 28929088Smarkm HandlerObj = ObjDesc->Device.SysHandler; 29029088Smarkm } 29129088Smarkm else 29229088Smarkm { 29329088Smarkm HandlerObj = ObjDesc->Device.DrvHandler; 29429088Smarkm } 29529088Smarkm break; 29629088Smarkm 29729088Smarkm 29829088Smarkm case ACPI_TYPE_THERMAL: 29929088Smarkm 30029088Smarkm if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) 30129088Smarkm { 30229088Smarkm HandlerObj = ObjDesc->ThermalZone.SysHandler; 30329088Smarkm } 30429088Smarkm else 30529088Smarkm { 30629088Smarkm HandlerObj = ObjDesc->ThermalZone.DrvHandler; 30729088Smarkm } 30829088Smarkm break; 30929088Smarkm } 31029088Smarkm } 31129088Smarkm 31229088Smarkm /* If there is any handler to run, schedule the dispatcher */ 31329088Smarkm 31429088Smarkm if ((AcpiGbl_SysNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) || 31529088Smarkm (AcpiGbl_DrvNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY)) || 31629088Smarkm HandlerObj) 31729088Smarkm { 31829088Smarkm NotifyInfo = AcpiUtCreateGenericState (); 31929088Smarkm if (!NotifyInfo) 32029088Smarkm { 32129088Smarkm return (AE_NO_MEMORY); 32229088Smarkm } 32329088Smarkm 32429088Smarkm NotifyInfo->Common.DataType = ACPI_DESC_TYPE_STATE_NOTIFY; 32529088Smarkm NotifyInfo->Notify.Node = Node; 32629088Smarkm NotifyInfo->Notify.Value = (UINT16) NotifyValue; 32729088Smarkm NotifyInfo->Notify.HandlerObj = HandlerObj; 32829088Smarkm 32929088Smarkm Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH, 33029088Smarkm AcpiEvNotifyDispatch, NotifyInfo); 33129088Smarkm if (ACPI_FAILURE (Status)) 33229088Smarkm { 33329088Smarkm AcpiUtDeleteGenericState (NotifyInfo); 33429088Smarkm } 33529088Smarkm } 33629088Smarkm 33729088Smarkm if (!HandlerObj) 33829088Smarkm { 33929088Smarkm /* There is no per-device notify handler for this device */ 34029088Smarkm 34129088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for node %p \n", Node)); 34229088Smarkm } 34329088Smarkm 34429088Smarkm return (Status); 34529088Smarkm} 34629088Smarkm 34729088Smarkm 34829088Smarkm/******************************************************************************* 34929088Smarkm * 35029088Smarkm * FUNCTION: AcpiEvNotifyDispatch 35129088Smarkm * 35229088Smarkm * PARAMETERS: 35329088Smarkm * 35429088Smarkm * RETURN: None. 35529088Smarkm * 35629088Smarkm * DESCRIPTION: Dispatch a device notification event to a previously 35729088Smarkm * installed handler. 35829088Smarkm * 35929088Smarkm ******************************************************************************/ 36029088Smarkm 36129088Smarkmvoid ACPI_SYSTEM_XFACE 36229088SmarkmAcpiEvNotifyDispatch ( 36329088Smarkm void *Context) 36429088Smarkm{ 36529088Smarkm ACPI_GENERIC_STATE *NotifyInfo = (ACPI_GENERIC_STATE *) Context; 36629088Smarkm ACPI_NOTIFY_HANDLER GlobalHandler = NULL; 36729088Smarkm void *GlobalContext = NULL; 36829088Smarkm ACPI_OPERAND_OBJECT *HandlerObj; 36929088Smarkm 37029088Smarkm 37129088Smarkm ACPI_FUNCTION_ENTRY (); 37229088Smarkm 37329088Smarkm 37429088Smarkm /* 37529088Smarkm * We will invoke a global notify handler if installed. 37629088Smarkm * This is done _before_ we invoke the per-device handler attached to the device. 37729088Smarkm */ 37829088Smarkm if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY) 37929088Smarkm { 38029088Smarkm /* Global system notification handler */ 38129088Smarkm 38229088Smarkm if (AcpiGbl_SysNotify.Handler) 38329088Smarkm { 38429088Smarkm GlobalHandler = AcpiGbl_SysNotify.Handler; 38529088Smarkm GlobalContext = AcpiGbl_SysNotify.Context; 38629088Smarkm } 38729088Smarkm } 38829088Smarkm else 38929088Smarkm { 39029088Smarkm /* Global driver notification handler */ 39129088Smarkm 39229088Smarkm if (AcpiGbl_DrvNotify.Handler) 39329088Smarkm { 39429088Smarkm GlobalHandler = AcpiGbl_DrvNotify.Handler; 39529088Smarkm GlobalContext = AcpiGbl_DrvNotify.Context; 39629088Smarkm } 39729088Smarkm } 39829088Smarkm 39929088Smarkm /* Invoke the system handler first, if present */ 40029088Smarkm 40129088Smarkm if (GlobalHandler) 40229088Smarkm { 40329088Smarkm GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, GlobalContext); 40429088Smarkm } 40529088Smarkm 40629088Smarkm /* Now invoke the per-device handler, if present */ 40729088Smarkm 40829088Smarkm HandlerObj = NotifyInfo->Notify.HandlerObj; 40929088Smarkm if (HandlerObj) 41029088Smarkm { 41129088Smarkm HandlerObj->NotifyHandler.Handler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, 41229088Smarkm HandlerObj->NotifyHandler.Context); 41329088Smarkm } 41429088Smarkm 41529088Smarkm /* All done with the info object */ 41629088Smarkm 41729088Smarkm AcpiUtDeleteGenericState (NotifyInfo); 41829088Smarkm} 41929088Smarkm 42029088Smarkm 42129088Smarkm/******************************************************************************* 42229088Smarkm * 42329088Smarkm * FUNCTION: AcpiEvGlobalLockThread 42429088Smarkm * 42529088Smarkm * RETURN: None 42629088Smarkm * 42729088Smarkm * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the 42829088Smarkm * Global Lock. Simply signal all threads that are waiting 42929088Smarkm * for the lock. 43029088Smarkm * 43129088Smarkm ******************************************************************************/ 43229088Smarkm 43329088Smarkmstatic void ACPI_SYSTEM_XFACE 43429088SmarkmAcpiEvGlobalLockThread ( 43529088Smarkm void *Context) 43629088Smarkm{ 43729088Smarkm 43829088Smarkm /* Signal threads that are waiting for the lock */ 43929088Smarkm 44029088Smarkm if (AcpiGbl_GlobalLockThreadCount) 44129088Smarkm { 44229088Smarkm /* Send sufficient units to the semaphore */ 44329088Smarkm 44429088Smarkm AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 44529088Smarkm AcpiGbl_GlobalLockThreadCount); 44629088Smarkm } 44729088Smarkm} 44829088Smarkm 44929088Smarkm 45029088Smarkm/******************************************************************************* 45129088Smarkm * 45229088Smarkm * FUNCTION: AcpiEvGlobalLockHandler 45329088Smarkm * 45429088Smarkm * RETURN: Status 45529088Smarkm * 45629088Smarkm * DESCRIPTION: Invoked directly from the SCI handler when a global lock 45729088Smarkm * release interrupt occurs. Grab the global lock and queue 45829088Smarkm * the global lock thread for execution 45929088Smarkm * 46029088Smarkm ******************************************************************************/ 46129088Smarkm 46229088Smarkmstatic UINT32 46329088SmarkmAcpiEvGlobalLockHandler ( 46429088Smarkm void *Context) 46529088Smarkm{ 46629088Smarkm BOOLEAN Acquired = FALSE; 46729088Smarkm 46829088Smarkm 46929088Smarkm /* 47029088Smarkm * Attempt to get the lock 47129088Smarkm * If we don't get it now, it will be marked pending and we will 47229088Smarkm * take another interrupt when it becomes free. 47329088Smarkm */ 47429088Smarkm ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired); 47529088Smarkm if (Acquired) 47629088Smarkm { 47729088Smarkm /* Got the lock, now wake all threads waiting for it */ 47829088Smarkm 47929088Smarkm AcpiGbl_GlobalLockAcquired = TRUE; 48029088Smarkm 48129088Smarkm /* Run the Global Lock thread which will signal all waiting threads */ 48229088Smarkm 48329088Smarkm AcpiOsQueueForExecution (OSD_PRIORITY_HIGH, AcpiEvGlobalLockThread, 48429088Smarkm Context); 48529088Smarkm } 48629088Smarkm 48729088Smarkm return (ACPI_INTERRUPT_HANDLED); 48829088Smarkm} 48929088Smarkm 49029088Smarkm 49129088Smarkm/******************************************************************************* 49229088Smarkm * 49329088Smarkm * FUNCTION: AcpiEvInitGlobalLockHandler 49429088Smarkm * 49529088Smarkm * RETURN: Status 49629088Smarkm * 49729088Smarkm * DESCRIPTION: Install a handler for the global lock release event 49829088Smarkm * 49929088Smarkm ******************************************************************************/ 50029088Smarkm 50129088SmarkmACPI_STATUS 50229088SmarkmAcpiEvInitGlobalLockHandler (void) 50329088Smarkm{ 50429088Smarkm ACPI_STATUS Status; 50529088Smarkm 50629088Smarkm 50729088Smarkm ACPI_FUNCTION_TRACE ("EvInitGlobalLockHandler"); 50829088Smarkm 50929088Smarkm 51029088Smarkm AcpiGbl_GlobalLockPresent = TRUE; 51129088Smarkm Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, 51229088Smarkm AcpiEvGlobalLockHandler, NULL); 51329088Smarkm 51429088Smarkm /* 51529088Smarkm * If the global lock does not exist on this platform, the attempt 51629088Smarkm * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick) 51729088Smarkm * Map to AE_OK, but mark global lock as not present. 51829088Smarkm * Any attempt to actually use the global lock will be flagged 51929088Smarkm * with an error. 52029088Smarkm */ 52129088Smarkm if (Status == AE_NO_HARDWARE_RESPONSE) 52229088Smarkm { 52329088Smarkm AcpiGbl_GlobalLockPresent = FALSE; 52429088Smarkm Status = AE_OK; 52529088Smarkm } 52629088Smarkm 52729088Smarkm return_ACPI_STATUS (Status); 52829088Smarkm} 52929088Smarkm 53029088Smarkm 53129088Smarkm/****************************************************************************** 53229088Smarkm * 53329088Smarkm * FUNCTION: AcpiEvAcquireGlobalLock 53429088Smarkm * 53529088Smarkm * RETURN: Status 53629088Smarkm * 53729088Smarkm * DESCRIPTION: Attempt to gain ownership of the Global Lock. 53829088Smarkm * 53929088Smarkm *****************************************************************************/ 54029088Smarkm 54129088SmarkmACPI_STATUS 54229088SmarkmAcpiEvAcquireGlobalLock ( 54329088Smarkm UINT32 Timeout) 54429088Smarkm{ 54529088Smarkm ACPI_STATUS Status = AE_OK; 54629088Smarkm BOOLEAN Acquired = FALSE; 54729088Smarkm 54829088Smarkm 54929088Smarkm ACPI_FUNCTION_TRACE ("EvAcquireGlobalLock"); 55029088Smarkm 55129088Smarkm 55229088Smarkm /* Make sure that we actually have a global lock */ 55329088Smarkm 55429088Smarkm if (!AcpiGbl_GlobalLockPresent) 55529088Smarkm { 55629088Smarkm return_ACPI_STATUS (AE_NO_GLOBAL_LOCK); 55729088Smarkm } 55829088Smarkm 55929088Smarkm /* One more thread wants the global lock */ 56029088Smarkm 56129088Smarkm AcpiGbl_GlobalLockThreadCount++; 56229088Smarkm 56329088Smarkm /* If we (OS side vs. BIOS side) have the hardware lock already, we are done */ 56429088Smarkm 56529088Smarkm if (AcpiGbl_GlobalLockAcquired) 56629088Smarkm { 56729088Smarkm return_ACPI_STATUS (AE_OK); 56829088Smarkm } 56929088Smarkm 57029088Smarkm /* We must acquire the actual hardware lock */ 57129088Smarkm 57229088Smarkm ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired); 57329088Smarkm if (Acquired) 57429088Smarkm { 57529088Smarkm /* We got the lock */ 57629088Smarkm 57729088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired the HW Global Lock\n")); 57829088Smarkm 57929088Smarkm AcpiGbl_GlobalLockAcquired = TRUE; 58029088Smarkm return_ACPI_STATUS (AE_OK); 58129088Smarkm } 58229088Smarkm 58329088Smarkm /* 58429088Smarkm * Did not get the lock. The pending bit was set above, and we must now 58529088Smarkm * wait until we get the global lock released interrupt. 58629088Smarkm */ 58729088Smarkm ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for the HW Global Lock\n")); 58829088Smarkm 58929088Smarkm /* 59029088Smarkm * Acquire the global lock semaphore first. 59129088Smarkm * Since this wait will block, we must release the interpreter 59229088Smarkm */ 59329088Smarkm Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, 59429088Smarkm Timeout); 59529088Smarkm return_ACPI_STATUS (Status); 59629088Smarkm} 59729088Smarkm 59829088Smarkm 59929088Smarkm/******************************************************************************* 60029088Smarkm * 60129088Smarkm * FUNCTION: AcpiEvReleaseGlobalLock 60229088Smarkm * 60329088Smarkm * DESCRIPTION: Releases ownership of the Global Lock. 60429088Smarkm * 60529088Smarkm ******************************************************************************/ 60629088Smarkm 60729088Smarkmvoid 60829088SmarkmAcpiEvReleaseGlobalLock (void) 60929088Smarkm{ 61029088Smarkm BOOLEAN Pending = FALSE; 61129088Smarkm 61229088Smarkm 61329088Smarkm ACPI_FUNCTION_TRACE ("EvReleaseGlobalLock"); 61429088Smarkm 61529088Smarkm 61629088Smarkm if (!AcpiGbl_GlobalLockThreadCount) 61729088Smarkm { 61829088Smarkm ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n")); 61929088Smarkm return_VOID; 62029088Smarkm } 62129088Smarkm 62229088Smarkm /* One fewer thread has the global lock */ 62329088Smarkm 62429088Smarkm AcpiGbl_GlobalLockThreadCount--; 62529088Smarkm if (AcpiGbl_GlobalLockThreadCount) 62629088Smarkm { 62729088Smarkm /* There are still some threads holding the lock, cannot release */ 62829088Smarkm 62929088Smarkm return_VOID; 63029088Smarkm } 63129088Smarkm 63229088Smarkm /* 63329088Smarkm * No more threads holding lock, we can do the actual hardware 63429088Smarkm * release 63529088Smarkm */ 63629088Smarkm ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Pending); 63729088Smarkm AcpiGbl_GlobalLockAcquired = FALSE; 63829088Smarkm 63929088Smarkm /* 64029088Smarkm * If the pending bit was set, we must write GBL_RLS to the control 64129088Smarkm * register 64229088Smarkm */ 64329088Smarkm if (Pending) 64429088Smarkm { 64529088Smarkm AcpiHwBitRegisterWrite (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK); 64629088Smarkm } 64729088Smarkm 64829088Smarkm return_VOID; 64929088Smarkm} 65029088Smarkm 65129088Smarkm 65229088Smarkm/****************************************************************************** 65329088Smarkm * 65429088Smarkm * FUNCTION: AcpiEvTerminate 65529088Smarkm * 65629088Smarkm * PARAMETERS: none 65729088Smarkm * 65829088Smarkm * RETURN: none 65929088Smarkm * 66029088Smarkm * DESCRIPTION: free memory allocated for table storage. 66129088Smarkm * 66229088Smarkm ******************************************************************************/ 66329088Smarkm 66429088Smarkmvoid 66529088SmarkmAcpiEvTerminate (void) 66629088Smarkm{ 66729088Smarkm 66829088Smarkm ACPI_FUNCTION_TRACE ("EvTerminate"); 66929088Smarkm 67029088Smarkm 67129088Smarkm /* 67229088Smarkm * Free global tables, etc. 67329088Smarkm */ 67429088Smarkm if (AcpiGbl_GpeRegisterInfo) 67529088Smarkm { 67629088Smarkm ACPI_MEM_FREE (AcpiGbl_GpeRegisterInfo); 67729088Smarkm AcpiGbl_GpeRegisterInfo = NULL; 67829088Smarkm } 67929088Smarkm 68029088Smarkm if (AcpiGbl_GpeNumberInfo) 68129088Smarkm { 68229088Smarkm ACPI_MEM_FREE (AcpiGbl_GpeNumberInfo); 68329088Smarkm AcpiGbl_GpeNumberInfo = NULL; 68429088Smarkm } 68529088Smarkm 68629088Smarkm if (AcpiGbl_GpeNumberToIndex) 68729088Smarkm { 68829088Smarkm ACPI_MEM_FREE (AcpiGbl_GpeNumberToIndex); 68929088Smarkm AcpiGbl_GpeNumberToIndex = NULL; 69029088Smarkm } 69129088Smarkm 69229088Smarkm return_VOID; 69329088Smarkm} 69429088Smarkm 69529088Smarkm