evxface.c revision 151937
1289694Sngie/******************************************************************************
2289694Sngie *
3289694Sngie * Module Name: evxface - External interfaces for ACPI events
4289694Sngie *              $Revision: 1.152 $
5289694Sngie *
6289694Sngie *****************************************************************************/
7289694Sngie
8289694Sngie/******************************************************************************
9289694Sngie *
10289694Sngie * 1. Copyright Notice
11289694Sngie *
12289694Sngie * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13289694Sngie * All rights reserved.
14289694Sngie *
15289694Sngie * 2. License
16289694Sngie *
17289694Sngie * 2.1. This is your license from Intel Corp. under its intellectual property
18289694Sngie * rights.  You may have additional license terms from the party that provided
19289694Sngie * you this software, covering your right to use that party's intellectual
20289694Sngie * property rights.
21289694Sngie *
22289694Sngie * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23289694Sngie * copy of the source code appearing in this file ("Covered Code") an
24289694Sngie * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25289694Sngie * base code distributed originally by Intel ("Original Intel Code") to copy,
26289694Sngie * make derivatives, distribute, use and display any portion of the Covered
27289694Sngie * Code in any form, with the right to sublicense such rights; and
28289694Sngie *
29289694Sngie * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30290586Sngie * license (with the right to sublicense), under only those claims of Intel
31290586Sngie * patents that are infringed by the Original Intel Code, to make, use, sell,
32290586Sngie * offer to sell, and import the Covered Code and derivative works thereof
33290586Sngie * solely to the minimum extent necessary to exercise the above copyright
34290586Sngie * license, and in no event shall the patent license extend to any additions
35290586Sngie * to or modifications of the Original Intel Code.  No other license or right
36290586Sngie * is granted directly or by implication, estoppel or otherwise;
37289694Sngie *
38289694Sngie * The above copyright and patent license is granted only if the following
39290586Sngie * conditions are met:
40289694Sngie *
41290586Sngie * 3. Conditions
42290586Sngie *
43290586Sngie * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44289694Sngie * Redistribution of source code of any substantial prton of the Covered
45290586Sngie * Code or modification with rights to further distribute source must include
46290586Sngie * the above Copyright Notice, the above License, this list of Conditions,
47290586Sngie * and the following Disclaimer and Export Compliance provision.  In addition,
48290586Sngie * Licensee must cause all Covered Code to which Licensee contributes to
49290586Sngie * contain a file documenting the changes Licensee made to create that Covered
50290586Sngie * Code and the date of any change.  Licensee must include in that file the
51290586Sngie * documentation of any changes made by any predecessor Licensee.  Licensee
52290586Sngie * must include a prominent statement that the modification is derived,
53290586Sngie * directly or indirectly, from Original Intel Code.
54290586Sngie *
55290586Sngie * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56290586Sngie * Redistribution of source code of any substantial portion of the Covered
57290586Sngie * Code or modification without rights to further distribute source must
58290586Sngie * include the following Disclaimer and Export Compliance provision in the
59290586Sngie * documentation and/or other materials provided with distribution.  In
60290586Sngie * addition, Licensee may not authorize further sublicense of source of any
61290586Sngie * portion of the Covered Code, and must include terms to the effect that the
62290586Sngie * license from Licensee to its licensee is limited to the intellectual
63290586Sngie * property embodied in the software Licensee provides to its licensee, and
64290586Sngie * not to intellectual property embodied in modifications its licensee may
65290586Sngie * make.
66290586Sngie *
67290586Sngie * 3.3. Redistribution of Executable. Redistribution in executable form of any
68290586Sngie * substantial portion of the Covered Code or modification must reproduce the
69289694Sngie * above Copyright Notice, and the following Disclaimer and Export Compliance
70289694Sngie * provision in the documentation and/or other materials provided with the
71290586Sngie * distribution.
72290586Sngie *
73290586Sngie * 3.4. Intel retains all right, title, and interest in and to the Original
74290586Sngie * Intel Code.
75290586Sngie *
76289694Sngie * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77290586Sngie * Intel shall be used in advertising or otherwise to promote the sale, use or
78290586Sngie * other dealings in products derived from or relating to the Covered Code
79290586Sngie * without prior written authorization from Intel.
80290586Sngie *
81290586Sngie * 4. Disclaimer and Export Compliance
82290586Sngie *
83290586Sngie * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84290586Sngie * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85290586Sngie * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86290586Sngie * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87290586Sngie * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88290586Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89290586Sngie * PARTICULAR PURPOSE.
90290586Sngie *
91290586Sngie * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92290586Sngie * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93290586Sngie * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94290586Sngie * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95290586Sngie * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96290586Sngie * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97290586Sngie * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98290586Sngie * LIMITED REMEDY.
99290586Sngie *
100290586Sngie * 4.3. Licensee shall not export, either directly or indirectly, any of this
101290586Sngie * software or system incorporating such software without first obtaining any
102290586Sngie * required license or other approval from the U. S. Department of Commerce or
103290586Sngie * any other agency or department of the United States Government.  In the
104290586Sngie * event Licensee exports any such software from the United States or
105290586Sngie * re-exports any such software from a foreign destination, Licensee shall
106290586Sngie * ensure that the distribution and export/re-export of the software is in
107290586Sngie * compliance with all laws, regulations, orders, or other restrictions of the
108290586Sngie * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109290586Sngie * any of its subsidiaries will export/re-export any technical data, process,
110290586Sngie * software, or service, directly or indirectly, to any country for which the
111290586Sngie * United States government or any agency thereof requires an export license,
112290586Sngie * other governmental approval, or letter of assurance, without first obtaining
113290586Sngie * such license, approval or letter.
114290586Sngie *
115290586Sngie *****************************************************************************/
116290594Sngie
117290586Sngie
118290586Sngie#define __EVXFACE_C__
119290586Sngie
120290586Sngie#include <contrib/dev/acpica/acpi.h>
121290586Sngie#include <contrib/dev/acpica/acnamesp.h>
122290586Sngie#include <contrib/dev/acpica/acevents.h>
123290586Sngie#include <contrib/dev/acpica/acinterp.h>
124290586Sngie
125290586Sngie#define _COMPONENT          ACPI_EVENTS
126290586Sngie        ACPI_MODULE_NAME    ("evxface")
127290586Sngie
128290586Sngie
129290586Sngie/*******************************************************************************
130290586Sngie *
131290586Sngie * FUNCTION:    AcpiInstallExceptionHandler
132290586Sngie *
133290586Sngie * PARAMETERS:  Handler         - Pointer to the handler function for the
134290586Sngie *                                event
135290586Sngie *
136290586Sngie * RETURN:      Status
137290586Sngie *
138290586Sngie * DESCRIPTION: Saves the pointer to the handler function
139290586Sngie *
140290586Sngie ******************************************************************************/
141290586Sngie
142290586SngieACPI_STATUS
143290586SngieAcpiInstallExceptionHandler (
144290586Sngie    ACPI_EXCEPTION_HANDLER  Handler)
145290586Sngie{
146290586Sngie    ACPI_STATUS             Status;
147290586Sngie
148290586Sngie
149290586Sngie    ACPI_FUNCTION_TRACE ("AcpiInstallExceptionHandler");
150290586Sngie
151290586Sngie
152290586Sngie    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153290586Sngie    if (ACPI_FAILURE (Status))
154290586Sngie    {
155290586Sngie        return_ACPI_STATUS (Status);
156290586Sngie    }
157290586Sngie
158289694Sngie    /* Don't allow two handlers. */
159290586Sngie
160290586Sngie    if (AcpiGbl_ExceptionHandler)
161290586Sngie    {
162290586Sngie        Status = AE_ALREADY_EXISTS;
163290586Sngie        goto Cleanup;
164290586Sngie    }
165290586Sngie
166290586Sngie    /* Install the handler */
167290586Sngie
168290586Sngie    AcpiGbl_ExceptionHandler = Handler;
169290586Sngie
170290586SngieCleanup:
171290586Sngie    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172290586Sngie    return_ACPI_STATUS (Status);
173290586Sngie}
174289694Sngie
175290586Sngie
176290586Sngie/*******************************************************************************
177290586Sngie *
178290586Sngie * FUNCTION:    AcpiInstallFixedEventHandler
179290586Sngie *
180290586Sngie * PARAMETERS:  Event           - Event type to enable.
181290586Sngie *              Handler         - Pointer to the handler function for the
182289694Sngie *                                event
183290586Sngie *              Context         - Value passed to the handler on each GPE
184289694Sngie *
185290586Sngie * RETURN:      Status
186290586Sngie *
187289694Sngie * DESCRIPTION: Saves the pointer to the handler function and then enables the
188290586Sngie *              event.
189290586Sngie *
190290586Sngie ******************************************************************************/
191290586Sngie
192289694SngieACPI_STATUS
193290586SngieAcpiInstallFixedEventHandler (
194290586Sngie    UINT32                  Event,
195290586Sngie    ACPI_EVENT_HANDLER      Handler,
196290586Sngie    void                    *Context)
197290586Sngie{
198290586Sngie    ACPI_STATUS             Status;
199290586Sngie
200290586Sngie
201290586Sngie    ACPI_FUNCTION_TRACE ("AcpiInstallFixedEventHandler");
202290586Sngie
203290586Sngie
204290586Sngie    /* Parameter validation */
205289694Sngie
206290586Sngie    if (Event > ACPI_EVENT_MAX)
207290586Sngie    {
208290586Sngie        return_ACPI_STATUS (AE_BAD_PARAMETER);
209290586Sngie    }
210289694Sngie
211290594Sngie    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
212290594Sngie    if (ACPI_FAILURE (Status))
213290594Sngie    {
214290594Sngie        return_ACPI_STATUS (Status);
215290594Sngie    }
216290594Sngie
217290594Sngie    /* Don't allow two handlers. */
218290594Sngie
219290594Sngie    if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
220290594Sngie    {
221290594Sngie        Status = AE_ALREADY_EXISTS;
222290594Sngie        goto Cleanup;
223290594Sngie    }
224290594Sngie
225290594Sngie    /* Install the handler before enabling the event */
226290594Sngie
227290594Sngie    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
228290594Sngie    AcpiGbl_FixedEventHandlers[Event].Context = Context;
229290594Sngie
230290594Sngie    Status = AcpiEnableEvent (Event, 0);
231290594Sngie    if (ACPI_FAILURE (Status))
232290594Sngie    {
233290594Sngie        ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
234290594Sngie
235290594Sngie        /* Remove the handler */
236290594Sngie
237290594Sngie        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
238290594Sngie        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
239290594Sngie    }
240290594Sngie    else
241290594Sngie    {
242290594Sngie        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
243290594Sngie            "Enabled fixed event %X, Handler=%p\n", Event, Handler));
244290594Sngie    }
245290594Sngie
246290594Sngie
247290594SngieCleanup:
248290594Sngie    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
249290594Sngie    return_ACPI_STATUS (Status);
250290594Sngie}
251290594Sngie
252290594Sngie
253290594Sngie/*******************************************************************************
254290594Sngie *
255290594Sngie * FUNCTION:    AcpiRemoveFixedEventHandler
256290594Sngie *
257290594Sngie * PARAMETERS:  Event           - Event type to disable.
258290594Sngie *              Handler         - Address of the handler
259290594Sngie *
260290594Sngie * RETURN:      Status
261290594Sngie *
262290594Sngie * DESCRIPTION: Disables the event and unregisters the event handler.
263290594Sngie *
264290594Sngie ******************************************************************************/
265290594Sngie
266290586SngieACPI_STATUS
267290586SngieAcpiRemoveFixedEventHandler (
268290586Sngie    UINT32                  Event,
269290586Sngie    ACPI_EVENT_HANDLER      Handler)
270290586Sngie{
271290586Sngie    ACPI_STATUS             Status = AE_OK;
272290586Sngie
273290586Sngie
274290586Sngie    ACPI_FUNCTION_TRACE ("AcpiRemoveFixedEventHandler");
275290586Sngie
276290586Sngie
277290586Sngie    /* Parameter validation */
278290586Sngie
279290586Sngie    if (Event > ACPI_EVENT_MAX)
280290586Sngie    {
281290586Sngie        return_ACPI_STATUS (AE_BAD_PARAMETER);
282290586Sngie    }
283290586Sngie
284290586Sngie    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
285290586Sngie    if (ACPI_FAILURE (Status))
286290586Sngie    {
287290586Sngie        return_ACPI_STATUS (Status);
288290586Sngie    }
289290586Sngie
290290586Sngie    /* Disable the event before removing the handler */
291290586Sngie
292290586Sngie    Status = AcpiDisableEvent (Event, 0);
293290586Sngie
294290586Sngie    /* Always Remove the handler */
295290586Sngie
296290586Sngie    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
297290586Sngie    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
298290586Sngie
299290586Sngie    if (ACPI_FAILURE (Status))
300290586Sngie    {
301290586Sngie        ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
302290586Sngie            "Could not write to fixed event enable register.\n"));
303290586Sngie    }
304290586Sngie    else
305290586Sngie    {
306290586Sngie        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", Event));
307290586Sngie    }
308290586Sngie
309290586Sngie    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
310290586Sngie    return_ACPI_STATUS (Status);
311290586Sngie}
312290586Sngie
313290586Sngie
314290586Sngie/*******************************************************************************
315290586Sngie *
316290586Sngie * FUNCTION:    AcpiInstallNotifyHandler
317290586Sngie *
318290586Sngie * PARAMETERS:  Device          - The device for which notifies will be handled
319290586Sngie *              HandlerType     - The type of handler:
320290586Sngie *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
321290586Sngie *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
322290586Sngie *                                  ACPI_ALL_NOTIFY:  both system and device
323290586Sngie *              Handler         - Address of the handler
324290586Sngie *              Context         - Value passed to the handler on each GPE
325290586Sngie *
326290586Sngie * RETURN:      Status
327290586Sngie *
328290586Sngie * DESCRIPTION: Install a handler for notifies on an ACPI device
329290592Sngie *
330290592Sngie ******************************************************************************/
331290592Sngie
332290592SngieACPI_STATUS
333290592SngieAcpiInstallNotifyHandler (
334290592Sngie    ACPI_HANDLE             Device,
335290592Sngie    UINT32                  HandlerType,
336290592Sngie    ACPI_NOTIFY_HANDLER     Handler,
337290592Sngie    void                    *Context)
338290592Sngie{
339290592Sngie    ACPI_OPERAND_OBJECT     *ObjDesc;
340290592Sngie    ACPI_OPERAND_OBJECT     *NotifyObj;
341290592Sngie    ACPI_NAMESPACE_NODE     *Node;
342290592Sngie    ACPI_STATUS             Status;
343290592Sngie
344290592Sngie
345290592Sngie    ACPI_FUNCTION_TRACE ("AcpiInstallNotifyHandler");
346290592Sngie
347290592Sngie
348290592Sngie    /* Parameter validation */
349290592Sngie
350290592Sngie    if ((!Device)  ||
351290592Sngie        (!Handler) ||
352290592Sngie        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
353290592Sngie    {
354290592Sngie        return_ACPI_STATUS (AE_BAD_PARAMETER);
355289694Sngie    }
356289694Sngie
357290586Sngie    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
358290586Sngie    if (ACPI_FAILURE (Status))
359289694Sngie    {
360290586Sngie        return_ACPI_STATUS (Status);
361290586Sngie    }
362290586Sngie
363290586Sngie    /* Convert and validate the device handle */
364290586Sngie
365290586Sngie    Node = AcpiNsMapHandleToNode (Device);
366290594Sngie    if (!Node)
367290594Sngie    {
368290594Sngie        Status = AE_BAD_PARAMETER;
369290586Sngie        goto UnlockAndExit;
370290586Sngie    }
371290586Sngie
372290592Sngie    /*
373289694Sngie     * Root Object:
374     * Registering a notify handler on the root object indicates that the
375     * caller wishes to receive notifications for all objects.  Note that
376     * only one <external> global handler can be regsitered (per notify type).
377     */
378    if (Device == ACPI_ROOT_OBJECT)
379    {
380        /* Make sure the handler is not already installed */
381
382        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
383                AcpiGbl_SystemNotify.Handler)       ||
384            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
385                AcpiGbl_DeviceNotify.Handler))
386        {
387            Status = AE_ALREADY_EXISTS;
388            goto UnlockAndExit;
389        }
390
391        if (HandlerType & ACPI_SYSTEM_NOTIFY)
392        {
393            AcpiGbl_SystemNotify.Node    = Node;
394            AcpiGbl_SystemNotify.Handler = Handler;
395            AcpiGbl_SystemNotify.Context = Context;
396        }
397
398        if (HandlerType & ACPI_DEVICE_NOTIFY)
399        {
400            AcpiGbl_DeviceNotify.Node    = Node;
401            AcpiGbl_DeviceNotify.Handler = Handler;
402            AcpiGbl_DeviceNotify.Context = Context;
403        }
404
405        /* Global notify handler installed */
406    }
407
408    /*
409     * All Other Objects:
410     * Caller will only receive notifications specific to the target object.
411     * Note that only certain object types can receive notifications.
412     */
413    else
414    {
415        /* Notifies allowed on this object? */
416
417        if (!AcpiEvIsNotifyObject (Node))
418        {
419            Status = AE_TYPE;
420            goto UnlockAndExit;
421        }
422
423        /* Check for an existing internal object */
424
425        ObjDesc = AcpiNsGetAttachedObject (Node);
426        if (ObjDesc)
427        {
428            /* Object exists - make sure there's no handler */
429
430            if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
431                    ObjDesc->CommonNotify.SystemNotify)   ||
432                ((HandlerType & ACPI_DEVICE_NOTIFY) &&
433                    ObjDesc->CommonNotify.DeviceNotify))
434            {
435                Status = AE_ALREADY_EXISTS;
436                goto UnlockAndExit;
437            }
438        }
439        else
440        {
441            /* Create a new object */
442
443            ObjDesc = AcpiUtCreateInternalObject (Node->Type);
444            if (!ObjDesc)
445            {
446                Status = AE_NO_MEMORY;
447                goto UnlockAndExit;
448            }
449
450            /* Attach new object to the Node */
451
452            Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
453
454            /* Remove local reference to the object */
455
456            AcpiUtRemoveReference (ObjDesc);
457            if (ACPI_FAILURE (Status))
458            {
459                goto UnlockAndExit;
460            }
461        }
462
463        /* Install the handler */
464
465        NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
466        if (!NotifyObj)
467        {
468            Status = AE_NO_MEMORY;
469            goto UnlockAndExit;
470        }
471
472        NotifyObj->Notify.Node    = Node;
473        NotifyObj->Notify.Handler = Handler;
474        NotifyObj->Notify.Context = Context;
475
476        if (HandlerType & ACPI_SYSTEM_NOTIFY)
477        {
478            ObjDesc->CommonNotify.SystemNotify = NotifyObj;
479        }
480
481        if (HandlerType & ACPI_DEVICE_NOTIFY)
482        {
483            ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
484        }
485
486        if (HandlerType == ACPI_ALL_NOTIFY)
487        {
488            /* Extra ref if installed in both */
489
490            AcpiUtAddReference (NotifyObj);
491        }
492    }
493
494
495UnlockAndExit:
496    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
497    return_ACPI_STATUS (Status);
498}
499
500
501/*******************************************************************************
502 *
503 * FUNCTION:    AcpiRemoveNotifyHandler
504 *
505 * PARAMETERS:  Device          - The device for which notifies will be handled
506 *              HandlerType     - The type of handler:
507 *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
508 *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
509 *                                  ACPI_ALL_NOTIFY:  both system and device
510 *              Handler         - Address of the handler
511 *
512 * RETURN:      Status
513 *
514 * DESCRIPTION: Remove a handler for notifies on an ACPI device
515 *
516 ******************************************************************************/
517
518ACPI_STATUS
519AcpiRemoveNotifyHandler (
520    ACPI_HANDLE             Device,
521    UINT32                  HandlerType,
522    ACPI_NOTIFY_HANDLER     Handler)
523{
524    ACPI_OPERAND_OBJECT     *NotifyObj;
525    ACPI_OPERAND_OBJECT     *ObjDesc;
526    ACPI_NAMESPACE_NODE     *Node;
527    ACPI_STATUS             Status;
528
529
530    ACPI_FUNCTION_TRACE ("AcpiRemoveNotifyHandler");
531
532
533    /* Parameter validation */
534
535    if ((!Device)  ||
536        (!Handler) ||
537        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
538    {
539        return_ACPI_STATUS (AE_BAD_PARAMETER);
540    }
541
542    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
543    if (ACPI_FAILURE (Status))
544    {
545        return_ACPI_STATUS (Status);
546    }
547
548    /* Convert and validate the device handle */
549
550    Node = AcpiNsMapHandleToNode (Device);
551    if (!Node)
552    {
553        Status = AE_BAD_PARAMETER;
554        goto UnlockAndExit;
555    }
556
557    /* Root Object */
558
559    if (Device == ACPI_ROOT_OBJECT)
560    {
561        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
562            "Removing notify handler for ROOT object.\n"));
563
564        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
565              !AcpiGbl_SystemNotify.Handler)        ||
566            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
567              !AcpiGbl_DeviceNotify.Handler))
568        {
569            Status = AE_NOT_EXIST;
570            goto UnlockAndExit;
571        }
572
573        if (HandlerType & ACPI_SYSTEM_NOTIFY)
574        {
575            AcpiGbl_SystemNotify.Node    = NULL;
576            AcpiGbl_SystemNotify.Handler = NULL;
577            AcpiGbl_SystemNotify.Context = NULL;
578        }
579
580        if (HandlerType & ACPI_DEVICE_NOTIFY)
581        {
582            AcpiGbl_DeviceNotify.Node    = NULL;
583            AcpiGbl_DeviceNotify.Handler = NULL;
584            AcpiGbl_DeviceNotify.Context = NULL;
585        }
586    }
587
588    /* All Other Objects */
589
590    else
591    {
592        /* Notifies allowed on this object? */
593
594        if (!AcpiEvIsNotifyObject (Node))
595        {
596            Status = AE_TYPE;
597            goto UnlockAndExit;
598        }
599
600        /* Check for an existing internal object */
601
602        ObjDesc = AcpiNsGetAttachedObject (Node);
603        if (!ObjDesc)
604        {
605            Status = AE_NOT_EXIST;
606            goto UnlockAndExit;
607        }
608
609        /* Object exists - make sure there's an existing handler */
610
611        if (HandlerType & ACPI_SYSTEM_NOTIFY)
612        {
613            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
614            if ((!NotifyObj) ||
615                 (NotifyObj->Notify.Handler != Handler))
616            {
617                Status = AE_BAD_PARAMETER;
618                goto UnlockAndExit;
619            }
620
621            /* Remove the handler */
622
623            ObjDesc->CommonNotify.SystemNotify = NULL;
624            AcpiUtRemoveReference (NotifyObj);
625        }
626
627        if (HandlerType & ACPI_DEVICE_NOTIFY)
628        {
629            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
630            if ((!NotifyObj) ||
631                 (NotifyObj->Notify.Handler != Handler))
632            {
633                Status = AE_BAD_PARAMETER;
634                goto UnlockAndExit;
635            }
636
637            /* Remove the handler */
638
639            ObjDesc->CommonNotify.DeviceNotify = NULL;
640            AcpiUtRemoveReference (NotifyObj);
641        }
642    }
643
644
645UnlockAndExit:
646    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
647    return_ACPI_STATUS (Status);
648}
649
650
651/*******************************************************************************
652 *
653 * FUNCTION:    AcpiInstallGpeHandler
654 *
655 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
656 *                                defined GPEs)
657 *              GpeNumber       - The GPE number within the GPE block
658 *              Type            - Whether this GPE should be treated as an
659 *                                edge- or level-triggered interrupt.
660 *              Address         - Address of the handler
661 *              Context         - Value passed to the handler on each GPE
662 *
663 * RETURN:      Status
664 *
665 * DESCRIPTION: Install a handler for a General Purpose Event.
666 *
667 ******************************************************************************/
668
669ACPI_STATUS
670AcpiInstallGpeHandler (
671    ACPI_HANDLE             GpeDevice,
672    UINT32                  GpeNumber,
673    UINT32                  Type,
674    ACPI_EVENT_HANDLER      Address,
675    void                    *Context)
676{
677    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
678    ACPI_HANDLER_INFO       *Handler;
679    ACPI_STATUS             Status;
680    ACPI_NATIVE_UINT        Flags;
681
682
683    ACPI_FUNCTION_TRACE ("AcpiInstallGpeHandler");
684
685
686    /* Parameter validation */
687
688    if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK))
689    {
690        return_ACPI_STATUS (AE_BAD_PARAMETER);
691    }
692
693    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
694    if (ACPI_FAILURE (Status))
695    {
696        return_ACPI_STATUS (Status);
697    }
698
699    /* Ensure that we have a valid GPE number */
700
701    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702    if (!GpeEventInfo)
703    {
704        Status = AE_BAD_PARAMETER;
705        goto UnlockAndExit;
706    }
707
708    /* Make sure that there isn't a handler there already */
709
710    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER)
711    {
712        Status = AE_ALREADY_EXISTS;
713        goto UnlockAndExit;
714    }
715
716    /* Allocate and init handler object */
717
718    Handler = ACPI_MEM_CALLOCATE (sizeof (ACPI_HANDLER_INFO));
719    if (!Handler)
720    {
721        Status = AE_NO_MEMORY;
722        goto UnlockAndExit;
723    }
724
725    Handler->Address    = Address;
726    Handler->Context    = Context;
727    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
728
729    /* Disable the GPE before installing the handler */
730
731    Status = AcpiEvDisableGpe (GpeEventInfo);
732    if (ACPI_FAILURE (Status))
733    {
734        goto UnlockAndExit;
735    }
736
737    /* Install the handler */
738
739    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
740    GpeEventInfo->Dispatch.Handler = Handler;
741
742    /* Setup up dispatch flags to indicate handler (vs. method) */
743
744    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);  /* Clear bits */
745    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
746
747    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
748
749
750UnlockAndExit:
751    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
752    return_ACPI_STATUS (Status);
753}
754
755
756/*******************************************************************************
757 *
758 * FUNCTION:    AcpiRemoveGpeHandler
759 *
760 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
761 *                                defined GPEs)
762 *              GpeNumber       - The event to remove a handler
763 *              Address         - Address of the handler
764 *
765 * RETURN:      Status
766 *
767 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
768 *
769 ******************************************************************************/
770
771ACPI_STATUS
772AcpiRemoveGpeHandler (
773    ACPI_HANDLE             GpeDevice,
774    UINT32                  GpeNumber,
775    ACPI_EVENT_HANDLER      Address)
776{
777    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
778    ACPI_HANDLER_INFO       *Handler;
779    ACPI_STATUS             Status;
780    ACPI_NATIVE_UINT        Flags;
781
782
783    ACPI_FUNCTION_TRACE ("AcpiRemoveGpeHandler");
784
785
786    /* Parameter validation */
787
788    if (!Address)
789    {
790        return_ACPI_STATUS (AE_BAD_PARAMETER);
791    }
792
793    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
794    if (ACPI_FAILURE (Status))
795    {
796        return_ACPI_STATUS (Status);
797    }
798
799    /* Ensure that we have a valid GPE number */
800
801    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
802    if (!GpeEventInfo)
803    {
804        Status = AE_BAD_PARAMETER;
805        goto UnlockAndExit;
806    }
807
808    /* Make sure that a handler is indeed installed */
809
810    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER)
811    {
812        Status = AE_NOT_EXIST;
813        goto UnlockAndExit;
814    }
815
816    /* Make sure that the installed handler is the same */
817
818    if (GpeEventInfo->Dispatch.Handler->Address != Address)
819    {
820        Status = AE_BAD_PARAMETER;
821        goto UnlockAndExit;
822    }
823
824    /* Disable the GPE before removing the handler */
825
826    Status = AcpiEvDisableGpe (GpeEventInfo);
827    if (ACPI_FAILURE (Status))
828    {
829        goto UnlockAndExit;
830    }
831
832    /* Remove the handler */
833
834    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
835    Handler = GpeEventInfo->Dispatch.Handler;
836
837    /* Restore Method node (if any), set dispatch flags */
838
839    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
840    GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;  /* Clear bits */
841    if (Handler->MethodNode)
842    {
843        GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
844    }
845    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
846
847    /* Now we can free the handler object */
848
849    ACPI_MEM_FREE (Handler);
850
851
852UnlockAndExit:
853    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
854    return_ACPI_STATUS (Status);
855}
856
857
858/*******************************************************************************
859 *
860 * FUNCTION:    AcpiAcquireGlobalLock
861 *
862 * PARAMETERS:  Timeout         - How long the caller is willing to wait
863 *              Handle          - Where the handle to the lock is returned
864 *                                (if acquired)
865 *
866 * RETURN:      Status
867 *
868 * DESCRIPTION: Acquire the ACPI Global Lock
869 *
870 ******************************************************************************/
871
872ACPI_STATUS
873AcpiAcquireGlobalLock (
874    UINT16                  Timeout,
875    UINT32                  *Handle)
876{
877    ACPI_STATUS             Status;
878
879
880    if (!Handle)
881    {
882        return (AE_BAD_PARAMETER);
883    }
884
885    Status = AcpiExEnterInterpreter ();
886    if (ACPI_FAILURE (Status))
887    {
888        return (Status);
889    }
890
891    Status = AcpiEvAcquireGlobalLock (Timeout);
892    AcpiExExitInterpreter ();
893
894    if (ACPI_SUCCESS (Status))
895    {
896        AcpiGbl_GlobalLockHandle++;
897        *Handle = AcpiGbl_GlobalLockHandle;
898    }
899
900    return (Status);
901}
902
903
904/*******************************************************************************
905 *
906 * FUNCTION:    AcpiReleaseGlobalLock
907 *
908 * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
909 *
910 * RETURN:      Status
911 *
912 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
913 *
914 ******************************************************************************/
915
916ACPI_STATUS
917AcpiReleaseGlobalLock (
918    UINT32                  Handle)
919{
920    ACPI_STATUS             Status;
921
922
923    if (Handle != AcpiGbl_GlobalLockHandle)
924    {
925        return (AE_NOT_ACQUIRED);
926    }
927
928    Status = AcpiEvReleaseGlobalLock ();
929    return (Status);
930}
931
932
933