evxface.c revision 172314
1193323Sed/******************************************************************************
2193323Sed *
3193323Sed * Module Name: evxface - External interfaces for ACPI events
4193323Sed *              $Revision: 1.165 $
5193323Sed *
6193323Sed *****************************************************************************/
7193323Sed
8193323Sed/******************************************************************************
9193323Sed *
10193323Sed * 1. Copyright Notice
11193323Sed *
12193323Sed * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
13193323Sed * All rights reserved.
14193323Sed *
15193323Sed * 2. License
16193323Sed *
17193323Sed * 2.1. This is your license from Intel Corp. under its intellectual property
18198090Srdivacky * rights.  You may have additional license terms from the party that provided
19198090Srdivacky * you this software, covering your right to use that party's intellectual
20193323Sed * property rights.
21193323Sed *
22193323Sed * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23193323Sed * copy of the source code appearing in this file ("Covered Code") an
24249423Sdim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25198090Srdivacky * base code distributed originally by Intel ("Original Intel Code") to copy,
26198090Srdivacky * make derivatives, distribute, use and display any portion of the Covered
27193323Sed * Code in any form, with the right to sublicense such rights; and
28193323Sed *
29193323Sed * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30193323Sed * license (with the right to sublicense), under only those claims of Intel
31193323Sed * patents that are infringed by the Original Intel Code, to make, use, sell,
32193323Sed * offer to sell, and import the Covered Code and derivative works thereof
33193323Sed * solely to the minimum extent necessary to exercise the above copyright
34202375Srdivacky * license, and in no event shall the patent license extend to any additions
35198090Srdivacky * to or modifications of the Original Intel Code.  No other license or right
36202375Srdivacky * is granted directly or by implication, estoppel or otherwise;
37193323Sed *
38193323Sed * The above copyright and patent license is granted only if the following
39193323Sed * conditions are met:
40193323Sed *
41193323Sed * 3. Conditions
42202375Srdivacky *
43198090Srdivacky * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44202375Srdivacky * Redistribution of source code of any substantial portion of the Covered
45193323Sed * Code or modification with rights to further distribute source must include
46226633Sdim * the above Copyright Notice, the above License, this list of Conditions,
47226633Sdim * and the following Disclaimer and Export Compliance provision.  In addition,
48193323Sed * Licensee must cause all Covered Code to which Licensee contributes to
49226633Sdim * contain a file documenting the changes Licensee made to create that Covered
50218893Sdim * Code and the date of any change.  Licensee must include in that file the
51239462Sdim * documentation of any changes made by any predecessor Licensee.  Licensee
52193323Sed * must include a prominent statement that the modification is derived,
53193323Sed * directly or indirectly, from Original Intel Code.
54221345Sdim *
55202375Srdivacky * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56193323Sed * Redistribution of source code of any substantial portion of the Covered
57193323Sed * Code or modification without rights to further distribute source must
58193323Sed * include the following Disclaimer and Export Compliance provision in the
59193323Sed * documentation and/or other materials provided with distribution.  In
60202375Srdivacky * addition, Licensee may not authorize further sublicense of source of any
61234353Sdim * portion of the Covered Code, and must include terms to the effect that the
62193323Sed * license from Licensee to its licensee is limited to the intellectual
63193323Sed * property embodied in the software Licensee provides to its licensee, and
64198090Srdivacky * not to intellectual property embodied in modifications its licensee may
65193323Sed * make.
66193323Sed *
67221345Sdim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68193323Sed * substantial portion of the Covered Code or modification must reproduce the
69193323Sed * above Copyright Notice, and the following Disclaimer and Export Compliance
70193323Sed * provision in the documentation and/or other materials provided with the
71193323Sed * distribution.
72221345Sdim *
73193323Sed * 3.4. Intel retains all right, title, and interest in and to the Original
74221345Sdim * Intel Code.
75221345Sdim *
76221345Sdim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77221345Sdim * Intel shall be used in advertising or otherwise to promote the sale, use or
78221345Sdim * other dealings in products derived from or relating to the Covered Code
79221345Sdim * without prior written authorization from Intel.
80221345Sdim *
81193323Sed * 4. Disclaimer and Export Compliance
82221345Sdim *
83193323Sed * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84193323Sed * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85221345Sdim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86193323Sed * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87193323Sed * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89221345Sdim * PARTICULAR PURPOSE.
90193323Sed *
91193323Sed * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92221345Sdim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93198090Srdivacky * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94198090Srdivacky * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95198090Srdivacky * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96193323Sed * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97193323Sed * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98193323Sed * LIMITED REMEDY.
99193323Sed *
100193323Sed * 4.3. Licensee shall not export, either directly or indirectly, any of this
101193323Sed * software or system incorporating such software without first obtaining any
102193323Sed * required license or other approval from the U. S. Department of Commerce or
103193323Sed * any other agency or department of the United States Government.  In the
104193323Sed * event Licensee exports any such software from the United States or
105193323Sed * re-exports any such software from a foreign destination, Licensee shall
106193323Sed * ensure that the distribution and export/re-export of the software is in
107193323Sed * compliance with all laws, regulations, orders, or other restrictions of the
108193323Sed * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109193323Sed * any of its subsidiaries will export/re-export any technical data, process,
110193323Sed * software, or service, directly or indirectly, to any country for which the
111193323Sed * United States government or any agency thereof requires an export license,
112198090Srdivacky * other governmental approval, or letter of assurance, without first obtaining
113193323Sed * such license, approval or letter.
114193323Sed *
115198090Srdivacky *****************************************************************************/
116198090Srdivacky
117198090Srdivacky
118239462Sdim#define __EVXFACE_C__
119239462Sdim
120239462Sdim#include <contrib/dev/acpica/acpi.h>
121193323Sed#include <contrib/dev/acpica/acnamesp.h>
122193323Sed#include <contrib/dev/acpica/acevents.h>
123193323Sed#include <contrib/dev/acpica/acinterp.h>
124193323Sed
125193323Sed#define _COMPONENT          ACPI_EVENTS
126193323Sed        ACPI_MODULE_NAME    ("evxface")
127193323Sed
128193323Sed
129193323Sed/*******************************************************************************
130193323Sed *
131193323Sed * FUNCTION:    AcpiInstallExceptionHandler
132193323Sed *
133193323Sed * PARAMETERS:  Handler         - Pointer to the handler function for the
134193323Sed *                                event
135239462Sdim *
136239462Sdim * RETURN:      Status
137239462Sdim *
138239462Sdim * DESCRIPTION: Saves the pointer to the handler function
139239462Sdim *
140239462Sdim ******************************************************************************/
141239462Sdim
142239462SdimACPI_STATUS
143226633SdimAcpiInstallExceptionHandler (
144226633Sdim    ACPI_EXCEPTION_HANDLER  Handler)
145226633Sdim{
146226633Sdim    ACPI_STATUS             Status;
147226633Sdim
148226633Sdim
149218893Sdim    ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
150198090Srdivacky
151218893Sdim
152193323Sed    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153193323Sed    if (ACPI_FAILURE (Status))
154193323Sed    {
155239462Sdim        return_ACPI_STATUS (Status);
156239462Sdim    }
157239462Sdim
158239462Sdim    /* Don't allow two handlers. */
159239462Sdim
160239462Sdim    if (AcpiGbl_ExceptionHandler)
161239462Sdim    {
162239462Sdim        Status = AE_ALREADY_EXISTS;
163239462Sdim        goto Cleanup;
164239462Sdim    }
165193323Sed
166198090Srdivacky    /* Install the handler */
167193323Sed
168193323Sed    AcpiGbl_ExceptionHandler = Handler;
169193323Sed
170193323SedCleanup:
171193323Sed    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172193323Sed    return_ACPI_STATUS (Status);
173193323Sed}
174193323Sed
175193323SedACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
176193323Sed
177193323Sed
178193323Sed/*******************************************************************************
179193323Sed *
180193323Sed * FUNCTION:    AcpiInstallFixedEventHandler
181193323Sed *
182221345Sdim * PARAMETERS:  Event           - Event type to enable.
183221345Sdim *              Handler         - Pointer to the handler function for the
184221345Sdim *                                event
185221345Sdim *              Context         - Value passed to the handler on each GPE
186221345Sdim *
187221345Sdim * RETURN:      Status
188221345Sdim *
189193323Sed * DESCRIPTION: Saves the pointer to the handler function and then enables the
190193323Sed *              event.
191193323Sed *
192193323Sed ******************************************************************************/
193193323Sed
194193323SedACPI_STATUS
195193323SedAcpiInstallFixedEventHandler (
196193323Sed    UINT32                  Event,
197193323Sed    ACPI_EVENT_HANDLER      Handler,
198193323Sed    void                    *Context)
199198090Srdivacky{
200193323Sed    ACPI_STATUS             Status;
201193323Sed
202193323Sed
203193323Sed    ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
204193323Sed
205193323Sed
206193323Sed    /* Parameter validation */
207193323Sed
208193323Sed    if (Event > ACPI_EVENT_MAX)
209210299Sed    {
210193323Sed        return_ACPI_STATUS (AE_BAD_PARAMETER);
211193323Sed    }
212210299Sed
213193323Sed    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
214193323Sed    if (ACPI_FAILURE (Status))
215218893Sdim    {
216193323Sed        return_ACPI_STATUS (Status);
217203954Srdivacky    }
218234353Sdim
219193323Sed    /* Don't allow two handlers. */
220193323Sed
221193323Sed    if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
222193323Sed    {
223193323Sed        Status = AE_ALREADY_EXISTS;
224193323Sed        goto Cleanup;
225193323Sed    }
226193323Sed
227193323Sed    /* Install the handler before enabling the event */
228198090Srdivacky
229193323Sed    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
230193323Sed    AcpiGbl_FixedEventHandlers[Event].Context = Context;
231193323Sed
232193323Sed    Status = AcpiEnableEvent (Event, 0);
233202375Srdivacky    if (ACPI_FAILURE (Status))
234202375Srdivacky    {
235202375Srdivacky        ACPI_WARNING ((AE_INFO, "Could not enable fixed event %X", Event));
236202375Srdivacky
237202375Srdivacky        /* Remove the handler */
238202375Srdivacky
239202375Srdivacky        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
240202375Srdivacky        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
241193323Sed    }
242193323Sed    else
243193323Sed    {
244198090Srdivacky        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
245193323Sed            "Enabled fixed event %X, Handler=%p\n", Event, Handler));
246193323Sed    }
247193323Sed
248193323Sed
249193323SedCleanup:
250193323Sed    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
251234353Sdim    return_ACPI_STATUS (Status);
252234353Sdim}
253234353Sdim
254234353SdimACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
255234353Sdim
256234353Sdim
257234353Sdim/*******************************************************************************
258234353Sdim *
259234353Sdim * FUNCTION:    AcpiRemoveFixedEventHandler
260234353Sdim *
261234353Sdim * PARAMETERS:  Event           - Event type to disable.
262234353Sdim *              Handler         - Address of the handler
263234353Sdim *
264234353Sdim * RETURN:      Status
265234353Sdim *
266234353Sdim * DESCRIPTION: Disables the event and unregisters the event handler.
267234353Sdim *
268234353Sdim ******************************************************************************/
269234353Sdim
270234353SdimACPI_STATUS
271234353SdimAcpiRemoveFixedEventHandler (
272234353Sdim    UINT32                  Event,
273234353Sdim    ACPI_EVENT_HANDLER      Handler)
274234353Sdim{
275234353Sdim    ACPI_STATUS             Status = AE_OK;
276234353Sdim
277234353Sdim
278234353Sdim    ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
279234353Sdim
280234353Sdim
281234353Sdim    /* Parameter validation */
282193323Sed
283193323Sed    if (Event > ACPI_EVENT_MAX)
284193323Sed    {
285193323Sed        return_ACPI_STATUS (AE_BAD_PARAMETER);
286193323Sed    }
287193323Sed
288193323Sed    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
289193323Sed    if (ACPI_FAILURE (Status))
290193323Sed    {
291193323Sed        return_ACPI_STATUS (Status);
292193323Sed    }
293193323Sed
294193323Sed    /* Disable the event before removing the handler */
295193323Sed
296193323Sed    Status = AcpiDisableEvent (Event, 0);
297198090Srdivacky
298226633Sdim    /* Always Remove the handler */
299226633Sdim
300226633Sdim    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
301226633Sdim    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
302226633Sdim
303226633Sdim    if (ACPI_FAILURE (Status))
304198090Srdivacky    {
305198090Srdivacky        ACPI_WARNING ((AE_INFO,
306198090Srdivacky            "Could not write to fixed event enable register %X", Event));
307198090Srdivacky    }
308198090Srdivacky    else
309198090Srdivacky    {
310198090Srdivacky        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
311198090Srdivacky    }
312193323Sed
313193323Sed    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
314193323Sed    return_ACPI_STATUS (Status);
315193323Sed}
316193323Sed
317193323SedACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
318193323Sed
319193323Sed
320193323Sed/*******************************************************************************
321193323Sed *
322193323Sed * FUNCTION:    AcpiInstallNotifyHandler
323193323Sed *
324193323Sed * PARAMETERS:  Device          - The device for which notifies will be handled
325193323Sed *              HandlerType     - The type of handler:
326226633Sdim *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
327226633Sdim *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
328226633Sdim *                                  ACPI_ALL_NOTIFY:  both system and device
329226633Sdim *              Handler         - Address of the handler
330193323Sed *              Context         - Value passed to the handler on each GPE
331193323Sed *
332198090Srdivacky * RETURN:      Status
333198090Srdivacky *
334193323Sed * DESCRIPTION: Install a handler for notifies on an ACPI device
335193323Sed *
336226633Sdim ******************************************************************************/
337226633Sdim
338226633SdimACPI_STATUS
339226633SdimAcpiInstallNotifyHandler (
340226633Sdim    ACPI_HANDLE             Device,
341226633Sdim    UINT32                  HandlerType,
342226633Sdim    ACPI_NOTIFY_HANDLER     Handler,
343193323Sed    void                    *Context)
344193323Sed{
345193323Sed    ACPI_OPERAND_OBJECT     *ObjDesc;
346193323Sed    ACPI_OPERAND_OBJECT     *NotifyObj;
347193323Sed    ACPI_NAMESPACE_NODE     *Node;
348193323Sed    ACPI_STATUS             Status;
349193323Sed
350193323Sed
351202375Srdivacky    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
352198090Srdivacky
353202375Srdivacky
354193323Sed    /* Parameter validation */
355193323Sed
356193323Sed    if ((!Device)  ||
357193323Sed        (!Handler) ||
358193323Sed        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
359193323Sed    {
360202375Srdivacky        return_ACPI_STATUS (AE_BAD_PARAMETER);
361198090Srdivacky    }
362202375Srdivacky
363193323Sed    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
364198090Srdivacky    if (ACPI_FAILURE (Status))
365218893Sdim    {
366218893Sdim        return_ACPI_STATUS (Status);
367198090Srdivacky    }
368249423Sdim
369249423Sdim    /* Convert and validate the device handle */
370249423Sdim
371249423Sdim    Node = AcpiNsMapHandleToNode (Device);
372249423Sdim    if (!Node)
373193323Sed    {
374198090Srdivacky        Status = AE_BAD_PARAMETER;
375198090Srdivacky        goto UnlockAndExit;
376193323Sed    }
377198090Srdivacky
378198090Srdivacky    /*
379193323Sed     * Root Object:
380198090Srdivacky     * Registering a notify handler on the root object indicates that the
381198090Srdivacky     * caller wishes to receive notifications for all objects.  Note that
382193323Sed     * only one <external> global handler can be regsitered (per notify type).
383193323Sed     */
384193323Sed    if (Device == ACPI_ROOT_OBJECT)
385193323Sed    {
386193323Sed        /* Make sure the handler is not already installed */
387193323Sed
388193323Sed        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
389193323Sed                AcpiGbl_SystemNotify.Handler)       ||
390193323Sed            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
391193323Sed                AcpiGbl_DeviceNotify.Handler))
392193323Sed        {
393193323Sed            Status = AE_ALREADY_EXISTS;
394193323Sed            goto UnlockAndExit;
395193323Sed        }
396193323Sed
397193323Sed        if (HandlerType & ACPI_SYSTEM_NOTIFY)
398193323Sed        {
399193323Sed            AcpiGbl_SystemNotify.Node    = Node;
400218893Sdim            AcpiGbl_SystemNotify.Handler = Handler;
401193323Sed            AcpiGbl_SystemNotify.Context = Context;
402218893Sdim        }
403193323Sed
404218893Sdim        if (HandlerType & ACPI_DEVICE_NOTIFY)
405193323Sed        {
406193323Sed            AcpiGbl_DeviceNotify.Node    = Node;
407193323Sed            AcpiGbl_DeviceNotify.Handler = Handler;
408249423Sdim            AcpiGbl_DeviceNotify.Context = Context;
409249423Sdim        }
410249423Sdim
411249423Sdim        /* Global notify handler installed */
412249423Sdim    }
413249423Sdim
414249423Sdim    /*
415249423Sdim     * All Other Objects:
416249423Sdim     * Caller will only receive notifications specific to the target object.
417249423Sdim     * Note that only certain object types can receive notifications.
418249423Sdim     */
419249423Sdim    else
420249423Sdim    {
421249423Sdim        /* Notifies allowed on this object? */
422249423Sdim
423193323Sed        if (!AcpiEvIsNotifyObject (Node))
424193323Sed        {
425193323Sed            Status = AE_TYPE;
426193323Sed            goto UnlockAndExit;
427193323Sed        }
428193323Sed
429193323Sed        /* Check for an existing internal object */
430193323Sed
431193323Sed        ObjDesc = AcpiNsGetAttachedObject (Node);
432193323Sed        if (ObjDesc)
433193323Sed        {
434193323Sed            /* Object exists - make sure there's no handler */
435193323Sed
436193323Sed            if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
437198090Srdivacky                    ObjDesc->CommonNotify.SystemNotify)   ||
438198090Srdivacky                ((HandlerType & ACPI_DEVICE_NOTIFY) &&
439198090Srdivacky                    ObjDesc->CommonNotify.DeviceNotify))
440198090Srdivacky            {
441198090Srdivacky                Status = AE_ALREADY_EXISTS;
442193323Sed                goto UnlockAndExit;
443193323Sed            }
444193323Sed        }
445193323Sed        else
446193323Sed        {
447193323Sed            /* Create a new object */
448193323Sed
449193323Sed            ObjDesc = AcpiUtCreateInternalObject (Node->Type);
450193323Sed            if (!ObjDesc)
451193323Sed            {
452193323Sed                Status = AE_NO_MEMORY;
453193323Sed                goto UnlockAndExit;
454218893Sdim            }
455193323Sed
456203954Srdivacky            /* Attach new object to the Node */
457203954Srdivacky
458193323Sed            Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
459193323Sed
460218893Sdim            /* Remove local reference to the object */
461203954Srdivacky
462203954Srdivacky            AcpiUtRemoveReference (ObjDesc);
463193323Sed            if (ACPI_FAILURE (Status))
464193323Sed            {
465193323Sed                goto UnlockAndExit;
466193323Sed            }
467193323Sed        }
468193323Sed
469193323Sed        /* Install the handler */
470193323Sed
471193323Sed        NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
472193323Sed        if (!NotifyObj)
473193323Sed        {
474193323Sed            Status = AE_NO_MEMORY;
475193323Sed            goto UnlockAndExit;
476202375Srdivacky        }
477198090Srdivacky
478202375Srdivacky        NotifyObj->Notify.Node    = Node;
479193323Sed        NotifyObj->Notify.Handler = Handler;
480239462Sdim        NotifyObj->Notify.Context = Context;
481234353Sdim
482234353Sdim        if (HandlerType & ACPI_SYSTEM_NOTIFY)
483234353Sdim        {
484193323Sed            ObjDesc->CommonNotify.SystemNotify = NotifyObj;
485193323Sed        }
486193323Sed
487193323Sed        if (HandlerType & ACPI_DEVICE_NOTIFY)
488202375Srdivacky        {
489198090Srdivacky            ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
490202375Srdivacky        }
491193323Sed
492239462Sdim        if (HandlerType == ACPI_ALL_NOTIFY)
493239462Sdim        {
494193323Sed            /* Extra ref if installed in both */
495226633Sdim
496226633Sdim            AcpiUtAddReference (NotifyObj);
497193323Sed        }
498193323Sed    }
499193323Sed
500218893Sdim
501193323SedUnlockAndExit:
502193323Sed    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
503193323Sed    return_ACPI_STATUS (Status);
504202375Srdivacky}
505193323Sed
506193323SedACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
507193323Sed
508202375Srdivacky
509198090Srdivacky/*******************************************************************************
510198090Srdivacky *
511198090Srdivacky * FUNCTION:    AcpiRemoveNotifyHandler
512198090Srdivacky *
513198090Srdivacky * PARAMETERS:  Device          - The device for which notifies will be handled
514198090Srdivacky *              HandlerType     - The type of handler:
515193323Sed *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
516198090Srdivacky *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
517198090Srdivacky *                                  ACPI_ALL_NOTIFY:  both system and device
518193323Sed *              Handler         - Address of the handler
519221345Sdim *
520221345Sdim * RETURN:      Status
521193323Sed *
522234353Sdim * DESCRIPTION: Remove a handler for notifies on an ACPI device
523234353Sdim *
524234353Sdim ******************************************************************************/
525193323Sed
526193323SedACPI_STATUS
527221345SdimAcpiRemoveNotifyHandler (
528193323Sed    ACPI_HANDLE             Device,
529221345Sdim    UINT32                  HandlerType,
530221345Sdim    ACPI_NOTIFY_HANDLER     Handler)
531193323Sed{
532221345Sdim    ACPI_OPERAND_OBJECT     *NotifyObj;
533221345Sdim    ACPI_OPERAND_OBJECT     *ObjDesc;
534221345Sdim    ACPI_NAMESPACE_NODE     *Node;
535193323Sed    ACPI_STATUS             Status;
536221345Sdim
537221345Sdim
538221345Sdim    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
539193323Sed
540193323Sed
541221345Sdim    /* Parameter validation */
542221345Sdim
543221345Sdim    if ((!Device)  ||
544221345Sdim        (!Handler) ||
545221345Sdim        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
546193323Sed    {
547221345Sdim        return_ACPI_STATUS (AE_BAD_PARAMETER);
548198090Srdivacky    }
549198090Srdivacky
550198090Srdivacky    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
551198090Srdivacky    if (ACPI_FAILURE (Status))
552193323Sed    {
553193323Sed        return_ACPI_STATUS (Status);
554193323Sed    }
555193323Sed
556193323Sed    /* Convert and validate the device handle */
557193323Sed
558193323Sed    Node = AcpiNsMapHandleToNode (Device);
559193323Sed    if (!Node)
560193323Sed    {
561193323Sed        Status = AE_BAD_PARAMETER;
562193323Sed        goto UnlockAndExit;
563193323Sed    }
564193323Sed
565193323Sed    /* Root Object */
566193323Sed
567193323Sed    if (Device == ACPI_ROOT_OBJECT)
568193323Sed    {
569193323Sed        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
570193323Sed            "Removing notify handler for namespace root object\n"));
571198090Srdivacky
572198090Srdivacky        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
573198090Srdivacky              !AcpiGbl_SystemNotify.Handler)        ||
574239462Sdim            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
575239462Sdim              !AcpiGbl_DeviceNotify.Handler))
576239462Sdim        {
577193323Sed            Status = AE_NOT_EXIST;
578193323Sed            goto UnlockAndExit;
579193323Sed        }
580193323Sed
581193323Sed        if (HandlerType & ACPI_SYSTEM_NOTIFY)
582193323Sed        {
583193323Sed            AcpiGbl_SystemNotify.Node    = NULL;
584193323Sed            AcpiGbl_SystemNotify.Handler = NULL;
585193323Sed            AcpiGbl_SystemNotify.Context = NULL;
586193323Sed        }
587193323Sed
588193323Sed        if (HandlerType & ACPI_DEVICE_NOTIFY)
589193323Sed        {
590193323Sed            AcpiGbl_DeviceNotify.Node    = NULL;
591193323Sed            AcpiGbl_DeviceNotify.Handler = NULL;
592193323Sed            AcpiGbl_DeviceNotify.Context = NULL;
593193323Sed        }
594193323Sed    }
595193323Sed
596239462Sdim    /* All Other Objects */
597239462Sdim
598239462Sdim    else
599239462Sdim    {
600239462Sdim        /* Notifies allowed on this object? */
601239462Sdim
602239462Sdim        if (!AcpiEvIsNotifyObject (Node))
603239462Sdim        {
604239462Sdim            Status = AE_TYPE;
605239462Sdim            goto UnlockAndExit;
606239462Sdim        }
607239462Sdim
608239462Sdim        /* Check for an existing internal object */
609239462Sdim
610239462Sdim        ObjDesc = AcpiNsGetAttachedObject (Node);
611239462Sdim        if (!ObjDesc)
612218893Sdim        {
613218893Sdim            Status = AE_NOT_EXIST;
614193323Sed            goto UnlockAndExit;
615193323Sed        }
616198090Srdivacky
617193323Sed        /* Object exists - make sure there's an existing handler */
618193323Sed
619193323Sed        if (HandlerType & ACPI_SYSTEM_NOTIFY)
620193323Sed        {
621198090Srdivacky            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
622193323Sed            if (!NotifyObj)
623193323Sed            {
624193323Sed                Status = AE_NOT_EXIST;
625223017Sdim                goto UnlockAndExit;
626223017Sdim            }
627223017Sdim
628223017Sdim            if (NotifyObj->Notify.Handler != Handler)
629226633Sdim            {
630193323Sed                Status = AE_BAD_PARAMETER;
631223017Sdim                goto UnlockAndExit;
632223017Sdim            }
633193323Sed
634193323Sed            /* Remove the handler */
635193323Sed
636193323Sed            ObjDesc->CommonNotify.SystemNotify = NULL;
637193323Sed            AcpiUtRemoveReference (NotifyObj);
638193323Sed        }
639193323Sed
640218893Sdim        if (HandlerType & ACPI_DEVICE_NOTIFY)
641218893Sdim        {
642193323Sed            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
643193323Sed            if (!NotifyObj)
644193323Sed            {
645223017Sdim                Status = AE_NOT_EXIST;
646193323Sed                goto UnlockAndExit;
647193323Sed            }
648193323Sed
649218893Sdim            if (NotifyObj->Notify.Handler != Handler)
650218893Sdim            {
651193323Sed                Status = AE_BAD_PARAMETER;
652193323Sed                goto UnlockAndExit;
653193323Sed            }
654193323Sed
655198090Srdivacky            /* Remove the handler */
656198090Srdivacky
657193323Sed            ObjDesc->CommonNotify.DeviceNotify = NULL;
658193323Sed            AcpiUtRemoveReference (NotifyObj);
659193323Sed        }
660193323Sed    }
661193323Sed
662193323Sed
663193323SedUnlockAndExit:
664218893Sdim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
665218893Sdim    return_ACPI_STATUS (Status);
666193323Sed}
667193323Sed
668193323SedACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
669193323Sed
670198090Srdivacky
671193323Sed/*******************************************************************************
672193323Sed *
673193323Sed * FUNCTION:    AcpiInstallGpeHandler
674193323Sed *
675193323Sed * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
676193323Sed *                                defined GPEs)
677193323Sed *              GpeNumber       - The GPE number within the GPE block
678193323Sed *              Type            - Whether this GPE should be treated as an
679193323Sed *                                edge- or level-triggered interrupt.
680193323Sed *              Address         - Address of the handler
681193323Sed *              Context         - Value passed to the handler on each GPE
682193323Sed *
683193323Sed * RETURN:      Status
684193323Sed *
685193323Sed * DESCRIPTION: Install a handler for a General Purpose Event.
686193323Sed *
687193323Sed ******************************************************************************/
688193323Sed
689193323SedACPI_STATUS
690193323SedAcpiInstallGpeHandler (
691193323Sed    ACPI_HANDLE             GpeDevice,
692198090Srdivacky    UINT32                  GpeNumber,
693193323Sed    UINT32                  Type,
694193323Sed    ACPI_EVENT_HANDLER      Address,
695193323Sed    void                    *Context)
696193323Sed{
697193323Sed    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
698193323Sed    ACPI_HANDLER_INFO       *Handler;
699193323Sed    ACPI_STATUS             Status;
700193323Sed    ACPI_CPU_FLAGS          Flags;
701193323Sed
702193323Sed
703193323Sed    ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
704193323Sed
705193323Sed
706193323Sed    /* Parameter validation */
707193323Sed
708198090Srdivacky    if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK))
709193323Sed    {
710193323Sed        return_ACPI_STATUS (AE_BAD_PARAMETER);
711193323Sed    }
712218893Sdim
713218893Sdim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
714218893Sdim    if (ACPI_FAILURE (Status))
715193323Sed    {
716193323Sed        return_ACPI_STATUS (Status);
717193323Sed    }
718193323Sed
719193323Sed    /* Ensure that we have a valid GPE number */
720193323Sed
721193323Sed    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
722193323Sed    if (!GpeEventInfo)
723193323Sed    {
724193323Sed        Status = AE_BAD_PARAMETER;
725202375Srdivacky        goto UnlockAndExit;
726202375Srdivacky    }
727202375Srdivacky
728202375Srdivacky    /* Make sure that there isn't a handler there already */
729202375Srdivacky
730202375Srdivacky    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER)
731202375Srdivacky    {
732202375Srdivacky        Status = AE_ALREADY_EXISTS;
733202375Srdivacky        goto UnlockAndExit;
734202375Srdivacky    }
735202375Srdivacky
736202375Srdivacky    /* Allocate and init handler object */
737202375Srdivacky
738202375Srdivacky    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO));
739202375Srdivacky    if (!Handler)
740193323Sed    {
741193323Sed        Status = AE_NO_MEMORY;
742193323Sed        goto UnlockAndExit;
743193323Sed    }
744193323Sed
745193323Sed    Handler->Address    = Address;
746193323Sed    Handler->Context    = Context;
747193323Sed    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
748193323Sed
749193323Sed    /* Disable the GPE before installing the handler */
750193323Sed
751193323Sed    Status = AcpiEvDisableGpe (GpeEventInfo);
752193323Sed    if (ACPI_FAILURE (Status))
753193323Sed    {
754193323Sed        goto UnlockAndExit;
755193323Sed    }
756193323Sed
757193323Sed    /* Install the handler */
758193323Sed
759193323Sed    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
760193323Sed    GpeEventInfo->Dispatch.Handler = Handler;
761198090Srdivacky
762198090Srdivacky    /* Setup up dispatch flags to indicate handler (vs. method) */
763193323Sed
764218893Sdim    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);  /* Clear bits */
765218893Sdim    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
766193323Sed
767193323Sed    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
768193323Sed
769193323Sed
770226633SdimUnlockAndExit:
771193323Sed    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
772243830Sdim    return_ACPI_STATUS (Status);
773218893Sdim}
774203954Srdivacky
775193323SedACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
776193323Sed
777218893Sdim
778234353Sdim/*******************************************************************************
779193323Sed *
780193323Sed * FUNCTION:    AcpiRemoveGpeHandler
781193323Sed *
782193323Sed * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
783193323Sed *                                defined GPEs)
784193323Sed *              GpeNumber       - The event to remove a handler
785193323Sed *              Address         - Address of the handler
786218893Sdim *
787234353Sdim * RETURN:      Status
788193323Sed *
789193323Sed * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
790193323Sed *
791193323Sed ******************************************************************************/
792198090Srdivacky
793193323SedACPI_STATUS
794193323SedAcpiRemoveGpeHandler (
795193323Sed    ACPI_HANDLE             GpeDevice,
796193323Sed    UINT32                  GpeNumber,
797193323Sed    ACPI_EVENT_HANDLER      Address)
798193323Sed{
799193323Sed    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
800193323Sed    ACPI_HANDLER_INFO       *Handler;
801193323Sed    ACPI_STATUS             Status;
802198090Srdivacky    ACPI_CPU_FLAGS          Flags;
803193323Sed
804193323Sed
805193323Sed    ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
806193323Sed
807193323Sed
808193323Sed    /* Parameter validation */
809193323Sed
810198090Srdivacky    if (!Address)
811198090Srdivacky    {
812193323Sed        return_ACPI_STATUS (AE_BAD_PARAMETER);
813203954Srdivacky    }
814234353Sdim
815193323Sed    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
816198090Srdivacky    if (ACPI_FAILURE (Status))
817193323Sed    {
818193323Sed        return_ACPI_STATUS (Status);
819210299Sed    }
820218893Sdim
821234353Sdim    /* Ensure that we have a valid GPE number */
822193323Sed
823193323Sed    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
824193323Sed    if (!GpeEventInfo)
825193323Sed    {
826210299Sed        Status = AE_BAD_PARAMETER;
827218893Sdim        goto UnlockAndExit;
828234353Sdim    }
829193323Sed
830193323Sed    /* Make sure that a handler is indeed installed */
831193323Sed
832193323Sed    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER)
833193323Sed    {
834193323Sed        Status = AE_NOT_EXIST;
835193323Sed        goto UnlockAndExit;
836193323Sed    }
837193323Sed
838193323Sed    /* Make sure that the installed handler is the same */
839193323Sed
840198090Srdivacky    if (GpeEventInfo->Dispatch.Handler->Address != Address)
841226633Sdim    {
842226633Sdim        Status = AE_BAD_PARAMETER;
843226633Sdim        goto UnlockAndExit;
844226633Sdim    }
845198090Srdivacky
846198090Srdivacky    /* Disable the GPE before removing the handler */
847198090Srdivacky
848198090Srdivacky    Status = AcpiEvDisableGpe (GpeEventInfo);
849198090Srdivacky    if (ACPI_FAILURE (Status))
850198090Srdivacky    {
851198090Srdivacky        goto UnlockAndExit;
852198090Srdivacky    }
853198090Srdivacky
854198090Srdivacky    /* Remove the handler */
855198090Srdivacky
856198090Srdivacky    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
857198090Srdivacky    Handler = GpeEventInfo->Dispatch.Handler;
858198090Srdivacky
859198090Srdivacky    /* Restore Method node (if any), set dispatch flags */
860198090Srdivacky
861198090Srdivacky    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
862198090Srdivacky    GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;  /* Clear bits */
863198090Srdivacky    if (Handler->MethodNode)
864198090Srdivacky    {
865198090Srdivacky        GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
866198090Srdivacky    }
867198090Srdivacky    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
868193323Sed
869193323Sed    /* Now we can free the handler object */
870193323Sed
871198090Srdivacky    ACPI_FREE (Handler);
872193323Sed
873193323Sed
874193323SedUnlockAndExit:
875234353Sdim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
876234353Sdim    return_ACPI_STATUS (Status);
877198090Srdivacky}
878234353Sdim
879234353SdimACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
880234353Sdim
881198090Srdivacky
882193323Sed/*******************************************************************************
883193323Sed *
884193323Sed * FUNCTION:    AcpiAcquireGlobalLock
885193323Sed *
886193323Sed * PARAMETERS:  Timeout         - How long the caller is willing to wait
887193323Sed *              Handle          - Where the handle to the lock is returned
888193323Sed *                                (if acquired)
889221345Sdim *
890221345Sdim * RETURN:      Status
891221345Sdim *
892221345Sdim * DESCRIPTION: Acquire the ACPI Global Lock
893221345Sdim *
894221345Sdim * Note: Allows callers with the same thread ID to acquire the global lock
895221345Sdim * multiple times. In other words, externally, the behavior of the global lock
896221345Sdim * is identical to an AML mutex. On the first acquire, a new handle is
897221345Sdim * returned. On any subsequent calls to acquire by the same thread, the same
898221345Sdim * handle is returned.
899221345Sdim *
900221345Sdim ******************************************************************************/
901221345Sdim
902221345SdimACPI_STATUS
903221345SdimAcpiAcquireGlobalLock (
904221345Sdim    UINT16                  Timeout,
905221345Sdim    UINT32                  *Handle)
906221345Sdim{
907221345Sdim    ACPI_STATUS             Status;
908193323Sed
909193323Sed
910193323Sed    if (!Handle)
911193323Sed    {
912193323Sed        return (AE_BAD_PARAMETER);
913193323Sed    }
914193323Sed
915193323Sed    /* Must lock interpreter to prevent race conditions */
916193323Sed
917198090Srdivacky    AcpiExEnterInterpreter ();
918193323Sed
919193323Sed    Status = AcpiExAcquireMutexObject (Timeout,
920193323Sed                AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
921193323Sed
922193323Sed    if (ACPI_SUCCESS (Status))
923193323Sed    {
924193323Sed        /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
925193323Sed
926193323Sed        *Handle = AcpiGbl_GlobalLockHandle;
927193323Sed    }
928193323Sed
929193323Sed    AcpiExExitInterpreter ();
930193323Sed    return (Status);
931193323Sed}
932193323Sed
933193323SedACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
934193323Sed
935193323Sed
936193323Sed/*******************************************************************************
937193323Sed *
938193323Sed * FUNCTION:    AcpiReleaseGlobalLock
939193323Sed *
940193323Sed * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
941193323Sed *
942193323Sed * RETURN:      Status
943193323Sed *
944193323Sed * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
945193323Sed *
946193323Sed ******************************************************************************/
947193323Sed
948193323SedACPI_STATUS
949193323SedAcpiReleaseGlobalLock (
950193323Sed    UINT32                  Handle)
951193323Sed{
952193323Sed    ACPI_STATUS             Status;
953193323Sed
954193323Sed
955193323Sed    if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
956193323Sed    {
957193323Sed        return (AE_NOT_ACQUIRED);
958193323Sed    }
959193323Sed
960193323Sed    Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
961193323Sed    return (Status);
962193323Sed}
963193323Sed
964193323SedACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
965193323Sed
966193323Sed