1433d6423SLionel Sambuc /******************************************************************************
2433d6423SLionel Sambuc *
3433d6423SLionel Sambuc * Module Name: evxface - External interfaces for ACPI events
4433d6423SLionel Sambuc *
5433d6423SLionel Sambuc *****************************************************************************/
6433d6423SLionel Sambuc
7*29492bb7SDavid van Moolenbroek /*
8*29492bb7SDavid van Moolenbroek * Copyright (C) 2000 - 2014, Intel Corp.
9433d6423SLionel Sambuc * All rights reserved.
10433d6423SLionel Sambuc *
11*29492bb7SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
12*29492bb7SDavid van Moolenbroek * modification, are permitted provided that the following conditions
13*29492bb7SDavid van Moolenbroek * are met:
14*29492bb7SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
15*29492bb7SDavid van Moolenbroek * notice, this list of conditions, and the following disclaimer,
16*29492bb7SDavid van Moolenbroek * without modification.
17*29492bb7SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*29492bb7SDavid van Moolenbroek * substantially similar to the "NO WARRANTY" disclaimer below
19*29492bb7SDavid van Moolenbroek * ("Disclaimer") and any redistribution must be conditioned upon
20*29492bb7SDavid van Moolenbroek * including a substantially similar Disclaimer requirement for further
21*29492bb7SDavid van Moolenbroek * binary redistribution.
22*29492bb7SDavid van Moolenbroek * 3. Neither the names of the above-listed copyright holders nor the names
23*29492bb7SDavid van Moolenbroek * of any contributors may be used to endorse or promote products derived
24*29492bb7SDavid van Moolenbroek * from this software without specific prior written permission.
25433d6423SLionel Sambuc *
26*29492bb7SDavid van Moolenbroek * Alternatively, this software may be distributed under the terms of the
27*29492bb7SDavid van Moolenbroek * GNU General Public License ("GPL") version 2 as published by the Free
28*29492bb7SDavid van Moolenbroek * Software Foundation.
29433d6423SLionel Sambuc *
30*29492bb7SDavid van Moolenbroek * NO WARRANTY
31*29492bb7SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*29492bb7SDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*29492bb7SDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*29492bb7SDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*29492bb7SDavid van Moolenbroek * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*29492bb7SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*29492bb7SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*29492bb7SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*29492bb7SDavid van Moolenbroek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*29492bb7SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*29492bb7SDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGES.
42*29492bb7SDavid van Moolenbroek */
43433d6423SLionel Sambuc
44*29492bb7SDavid van Moolenbroek #define EXPORT_ACPI_INTERFACES
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc #include "acpi.h"
47433d6423SLionel Sambuc #include "accommon.h"
48433d6423SLionel Sambuc #include "acnamesp.h"
49433d6423SLionel Sambuc #include "acevents.h"
50433d6423SLionel Sambuc #include "acinterp.h"
51433d6423SLionel Sambuc
52433d6423SLionel Sambuc #define _COMPONENT ACPI_EVENTS
53433d6423SLionel Sambuc ACPI_MODULE_NAME ("evxface")
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc /*******************************************************************************
57433d6423SLionel Sambuc *
58*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiInstallNotifyHandler
59*29492bb7SDavid van Moolenbroek *
60*29492bb7SDavid van Moolenbroek * PARAMETERS: Device - The device for which notifies will be handled
61*29492bb7SDavid van Moolenbroek * HandlerType - The type of handler:
62*29492bb7SDavid van Moolenbroek * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
63*29492bb7SDavid van Moolenbroek * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
64*29492bb7SDavid van Moolenbroek * ACPI_ALL_NOTIFY: Both System and Device
65*29492bb7SDavid van Moolenbroek * Handler - Address of the handler
66*29492bb7SDavid van Moolenbroek * Context - Value passed to the handler on each GPE
67*29492bb7SDavid van Moolenbroek *
68*29492bb7SDavid van Moolenbroek * RETURN: Status
69*29492bb7SDavid van Moolenbroek *
70*29492bb7SDavid van Moolenbroek * DESCRIPTION: Install a handler for notifications on an ACPI Device,
71*29492bb7SDavid van Moolenbroek * ThermalZone, or Processor object.
72*29492bb7SDavid van Moolenbroek *
73*29492bb7SDavid van Moolenbroek * NOTES: The Root namespace object may have only one handler for each
74*29492bb7SDavid van Moolenbroek * type of notify (System/Device). Device/Thermal/Processor objects
75*29492bb7SDavid van Moolenbroek * may have one device notify handler, and multiple system notify
76*29492bb7SDavid van Moolenbroek * handlers.
77*29492bb7SDavid van Moolenbroek *
78*29492bb7SDavid van Moolenbroek ******************************************************************************/
79*29492bb7SDavid van Moolenbroek
80*29492bb7SDavid van Moolenbroek ACPI_STATUS
AcpiInstallNotifyHandler(ACPI_HANDLE Device,UINT32 HandlerType,ACPI_NOTIFY_HANDLER Handler,void * Context)81*29492bb7SDavid van Moolenbroek AcpiInstallNotifyHandler (
82*29492bb7SDavid van Moolenbroek ACPI_HANDLE Device,
83*29492bb7SDavid van Moolenbroek UINT32 HandlerType,
84*29492bb7SDavid van Moolenbroek ACPI_NOTIFY_HANDLER Handler,
85*29492bb7SDavid van Moolenbroek void *Context)
86*29492bb7SDavid van Moolenbroek {
87*29492bb7SDavid van Moolenbroek ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
88*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *ObjDesc;
89*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *HandlerObj;
90*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
91*29492bb7SDavid van Moolenbroek UINT32 i;
92*29492bb7SDavid van Moolenbroek
93*29492bb7SDavid van Moolenbroek
94*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
95*29492bb7SDavid van Moolenbroek
96*29492bb7SDavid van Moolenbroek
97*29492bb7SDavid van Moolenbroek /* Parameter validation */
98*29492bb7SDavid van Moolenbroek
99*29492bb7SDavid van Moolenbroek if ((!Device) || (!Handler) || (!HandlerType) ||
100*29492bb7SDavid van Moolenbroek (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
101*29492bb7SDavid van Moolenbroek {
102*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_BAD_PARAMETER);
103*29492bb7SDavid van Moolenbroek }
104*29492bb7SDavid van Moolenbroek
105*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
106*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
107*29492bb7SDavid van Moolenbroek {
108*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
109*29492bb7SDavid van Moolenbroek }
110*29492bb7SDavid van Moolenbroek
111*29492bb7SDavid van Moolenbroek /*
112*29492bb7SDavid van Moolenbroek * Root Object:
113*29492bb7SDavid van Moolenbroek * Registering a notify handler on the root object indicates that the
114*29492bb7SDavid van Moolenbroek * caller wishes to receive notifications for all objects. Note that
115*29492bb7SDavid van Moolenbroek * only one global handler can be registered per notify type.
116*29492bb7SDavid van Moolenbroek * Ensure that a handler is not already installed.
117*29492bb7SDavid van Moolenbroek */
118*29492bb7SDavid van Moolenbroek if (Device == ACPI_ROOT_OBJECT)
119*29492bb7SDavid van Moolenbroek {
120*29492bb7SDavid van Moolenbroek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
121*29492bb7SDavid van Moolenbroek {
122*29492bb7SDavid van Moolenbroek if (HandlerType & (i+1))
123*29492bb7SDavid van Moolenbroek {
124*29492bb7SDavid van Moolenbroek if (AcpiGbl_GlobalNotify[i].Handler)
125*29492bb7SDavid van Moolenbroek {
126*29492bb7SDavid van Moolenbroek Status = AE_ALREADY_EXISTS;
127*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
128*29492bb7SDavid van Moolenbroek }
129*29492bb7SDavid van Moolenbroek
130*29492bb7SDavid van Moolenbroek AcpiGbl_GlobalNotify[i].Handler = Handler;
131*29492bb7SDavid van Moolenbroek AcpiGbl_GlobalNotify[i].Context = Context;
132*29492bb7SDavid van Moolenbroek }
133*29492bb7SDavid van Moolenbroek }
134*29492bb7SDavid van Moolenbroek
135*29492bb7SDavid van Moolenbroek goto UnlockAndExit; /* Global notify handler installed, all done */
136*29492bb7SDavid van Moolenbroek }
137*29492bb7SDavid van Moolenbroek
138*29492bb7SDavid van Moolenbroek /*
139*29492bb7SDavid van Moolenbroek * All Other Objects:
140*29492bb7SDavid van Moolenbroek * Caller will only receive notifications specific to the target
141*29492bb7SDavid van Moolenbroek * object. Note that only certain object types are allowed to
142*29492bb7SDavid van Moolenbroek * receive notifications.
143*29492bb7SDavid van Moolenbroek */
144*29492bb7SDavid van Moolenbroek
145*29492bb7SDavid van Moolenbroek /* Are Notifies allowed on this object? */
146*29492bb7SDavid van Moolenbroek
147*29492bb7SDavid van Moolenbroek if (!AcpiEvIsNotifyObject (Node))
148*29492bb7SDavid van Moolenbroek {
149*29492bb7SDavid van Moolenbroek Status = AE_TYPE;
150*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
151*29492bb7SDavid van Moolenbroek }
152*29492bb7SDavid van Moolenbroek
153*29492bb7SDavid van Moolenbroek /* Check for an existing internal object, might not exist */
154*29492bb7SDavid van Moolenbroek
155*29492bb7SDavid van Moolenbroek ObjDesc = AcpiNsGetAttachedObject (Node);
156*29492bb7SDavid van Moolenbroek if (!ObjDesc)
157*29492bb7SDavid van Moolenbroek {
158*29492bb7SDavid van Moolenbroek /* Create a new object */
159*29492bb7SDavid van Moolenbroek
160*29492bb7SDavid van Moolenbroek ObjDesc = AcpiUtCreateInternalObject (Node->Type);
161*29492bb7SDavid van Moolenbroek if (!ObjDesc)
162*29492bb7SDavid van Moolenbroek {
163*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
164*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
165*29492bb7SDavid van Moolenbroek }
166*29492bb7SDavid van Moolenbroek
167*29492bb7SDavid van Moolenbroek /* Attach new object to the Node, remove local reference */
168*29492bb7SDavid van Moolenbroek
169*29492bb7SDavid van Moolenbroek Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
170*29492bb7SDavid van Moolenbroek AcpiUtRemoveReference (ObjDesc);
171*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
172*29492bb7SDavid van Moolenbroek {
173*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
174*29492bb7SDavid van Moolenbroek }
175*29492bb7SDavid van Moolenbroek }
176*29492bb7SDavid van Moolenbroek
177*29492bb7SDavid van Moolenbroek /* Ensure that the handler is not already installed in the lists */
178*29492bb7SDavid van Moolenbroek
179*29492bb7SDavid van Moolenbroek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
180*29492bb7SDavid van Moolenbroek {
181*29492bb7SDavid van Moolenbroek if (HandlerType & (i+1))
182*29492bb7SDavid van Moolenbroek {
183*29492bb7SDavid van Moolenbroek HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
184*29492bb7SDavid van Moolenbroek while (HandlerObj)
185*29492bb7SDavid van Moolenbroek {
186*29492bb7SDavid van Moolenbroek if (HandlerObj->Notify.Handler == Handler)
187*29492bb7SDavid van Moolenbroek {
188*29492bb7SDavid van Moolenbroek Status = AE_ALREADY_EXISTS;
189*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
190*29492bb7SDavid van Moolenbroek }
191*29492bb7SDavid van Moolenbroek
192*29492bb7SDavid van Moolenbroek HandlerObj = HandlerObj->Notify.Next[i];
193*29492bb7SDavid van Moolenbroek }
194*29492bb7SDavid van Moolenbroek }
195*29492bb7SDavid van Moolenbroek }
196*29492bb7SDavid van Moolenbroek
197*29492bb7SDavid van Moolenbroek /* Create and populate a new notify handler object */
198*29492bb7SDavid van Moolenbroek
199*29492bb7SDavid van Moolenbroek HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
200*29492bb7SDavid van Moolenbroek if (!HandlerObj)
201*29492bb7SDavid van Moolenbroek {
202*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
203*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
204*29492bb7SDavid van Moolenbroek }
205*29492bb7SDavid van Moolenbroek
206*29492bb7SDavid van Moolenbroek HandlerObj->Notify.Node = Node;
207*29492bb7SDavid van Moolenbroek HandlerObj->Notify.HandlerType = HandlerType;
208*29492bb7SDavid van Moolenbroek HandlerObj->Notify.Handler = Handler;
209*29492bb7SDavid van Moolenbroek HandlerObj->Notify.Context = Context;
210*29492bb7SDavid van Moolenbroek
211*29492bb7SDavid van Moolenbroek /* Install the handler at the list head(s) */
212*29492bb7SDavid van Moolenbroek
213*29492bb7SDavid van Moolenbroek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
214*29492bb7SDavid van Moolenbroek {
215*29492bb7SDavid van Moolenbroek if (HandlerType & (i+1))
216*29492bb7SDavid van Moolenbroek {
217*29492bb7SDavid van Moolenbroek HandlerObj->Notify.Next[i] =
218*29492bb7SDavid van Moolenbroek ObjDesc->CommonNotify.NotifyList[i];
219*29492bb7SDavid van Moolenbroek
220*29492bb7SDavid van Moolenbroek ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
221*29492bb7SDavid van Moolenbroek }
222*29492bb7SDavid van Moolenbroek }
223*29492bb7SDavid van Moolenbroek
224*29492bb7SDavid van Moolenbroek /* Add an extra reference if handler was installed in both lists */
225*29492bb7SDavid van Moolenbroek
226*29492bb7SDavid van Moolenbroek if (HandlerType == ACPI_ALL_NOTIFY)
227*29492bb7SDavid van Moolenbroek {
228*29492bb7SDavid van Moolenbroek AcpiUtAddReference (HandlerObj);
229*29492bb7SDavid van Moolenbroek }
230*29492bb7SDavid van Moolenbroek
231*29492bb7SDavid van Moolenbroek
232*29492bb7SDavid van Moolenbroek UnlockAndExit:
233*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
234*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
235*29492bb7SDavid van Moolenbroek }
236*29492bb7SDavid van Moolenbroek
ACPI_EXPORT_SYMBOL(AcpiInstallNotifyHandler)237*29492bb7SDavid van Moolenbroek ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
238*29492bb7SDavid van Moolenbroek
239*29492bb7SDavid van Moolenbroek
240*29492bb7SDavid van Moolenbroek /*******************************************************************************
241*29492bb7SDavid van Moolenbroek *
242*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiRemoveNotifyHandler
243*29492bb7SDavid van Moolenbroek *
244*29492bb7SDavid van Moolenbroek * PARAMETERS: Device - The device for which the handler is installed
245*29492bb7SDavid van Moolenbroek * HandlerType - The type of handler:
246*29492bb7SDavid van Moolenbroek * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
247*29492bb7SDavid van Moolenbroek * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
248*29492bb7SDavid van Moolenbroek * ACPI_ALL_NOTIFY: Both System and Device
249*29492bb7SDavid van Moolenbroek * Handler - Address of the handler
250*29492bb7SDavid van Moolenbroek *
251*29492bb7SDavid van Moolenbroek * RETURN: Status
252*29492bb7SDavid van Moolenbroek *
253*29492bb7SDavid van Moolenbroek * DESCRIPTION: Remove a handler for notifies on an ACPI device
254*29492bb7SDavid van Moolenbroek *
255*29492bb7SDavid van Moolenbroek ******************************************************************************/
256*29492bb7SDavid van Moolenbroek
257*29492bb7SDavid van Moolenbroek ACPI_STATUS
258*29492bb7SDavid van Moolenbroek AcpiRemoveNotifyHandler (
259*29492bb7SDavid van Moolenbroek ACPI_HANDLE Device,
260*29492bb7SDavid van Moolenbroek UINT32 HandlerType,
261*29492bb7SDavid van Moolenbroek ACPI_NOTIFY_HANDLER Handler)
262*29492bb7SDavid van Moolenbroek {
263*29492bb7SDavid van Moolenbroek ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
264*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *ObjDesc;
265*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *HandlerObj;
266*29492bb7SDavid van Moolenbroek ACPI_OPERAND_OBJECT *PreviousHandlerObj;
267*29492bb7SDavid van Moolenbroek ACPI_STATUS Status = AE_OK;
268*29492bb7SDavid van Moolenbroek UINT32 i;
269*29492bb7SDavid van Moolenbroek
270*29492bb7SDavid van Moolenbroek
271*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
272*29492bb7SDavid van Moolenbroek
273*29492bb7SDavid van Moolenbroek
274*29492bb7SDavid van Moolenbroek /* Parameter validation */
275*29492bb7SDavid van Moolenbroek
276*29492bb7SDavid van Moolenbroek if ((!Device) || (!Handler) || (!HandlerType) ||
277*29492bb7SDavid van Moolenbroek (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
278*29492bb7SDavid van Moolenbroek {
279*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_BAD_PARAMETER);
280*29492bb7SDavid van Moolenbroek }
281*29492bb7SDavid van Moolenbroek
282*29492bb7SDavid van Moolenbroek /* Root Object. Global handlers are removed here */
283*29492bb7SDavid van Moolenbroek
284*29492bb7SDavid van Moolenbroek if (Device == ACPI_ROOT_OBJECT)
285*29492bb7SDavid van Moolenbroek {
286*29492bb7SDavid van Moolenbroek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
287*29492bb7SDavid van Moolenbroek {
288*29492bb7SDavid van Moolenbroek if (HandlerType & (i+1))
289*29492bb7SDavid van Moolenbroek {
290*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
291*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
292*29492bb7SDavid van Moolenbroek {
293*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
294*29492bb7SDavid van Moolenbroek }
295*29492bb7SDavid van Moolenbroek
296*29492bb7SDavid van Moolenbroek if (!AcpiGbl_GlobalNotify[i].Handler ||
297*29492bb7SDavid van Moolenbroek (AcpiGbl_GlobalNotify[i].Handler != Handler))
298*29492bb7SDavid van Moolenbroek {
299*29492bb7SDavid van Moolenbroek Status = AE_NOT_EXIST;
300*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
301*29492bb7SDavid van Moolenbroek }
302*29492bb7SDavid van Moolenbroek
303*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
304*29492bb7SDavid van Moolenbroek "Removing global notify handler\n"));
305*29492bb7SDavid van Moolenbroek
306*29492bb7SDavid van Moolenbroek AcpiGbl_GlobalNotify[i].Handler = NULL;
307*29492bb7SDavid van Moolenbroek AcpiGbl_GlobalNotify[i].Context = NULL;
308*29492bb7SDavid van Moolenbroek
309*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
310*29492bb7SDavid van Moolenbroek
311*29492bb7SDavid van Moolenbroek /* Make sure all deferred notify tasks are completed */
312*29492bb7SDavid van Moolenbroek
313*29492bb7SDavid van Moolenbroek AcpiOsWaitEventsComplete ();
314*29492bb7SDavid van Moolenbroek }
315*29492bb7SDavid van Moolenbroek }
316*29492bb7SDavid van Moolenbroek
317*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_OK);
318*29492bb7SDavid van Moolenbroek }
319*29492bb7SDavid van Moolenbroek
320*29492bb7SDavid van Moolenbroek /* All other objects: Are Notifies allowed on this object? */
321*29492bb7SDavid van Moolenbroek
322*29492bb7SDavid van Moolenbroek if (!AcpiEvIsNotifyObject (Node))
323*29492bb7SDavid van Moolenbroek {
324*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_TYPE);
325*29492bb7SDavid van Moolenbroek }
326*29492bb7SDavid van Moolenbroek
327*29492bb7SDavid van Moolenbroek /* Must have an existing internal object */
328*29492bb7SDavid van Moolenbroek
329*29492bb7SDavid van Moolenbroek ObjDesc = AcpiNsGetAttachedObject (Node);
330*29492bb7SDavid van Moolenbroek if (!ObjDesc)
331*29492bb7SDavid van Moolenbroek {
332*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_NOT_EXIST);
333*29492bb7SDavid van Moolenbroek }
334*29492bb7SDavid van Moolenbroek
335*29492bb7SDavid van Moolenbroek /* Internal object exists. Find the handler and remove it */
336*29492bb7SDavid van Moolenbroek
337*29492bb7SDavid van Moolenbroek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
338*29492bb7SDavid van Moolenbroek {
339*29492bb7SDavid van Moolenbroek if (HandlerType & (i+1))
340*29492bb7SDavid van Moolenbroek {
341*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
342*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
343*29492bb7SDavid van Moolenbroek {
344*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
345*29492bb7SDavid van Moolenbroek }
346*29492bb7SDavid van Moolenbroek
347*29492bb7SDavid van Moolenbroek HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
348*29492bb7SDavid van Moolenbroek PreviousHandlerObj = NULL;
349*29492bb7SDavid van Moolenbroek
350*29492bb7SDavid van Moolenbroek /* Attempt to find the handler in the handler list */
351*29492bb7SDavid van Moolenbroek
352*29492bb7SDavid van Moolenbroek while (HandlerObj &&
353*29492bb7SDavid van Moolenbroek (HandlerObj->Notify.Handler != Handler))
354*29492bb7SDavid van Moolenbroek {
355*29492bb7SDavid van Moolenbroek PreviousHandlerObj = HandlerObj;
356*29492bb7SDavid van Moolenbroek HandlerObj = HandlerObj->Notify.Next[i];
357*29492bb7SDavid van Moolenbroek }
358*29492bb7SDavid van Moolenbroek
359*29492bb7SDavid van Moolenbroek if (!HandlerObj)
360*29492bb7SDavid van Moolenbroek {
361*29492bb7SDavid van Moolenbroek Status = AE_NOT_EXIST;
362*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
363*29492bb7SDavid van Moolenbroek }
364*29492bb7SDavid van Moolenbroek
365*29492bb7SDavid van Moolenbroek /* Remove the handler object from the list */
366*29492bb7SDavid van Moolenbroek
367*29492bb7SDavid van Moolenbroek if (PreviousHandlerObj) /* Handler is not at the list head */
368*29492bb7SDavid van Moolenbroek {
369*29492bb7SDavid van Moolenbroek PreviousHandlerObj->Notify.Next[i] =
370*29492bb7SDavid van Moolenbroek HandlerObj->Notify.Next[i];
371*29492bb7SDavid van Moolenbroek }
372*29492bb7SDavid van Moolenbroek else /* Handler is at the list head */
373*29492bb7SDavid van Moolenbroek {
374*29492bb7SDavid van Moolenbroek ObjDesc->CommonNotify.NotifyList[i] =
375*29492bb7SDavid van Moolenbroek HandlerObj->Notify.Next[i];
376*29492bb7SDavid van Moolenbroek }
377*29492bb7SDavid van Moolenbroek
378*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
379*29492bb7SDavid van Moolenbroek
380*29492bb7SDavid van Moolenbroek /* Make sure all deferred notify tasks are completed */
381*29492bb7SDavid van Moolenbroek
382*29492bb7SDavid van Moolenbroek AcpiOsWaitEventsComplete ();
383*29492bb7SDavid van Moolenbroek AcpiUtRemoveReference (HandlerObj);
384*29492bb7SDavid van Moolenbroek }
385*29492bb7SDavid van Moolenbroek }
386*29492bb7SDavid van Moolenbroek
387*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
388*29492bb7SDavid van Moolenbroek
389*29492bb7SDavid van Moolenbroek
390*29492bb7SDavid van Moolenbroek UnlockAndExit:
391*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
392*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
393*29492bb7SDavid van Moolenbroek }
394*29492bb7SDavid van Moolenbroek
ACPI_EXPORT_SYMBOL(AcpiRemoveNotifyHandler)395*29492bb7SDavid van Moolenbroek ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
396*29492bb7SDavid van Moolenbroek
397*29492bb7SDavid van Moolenbroek
398*29492bb7SDavid van Moolenbroek /*******************************************************************************
399*29492bb7SDavid van Moolenbroek *
400433d6423SLionel Sambuc * FUNCTION: AcpiInstallExceptionHandler
401433d6423SLionel Sambuc *
402433d6423SLionel Sambuc * PARAMETERS: Handler - Pointer to the handler function for the
403433d6423SLionel Sambuc * event
404433d6423SLionel Sambuc *
405433d6423SLionel Sambuc * RETURN: Status
406433d6423SLionel Sambuc *
407433d6423SLionel Sambuc * DESCRIPTION: Saves the pointer to the handler function
408433d6423SLionel Sambuc *
409433d6423SLionel Sambuc ******************************************************************************/
410433d6423SLionel Sambuc
411433d6423SLionel Sambuc ACPI_STATUS
412433d6423SLionel Sambuc AcpiInstallExceptionHandler (
413433d6423SLionel Sambuc ACPI_EXCEPTION_HANDLER Handler)
414433d6423SLionel Sambuc {
415433d6423SLionel Sambuc ACPI_STATUS Status;
416433d6423SLionel Sambuc
417433d6423SLionel Sambuc
418433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
419433d6423SLionel Sambuc
420433d6423SLionel Sambuc
421433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
422433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
423433d6423SLionel Sambuc {
424433d6423SLionel Sambuc return_ACPI_STATUS (Status);
425433d6423SLionel Sambuc }
426433d6423SLionel Sambuc
427433d6423SLionel Sambuc /* Don't allow two handlers. */
428433d6423SLionel Sambuc
429433d6423SLionel Sambuc if (AcpiGbl_ExceptionHandler)
430433d6423SLionel Sambuc {
431433d6423SLionel Sambuc Status = AE_ALREADY_EXISTS;
432433d6423SLionel Sambuc goto Cleanup;
433433d6423SLionel Sambuc }
434433d6423SLionel Sambuc
435433d6423SLionel Sambuc /* Install the handler */
436433d6423SLionel Sambuc
437433d6423SLionel Sambuc AcpiGbl_ExceptionHandler = Handler;
438433d6423SLionel Sambuc
439433d6423SLionel Sambuc Cleanup:
440433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
441433d6423SLionel Sambuc return_ACPI_STATUS (Status);
442433d6423SLionel Sambuc }
443433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiInstallExceptionHandler)444433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
445433d6423SLionel Sambuc
446433d6423SLionel Sambuc
447*29492bb7SDavid van Moolenbroek #if (!ACPI_REDUCED_HARDWARE)
448*29492bb7SDavid van Moolenbroek /*******************************************************************************
449*29492bb7SDavid van Moolenbroek *
450*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiInstallSciHandler
451*29492bb7SDavid van Moolenbroek *
452*29492bb7SDavid van Moolenbroek * PARAMETERS: Address - Address of the handler
453*29492bb7SDavid van Moolenbroek * Context - Value passed to the handler on each SCI
454*29492bb7SDavid van Moolenbroek *
455*29492bb7SDavid van Moolenbroek * RETURN: Status
456*29492bb7SDavid van Moolenbroek *
457*29492bb7SDavid van Moolenbroek * DESCRIPTION: Install a handler for a System Control Interrupt.
458*29492bb7SDavid van Moolenbroek *
459*29492bb7SDavid van Moolenbroek ******************************************************************************/
460*29492bb7SDavid van Moolenbroek
461*29492bb7SDavid van Moolenbroek ACPI_STATUS
462*29492bb7SDavid van Moolenbroek AcpiInstallSciHandler (
463*29492bb7SDavid van Moolenbroek ACPI_SCI_HANDLER Address,
464*29492bb7SDavid van Moolenbroek void *Context)
465*29492bb7SDavid van Moolenbroek {
466*29492bb7SDavid van Moolenbroek ACPI_SCI_HANDLER_INFO *NewSciHandler;
467*29492bb7SDavid van Moolenbroek ACPI_SCI_HANDLER_INFO *SciHandler;
468*29492bb7SDavid van Moolenbroek ACPI_CPU_FLAGS Flags;
469*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
470*29492bb7SDavid van Moolenbroek
471*29492bb7SDavid van Moolenbroek
472*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
473*29492bb7SDavid van Moolenbroek
474*29492bb7SDavid van Moolenbroek
475*29492bb7SDavid van Moolenbroek if (!Address)
476*29492bb7SDavid van Moolenbroek {
477*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_BAD_PARAMETER);
478*29492bb7SDavid van Moolenbroek }
479*29492bb7SDavid van Moolenbroek
480*29492bb7SDavid van Moolenbroek /* Allocate and init a handler object */
481*29492bb7SDavid van Moolenbroek
482*29492bb7SDavid van Moolenbroek NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
483*29492bb7SDavid van Moolenbroek if (!NewSciHandler)
484*29492bb7SDavid van Moolenbroek {
485*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_NO_MEMORY);
486*29492bb7SDavid van Moolenbroek }
487*29492bb7SDavid van Moolenbroek
488*29492bb7SDavid van Moolenbroek NewSciHandler->Address = Address;
489*29492bb7SDavid van Moolenbroek NewSciHandler->Context = Context;
490*29492bb7SDavid van Moolenbroek
491*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
492*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
493*29492bb7SDavid van Moolenbroek {
494*29492bb7SDavid van Moolenbroek goto Exit;
495*29492bb7SDavid van Moolenbroek }
496*29492bb7SDavid van Moolenbroek
497*29492bb7SDavid van Moolenbroek /* Lock list during installation */
498*29492bb7SDavid van Moolenbroek
499*29492bb7SDavid van Moolenbroek Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
500*29492bb7SDavid van Moolenbroek SciHandler = AcpiGbl_SciHandlerList;
501*29492bb7SDavid van Moolenbroek
502*29492bb7SDavid van Moolenbroek /* Ensure handler does not already exist */
503*29492bb7SDavid van Moolenbroek
504*29492bb7SDavid van Moolenbroek while (SciHandler)
505*29492bb7SDavid van Moolenbroek {
506*29492bb7SDavid van Moolenbroek if (Address == SciHandler->Address)
507*29492bb7SDavid van Moolenbroek {
508*29492bb7SDavid van Moolenbroek Status = AE_ALREADY_EXISTS;
509*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
510*29492bb7SDavid van Moolenbroek }
511*29492bb7SDavid van Moolenbroek
512*29492bb7SDavid van Moolenbroek SciHandler = SciHandler->Next;
513*29492bb7SDavid van Moolenbroek }
514*29492bb7SDavid van Moolenbroek
515*29492bb7SDavid van Moolenbroek /* Install the new handler into the global list (at head) */
516*29492bb7SDavid van Moolenbroek
517*29492bb7SDavid van Moolenbroek NewSciHandler->Next = AcpiGbl_SciHandlerList;
518*29492bb7SDavid van Moolenbroek AcpiGbl_SciHandlerList = NewSciHandler;
519*29492bb7SDavid van Moolenbroek
520*29492bb7SDavid van Moolenbroek
521*29492bb7SDavid van Moolenbroek UnlockAndExit:
522*29492bb7SDavid van Moolenbroek
523*29492bb7SDavid van Moolenbroek AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
524*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
525*29492bb7SDavid van Moolenbroek
526*29492bb7SDavid van Moolenbroek Exit:
527*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
528*29492bb7SDavid van Moolenbroek {
529*29492bb7SDavid van Moolenbroek ACPI_FREE (NewSciHandler);
530*29492bb7SDavid van Moolenbroek }
531*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
532*29492bb7SDavid van Moolenbroek }
533*29492bb7SDavid van Moolenbroek
ACPI_EXPORT_SYMBOL(AcpiInstallSciHandler)534*29492bb7SDavid van Moolenbroek ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
535*29492bb7SDavid van Moolenbroek
536*29492bb7SDavid van Moolenbroek
537*29492bb7SDavid van Moolenbroek /*******************************************************************************
538*29492bb7SDavid van Moolenbroek *
539*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiRemoveSciHandler
540*29492bb7SDavid van Moolenbroek *
541*29492bb7SDavid van Moolenbroek * PARAMETERS: Address - Address of the handler
542*29492bb7SDavid van Moolenbroek *
543*29492bb7SDavid van Moolenbroek * RETURN: Status
544*29492bb7SDavid van Moolenbroek *
545*29492bb7SDavid van Moolenbroek * DESCRIPTION: Remove a handler for a System Control Interrupt.
546*29492bb7SDavid van Moolenbroek *
547*29492bb7SDavid van Moolenbroek ******************************************************************************/
548*29492bb7SDavid van Moolenbroek
549*29492bb7SDavid van Moolenbroek ACPI_STATUS
550*29492bb7SDavid van Moolenbroek AcpiRemoveSciHandler (
551*29492bb7SDavid van Moolenbroek ACPI_SCI_HANDLER Address)
552*29492bb7SDavid van Moolenbroek {
553*29492bb7SDavid van Moolenbroek ACPI_SCI_HANDLER_INFO *PrevSciHandler;
554*29492bb7SDavid van Moolenbroek ACPI_SCI_HANDLER_INFO *NextSciHandler;
555*29492bb7SDavid van Moolenbroek ACPI_CPU_FLAGS Flags;
556*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
557*29492bb7SDavid van Moolenbroek
558*29492bb7SDavid van Moolenbroek
559*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
560*29492bb7SDavid van Moolenbroek
561*29492bb7SDavid van Moolenbroek
562*29492bb7SDavid van Moolenbroek if (!Address)
563*29492bb7SDavid van Moolenbroek {
564*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_BAD_PARAMETER);
565*29492bb7SDavid van Moolenbroek }
566*29492bb7SDavid van Moolenbroek
567*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
568*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
569*29492bb7SDavid van Moolenbroek {
570*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
571*29492bb7SDavid van Moolenbroek }
572*29492bb7SDavid van Moolenbroek
573*29492bb7SDavid van Moolenbroek /* Remove the SCI handler with lock */
574*29492bb7SDavid van Moolenbroek
575*29492bb7SDavid van Moolenbroek Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
576*29492bb7SDavid van Moolenbroek
577*29492bb7SDavid van Moolenbroek PrevSciHandler = NULL;
578*29492bb7SDavid van Moolenbroek NextSciHandler = AcpiGbl_SciHandlerList;
579*29492bb7SDavid van Moolenbroek while (NextSciHandler)
580*29492bb7SDavid van Moolenbroek {
581*29492bb7SDavid van Moolenbroek if (NextSciHandler->Address == Address)
582*29492bb7SDavid van Moolenbroek {
583*29492bb7SDavid van Moolenbroek /* Unlink and free the SCI handler info block */
584*29492bb7SDavid van Moolenbroek
585*29492bb7SDavid van Moolenbroek if (PrevSciHandler)
586*29492bb7SDavid van Moolenbroek {
587*29492bb7SDavid van Moolenbroek PrevSciHandler->Next = NextSciHandler->Next;
588*29492bb7SDavid van Moolenbroek }
589*29492bb7SDavid van Moolenbroek else
590*29492bb7SDavid van Moolenbroek {
591*29492bb7SDavid van Moolenbroek AcpiGbl_SciHandlerList = NextSciHandler->Next;
592*29492bb7SDavid van Moolenbroek }
593*29492bb7SDavid van Moolenbroek
594*29492bb7SDavid van Moolenbroek AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
595*29492bb7SDavid van Moolenbroek ACPI_FREE (NextSciHandler);
596*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
597*29492bb7SDavid van Moolenbroek }
598*29492bb7SDavid van Moolenbroek
599*29492bb7SDavid van Moolenbroek PrevSciHandler = NextSciHandler;
600*29492bb7SDavid van Moolenbroek NextSciHandler = NextSciHandler->Next;
601*29492bb7SDavid van Moolenbroek }
602*29492bb7SDavid van Moolenbroek
603*29492bb7SDavid van Moolenbroek AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
604*29492bb7SDavid van Moolenbroek Status = AE_NOT_EXIST;
605*29492bb7SDavid van Moolenbroek
606*29492bb7SDavid van Moolenbroek
607*29492bb7SDavid van Moolenbroek UnlockAndExit:
608*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
609*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
610*29492bb7SDavid van Moolenbroek }
611*29492bb7SDavid van Moolenbroek
ACPI_EXPORT_SYMBOL(AcpiRemoveSciHandler)612*29492bb7SDavid van Moolenbroek ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
613*29492bb7SDavid van Moolenbroek
614*29492bb7SDavid van Moolenbroek
615*29492bb7SDavid van Moolenbroek /*******************************************************************************
616*29492bb7SDavid van Moolenbroek *
617*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiInstallGlobalEventHandler
618*29492bb7SDavid van Moolenbroek *
619*29492bb7SDavid van Moolenbroek * PARAMETERS: Handler - Pointer to the global event handler function
620*29492bb7SDavid van Moolenbroek * Context - Value passed to the handler on each event
621*29492bb7SDavid van Moolenbroek *
622*29492bb7SDavid van Moolenbroek * RETURN: Status
623*29492bb7SDavid van Moolenbroek *
624*29492bb7SDavid van Moolenbroek * DESCRIPTION: Saves the pointer to the handler function. The global handler
625*29492bb7SDavid van Moolenbroek * is invoked upon each incoming GPE and Fixed Event. It is
626*29492bb7SDavid van Moolenbroek * invoked at interrupt level at the time of the event dispatch.
627*29492bb7SDavid van Moolenbroek * Can be used to update event counters, etc.
628*29492bb7SDavid van Moolenbroek *
629*29492bb7SDavid van Moolenbroek ******************************************************************************/
630*29492bb7SDavid van Moolenbroek
631*29492bb7SDavid van Moolenbroek ACPI_STATUS
632*29492bb7SDavid van Moolenbroek AcpiInstallGlobalEventHandler (
633*29492bb7SDavid van Moolenbroek ACPI_GBL_EVENT_HANDLER Handler,
634*29492bb7SDavid van Moolenbroek void *Context)
635*29492bb7SDavid van Moolenbroek {
636*29492bb7SDavid van Moolenbroek ACPI_STATUS Status;
637*29492bb7SDavid van Moolenbroek
638*29492bb7SDavid van Moolenbroek
639*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
640*29492bb7SDavid van Moolenbroek
641*29492bb7SDavid van Moolenbroek
642*29492bb7SDavid van Moolenbroek /* Parameter validation */
643*29492bb7SDavid van Moolenbroek
644*29492bb7SDavid van Moolenbroek if (!Handler)
645*29492bb7SDavid van Moolenbroek {
646*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (AE_BAD_PARAMETER);
647*29492bb7SDavid van Moolenbroek }
648*29492bb7SDavid van Moolenbroek
649*29492bb7SDavid van Moolenbroek Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
650*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
651*29492bb7SDavid van Moolenbroek {
652*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
653*29492bb7SDavid van Moolenbroek }
654*29492bb7SDavid van Moolenbroek
655*29492bb7SDavid van Moolenbroek /* Don't allow two handlers. */
656*29492bb7SDavid van Moolenbroek
657*29492bb7SDavid van Moolenbroek if (AcpiGbl_GlobalEventHandler)
658*29492bb7SDavid van Moolenbroek {
659*29492bb7SDavid van Moolenbroek Status = AE_ALREADY_EXISTS;
660*29492bb7SDavid van Moolenbroek goto Cleanup;
661*29492bb7SDavid van Moolenbroek }
662*29492bb7SDavid van Moolenbroek
663*29492bb7SDavid van Moolenbroek AcpiGbl_GlobalEventHandler = Handler;
664*29492bb7SDavid van Moolenbroek AcpiGbl_GlobalEventHandlerContext = Context;
665*29492bb7SDavid van Moolenbroek
666*29492bb7SDavid van Moolenbroek
667*29492bb7SDavid van Moolenbroek Cleanup:
668*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
669*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
670*29492bb7SDavid van Moolenbroek }
671*29492bb7SDavid van Moolenbroek
ACPI_EXPORT_SYMBOL(AcpiInstallGlobalEventHandler)672*29492bb7SDavid van Moolenbroek ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
673*29492bb7SDavid van Moolenbroek
674*29492bb7SDavid van Moolenbroek
675433d6423SLionel Sambuc /*******************************************************************************
676433d6423SLionel Sambuc *
677433d6423SLionel Sambuc * FUNCTION: AcpiInstallFixedEventHandler
678433d6423SLionel Sambuc *
679433d6423SLionel Sambuc * PARAMETERS: Event - Event type to enable.
680433d6423SLionel Sambuc * Handler - Pointer to the handler function for the
681433d6423SLionel Sambuc * event
682433d6423SLionel Sambuc * Context - Value passed to the handler on each GPE
683433d6423SLionel Sambuc *
684433d6423SLionel Sambuc * RETURN: Status
685433d6423SLionel Sambuc *
686433d6423SLionel Sambuc * DESCRIPTION: Saves the pointer to the handler function and then enables the
687433d6423SLionel Sambuc * event.
688433d6423SLionel Sambuc *
689433d6423SLionel Sambuc ******************************************************************************/
690433d6423SLionel Sambuc
691433d6423SLionel Sambuc ACPI_STATUS
692433d6423SLionel Sambuc AcpiInstallFixedEventHandler (
693433d6423SLionel Sambuc UINT32 Event,
694433d6423SLionel Sambuc ACPI_EVENT_HANDLER Handler,
695433d6423SLionel Sambuc void *Context)
696433d6423SLionel Sambuc {
697433d6423SLionel Sambuc ACPI_STATUS Status;
698433d6423SLionel Sambuc
699433d6423SLionel Sambuc
700433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
701433d6423SLionel Sambuc
702433d6423SLionel Sambuc
703433d6423SLionel Sambuc /* Parameter validation */
704433d6423SLionel Sambuc
705433d6423SLionel Sambuc if (Event > ACPI_EVENT_MAX)
706433d6423SLionel Sambuc {
707433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
708433d6423SLionel Sambuc }
709433d6423SLionel Sambuc
710433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
711433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
712433d6423SLionel Sambuc {
713433d6423SLionel Sambuc return_ACPI_STATUS (Status);
714433d6423SLionel Sambuc }
715433d6423SLionel Sambuc
716*29492bb7SDavid van Moolenbroek /* Do not allow multiple handlers */
717433d6423SLionel Sambuc
718*29492bb7SDavid van Moolenbroek if (AcpiGbl_FixedEventHandlers[Event].Handler)
719433d6423SLionel Sambuc {
720433d6423SLionel Sambuc Status = AE_ALREADY_EXISTS;
721433d6423SLionel Sambuc goto Cleanup;
722433d6423SLionel Sambuc }
723433d6423SLionel Sambuc
724433d6423SLionel Sambuc /* Install the handler before enabling the event */
725433d6423SLionel Sambuc
726433d6423SLionel Sambuc AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
727433d6423SLionel Sambuc AcpiGbl_FixedEventHandlers[Event].Context = Context;
728433d6423SLionel Sambuc
729433d6423SLionel Sambuc Status = AcpiEnableEvent (Event, 0);
730433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
731433d6423SLionel Sambuc {
732*29492bb7SDavid van Moolenbroek ACPI_WARNING ((AE_INFO,
733*29492bb7SDavid van Moolenbroek "Could not enable fixed event - %s (%u)",
734*29492bb7SDavid van Moolenbroek AcpiUtGetEventName (Event), Event));
735433d6423SLionel Sambuc
736433d6423SLionel Sambuc /* Remove the handler */
737433d6423SLionel Sambuc
738433d6423SLionel Sambuc AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
739433d6423SLionel Sambuc AcpiGbl_FixedEventHandlers[Event].Context = NULL;
740433d6423SLionel Sambuc }
741433d6423SLionel Sambuc else
742433d6423SLionel Sambuc {
743433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
744*29492bb7SDavid van Moolenbroek "Enabled fixed event %s (%X), Handler=%p\n",
745*29492bb7SDavid van Moolenbroek AcpiUtGetEventName (Event), Event, Handler));
746433d6423SLionel Sambuc }
747433d6423SLionel Sambuc
748433d6423SLionel Sambuc
749433d6423SLionel Sambuc Cleanup:
750433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
751433d6423SLionel Sambuc return_ACPI_STATUS (Status);
752433d6423SLionel Sambuc }
753433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiInstallFixedEventHandler)754433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
755433d6423SLionel Sambuc
756433d6423SLionel Sambuc
757433d6423SLionel Sambuc /*******************************************************************************
758433d6423SLionel Sambuc *
759433d6423SLionel Sambuc * FUNCTION: AcpiRemoveFixedEventHandler
760433d6423SLionel Sambuc *
761433d6423SLionel Sambuc * PARAMETERS: Event - Event type to disable.
762433d6423SLionel Sambuc * Handler - Address of the handler
763433d6423SLionel Sambuc *
764433d6423SLionel Sambuc * RETURN: Status
765433d6423SLionel Sambuc *
766433d6423SLionel Sambuc * DESCRIPTION: Disables the event and unregisters the event handler.
767433d6423SLionel Sambuc *
768433d6423SLionel Sambuc ******************************************************************************/
769433d6423SLionel Sambuc
770433d6423SLionel Sambuc ACPI_STATUS
771433d6423SLionel Sambuc AcpiRemoveFixedEventHandler (
772433d6423SLionel Sambuc UINT32 Event,
773433d6423SLionel Sambuc ACPI_EVENT_HANDLER Handler)
774433d6423SLionel Sambuc {
775433d6423SLionel Sambuc ACPI_STATUS Status = AE_OK;
776433d6423SLionel Sambuc
777433d6423SLionel Sambuc
778433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
779433d6423SLionel Sambuc
780433d6423SLionel Sambuc
781433d6423SLionel Sambuc /* Parameter validation */
782433d6423SLionel Sambuc
783433d6423SLionel Sambuc if (Event > ACPI_EVENT_MAX)
784433d6423SLionel Sambuc {
785433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
786433d6423SLionel Sambuc }
787433d6423SLionel Sambuc
788433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
789433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
790433d6423SLionel Sambuc {
791433d6423SLionel Sambuc return_ACPI_STATUS (Status);
792433d6423SLionel Sambuc }
793433d6423SLionel Sambuc
794433d6423SLionel Sambuc /* Disable the event before removing the handler */
795433d6423SLionel Sambuc
796433d6423SLionel Sambuc Status = AcpiDisableEvent (Event, 0);
797433d6423SLionel Sambuc
798433d6423SLionel Sambuc /* Always Remove the handler */
799433d6423SLionel Sambuc
800433d6423SLionel Sambuc AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
801433d6423SLionel Sambuc AcpiGbl_FixedEventHandlers[Event].Context = NULL;
802433d6423SLionel Sambuc
803433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
804433d6423SLionel Sambuc {
805433d6423SLionel Sambuc ACPI_WARNING ((AE_INFO,
806*29492bb7SDavid van Moolenbroek "Could not disable fixed event - %s (%u)",
807*29492bb7SDavid van Moolenbroek AcpiUtGetEventName (Event), Event));
808433d6423SLionel Sambuc }
809433d6423SLionel Sambuc else
810433d6423SLionel Sambuc {
811*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
812*29492bb7SDavid van Moolenbroek "Disabled fixed event - %s (%X)\n",
813*29492bb7SDavid van Moolenbroek AcpiUtGetEventName (Event), Event));
814433d6423SLionel Sambuc }
815433d6423SLionel Sambuc
816433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
817433d6423SLionel Sambuc return_ACPI_STATUS (Status);
818433d6423SLionel Sambuc }
819433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiRemoveFixedEventHandler)820433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
821433d6423SLionel Sambuc
822433d6423SLionel Sambuc
823433d6423SLionel Sambuc /*******************************************************************************
824433d6423SLionel Sambuc *
825433d6423SLionel Sambuc * FUNCTION: AcpiInstallGpeHandler
826433d6423SLionel Sambuc *
827433d6423SLionel Sambuc * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
828433d6423SLionel Sambuc * defined GPEs)
829433d6423SLionel Sambuc * GpeNumber - The GPE number within the GPE block
830433d6423SLionel Sambuc * Type - Whether this GPE should be treated as an
831433d6423SLionel Sambuc * edge- or level-triggered interrupt.
832433d6423SLionel Sambuc * Address - Address of the handler
833433d6423SLionel Sambuc * Context - Value passed to the handler on each GPE
834433d6423SLionel Sambuc *
835433d6423SLionel Sambuc * RETURN: Status
836433d6423SLionel Sambuc *
837433d6423SLionel Sambuc * DESCRIPTION: Install a handler for a General Purpose Event.
838433d6423SLionel Sambuc *
839433d6423SLionel Sambuc ******************************************************************************/
840433d6423SLionel Sambuc
841433d6423SLionel Sambuc ACPI_STATUS
842433d6423SLionel Sambuc AcpiInstallGpeHandler (
843433d6423SLionel Sambuc ACPI_HANDLE GpeDevice,
844433d6423SLionel Sambuc UINT32 GpeNumber,
845433d6423SLionel Sambuc UINT32 Type,
846*29492bb7SDavid van Moolenbroek ACPI_GPE_HANDLER Address,
847433d6423SLionel Sambuc void *Context)
848433d6423SLionel Sambuc {
849433d6423SLionel Sambuc ACPI_GPE_EVENT_INFO *GpeEventInfo;
850*29492bb7SDavid van Moolenbroek ACPI_GPE_HANDLER_INFO *Handler;
851433d6423SLionel Sambuc ACPI_STATUS Status;
852433d6423SLionel Sambuc ACPI_CPU_FLAGS Flags;
853433d6423SLionel Sambuc
854433d6423SLionel Sambuc
855433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
856433d6423SLionel Sambuc
857433d6423SLionel Sambuc
858433d6423SLionel Sambuc /* Parameter validation */
859433d6423SLionel Sambuc
860433d6423SLionel Sambuc if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
861433d6423SLionel Sambuc {
862433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
863433d6423SLionel Sambuc }
864433d6423SLionel Sambuc
865433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
866433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
867433d6423SLionel Sambuc {
868433d6423SLionel Sambuc return_ACPI_STATUS (Status);
869433d6423SLionel Sambuc }
870433d6423SLionel Sambuc
871*29492bb7SDavid van Moolenbroek /* Allocate and init handler object (before lock) */
872*29492bb7SDavid van Moolenbroek
873*29492bb7SDavid van Moolenbroek Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
874*29492bb7SDavid van Moolenbroek if (!Handler)
875*29492bb7SDavid van Moolenbroek {
876*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
877*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
878*29492bb7SDavid van Moolenbroek }
879*29492bb7SDavid van Moolenbroek
880*29492bb7SDavid van Moolenbroek Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
881*29492bb7SDavid van Moolenbroek
882433d6423SLionel Sambuc /* Ensure that we have a valid GPE number */
883433d6423SLionel Sambuc
884433d6423SLionel Sambuc GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
885433d6423SLionel Sambuc if (!GpeEventInfo)
886433d6423SLionel Sambuc {
887433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
888*29492bb7SDavid van Moolenbroek goto FreeAndExit;
889433d6423SLionel Sambuc }
890433d6423SLionel Sambuc
891433d6423SLionel Sambuc /* Make sure that there isn't a handler there already */
892433d6423SLionel Sambuc
893433d6423SLionel Sambuc if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
894433d6423SLionel Sambuc ACPI_GPE_DISPATCH_HANDLER)
895433d6423SLionel Sambuc {
896433d6423SLionel Sambuc Status = AE_ALREADY_EXISTS;
897*29492bb7SDavid van Moolenbroek goto FreeAndExit;
898433d6423SLionel Sambuc }
899433d6423SLionel Sambuc
900433d6423SLionel Sambuc Handler->Address = Address;
901433d6423SLionel Sambuc Handler->Context = Context;
902433d6423SLionel Sambuc Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
903*29492bb7SDavid van Moolenbroek Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
904*29492bb7SDavid van Moolenbroek (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
905*29492bb7SDavid van Moolenbroek
906*29492bb7SDavid van Moolenbroek /*
907*29492bb7SDavid van Moolenbroek * If the GPE is associated with a method, it may have been enabled
908*29492bb7SDavid van Moolenbroek * automatically during initialization, in which case it has to be
909*29492bb7SDavid van Moolenbroek * disabled now to avoid spurious execution of the handler.
910*29492bb7SDavid van Moolenbroek */
911*29492bb7SDavid van Moolenbroek if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
912*29492bb7SDavid van Moolenbroek (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
913*29492bb7SDavid van Moolenbroek GpeEventInfo->RuntimeCount)
914*29492bb7SDavid van Moolenbroek {
915*29492bb7SDavid van Moolenbroek Handler->OriginallyEnabled = TRUE;
916*29492bb7SDavid van Moolenbroek (void) AcpiEvRemoveGpeReference (GpeEventInfo);
917*29492bb7SDavid van Moolenbroek
918*29492bb7SDavid van Moolenbroek /* Sanity check of original type against new type */
919*29492bb7SDavid van Moolenbroek
920*29492bb7SDavid van Moolenbroek if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
921*29492bb7SDavid van Moolenbroek {
922*29492bb7SDavid van Moolenbroek ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
923*29492bb7SDavid van Moolenbroek }
924*29492bb7SDavid van Moolenbroek }
925433d6423SLionel Sambuc
926433d6423SLionel Sambuc /* Install the handler */
927433d6423SLionel Sambuc
928433d6423SLionel Sambuc GpeEventInfo->Dispatch.Handler = Handler;
929433d6423SLionel Sambuc
930*29492bb7SDavid van Moolenbroek /* Setup up dispatch flags to indicate handler (vs. method/notify) */
931433d6423SLionel Sambuc
932433d6423SLionel Sambuc GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
933433d6423SLionel Sambuc GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
934433d6423SLionel Sambuc
935433d6423SLionel Sambuc AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
936433d6423SLionel Sambuc
937433d6423SLionel Sambuc
938433d6423SLionel Sambuc UnlockAndExit:
939433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
940433d6423SLionel Sambuc return_ACPI_STATUS (Status);
941*29492bb7SDavid van Moolenbroek
942*29492bb7SDavid van Moolenbroek FreeAndExit:
943*29492bb7SDavid van Moolenbroek AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
944*29492bb7SDavid van Moolenbroek ACPI_FREE (Handler);
945*29492bb7SDavid van Moolenbroek goto UnlockAndExit;
946433d6423SLionel Sambuc }
947433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiInstallGpeHandler)948433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
949433d6423SLionel Sambuc
950433d6423SLionel Sambuc
951433d6423SLionel Sambuc /*******************************************************************************
952433d6423SLionel Sambuc *
953433d6423SLionel Sambuc * FUNCTION: AcpiRemoveGpeHandler
954433d6423SLionel Sambuc *
955433d6423SLionel Sambuc * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
956433d6423SLionel Sambuc * defined GPEs)
957433d6423SLionel Sambuc * GpeNumber - The event to remove a handler
958433d6423SLionel Sambuc * Address - Address of the handler
959433d6423SLionel Sambuc *
960433d6423SLionel Sambuc * RETURN: Status
961433d6423SLionel Sambuc *
962433d6423SLionel Sambuc * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
963433d6423SLionel Sambuc *
964433d6423SLionel Sambuc ******************************************************************************/
965433d6423SLionel Sambuc
966433d6423SLionel Sambuc ACPI_STATUS
967433d6423SLionel Sambuc AcpiRemoveGpeHandler (
968433d6423SLionel Sambuc ACPI_HANDLE GpeDevice,
969433d6423SLionel Sambuc UINT32 GpeNumber,
970*29492bb7SDavid van Moolenbroek ACPI_GPE_HANDLER Address)
971433d6423SLionel Sambuc {
972433d6423SLionel Sambuc ACPI_GPE_EVENT_INFO *GpeEventInfo;
973*29492bb7SDavid van Moolenbroek ACPI_GPE_HANDLER_INFO *Handler;
974433d6423SLionel Sambuc ACPI_STATUS Status;
975433d6423SLionel Sambuc ACPI_CPU_FLAGS Flags;
976433d6423SLionel Sambuc
977433d6423SLionel Sambuc
978433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
979433d6423SLionel Sambuc
980433d6423SLionel Sambuc
981433d6423SLionel Sambuc /* Parameter validation */
982433d6423SLionel Sambuc
983433d6423SLionel Sambuc if (!Address)
984433d6423SLionel Sambuc {
985433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
986433d6423SLionel Sambuc }
987433d6423SLionel Sambuc
988433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
989433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
990433d6423SLionel Sambuc {
991433d6423SLionel Sambuc return_ACPI_STATUS (Status);
992433d6423SLionel Sambuc }
993433d6423SLionel Sambuc
994*29492bb7SDavid van Moolenbroek Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
995*29492bb7SDavid van Moolenbroek
996433d6423SLionel Sambuc /* Ensure that we have a valid GPE number */
997433d6423SLionel Sambuc
998433d6423SLionel Sambuc GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
999433d6423SLionel Sambuc if (!GpeEventInfo)
1000433d6423SLionel Sambuc {
1001433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
1002433d6423SLionel Sambuc goto UnlockAndExit;
1003433d6423SLionel Sambuc }
1004433d6423SLionel Sambuc
1005433d6423SLionel Sambuc /* Make sure that a handler is indeed installed */
1006433d6423SLionel Sambuc
1007433d6423SLionel Sambuc if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
1008433d6423SLionel Sambuc ACPI_GPE_DISPATCH_HANDLER)
1009433d6423SLionel Sambuc {
1010433d6423SLionel Sambuc Status = AE_NOT_EXIST;
1011433d6423SLionel Sambuc goto UnlockAndExit;
1012433d6423SLionel Sambuc }
1013433d6423SLionel Sambuc
1014433d6423SLionel Sambuc /* Make sure that the installed handler is the same */
1015433d6423SLionel Sambuc
1016433d6423SLionel Sambuc if (GpeEventInfo->Dispatch.Handler->Address != Address)
1017433d6423SLionel Sambuc {
1018433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
1019433d6423SLionel Sambuc goto UnlockAndExit;
1020433d6423SLionel Sambuc }
1021433d6423SLionel Sambuc
1022433d6423SLionel Sambuc /* Remove the handler */
1023433d6423SLionel Sambuc
1024433d6423SLionel Sambuc Handler = GpeEventInfo->Dispatch.Handler;
1025433d6423SLionel Sambuc
1026433d6423SLionel Sambuc /* Restore Method node (if any), set dispatch flags */
1027433d6423SLionel Sambuc
1028433d6423SLionel Sambuc GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1029*29492bb7SDavid van Moolenbroek GpeEventInfo->Flags &=
1030*29492bb7SDavid van Moolenbroek ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1031*29492bb7SDavid van Moolenbroek GpeEventInfo->Flags |= Handler->OriginalFlags;
1032*29492bb7SDavid van Moolenbroek
1033*29492bb7SDavid van Moolenbroek /*
1034*29492bb7SDavid van Moolenbroek * If the GPE was previously associated with a method and it was
1035*29492bb7SDavid van Moolenbroek * enabled, it should be enabled at this point to restore the
1036*29492bb7SDavid van Moolenbroek * post-initialization configuration.
1037*29492bb7SDavid van Moolenbroek */
1038*29492bb7SDavid van Moolenbroek if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
1039*29492bb7SDavid van Moolenbroek (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
1040*29492bb7SDavid van Moolenbroek Handler->OriginallyEnabled)
1041433d6423SLionel Sambuc {
1042*29492bb7SDavid van Moolenbroek (void) AcpiEvAddGpeReference (GpeEventInfo);
1043433d6423SLionel Sambuc }
1044*29492bb7SDavid van Moolenbroek
1045433d6423SLionel Sambuc AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1046*29492bb7SDavid van Moolenbroek (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1047*29492bb7SDavid van Moolenbroek
1048*29492bb7SDavid van Moolenbroek /* Make sure all deferred GPE tasks are completed */
1049*29492bb7SDavid van Moolenbroek
1050*29492bb7SDavid van Moolenbroek AcpiOsWaitEventsComplete ();
1051433d6423SLionel Sambuc
1052433d6423SLionel Sambuc /* Now we can free the handler object */
1053433d6423SLionel Sambuc
1054433d6423SLionel Sambuc ACPI_FREE (Handler);
1055*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
1056433d6423SLionel Sambuc
1057433d6423SLionel Sambuc UnlockAndExit:
1058*29492bb7SDavid van Moolenbroek AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1059433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1060433d6423SLionel Sambuc return_ACPI_STATUS (Status);
1061433d6423SLionel Sambuc }
1062433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiRemoveGpeHandler)1063433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1064433d6423SLionel Sambuc
1065433d6423SLionel Sambuc
1066433d6423SLionel Sambuc /*******************************************************************************
1067433d6423SLionel Sambuc *
1068433d6423SLionel Sambuc * FUNCTION: AcpiAcquireGlobalLock
1069433d6423SLionel Sambuc *
1070433d6423SLionel Sambuc * PARAMETERS: Timeout - How long the caller is willing to wait
1071433d6423SLionel Sambuc * Handle - Where the handle to the lock is returned
1072433d6423SLionel Sambuc * (if acquired)
1073433d6423SLionel Sambuc *
1074433d6423SLionel Sambuc * RETURN: Status
1075433d6423SLionel Sambuc *
1076433d6423SLionel Sambuc * DESCRIPTION: Acquire the ACPI Global Lock
1077433d6423SLionel Sambuc *
1078433d6423SLionel Sambuc * Note: Allows callers with the same thread ID to acquire the global lock
1079433d6423SLionel Sambuc * multiple times. In other words, externally, the behavior of the global lock
1080433d6423SLionel Sambuc * is identical to an AML mutex. On the first acquire, a new handle is
1081433d6423SLionel Sambuc * returned. On any subsequent calls to acquire by the same thread, the same
1082433d6423SLionel Sambuc * handle is returned.
1083433d6423SLionel Sambuc *
1084433d6423SLionel Sambuc ******************************************************************************/
1085433d6423SLionel Sambuc
1086433d6423SLionel Sambuc ACPI_STATUS
1087433d6423SLionel Sambuc AcpiAcquireGlobalLock (
1088433d6423SLionel Sambuc UINT16 Timeout,
1089433d6423SLionel Sambuc UINT32 *Handle)
1090433d6423SLionel Sambuc {
1091433d6423SLionel Sambuc ACPI_STATUS Status;
1092433d6423SLionel Sambuc
1093433d6423SLionel Sambuc
1094433d6423SLionel Sambuc if (!Handle)
1095433d6423SLionel Sambuc {
1096433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
1097433d6423SLionel Sambuc }
1098433d6423SLionel Sambuc
1099433d6423SLionel Sambuc /* Must lock interpreter to prevent race conditions */
1100433d6423SLionel Sambuc
1101433d6423SLionel Sambuc AcpiExEnterInterpreter ();
1102433d6423SLionel Sambuc
1103433d6423SLionel Sambuc Status = AcpiExAcquireMutexObject (Timeout,
1104433d6423SLionel Sambuc AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1105433d6423SLionel Sambuc
1106433d6423SLionel Sambuc if (ACPI_SUCCESS (Status))
1107433d6423SLionel Sambuc {
1108433d6423SLionel Sambuc /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1109433d6423SLionel Sambuc
1110433d6423SLionel Sambuc *Handle = AcpiGbl_GlobalLockHandle;
1111433d6423SLionel Sambuc }
1112433d6423SLionel Sambuc
1113433d6423SLionel Sambuc AcpiExExitInterpreter ();
1114433d6423SLionel Sambuc return (Status);
1115433d6423SLionel Sambuc }
1116433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiAcquireGlobalLock)1117433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1118433d6423SLionel Sambuc
1119433d6423SLionel Sambuc
1120433d6423SLionel Sambuc /*******************************************************************************
1121433d6423SLionel Sambuc *
1122433d6423SLionel Sambuc * FUNCTION: AcpiReleaseGlobalLock
1123433d6423SLionel Sambuc *
1124433d6423SLionel Sambuc * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock
1125433d6423SLionel Sambuc *
1126433d6423SLionel Sambuc * RETURN: Status
1127433d6423SLionel Sambuc *
1128433d6423SLionel Sambuc * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1129433d6423SLionel Sambuc *
1130433d6423SLionel Sambuc ******************************************************************************/
1131433d6423SLionel Sambuc
1132433d6423SLionel Sambuc ACPI_STATUS
1133433d6423SLionel Sambuc AcpiReleaseGlobalLock (
1134433d6423SLionel Sambuc UINT32 Handle)
1135433d6423SLionel Sambuc {
1136433d6423SLionel Sambuc ACPI_STATUS Status;
1137433d6423SLionel Sambuc
1138433d6423SLionel Sambuc
1139433d6423SLionel Sambuc if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1140433d6423SLionel Sambuc {
1141433d6423SLionel Sambuc return (AE_NOT_ACQUIRED);
1142433d6423SLionel Sambuc }
1143433d6423SLionel Sambuc
1144433d6423SLionel Sambuc Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1145433d6423SLionel Sambuc return (Status);
1146433d6423SLionel Sambuc }
1147433d6423SLionel Sambuc
1148433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1149433d6423SLionel Sambuc
1150*29492bb7SDavid van Moolenbroek #endif /* !ACPI_REDUCED_HARDWARE */
1151