evxface.c revision 216471
1469Ssjiang/******************************************************************************
211884Sykantser *
3469Ssjiang * Module Name: evxface - External interfaces for ACPI events
4469Ssjiang *
5469Ssjiang *****************************************************************************/
6469Ssjiang
7469Ssjiang/******************************************************************************
8469Ssjiang *
9469Ssjiang * 1. Copyright Notice
10469Ssjiang *
11469Ssjiang * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
12469Ssjiang * All rights reserved.
13469Ssjiang *
14469Ssjiang * 2. License
15469Ssjiang *
16469Ssjiang * 2.1. This is your license from Intel Corp. under its intellectual property
17469Ssjiang * rights.  You may have additional license terms from the party that provided
18469Ssjiang * you this software, covering your right to use that party's intellectual
192362Sohair * property rights.
202362Sohair *
212362Sohair * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22469Ssjiang * copy of the source code appearing in this file ("Covered Code") an
23469Ssjiang * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24469Ssjiang * base code distributed originally by Intel ("Original Intel Code") to copy,
25469Ssjiang * make derivatives, distribute, use and display any portion of the Covered
26469Ssjiang * Code in any form, with the right to sublicense such rights; and
27469Ssjiang *
28469Ssjiang * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29469Ssjiang * license (with the right to sublicense), under only those claims of Intel
30469Ssjiang * patents that are infringed by the Original Intel Code, to make, use, sell,
31469Ssjiang * offer to sell, and import the Covered Code and derivative works thereof
32469Ssjiang * solely to the minimum extent necessary to exercise the above copyright
33469Ssjiang * license, and in no event shall the patent license extend to any additions
34469Ssjiang * to or modifications of the Original Intel Code.  No other license or right
35469Ssjiang * is granted directly or by implication, estoppel or otherwise;
36469Ssjiang *
37469Ssjiang * The above copyright and patent license is granted only if the following
38469Ssjiang * conditions are met:
39469Ssjiang *
40469Ssjiang * 3. Conditions
41469Ssjiang *
42469Ssjiang * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43469Ssjiang * Redistribution of source code of any substantial portion of the Covered
44469Ssjiang * Code or modification with rights to further distribute source must include
45469Ssjiang * the above Copyright Notice, the above License, this list of Conditions,
46469Ssjiang * and the following Disclaimer and Export Compliance provision.  In addition,
47469Ssjiang * Licensee must cause all Covered Code to which Licensee contributes to
48469Ssjiang * contain a file documenting the changes Licensee made to create that Covered
49469Ssjiang * Code and the date of any change.  Licensee must include in that file the
50469Ssjiang * documentation of any changes made by any predecessor Licensee.  Licensee
51469Ssjiang * must include a prominent statement that the modification is derived,
52469Ssjiang * directly or indirectly, from Original Intel Code.
53469Ssjiang *
54469Ssjiang * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55469Ssjiang * Redistribution of source code of any substantial portion of the Covered
56469Ssjiang * Code or modification without rights to further distribute source must
57469Ssjiang * include the following Disclaimer and Export Compliance provision in the
58469Ssjiang * documentation and/or other materials provided with distribution.  In
59469Ssjiang * addition, Licensee may not authorize further sublicense of source of any
60469Ssjiang * portion of the Covered Code, and must include terms to the effect that the
61469Ssjiang * license from Licensee to its licensee is limited to the intellectual
62469Ssjiang * property embodied in the software Licensee provides to its licensee, and
63469Ssjiang * not to intellectual property embodied in modifications its licensee may
64469Ssjiang * make.
65469Ssjiang *
66469Ssjiang * 3.3. Redistribution of Executable. Redistribution in executable form of any
67469Ssjiang * substantial portion of the Covered Code or modification must reproduce the
68469Ssjiang * above Copyright Notice, and the following Disclaimer and Export Compliance
69469Ssjiang * provision in the documentation and/or other materials provided with the
70469Ssjiang * distribution.
71469Ssjiang *
72469Ssjiang * 3.4. Intel retains all right, title, and interest in and to the Original
73469Ssjiang * Intel Code.
74469Ssjiang *
75469Ssjiang * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76469Ssjiang * Intel shall be used in advertising or otherwise to promote the sale, use or
77469Ssjiang * other dealings in products derived from or relating to the Covered Code
78469Ssjiang * without prior written authorization from Intel.
79469Ssjiang *
80469Ssjiang * 4. Disclaimer and Export Compliance
81469Ssjiang *
82469Ssjiang * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83469Ssjiang * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84469Ssjiang * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85469Ssjiang * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86469Ssjiang * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87469Ssjiang * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88469Ssjiang * PARTICULAR PURPOSE.
89469Ssjiang *
90469Ssjiang * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91469Ssjiang * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92469Ssjiang * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93469Ssjiang * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94469Ssjiang * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95469Ssjiang * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96469Ssjiang * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97469Ssjiang * LIMITED REMEDY.
98469Ssjiang *
99469Ssjiang * 4.3. Licensee shall not export, either directly or indirectly, any of this
10016613Sdfuchs * software or system incorporating such software without first obtaining any
101469Ssjiang * required license or other approval from the U. S. Department of Commerce or
102469Ssjiang * any other agency or department of the United States Government.  In the
103469Ssjiang * event Licensee exports any such software from the United States or
104469Ssjiang * re-exports any such software from a foreign destination, Licensee shall
105469Ssjiang * ensure that the distribution and export/re-export of the software is in
106469Ssjiang * compliance with all laws, regulations, orders, or other restrictions of the
107469Ssjiang * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108469Ssjiang * any of its subsidiaries will export/re-export any technical data, process,
109469Ssjiang * software, or service, directly or indirectly, to any country for which the
110469Ssjiang * United States government or any agency thereof requires an export license,
111469Ssjiang * other governmental approval, or letter of assurance, without first obtaining
112469Ssjiang * such license, approval or letter.
113469Ssjiang *
114469Ssjiang *****************************************************************************/
115469Ssjiang
116469Ssjiang
117469Ssjiang#define __EVXFACE_C__
118469Ssjiang
119469Ssjiang#include <contrib/dev/acpica/include/acpi.h>
120469Ssjiang#include <contrib/dev/acpica/include/accommon.h>
121469Ssjiang#include <contrib/dev/acpica/include/acnamesp.h>
122469Ssjiang#include <contrib/dev/acpica/include/acevents.h>
123469Ssjiang#include <contrib/dev/acpica/include/acinterp.h>
124469Ssjiang
125469Ssjiang#define _COMPONENT          ACPI_EVENTS
126469Ssjiang        ACPI_MODULE_NAME    ("evxface")
127469Ssjiang
128469Ssjiang
129469Ssjiang/*******************************************************************************
130469Ssjiang *
131469Ssjiang * FUNCTION:    AcpiInstallExceptionHandler
132469Ssjiang *
133469Ssjiang * PARAMETERS:  Handler         - Pointer to the handler function for the
134469Ssjiang *                                event
135469Ssjiang *
136469Ssjiang * RETURN:      Status
137469Ssjiang *
138469Ssjiang * DESCRIPTION: Saves the pointer to the handler function
139469Ssjiang *
140469Ssjiang ******************************************************************************/
141469Ssjiang
142469SsjiangACPI_STATUS
143469SsjiangAcpiInstallExceptionHandler (
144469Ssjiang    ACPI_EXCEPTION_HANDLER  Handler)
145469Ssjiang{
146469Ssjiang    ACPI_STATUS             Status;
147469Ssjiang
148469Ssjiang
149469Ssjiang    ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
150469Ssjiang
151469Ssjiang
152469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153469Ssjiang    if (ACPI_FAILURE (Status))
154469Ssjiang    {
155469Ssjiang        return_ACPI_STATUS (Status);
156469Ssjiang    }
157469Ssjiang
158469Ssjiang    /* Don't allow two handlers. */
159469Ssjiang
160469Ssjiang    if (AcpiGbl_ExceptionHandler)
161469Ssjiang    {
162469Ssjiang        Status = AE_ALREADY_EXISTS;
163469Ssjiang        goto Cleanup;
164469Ssjiang    }
165469Ssjiang
166469Ssjiang    /* Install the handler */
167469Ssjiang
168469Ssjiang    AcpiGbl_ExceptionHandler = Handler;
169469Ssjiang
170469SsjiangCleanup:
171469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172469Ssjiang    return_ACPI_STATUS (Status);
173469Ssjiang}
174469Ssjiang
175469SsjiangACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
176469Ssjiang
177469Ssjiang
178469Ssjiang/*******************************************************************************
179469Ssjiang *
180469Ssjiang * FUNCTION:    AcpiInstallGlobalEventHandler
181469Ssjiang *
182469Ssjiang * PARAMETERS:  Handler         - Pointer to the global event handler function
183469Ssjiang *              Context         - Value passed to the handler on each event
184469Ssjiang *
185469Ssjiang * RETURN:      Status
186469Ssjiang *
187469Ssjiang * DESCRIPTION: Saves the pointer to the handler function. The global handler
188469Ssjiang *              is invoked upon each incoming GPE and Fixed Event. It is
189469Ssjiang *              invoked at interrupt level at the time of the event dispatch.
190469Ssjiang *              Can be used to update event counters, etc.
191469Ssjiang *
192469Ssjiang ******************************************************************************/
193469Ssjiang
194469SsjiangACPI_STATUS
195469SsjiangAcpiInstallGlobalEventHandler (
196469Ssjiang    ACPI_GBL_EVENT_HANDLER  Handler,
197469Ssjiang    void                    *Context)
198469Ssjiang{
199469Ssjiang    ACPI_STATUS             Status;
200469Ssjiang
201469Ssjiang
202469Ssjiang    ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
203469Ssjiang
204469Ssjiang
205469Ssjiang    /* Parameter validation */
206469Ssjiang
207469Ssjiang    if (!Handler)
208469Ssjiang    {
209469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
210469Ssjiang    }
211469Ssjiang
212469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
213469Ssjiang    if (ACPI_FAILURE (Status))
214469Ssjiang    {
215469Ssjiang        return_ACPI_STATUS (Status);
216469Ssjiang    }
217469Ssjiang
218469Ssjiang    /* Don't allow two handlers. */
219469Ssjiang
220469Ssjiang    if (AcpiGbl_GlobalEventHandler)
221469Ssjiang    {
222469Ssjiang        Status = AE_ALREADY_EXISTS;
223469Ssjiang        goto Cleanup;
224469Ssjiang    }
225469Ssjiang
226469Ssjiang    AcpiGbl_GlobalEventHandler = Handler;
227469Ssjiang    AcpiGbl_GlobalEventHandlerContext = Context;
228469Ssjiang
229469Ssjiang
230469SsjiangCleanup:
231469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
232469Ssjiang    return_ACPI_STATUS (Status);
233469Ssjiang}
234469Ssjiang
235469SsjiangACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
236469Ssjiang
237469Ssjiang
238469Ssjiang/*******************************************************************************
239469Ssjiang *
240469Ssjiang * FUNCTION:    AcpiInstallFixedEventHandler
241469Ssjiang *
242469Ssjiang * PARAMETERS:  Event           - Event type to enable.
243469Ssjiang *              Handler         - Pointer to the handler function for the
244469Ssjiang *                                event
245469Ssjiang *              Context         - Value passed to the handler on each GPE
246469Ssjiang *
247469Ssjiang * RETURN:      Status
248469Ssjiang *
249469Ssjiang * DESCRIPTION: Saves the pointer to the handler function and then enables the
250469Ssjiang *              event.
251469Ssjiang *
252469Ssjiang ******************************************************************************/
253469Ssjiang
254469SsjiangACPI_STATUS
255469SsjiangAcpiInstallFixedEventHandler (
256469Ssjiang    UINT32                  Event,
257469Ssjiang    ACPI_EVENT_HANDLER      Handler,
258469Ssjiang    void                    *Context)
259469Ssjiang{
260469Ssjiang    ACPI_STATUS             Status;
261469Ssjiang
262469Ssjiang
263469Ssjiang    ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
264469Ssjiang
265469Ssjiang
266469Ssjiang    /* Parameter validation */
267469Ssjiang
268469Ssjiang    if (Event > ACPI_EVENT_MAX)
269469Ssjiang    {
270469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
271469Ssjiang    }
272469Ssjiang
273469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
274469Ssjiang    if (ACPI_FAILURE (Status))
275469Ssjiang    {
276469Ssjiang        return_ACPI_STATUS (Status);
277469Ssjiang    }
278469Ssjiang
279469Ssjiang    /* Don't allow two handlers. */
280469Ssjiang
281469Ssjiang    if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
282469Ssjiang    {
283469Ssjiang        Status = AE_ALREADY_EXISTS;
284469Ssjiang        goto Cleanup;
285469Ssjiang    }
286469Ssjiang
287469Ssjiang    /* Install the handler before enabling the event */
288469Ssjiang
289469Ssjiang    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
290469Ssjiang    AcpiGbl_FixedEventHandlers[Event].Context = Context;
291469Ssjiang
292469Ssjiang    Status = AcpiEnableEvent (Event, 0);
293469Ssjiang    if (ACPI_FAILURE (Status))
294469Ssjiang    {
295469Ssjiang        ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
296469Ssjiang
297469Ssjiang        /* Remove the handler */
298469Ssjiang
299469Ssjiang        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
300469Ssjiang        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
301469Ssjiang    }
302469Ssjiang    else
303469Ssjiang    {
304469Ssjiang        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
305469Ssjiang            "Enabled fixed event %X, Handler=%p\n", Event, Handler));
306469Ssjiang    }
307469Ssjiang
308469Ssjiang
309469SsjiangCleanup:
310469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
311469Ssjiang    return_ACPI_STATUS (Status);
312469Ssjiang}
313469Ssjiang
314469SsjiangACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
315469Ssjiang
316469Ssjiang
317469Ssjiang/*******************************************************************************
318469Ssjiang *
319469Ssjiang * FUNCTION:    AcpiRemoveFixedEventHandler
320469Ssjiang *
321469Ssjiang * PARAMETERS:  Event           - Event type to disable.
322469Ssjiang *              Handler         - Address of the handler
323469Ssjiang *
324469Ssjiang * RETURN:      Status
325469Ssjiang *
326469Ssjiang * DESCRIPTION: Disables the event and unregisters the event handler.
327469Ssjiang *
328469Ssjiang ******************************************************************************/
329469Ssjiang
330469SsjiangACPI_STATUS
331469SsjiangAcpiRemoveFixedEventHandler (
332469Ssjiang    UINT32                  Event,
333469Ssjiang    ACPI_EVENT_HANDLER      Handler)
334469Ssjiang{
335469Ssjiang    ACPI_STATUS             Status = AE_OK;
336469Ssjiang
337469Ssjiang
338469Ssjiang    ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
339469Ssjiang
340469Ssjiang
341469Ssjiang    /* Parameter validation */
342469Ssjiang
343469Ssjiang    if (Event > ACPI_EVENT_MAX)
344469Ssjiang    {
345469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
346469Ssjiang    }
347469Ssjiang
348469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
349469Ssjiang    if (ACPI_FAILURE (Status))
350469Ssjiang    {
351469Ssjiang        return_ACPI_STATUS (Status);
352469Ssjiang    }
353469Ssjiang
354469Ssjiang    /* Disable the event before removing the handler */
355469Ssjiang
356469Ssjiang    Status = AcpiDisableEvent (Event, 0);
357469Ssjiang
358469Ssjiang    /* Always Remove the handler */
359469Ssjiang
360469Ssjiang    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
361469Ssjiang    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
362469Ssjiang
363469Ssjiang    if (ACPI_FAILURE (Status))
364469Ssjiang    {
365469Ssjiang        ACPI_WARNING ((AE_INFO,
366469Ssjiang            "Could not write to fixed event enable register 0x%X", Event));
367469Ssjiang    }
368469Ssjiang    else
369469Ssjiang    {
370469Ssjiang        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
371469Ssjiang    }
372469Ssjiang
373469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
374469Ssjiang    return_ACPI_STATUS (Status);
375469Ssjiang}
376469Ssjiang
377469SsjiangACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
378469Ssjiang
379469Ssjiang
380469Ssjiang/*******************************************************************************
381469Ssjiang *
382469Ssjiang * FUNCTION:    AcpiInstallNotifyHandler
383469Ssjiang *
384469Ssjiang * PARAMETERS:  Device          - The device for which notifies will be handled
385469Ssjiang *              HandlerType     - The type of handler:
386469Ssjiang *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
387469Ssjiang *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
388469Ssjiang *                                  ACPI_ALL_NOTIFY:  both system and device
389469Ssjiang *              Handler         - Address of the handler
390469Ssjiang *              Context         - Value passed to the handler on each GPE
391469Ssjiang *
392469Ssjiang * RETURN:      Status
393469Ssjiang *
394469Ssjiang * DESCRIPTION: Install a handler for notifies on an ACPI device
395469Ssjiang *
396469Ssjiang ******************************************************************************/
397469Ssjiang
398469SsjiangACPI_STATUS
399469SsjiangAcpiInstallNotifyHandler (
400469Ssjiang    ACPI_HANDLE             Device,
401469Ssjiang    UINT32                  HandlerType,
402469Ssjiang    ACPI_NOTIFY_HANDLER     Handler,
403469Ssjiang    void                    *Context)
404469Ssjiang{
405469Ssjiang    ACPI_OPERAND_OBJECT     *ObjDesc;
406469Ssjiang    ACPI_OPERAND_OBJECT     *NotifyObj;
407469Ssjiang    ACPI_NAMESPACE_NODE     *Node;
408469Ssjiang    ACPI_STATUS             Status;
409469Ssjiang
410469Ssjiang
411469Ssjiang    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
412469Ssjiang
413469Ssjiang
414469Ssjiang    /* Parameter validation */
415469Ssjiang
416469Ssjiang    if ((!Device)  ||
417469Ssjiang        (!Handler) ||
418469Ssjiang        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
419469Ssjiang    {
420469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
421469Ssjiang    }
422469Ssjiang
423469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
424469Ssjiang    if (ACPI_FAILURE (Status))
425469Ssjiang    {
426469Ssjiang        return_ACPI_STATUS (Status);
427469Ssjiang    }
428469Ssjiang
429469Ssjiang    /* Convert and validate the device handle */
430469Ssjiang
431469Ssjiang    Node = AcpiNsValidateHandle (Device);
432469Ssjiang    if (!Node)
433469Ssjiang    {
434469Ssjiang        Status = AE_BAD_PARAMETER;
435469Ssjiang        goto UnlockAndExit;
436469Ssjiang    }
437469Ssjiang
438469Ssjiang    /*
439469Ssjiang     * Root Object:
440469Ssjiang     * Registering a notify handler on the root object indicates that the
441469Ssjiang     * caller wishes to receive notifications for all objects. Note that
442469Ssjiang     * only one <external> global handler can be regsitered (per notify type).
443469Ssjiang     */
444469Ssjiang    if (Device == ACPI_ROOT_OBJECT)
445469Ssjiang    {
446469Ssjiang        /* Make sure the handler is not already installed */
447469Ssjiang
448469Ssjiang        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
449469Ssjiang                AcpiGbl_SystemNotify.Handler)       ||
450469Ssjiang            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
451469Ssjiang                AcpiGbl_DeviceNotify.Handler))
452469Ssjiang        {
453469Ssjiang            Status = AE_ALREADY_EXISTS;
454469Ssjiang            goto UnlockAndExit;
455469Ssjiang        }
456469Ssjiang
457469Ssjiang        if (HandlerType & ACPI_SYSTEM_NOTIFY)
458469Ssjiang        {
459469Ssjiang            AcpiGbl_SystemNotify.Node    = Node;
460469Ssjiang            AcpiGbl_SystemNotify.Handler = Handler;
461469Ssjiang            AcpiGbl_SystemNotify.Context = Context;
462469Ssjiang        }
463469Ssjiang
464469Ssjiang        if (HandlerType & ACPI_DEVICE_NOTIFY)
465469Ssjiang        {
466469Ssjiang            AcpiGbl_DeviceNotify.Node    = Node;
467469Ssjiang            AcpiGbl_DeviceNotify.Handler = Handler;
468469Ssjiang            AcpiGbl_DeviceNotify.Context = Context;
469469Ssjiang        }
470469Ssjiang
471469Ssjiang        /* Global notify handler installed */
472469Ssjiang    }
473469Ssjiang
474469Ssjiang    /*
475469Ssjiang     * All Other Objects:
476469Ssjiang     * Caller will only receive notifications specific to the target object.
477469Ssjiang     * Note that only certain object types can receive notifications.
478469Ssjiang     */
479469Ssjiang    else
480469Ssjiang    {
481469Ssjiang        /* Notifies allowed on this object? */
482469Ssjiang
483469Ssjiang        if (!AcpiEvIsNotifyObject (Node))
484469Ssjiang        {
485469Ssjiang            Status = AE_TYPE;
486469Ssjiang            goto UnlockAndExit;
487469Ssjiang        }
488469Ssjiang
489469Ssjiang        /* Check for an existing internal object */
490469Ssjiang
491469Ssjiang        ObjDesc = AcpiNsGetAttachedObject (Node);
492469Ssjiang        if (ObjDesc)
493469Ssjiang        {
494469Ssjiang            /* Object exists - make sure there's no handler */
495469Ssjiang
496469Ssjiang            if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
497469Ssjiang                    ObjDesc->CommonNotify.SystemNotify)   ||
498469Ssjiang                ((HandlerType & ACPI_DEVICE_NOTIFY) &&
499469Ssjiang                    ObjDesc->CommonNotify.DeviceNotify))
500469Ssjiang            {
501469Ssjiang                Status = AE_ALREADY_EXISTS;
502469Ssjiang                goto UnlockAndExit;
503469Ssjiang            }
504469Ssjiang        }
505469Ssjiang        else
506469Ssjiang        {
507469Ssjiang            /* Create a new object */
508469Ssjiang
509469Ssjiang            ObjDesc = AcpiUtCreateInternalObject (Node->Type);
510469Ssjiang            if (!ObjDesc)
511469Ssjiang            {
512469Ssjiang                Status = AE_NO_MEMORY;
513469Ssjiang                goto UnlockAndExit;
514469Ssjiang            }
515469Ssjiang
516469Ssjiang            /* Attach new object to the Node */
517469Ssjiang
518469Ssjiang            Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
519469Ssjiang
520469Ssjiang            /* Remove local reference to the object */
521469Ssjiang
522469Ssjiang            AcpiUtRemoveReference (ObjDesc);
523469Ssjiang            if (ACPI_FAILURE (Status))
524469Ssjiang            {
525469Ssjiang                goto UnlockAndExit;
526469Ssjiang            }
527469Ssjiang        }
528469Ssjiang
529469Ssjiang        /* Install the handler */
530469Ssjiang
531469Ssjiang        NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
532469Ssjiang        if (!NotifyObj)
533469Ssjiang        {
534469Ssjiang            Status = AE_NO_MEMORY;
535469Ssjiang            goto UnlockAndExit;
536469Ssjiang        }
537469Ssjiang
538469Ssjiang        NotifyObj->Notify.Node    = Node;
539469Ssjiang        NotifyObj->Notify.Handler = Handler;
540469Ssjiang        NotifyObj->Notify.Context = Context;
541469Ssjiang
542469Ssjiang        if (HandlerType & ACPI_SYSTEM_NOTIFY)
543469Ssjiang        {
544469Ssjiang            ObjDesc->CommonNotify.SystemNotify = NotifyObj;
545469Ssjiang        }
546469Ssjiang
547469Ssjiang        if (HandlerType & ACPI_DEVICE_NOTIFY)
548469Ssjiang        {
549469Ssjiang            ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
550469Ssjiang        }
551469Ssjiang
552469Ssjiang        if (HandlerType == ACPI_ALL_NOTIFY)
553469Ssjiang        {
554469Ssjiang            /* Extra ref if installed in both */
555469Ssjiang
556469Ssjiang            AcpiUtAddReference (NotifyObj);
557469Ssjiang        }
558469Ssjiang    }
559469Ssjiang
560469Ssjiang
561469SsjiangUnlockAndExit:
562469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
563469Ssjiang    return_ACPI_STATUS (Status);
564469Ssjiang}
565469Ssjiang
566469SsjiangACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
567469Ssjiang
568469Ssjiang
569469Ssjiang/*******************************************************************************
570469Ssjiang *
571469Ssjiang * FUNCTION:    AcpiRemoveNotifyHandler
572469Ssjiang *
573469Ssjiang * PARAMETERS:  Device          - The device for which notifies will be handled
574469Ssjiang *              HandlerType     - The type of handler:
575469Ssjiang *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
576469Ssjiang *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
577469Ssjiang *                                  ACPI_ALL_NOTIFY:  both system and device
578469Ssjiang *              Handler         - Address of the handler
579469Ssjiang *
580469Ssjiang * RETURN:      Status
581469Ssjiang *
582469Ssjiang * DESCRIPTION: Remove a handler for notifies on an ACPI device
583469Ssjiang *
584469Ssjiang ******************************************************************************/
585469Ssjiang
586469SsjiangACPI_STATUS
587469SsjiangAcpiRemoveNotifyHandler (
588469Ssjiang    ACPI_HANDLE             Device,
589469Ssjiang    UINT32                  HandlerType,
590469Ssjiang    ACPI_NOTIFY_HANDLER     Handler)
591469Ssjiang{
592469Ssjiang    ACPI_OPERAND_OBJECT     *NotifyObj;
593469Ssjiang    ACPI_OPERAND_OBJECT     *ObjDesc;
594469Ssjiang    ACPI_NAMESPACE_NODE     *Node;
595469Ssjiang    ACPI_STATUS             Status;
596469Ssjiang
597469Ssjiang
598469Ssjiang    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
599469Ssjiang
600469Ssjiang
601469Ssjiang    /* Parameter validation */
602469Ssjiang
603469Ssjiang    if ((!Device)  ||
604469Ssjiang        (!Handler) ||
605469Ssjiang        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
606469Ssjiang    {
607469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
608469Ssjiang    }
609469Ssjiang
610469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
611469Ssjiang    if (ACPI_FAILURE (Status))
612469Ssjiang    {
613469Ssjiang        return_ACPI_STATUS (Status);
614469Ssjiang    }
615469Ssjiang
616469Ssjiang    /* Convert and validate the device handle */
617469Ssjiang
618469Ssjiang    Node = AcpiNsValidateHandle (Device);
619469Ssjiang    if (!Node)
620469Ssjiang    {
621469Ssjiang        Status = AE_BAD_PARAMETER;
622469Ssjiang        goto UnlockAndExit;
623469Ssjiang    }
624469Ssjiang
625469Ssjiang    /* Root Object */
626469Ssjiang
627469Ssjiang    if (Device == ACPI_ROOT_OBJECT)
628469Ssjiang    {
629469Ssjiang        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
630469Ssjiang            "Removing notify handler for namespace root object\n"));
631469Ssjiang
632469Ssjiang        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
633469Ssjiang              !AcpiGbl_SystemNotify.Handler)        ||
634469Ssjiang            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
635469Ssjiang              !AcpiGbl_DeviceNotify.Handler))
636469Ssjiang        {
637469Ssjiang            Status = AE_NOT_EXIST;
638469Ssjiang            goto UnlockAndExit;
639469Ssjiang        }
640469Ssjiang
641469Ssjiang        if (HandlerType & ACPI_SYSTEM_NOTIFY)
642469Ssjiang        {
643469Ssjiang            AcpiGbl_SystemNotify.Node    = NULL;
644469Ssjiang            AcpiGbl_SystemNotify.Handler = NULL;
645469Ssjiang            AcpiGbl_SystemNotify.Context = NULL;
646469Ssjiang        }
647469Ssjiang
648469Ssjiang        if (HandlerType & ACPI_DEVICE_NOTIFY)
649469Ssjiang        {
650469Ssjiang            AcpiGbl_DeviceNotify.Node    = NULL;
651469Ssjiang            AcpiGbl_DeviceNotify.Handler = NULL;
652469Ssjiang            AcpiGbl_DeviceNotify.Context = NULL;
653469Ssjiang        }
654469Ssjiang    }
655469Ssjiang
656469Ssjiang    /* All Other Objects */
657469Ssjiang
658469Ssjiang    else
659469Ssjiang    {
660469Ssjiang        /* Notifies allowed on this object? */
661469Ssjiang
662469Ssjiang        if (!AcpiEvIsNotifyObject (Node))
663469Ssjiang        {
664469Ssjiang            Status = AE_TYPE;
665469Ssjiang            goto UnlockAndExit;
666469Ssjiang        }
667469Ssjiang
668469Ssjiang        /* Check for an existing internal object */
669469Ssjiang
670469Ssjiang        ObjDesc = AcpiNsGetAttachedObject (Node);
671469Ssjiang        if (!ObjDesc)
672469Ssjiang        {
673469Ssjiang            Status = AE_NOT_EXIST;
674469Ssjiang            goto UnlockAndExit;
675469Ssjiang        }
676469Ssjiang
677469Ssjiang        /* Object exists - make sure there's an existing handler */
678469Ssjiang
679469Ssjiang        if (HandlerType & ACPI_SYSTEM_NOTIFY)
680469Ssjiang        {
681469Ssjiang            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
682469Ssjiang            if (!NotifyObj)
683469Ssjiang            {
684469Ssjiang                Status = AE_NOT_EXIST;
685469Ssjiang                goto UnlockAndExit;
686469Ssjiang            }
687469Ssjiang
688469Ssjiang            if (NotifyObj->Notify.Handler != Handler)
689469Ssjiang            {
690469Ssjiang                Status = AE_BAD_PARAMETER;
691469Ssjiang                goto UnlockAndExit;
692469Ssjiang            }
693469Ssjiang
694469Ssjiang            /* Remove the handler */
695469Ssjiang
696469Ssjiang            ObjDesc->CommonNotify.SystemNotify = NULL;
697469Ssjiang            AcpiUtRemoveReference (NotifyObj);
698469Ssjiang        }
699469Ssjiang
700469Ssjiang        if (HandlerType & ACPI_DEVICE_NOTIFY)
701469Ssjiang        {
702469Ssjiang            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
703469Ssjiang            if (!NotifyObj)
704469Ssjiang            {
705469Ssjiang                Status = AE_NOT_EXIST;
706469Ssjiang                goto UnlockAndExit;
707469Ssjiang            }
708469Ssjiang
709469Ssjiang            if (NotifyObj->Notify.Handler != Handler)
710469Ssjiang            {
711469Ssjiang                Status = AE_BAD_PARAMETER;
712469Ssjiang                goto UnlockAndExit;
713469Ssjiang            }
714469Ssjiang
715469Ssjiang            /* Remove the handler */
716469Ssjiang
717469Ssjiang            ObjDesc->CommonNotify.DeviceNotify = NULL;
718469Ssjiang            AcpiUtRemoveReference (NotifyObj);
719469Ssjiang        }
720469Ssjiang    }
721469Ssjiang
722469Ssjiang
723469SsjiangUnlockAndExit:
724469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
725469Ssjiang    return_ACPI_STATUS (Status);
726469Ssjiang}
727469Ssjiang
728469SsjiangACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
729469Ssjiang
730469Ssjiang
731469Ssjiang/*******************************************************************************
732469Ssjiang *
733469Ssjiang * FUNCTION:    AcpiInstallGpeHandler
734469Ssjiang *
735469Ssjiang * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
736469Ssjiang *                                defined GPEs)
737469Ssjiang *              GpeNumber       - The GPE number within the GPE block
738469Ssjiang *              Type            - Whether this GPE should be treated as an
739469Ssjiang *                                edge- or level-triggered interrupt.
740469Ssjiang *              Address         - Address of the handler
741469Ssjiang *              Context         - Value passed to the handler on each GPE
742469Ssjiang *
743469Ssjiang * RETURN:      Status
744469Ssjiang *
745469Ssjiang * DESCRIPTION: Install a handler for a General Purpose Event.
746469Ssjiang *
747469Ssjiang ******************************************************************************/
748469Ssjiang
749469SsjiangACPI_STATUS
750469SsjiangAcpiInstallGpeHandler (
751469Ssjiang    ACPI_HANDLE             GpeDevice,
752469Ssjiang    UINT32                  GpeNumber,
753469Ssjiang    UINT32                  Type,
754469Ssjiang    ACPI_GPE_HANDLER        Address,
755469Ssjiang    void                    *Context)
756469Ssjiang{
757469Ssjiang    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
758469Ssjiang    ACPI_GPE_HANDLER_INFO   *Handler;
759469Ssjiang    ACPI_STATUS             Status;
760469Ssjiang    ACPI_CPU_FLAGS          Flags;
761469Ssjiang
762469Ssjiang
763469Ssjiang    ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
764469Ssjiang
765469Ssjiang
766469Ssjiang    /* Parameter validation */
767469Ssjiang
768469Ssjiang    if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
769469Ssjiang    {
770469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
771469Ssjiang    }
772469Ssjiang
773469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
774469Ssjiang    if (ACPI_FAILURE (Status))
775469Ssjiang    {
776469Ssjiang        return_ACPI_STATUS (Status);
777469Ssjiang    }
778469Ssjiang
779469Ssjiang    /* Allocate and init handler object (before lock) */
780469Ssjiang
781469Ssjiang    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
782469Ssjiang    if (!Handler)
783469Ssjiang    {
784469Ssjiang        Status = AE_NO_MEMORY;
785469Ssjiang        goto UnlockAndExit;
786469Ssjiang    }
787469Ssjiang
788469Ssjiang    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
789469Ssjiang
790469Ssjiang    /* Ensure that we have a valid GPE number */
791469Ssjiang
792469Ssjiang    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
793469Ssjiang    if (!GpeEventInfo)
794469Ssjiang    {
795469Ssjiang        Status = AE_BAD_PARAMETER;
796469Ssjiang        goto FreeAndExit;
797469Ssjiang    }
798469Ssjiang
799469Ssjiang    /* Make sure that there isn't a handler there already */
800469Ssjiang
801469Ssjiang    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
802469Ssjiang            ACPI_GPE_DISPATCH_HANDLER)
803469Ssjiang    {
804469Ssjiang        Status = AE_ALREADY_EXISTS;
805469Ssjiang        goto FreeAndExit;
806469Ssjiang    }
807469Ssjiang
808469Ssjiang    Handler->Address = Address;
809469Ssjiang    Handler->Context = Context;
810469Ssjiang    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
811469Ssjiang    Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
812469Ssjiang        (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
813469Ssjiang
814469Ssjiang    /*
815469Ssjiang     * If the GPE is associated with a method, it may have been enabled
816469Ssjiang     * automatically during initialization, in which case it has to be
817469Ssjiang     * disabled now to avoid spurious execution of the handler.
818469Ssjiang     */
819469Ssjiang    if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
820469Ssjiang         (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
821469Ssjiang        GpeEventInfo->RuntimeCount)
822469Ssjiang    {
823469Ssjiang        Handler->OriginallyEnabled = TRUE;
824469Ssjiang        (void) AcpiEvRemoveGpeReference (GpeEventInfo);
825469Ssjiang
826469Ssjiang        /* Sanity check of original type against new type */
827469Ssjiang
828469Ssjiang        if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
829469Ssjiang        {
830469Ssjiang            ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
831469Ssjiang        }
832469Ssjiang    }
833469Ssjiang
834469Ssjiang    /* Install the handler */
835469Ssjiang
836469Ssjiang    GpeEventInfo->Dispatch.Handler = Handler;
837469Ssjiang
838469Ssjiang    /* Setup up dispatch flags to indicate handler (vs. method/notify) */
839469Ssjiang
840469Ssjiang    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
841469Ssjiang    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
842469Ssjiang
843469Ssjiang    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
844469Ssjiang
845469Ssjiang
846469SsjiangUnlockAndExit:
847469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
848469Ssjiang    return_ACPI_STATUS (Status);
849469Ssjiang
850469SsjiangFreeAndExit:
851469Ssjiang    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
852469Ssjiang    ACPI_FREE (Handler);
853469Ssjiang    goto UnlockAndExit;
854469Ssjiang}
855469Ssjiang
856469SsjiangACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
857469Ssjiang
858469Ssjiang
859469Ssjiang/*******************************************************************************
860469Ssjiang *
861469Ssjiang * FUNCTION:    AcpiRemoveGpeHandler
862469Ssjiang *
863469Ssjiang * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
864469Ssjiang *                                defined GPEs)
865469Ssjiang *              GpeNumber       - The event to remove a handler
866469Ssjiang *              Address         - Address of the handler
867469Ssjiang *
868469Ssjiang * RETURN:      Status
869469Ssjiang *
870469Ssjiang * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
871469Ssjiang *
872469Ssjiang ******************************************************************************/
873469Ssjiang
874469SsjiangACPI_STATUS
875469SsjiangAcpiRemoveGpeHandler (
876469Ssjiang    ACPI_HANDLE             GpeDevice,
877469Ssjiang    UINT32                  GpeNumber,
878469Ssjiang    ACPI_GPE_HANDLER        Address)
879469Ssjiang{
880469Ssjiang    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
881469Ssjiang    ACPI_GPE_HANDLER_INFO   *Handler;
882469Ssjiang    ACPI_STATUS             Status;
883469Ssjiang    ACPI_CPU_FLAGS          Flags;
884469Ssjiang
885469Ssjiang
886469Ssjiang    ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
887469Ssjiang
888469Ssjiang
889469Ssjiang    /* Parameter validation */
890469Ssjiang
891469Ssjiang    if (!Address)
892469Ssjiang    {
893469Ssjiang        return_ACPI_STATUS (AE_BAD_PARAMETER);
894469Ssjiang    }
895469Ssjiang
896469Ssjiang    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
897469Ssjiang    if (ACPI_FAILURE (Status))
898469Ssjiang    {
899469Ssjiang        return_ACPI_STATUS (Status);
900469Ssjiang    }
901469Ssjiang
902469Ssjiang    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
903469Ssjiang
904469Ssjiang    /* Ensure that we have a valid GPE number */
905469Ssjiang
906469Ssjiang    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
907469Ssjiang    if (!GpeEventInfo)
908469Ssjiang    {
909469Ssjiang        Status = AE_BAD_PARAMETER;
910469Ssjiang        goto UnlockAndExit;
911469Ssjiang    }
912469Ssjiang
913469Ssjiang    /* Make sure that a handler is indeed installed */
914469Ssjiang
915469Ssjiang    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
916469Ssjiang            ACPI_GPE_DISPATCH_HANDLER)
917469Ssjiang    {
918469Ssjiang        Status = AE_NOT_EXIST;
919469Ssjiang        goto UnlockAndExit;
920469Ssjiang    }
921469Ssjiang
922469Ssjiang    /* Make sure that the installed handler is the same */
923469Ssjiang
924469Ssjiang    if (GpeEventInfo->Dispatch.Handler->Address != Address)
925469Ssjiang    {
926469Ssjiang        Status = AE_BAD_PARAMETER;
927469Ssjiang        goto UnlockAndExit;
928469Ssjiang    }
929469Ssjiang
930469Ssjiang    /* Remove the handler */
931469Ssjiang
932469Ssjiang    Handler = GpeEventInfo->Dispatch.Handler;
933469Ssjiang
934469Ssjiang    /* Restore Method node (if any), set dispatch flags */
935469Ssjiang
936469Ssjiang    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
937469Ssjiang    GpeEventInfo->Flags &=
938469Ssjiang        ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
939469Ssjiang    GpeEventInfo->Flags |= Handler->OriginalFlags;
940469Ssjiang
941469Ssjiang    /*
942469Ssjiang     * If the GPE was previously associated with a method and it was
943469Ssjiang     * enabled, it should be enabled at this point to restore the
944469Ssjiang     * post-initialization configuration.
945469Ssjiang     */
946469Ssjiang    if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
947469Ssjiang        Handler->OriginallyEnabled)
948469Ssjiang    {
949469Ssjiang        (void) AcpiEvAddGpeReference (GpeEventInfo);
950469Ssjiang    }
951469Ssjiang
952469Ssjiang    /* Now we can free the handler object */
953469Ssjiang
954469Ssjiang    ACPI_FREE (Handler);
955469Ssjiang
956469Ssjiang
957469SsjiangUnlockAndExit:
958469Ssjiang    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
959469Ssjiang    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
960469Ssjiang    return_ACPI_STATUS (Status);
961469Ssjiang}
962469Ssjiang
963469SsjiangACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
964469Ssjiang
965469Ssjiang
966469Ssjiang/*******************************************************************************
967469Ssjiang *
968469Ssjiang * FUNCTION:    AcpiAcquireGlobalLock
969469Ssjiang *
970469Ssjiang * PARAMETERS:  Timeout         - How long the caller is willing to wait
971469Ssjiang *              Handle          - Where the handle to the lock is returned
972469Ssjiang *                                (if acquired)
973469Ssjiang *
974469Ssjiang * RETURN:      Status
975469Ssjiang *
976469Ssjiang * DESCRIPTION: Acquire the ACPI Global Lock
977469Ssjiang *
978469Ssjiang * Note: Allows callers with the same thread ID to acquire the global lock
979469Ssjiang * multiple times. In other words, externally, the behavior of the global lock
980469Ssjiang * is identical to an AML mutex. On the first acquire, a new handle is
981469Ssjiang * returned. On any subsequent calls to acquire by the same thread, the same
982469Ssjiang * handle is returned.
983469Ssjiang *
984469Ssjiang ******************************************************************************/
985469Ssjiang
986469SsjiangACPI_STATUS
987469SsjiangAcpiAcquireGlobalLock (
988469Ssjiang    UINT16                  Timeout,
989469Ssjiang    UINT32                  *Handle)
990469Ssjiang{
991469Ssjiang    ACPI_STATUS             Status;
992469Ssjiang
993469Ssjiang
994469Ssjiang    if (!Handle)
995469Ssjiang    {
996469Ssjiang        return (AE_BAD_PARAMETER);
997469Ssjiang    }
998469Ssjiang
999469Ssjiang    /* Must lock interpreter to prevent race conditions */
1000469Ssjiang
1001469Ssjiang    AcpiExEnterInterpreter ();
1002469Ssjiang
1003469Ssjiang    Status = AcpiExAcquireMutexObject (Timeout,
1004469Ssjiang                AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1005469Ssjiang
1006469Ssjiang    if (ACPI_SUCCESS (Status))
1007469Ssjiang    {
1008469Ssjiang        /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1009469Ssjiang
1010469Ssjiang        *Handle = AcpiGbl_GlobalLockHandle;
1011469Ssjiang    }
1012469Ssjiang
1013469Ssjiang    AcpiExExitInterpreter ();
1014469Ssjiang    return (Status);
1015469Ssjiang}
1016469Ssjiang
1017469SsjiangACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1018469Ssjiang
1019469Ssjiang
1020469Ssjiang/*******************************************************************************
1021469Ssjiang *
1022469Ssjiang * FUNCTION:    AcpiReleaseGlobalLock
1023469Ssjiang *
1024469Ssjiang * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1025469Ssjiang *
1026469Ssjiang * RETURN:      Status
1027469Ssjiang *
1028469Ssjiang * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1029469Ssjiang *
1030469Ssjiang ******************************************************************************/
1031469Ssjiang
1032469SsjiangACPI_STATUS
1033469SsjiangAcpiReleaseGlobalLock (
1034469Ssjiang    UINT32                  Handle)
1035469Ssjiang{
1036469Ssjiang    ACPI_STATUS             Status;
1037469Ssjiang
1038469Ssjiang
1039469Ssjiang    if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1040469Ssjiang    {
1041469Ssjiang        return (AE_NOT_ACQUIRED);
1042469Ssjiang    }
1043469Ssjiang
1044469Ssjiang    Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1045469Ssjiang    return (Status);
1046469Ssjiang}
1047469Ssjiang
1048469SsjiangACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1049469Ssjiang
1050469Ssjiang