Deleted Added
full compact
evxface.c (234623) evxface.c (235945)
1/******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#define __EVXFACE_C__
46
47#include <contrib/dev/acpica/include/acpi.h>
48#include <contrib/dev/acpica/include/accommon.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50#include <contrib/dev/acpica/include/acevents.h>
51#include <contrib/dev/acpica/include/acinterp.h>
52
53#define _COMPONENT ACPI_EVENTS
54 ACPI_MODULE_NAME ("evxface")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: AcpiInstallNotifyHandler
60 *
61 * PARAMETERS: Device - The device for which notifies will be handled
62 * HandlerType - The type of handler:
63 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
64 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
65 * ACPI_ALL_NOTIFY: Both System and Device
66 * Handler - Address of the handler
67 * Context - Value passed to the handler on each GPE
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
72 * ThermalZone, or Processor object.
73 *
74 * NOTES: The Root namespace object may have only one handler for each
75 * type of notify (System/Device). Device/Thermal/Processor objects
76 * may have one device notify handler, and multiple system notify
77 * handlers.
78 *
79 ******************************************************************************/
80
81ACPI_STATUS
82AcpiInstallNotifyHandler (
83 ACPI_HANDLE Device,
84 UINT32 HandlerType,
85 ACPI_NOTIFY_HANDLER Handler,
86 void *Context)
87{
88 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
89 ACPI_OPERAND_OBJECT *ObjDesc;
90 ACPI_OPERAND_OBJECT *HandlerObj;
91 ACPI_STATUS Status;
92 UINT32 i;
93
94
95 ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
96
97
98 /* Parameter validation */
99
100 if ((!Device) || (!Handler) || (!HandlerType) ||
101 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
102 {
103 return_ACPI_STATUS (AE_BAD_PARAMETER);
104 }
105
106 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
107 if (ACPI_FAILURE (Status))
108 {
109 return_ACPI_STATUS (Status);
110 }
111
112 /*
113 * Root Object:
114 * Registering a notify handler on the root object indicates that the
115 * caller wishes to receive notifications for all objects. Note that
116 * only one global handler can be registered per notify type.
117 * Ensure that a handler is not already installed.
118 */
119 if (Device == ACPI_ROOT_OBJECT)
120 {
121 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
122 {
123 if (HandlerType & (i+1))
124 {
125 if (AcpiGbl_GlobalNotify[i].Handler)
126 {
127 Status = AE_ALREADY_EXISTS;
128 goto UnlockAndExit;
129 }
130
131 AcpiGbl_GlobalNotify[i].Handler = Handler;
132 AcpiGbl_GlobalNotify[i].Context = Context;
133 }
134 }
135
136 goto UnlockAndExit; /* Global notify handler installed, all done */
137 }
138
139 /*
140 * All Other Objects:
141 * Caller will only receive notifications specific to the target
142 * object. Note that only certain object types are allowed to
143 * receive notifications.
144 */
145
146 /* Are Notifies allowed on this object? */
147
148 if (!AcpiEvIsNotifyObject (Node))
149 {
150 Status = AE_TYPE;
151 goto UnlockAndExit;
152 }
153
154 /* Check for an existing internal object, might not exist */
155
156 ObjDesc = AcpiNsGetAttachedObject (Node);
157 if (!ObjDesc)
158 {
159 /* Create a new object */
160
161 ObjDesc = AcpiUtCreateInternalObject (Node->Type);
162 if (!ObjDesc)
163 {
164 Status = AE_NO_MEMORY;
165 goto UnlockAndExit;
166 }
167
168 /* Attach new object to the Node, remove local reference */
169
170 Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
171 AcpiUtRemoveReference (ObjDesc);
172 if (ACPI_FAILURE (Status))
173 {
174 goto UnlockAndExit;
175 }
176 }
177
178 /* Ensure that the handler is not already installed in the lists */
179
180 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
181 {
182 if (HandlerType & (i+1))
183 {
184 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
185 while (HandlerObj)
186 {
187 if (HandlerObj->Notify.Handler == Handler)
188 {
189 Status = AE_ALREADY_EXISTS;
190 goto UnlockAndExit;
191 }
192
193 HandlerObj = HandlerObj->Notify.Next[i];
194 }
195 }
196 }
197
198 /* Create and populate a new notify handler object */
199
200 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
201 if (!HandlerObj)
202 {
203 Status = AE_NO_MEMORY;
204 goto UnlockAndExit;
205 }
206
207 HandlerObj->Notify.Node = Node;
208 HandlerObj->Notify.HandlerType = HandlerType;
209 HandlerObj->Notify.Handler = Handler;
210 HandlerObj->Notify.Context = Context;
211
212 /* Install the handler at the list head(s) */
213
214 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
215 {
216 if (HandlerType & (i+1))
217 {
218 HandlerObj->Notify.Next[i] =
219 ObjDesc->CommonNotify.NotifyList[i];
220
221 ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
222 }
223 }
224
225 /* Add an extra reference if handler was installed in both lists */
226
227 if (HandlerType == ACPI_ALL_NOTIFY)
228 {
229 AcpiUtAddReference (HandlerObj);
230 }
231
232
233UnlockAndExit:
234 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
235 return_ACPI_STATUS (Status);
236}
237
238ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
239
240
241/*******************************************************************************
242 *
243 * FUNCTION: AcpiRemoveNotifyHandler
244 *
245 * PARAMETERS: Device - The device for which the handler is installed
246 * HandlerType - The type of handler:
247 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
248 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
249 * ACPI_ALL_NOTIFY: Both System and Device
250 * Handler - Address of the handler
251 *
252 * RETURN: Status
253 *
254 * DESCRIPTION: Remove a handler for notifies on an ACPI device
255 *
256 ******************************************************************************/
257
258ACPI_STATUS
259AcpiRemoveNotifyHandler (
260 ACPI_HANDLE Device,
261 UINT32 HandlerType,
262 ACPI_NOTIFY_HANDLER Handler)
263{
264 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
265 ACPI_OPERAND_OBJECT *ObjDesc;
266 ACPI_OPERAND_OBJECT *HandlerObj;
267 ACPI_OPERAND_OBJECT *PreviousHandlerObj;
268 ACPI_STATUS Status;
269 UINT32 i;
270
271
272 ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
273
274
275 /* Parameter validation */
276
277 if ((!Device) || (!Handler) || (!HandlerType) ||
278 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
279 {
280 return_ACPI_STATUS (AE_BAD_PARAMETER);
281 }
282
1/******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#define __EVXFACE_C__
46
47#include <contrib/dev/acpica/include/acpi.h>
48#include <contrib/dev/acpica/include/accommon.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50#include <contrib/dev/acpica/include/acevents.h>
51#include <contrib/dev/acpica/include/acinterp.h>
52
53#define _COMPONENT ACPI_EVENTS
54 ACPI_MODULE_NAME ("evxface")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: AcpiInstallNotifyHandler
60 *
61 * PARAMETERS: Device - The device for which notifies will be handled
62 * HandlerType - The type of handler:
63 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
64 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
65 * ACPI_ALL_NOTIFY: Both System and Device
66 * Handler - Address of the handler
67 * Context - Value passed to the handler on each GPE
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
72 * ThermalZone, or Processor object.
73 *
74 * NOTES: The Root namespace object may have only one handler for each
75 * type of notify (System/Device). Device/Thermal/Processor objects
76 * may have one device notify handler, and multiple system notify
77 * handlers.
78 *
79 ******************************************************************************/
80
81ACPI_STATUS
82AcpiInstallNotifyHandler (
83 ACPI_HANDLE Device,
84 UINT32 HandlerType,
85 ACPI_NOTIFY_HANDLER Handler,
86 void *Context)
87{
88 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
89 ACPI_OPERAND_OBJECT *ObjDesc;
90 ACPI_OPERAND_OBJECT *HandlerObj;
91 ACPI_STATUS Status;
92 UINT32 i;
93
94
95 ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
96
97
98 /* Parameter validation */
99
100 if ((!Device) || (!Handler) || (!HandlerType) ||
101 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
102 {
103 return_ACPI_STATUS (AE_BAD_PARAMETER);
104 }
105
106 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
107 if (ACPI_FAILURE (Status))
108 {
109 return_ACPI_STATUS (Status);
110 }
111
112 /*
113 * Root Object:
114 * Registering a notify handler on the root object indicates that the
115 * caller wishes to receive notifications for all objects. Note that
116 * only one global handler can be registered per notify type.
117 * Ensure that a handler is not already installed.
118 */
119 if (Device == ACPI_ROOT_OBJECT)
120 {
121 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
122 {
123 if (HandlerType & (i+1))
124 {
125 if (AcpiGbl_GlobalNotify[i].Handler)
126 {
127 Status = AE_ALREADY_EXISTS;
128 goto UnlockAndExit;
129 }
130
131 AcpiGbl_GlobalNotify[i].Handler = Handler;
132 AcpiGbl_GlobalNotify[i].Context = Context;
133 }
134 }
135
136 goto UnlockAndExit; /* Global notify handler installed, all done */
137 }
138
139 /*
140 * All Other Objects:
141 * Caller will only receive notifications specific to the target
142 * object. Note that only certain object types are allowed to
143 * receive notifications.
144 */
145
146 /* Are Notifies allowed on this object? */
147
148 if (!AcpiEvIsNotifyObject (Node))
149 {
150 Status = AE_TYPE;
151 goto UnlockAndExit;
152 }
153
154 /* Check for an existing internal object, might not exist */
155
156 ObjDesc = AcpiNsGetAttachedObject (Node);
157 if (!ObjDesc)
158 {
159 /* Create a new object */
160
161 ObjDesc = AcpiUtCreateInternalObject (Node->Type);
162 if (!ObjDesc)
163 {
164 Status = AE_NO_MEMORY;
165 goto UnlockAndExit;
166 }
167
168 /* Attach new object to the Node, remove local reference */
169
170 Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
171 AcpiUtRemoveReference (ObjDesc);
172 if (ACPI_FAILURE (Status))
173 {
174 goto UnlockAndExit;
175 }
176 }
177
178 /* Ensure that the handler is not already installed in the lists */
179
180 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
181 {
182 if (HandlerType & (i+1))
183 {
184 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
185 while (HandlerObj)
186 {
187 if (HandlerObj->Notify.Handler == Handler)
188 {
189 Status = AE_ALREADY_EXISTS;
190 goto UnlockAndExit;
191 }
192
193 HandlerObj = HandlerObj->Notify.Next[i];
194 }
195 }
196 }
197
198 /* Create and populate a new notify handler object */
199
200 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
201 if (!HandlerObj)
202 {
203 Status = AE_NO_MEMORY;
204 goto UnlockAndExit;
205 }
206
207 HandlerObj->Notify.Node = Node;
208 HandlerObj->Notify.HandlerType = HandlerType;
209 HandlerObj->Notify.Handler = Handler;
210 HandlerObj->Notify.Context = Context;
211
212 /* Install the handler at the list head(s) */
213
214 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
215 {
216 if (HandlerType & (i+1))
217 {
218 HandlerObj->Notify.Next[i] =
219 ObjDesc->CommonNotify.NotifyList[i];
220
221 ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
222 }
223 }
224
225 /* Add an extra reference if handler was installed in both lists */
226
227 if (HandlerType == ACPI_ALL_NOTIFY)
228 {
229 AcpiUtAddReference (HandlerObj);
230 }
231
232
233UnlockAndExit:
234 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
235 return_ACPI_STATUS (Status);
236}
237
238ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
239
240
241/*******************************************************************************
242 *
243 * FUNCTION: AcpiRemoveNotifyHandler
244 *
245 * PARAMETERS: Device - The device for which the handler is installed
246 * HandlerType - The type of handler:
247 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
248 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
249 * ACPI_ALL_NOTIFY: Both System and Device
250 * Handler - Address of the handler
251 *
252 * RETURN: Status
253 *
254 * DESCRIPTION: Remove a handler for notifies on an ACPI device
255 *
256 ******************************************************************************/
257
258ACPI_STATUS
259AcpiRemoveNotifyHandler (
260 ACPI_HANDLE Device,
261 UINT32 HandlerType,
262 ACPI_NOTIFY_HANDLER Handler)
263{
264 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
265 ACPI_OPERAND_OBJECT *ObjDesc;
266 ACPI_OPERAND_OBJECT *HandlerObj;
267 ACPI_OPERAND_OBJECT *PreviousHandlerObj;
268 ACPI_STATUS Status;
269 UINT32 i;
270
271
272 ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
273
274
275 /* Parameter validation */
276
277 if ((!Device) || (!Handler) || (!HandlerType) ||
278 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
279 {
280 return_ACPI_STATUS (AE_BAD_PARAMETER);
281 }
282
283#ifdef _UNDER_DEVELOPMENT
284 /* Make sure all deferred tasks are completed */
283 /* Make sure all deferred notify tasks are completed */
285
284
286 AcpiOsWaitEventsComplete (NULL);
287#endif
285 AcpiOsWaitEventsComplete ();
288
289 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
290 if (ACPI_FAILURE (Status))
291 {
292 return_ACPI_STATUS (Status);
293 }
294
295 /* Root Object. Global handlers are removed here */
296
297 if (Device == ACPI_ROOT_OBJECT)
298 {
299 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
300 {
301 if (HandlerType & (i+1))
302 {
303 if (!AcpiGbl_GlobalNotify[i].Handler ||
304 (AcpiGbl_GlobalNotify[i].Handler != Handler))
305 {
306 Status = AE_NOT_EXIST;
307 goto UnlockAndExit;
308 }
309
310 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
311 "Removing global notify handler\n"));
312
313 AcpiGbl_GlobalNotify[i].Handler = NULL;
314 AcpiGbl_GlobalNotify[i].Context = NULL;
315 }
316 }
317
318 goto UnlockAndExit;
319 }
320
321 /* All other objects: Are Notifies allowed on this object? */
322
323 if (!AcpiEvIsNotifyObject (Node))
324 {
325 Status = AE_TYPE;
326 goto UnlockAndExit;
327 }
328
329 /* Must have an existing internal object */
330
331 ObjDesc = AcpiNsGetAttachedObject (Node);
332 if (!ObjDesc)
333 {
334 Status = AE_NOT_EXIST;
335 goto UnlockAndExit;
336 }
337
338 /* Internal object exists. Find the handler and remove it */
339
340 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
341 {
342 if (HandlerType & (i+1))
343 {
344 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
345 PreviousHandlerObj = NULL;
346
347 /* Attempt to find the handler in the handler list */
348
349 while (HandlerObj &&
350 (HandlerObj->Notify.Handler != Handler))
351 {
352 PreviousHandlerObj = HandlerObj;
353 HandlerObj = HandlerObj->Notify.Next[i];
354 }
355
356 if (!HandlerObj)
357 {
358 Status = AE_NOT_EXIST;
359 goto UnlockAndExit;
360 }
361
362 /* Remove the handler object from the list */
363
364 if (PreviousHandlerObj) /* Handler is not at the list head */
365 {
366 PreviousHandlerObj->Notify.Next[i] =
367 HandlerObj->Notify.Next[i];
368 }
369 else /* Handler is at the list head */
370 {
371 ObjDesc->CommonNotify.NotifyList[i] =
372 HandlerObj->Notify.Next[i];
373 }
374
375 AcpiUtRemoveReference (HandlerObj);
376 }
377 }
378
379
380UnlockAndExit:
381 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
382 return_ACPI_STATUS (Status);
383}
384
385ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
386
387
388/*******************************************************************************
389 *
390 * FUNCTION: AcpiInstallExceptionHandler
391 *
392 * PARAMETERS: Handler - Pointer to the handler function for the
393 * event
394 *
395 * RETURN: Status
396 *
397 * DESCRIPTION: Saves the pointer to the handler function
398 *
399 ******************************************************************************/
400
401ACPI_STATUS
402AcpiInstallExceptionHandler (
403 ACPI_EXCEPTION_HANDLER Handler)
404{
405 ACPI_STATUS Status;
406
407
408 ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
409
410
411 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
412 if (ACPI_FAILURE (Status))
413 {
414 return_ACPI_STATUS (Status);
415 }
416
417 /* Don't allow two handlers. */
418
419 if (AcpiGbl_ExceptionHandler)
420 {
421 Status = AE_ALREADY_EXISTS;
422 goto Cleanup;
423 }
424
425 /* Install the handler */
426
427 AcpiGbl_ExceptionHandler = Handler;
428
429Cleanup:
430 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
431 return_ACPI_STATUS (Status);
432}
433
434ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
435
436
437#if (!ACPI_REDUCED_HARDWARE)
438/*******************************************************************************
439 *
440 * FUNCTION: AcpiInstallGlobalEventHandler
441 *
442 * PARAMETERS: Handler - Pointer to the global event handler function
443 * Context - Value passed to the handler on each event
444 *
445 * RETURN: Status
446 *
447 * DESCRIPTION: Saves the pointer to the handler function. The global handler
448 * is invoked upon each incoming GPE and Fixed Event. It is
449 * invoked at interrupt level at the time of the event dispatch.
450 * Can be used to update event counters, etc.
451 *
452 ******************************************************************************/
453
454ACPI_STATUS
455AcpiInstallGlobalEventHandler (
456 ACPI_GBL_EVENT_HANDLER Handler,
457 void *Context)
458{
459 ACPI_STATUS Status;
460
461
462 ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
463
464
465 /* Parameter validation */
466
467 if (!Handler)
468 {
469 return_ACPI_STATUS (AE_BAD_PARAMETER);
470 }
471
472 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
473 if (ACPI_FAILURE (Status))
474 {
475 return_ACPI_STATUS (Status);
476 }
477
478 /* Don't allow two handlers. */
479
480 if (AcpiGbl_GlobalEventHandler)
481 {
482 Status = AE_ALREADY_EXISTS;
483 goto Cleanup;
484 }
485
486 AcpiGbl_GlobalEventHandler = Handler;
487 AcpiGbl_GlobalEventHandlerContext = Context;
488
489
490Cleanup:
491 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
492 return_ACPI_STATUS (Status);
493}
494
495ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
496
497
498/*******************************************************************************
499 *
500 * FUNCTION: AcpiInstallFixedEventHandler
501 *
502 * PARAMETERS: Event - Event type to enable.
503 * Handler - Pointer to the handler function for the
504 * event
505 * Context - Value passed to the handler on each GPE
506 *
507 * RETURN: Status
508 *
509 * DESCRIPTION: Saves the pointer to the handler function and then enables the
510 * event.
511 *
512 ******************************************************************************/
513
514ACPI_STATUS
515AcpiInstallFixedEventHandler (
516 UINT32 Event,
517 ACPI_EVENT_HANDLER Handler,
518 void *Context)
519{
520 ACPI_STATUS Status;
521
522
523 ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
524
525
526 /* Parameter validation */
527
528 if (Event > ACPI_EVENT_MAX)
529 {
530 return_ACPI_STATUS (AE_BAD_PARAMETER);
531 }
532
533 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
534 if (ACPI_FAILURE (Status))
535 {
536 return_ACPI_STATUS (Status);
537 }
538
539 /* Don't allow two handlers. */
540
541 if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
542 {
543 Status = AE_ALREADY_EXISTS;
544 goto Cleanup;
545 }
546
547 /* Install the handler before enabling the event */
548
549 AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
550 AcpiGbl_FixedEventHandlers[Event].Context = Context;
551
552 Status = AcpiEnableEvent (Event, 0);
553 if (ACPI_FAILURE (Status))
554 {
555 ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
556
557 /* Remove the handler */
558
559 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
560 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
561 }
562 else
563 {
564 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
565 "Enabled fixed event %X, Handler=%p\n", Event, Handler));
566 }
567
568
569Cleanup:
570 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
571 return_ACPI_STATUS (Status);
572}
573
574ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
575
576
577/*******************************************************************************
578 *
579 * FUNCTION: AcpiRemoveFixedEventHandler
580 *
581 * PARAMETERS: Event - Event type to disable.
582 * Handler - Address of the handler
583 *
584 * RETURN: Status
585 *
586 * DESCRIPTION: Disables the event and unregisters the event handler.
587 *
588 ******************************************************************************/
589
590ACPI_STATUS
591AcpiRemoveFixedEventHandler (
592 UINT32 Event,
593 ACPI_EVENT_HANDLER Handler)
594{
595 ACPI_STATUS Status = AE_OK;
596
597
598 ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
599
600
601 /* Parameter validation */
602
603 if (Event > ACPI_EVENT_MAX)
604 {
605 return_ACPI_STATUS (AE_BAD_PARAMETER);
606 }
607
608 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
609 if (ACPI_FAILURE (Status))
610 {
611 return_ACPI_STATUS (Status);
612 }
613
614 /* Disable the event before removing the handler */
615
616 Status = AcpiDisableEvent (Event, 0);
617
618 /* Always Remove the handler */
619
620 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
621 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
622
623 if (ACPI_FAILURE (Status))
624 {
625 ACPI_WARNING ((AE_INFO,
626 "Could not write to fixed event enable register 0x%X", Event));
627 }
628 else
629 {
630 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
631 }
632
633 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
634 return_ACPI_STATUS (Status);
635}
636
637ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
638
639
640/*******************************************************************************
641 *
642 * FUNCTION: AcpiInstallGpeHandler
643 *
644 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
645 * defined GPEs)
646 * GpeNumber - The GPE number within the GPE block
647 * Type - Whether this GPE should be treated as an
648 * edge- or level-triggered interrupt.
649 * Address - Address of the handler
650 * Context - Value passed to the handler on each GPE
651 *
652 * RETURN: Status
653 *
654 * DESCRIPTION: Install a handler for a General Purpose Event.
655 *
656 ******************************************************************************/
657
658ACPI_STATUS
659AcpiInstallGpeHandler (
660 ACPI_HANDLE GpeDevice,
661 UINT32 GpeNumber,
662 UINT32 Type,
663 ACPI_GPE_HANDLER Address,
664 void *Context)
665{
666 ACPI_GPE_EVENT_INFO *GpeEventInfo;
667 ACPI_GPE_HANDLER_INFO *Handler;
668 ACPI_STATUS Status;
669 ACPI_CPU_FLAGS Flags;
670
671
672 ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
673
674
675 /* Parameter validation */
676
677 if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
678 {
679 return_ACPI_STATUS (AE_BAD_PARAMETER);
680 }
681
682 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
683 if (ACPI_FAILURE (Status))
684 {
685 return_ACPI_STATUS (Status);
686 }
687
688 /* Allocate and init handler object (before lock) */
689
690 Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
691 if (!Handler)
692 {
693 Status = AE_NO_MEMORY;
694 goto UnlockAndExit;
695 }
696
697 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
698
699 /* Ensure that we have a valid GPE number */
700
701 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702 if (!GpeEventInfo)
703 {
704 Status = AE_BAD_PARAMETER;
705 goto FreeAndExit;
706 }
707
708 /* Make sure that there isn't a handler there already */
709
710 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
711 ACPI_GPE_DISPATCH_HANDLER)
712 {
713 Status = AE_ALREADY_EXISTS;
714 goto FreeAndExit;
715 }
716
717 Handler->Address = Address;
718 Handler->Context = Context;
719 Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
720 Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
721 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
722
723 /*
724 * If the GPE is associated with a method, it may have been enabled
725 * automatically during initialization, in which case it has to be
726 * disabled now to avoid spurious execution of the handler.
727 */
728 if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
729 (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
730 GpeEventInfo->RuntimeCount)
731 {
732 Handler->OriginallyEnabled = TRUE;
733 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
734
735 /* Sanity check of original type against new type */
736
737 if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
738 {
739 ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
740 }
741 }
742
743 /* Install the handler */
744
745 GpeEventInfo->Dispatch.Handler = Handler;
746
747 /* Setup up dispatch flags to indicate handler (vs. method/notify) */
748
749 GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
750 GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
751
752 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
753
754
755UnlockAndExit:
756 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
757 return_ACPI_STATUS (Status);
758
759FreeAndExit:
760 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
761 ACPI_FREE (Handler);
762 goto UnlockAndExit;
763}
764
765ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
766
767
768/*******************************************************************************
769 *
770 * FUNCTION: AcpiRemoveGpeHandler
771 *
772 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
773 * defined GPEs)
774 * GpeNumber - The event to remove a handler
775 * Address - Address of the handler
776 *
777 * RETURN: Status
778 *
779 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
780 *
781 ******************************************************************************/
782
783ACPI_STATUS
784AcpiRemoveGpeHandler (
785 ACPI_HANDLE GpeDevice,
786 UINT32 GpeNumber,
787 ACPI_GPE_HANDLER Address)
788{
789 ACPI_GPE_EVENT_INFO *GpeEventInfo;
790 ACPI_GPE_HANDLER_INFO *Handler;
791 ACPI_STATUS Status;
792 ACPI_CPU_FLAGS Flags;
793
794
795 ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
796
797
798 /* Parameter validation */
799
800 if (!Address)
801 {
802 return_ACPI_STATUS (AE_BAD_PARAMETER);
803 }
804
286
287 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
288 if (ACPI_FAILURE (Status))
289 {
290 return_ACPI_STATUS (Status);
291 }
292
293 /* Root Object. Global handlers are removed here */
294
295 if (Device == ACPI_ROOT_OBJECT)
296 {
297 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
298 {
299 if (HandlerType & (i+1))
300 {
301 if (!AcpiGbl_GlobalNotify[i].Handler ||
302 (AcpiGbl_GlobalNotify[i].Handler != Handler))
303 {
304 Status = AE_NOT_EXIST;
305 goto UnlockAndExit;
306 }
307
308 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
309 "Removing global notify handler\n"));
310
311 AcpiGbl_GlobalNotify[i].Handler = NULL;
312 AcpiGbl_GlobalNotify[i].Context = NULL;
313 }
314 }
315
316 goto UnlockAndExit;
317 }
318
319 /* All other objects: Are Notifies allowed on this object? */
320
321 if (!AcpiEvIsNotifyObject (Node))
322 {
323 Status = AE_TYPE;
324 goto UnlockAndExit;
325 }
326
327 /* Must have an existing internal object */
328
329 ObjDesc = AcpiNsGetAttachedObject (Node);
330 if (!ObjDesc)
331 {
332 Status = AE_NOT_EXIST;
333 goto UnlockAndExit;
334 }
335
336 /* Internal object exists. Find the handler and remove it */
337
338 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
339 {
340 if (HandlerType & (i+1))
341 {
342 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
343 PreviousHandlerObj = NULL;
344
345 /* Attempt to find the handler in the handler list */
346
347 while (HandlerObj &&
348 (HandlerObj->Notify.Handler != Handler))
349 {
350 PreviousHandlerObj = HandlerObj;
351 HandlerObj = HandlerObj->Notify.Next[i];
352 }
353
354 if (!HandlerObj)
355 {
356 Status = AE_NOT_EXIST;
357 goto UnlockAndExit;
358 }
359
360 /* Remove the handler object from the list */
361
362 if (PreviousHandlerObj) /* Handler is not at the list head */
363 {
364 PreviousHandlerObj->Notify.Next[i] =
365 HandlerObj->Notify.Next[i];
366 }
367 else /* Handler is at the list head */
368 {
369 ObjDesc->CommonNotify.NotifyList[i] =
370 HandlerObj->Notify.Next[i];
371 }
372
373 AcpiUtRemoveReference (HandlerObj);
374 }
375 }
376
377
378UnlockAndExit:
379 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
380 return_ACPI_STATUS (Status);
381}
382
383ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
384
385
386/*******************************************************************************
387 *
388 * FUNCTION: AcpiInstallExceptionHandler
389 *
390 * PARAMETERS: Handler - Pointer to the handler function for the
391 * event
392 *
393 * RETURN: Status
394 *
395 * DESCRIPTION: Saves the pointer to the handler function
396 *
397 ******************************************************************************/
398
399ACPI_STATUS
400AcpiInstallExceptionHandler (
401 ACPI_EXCEPTION_HANDLER Handler)
402{
403 ACPI_STATUS Status;
404
405
406 ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
407
408
409 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
410 if (ACPI_FAILURE (Status))
411 {
412 return_ACPI_STATUS (Status);
413 }
414
415 /* Don't allow two handlers. */
416
417 if (AcpiGbl_ExceptionHandler)
418 {
419 Status = AE_ALREADY_EXISTS;
420 goto Cleanup;
421 }
422
423 /* Install the handler */
424
425 AcpiGbl_ExceptionHandler = Handler;
426
427Cleanup:
428 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
429 return_ACPI_STATUS (Status);
430}
431
432ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
433
434
435#if (!ACPI_REDUCED_HARDWARE)
436/*******************************************************************************
437 *
438 * FUNCTION: AcpiInstallGlobalEventHandler
439 *
440 * PARAMETERS: Handler - Pointer to the global event handler function
441 * Context - Value passed to the handler on each event
442 *
443 * RETURN: Status
444 *
445 * DESCRIPTION: Saves the pointer to the handler function. The global handler
446 * is invoked upon each incoming GPE and Fixed Event. It is
447 * invoked at interrupt level at the time of the event dispatch.
448 * Can be used to update event counters, etc.
449 *
450 ******************************************************************************/
451
452ACPI_STATUS
453AcpiInstallGlobalEventHandler (
454 ACPI_GBL_EVENT_HANDLER Handler,
455 void *Context)
456{
457 ACPI_STATUS Status;
458
459
460 ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
461
462
463 /* Parameter validation */
464
465 if (!Handler)
466 {
467 return_ACPI_STATUS (AE_BAD_PARAMETER);
468 }
469
470 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
471 if (ACPI_FAILURE (Status))
472 {
473 return_ACPI_STATUS (Status);
474 }
475
476 /* Don't allow two handlers. */
477
478 if (AcpiGbl_GlobalEventHandler)
479 {
480 Status = AE_ALREADY_EXISTS;
481 goto Cleanup;
482 }
483
484 AcpiGbl_GlobalEventHandler = Handler;
485 AcpiGbl_GlobalEventHandlerContext = Context;
486
487
488Cleanup:
489 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
490 return_ACPI_STATUS (Status);
491}
492
493ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
494
495
496/*******************************************************************************
497 *
498 * FUNCTION: AcpiInstallFixedEventHandler
499 *
500 * PARAMETERS: Event - Event type to enable.
501 * Handler - Pointer to the handler function for the
502 * event
503 * Context - Value passed to the handler on each GPE
504 *
505 * RETURN: Status
506 *
507 * DESCRIPTION: Saves the pointer to the handler function and then enables the
508 * event.
509 *
510 ******************************************************************************/
511
512ACPI_STATUS
513AcpiInstallFixedEventHandler (
514 UINT32 Event,
515 ACPI_EVENT_HANDLER Handler,
516 void *Context)
517{
518 ACPI_STATUS Status;
519
520
521 ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
522
523
524 /* Parameter validation */
525
526 if (Event > ACPI_EVENT_MAX)
527 {
528 return_ACPI_STATUS (AE_BAD_PARAMETER);
529 }
530
531 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
532 if (ACPI_FAILURE (Status))
533 {
534 return_ACPI_STATUS (Status);
535 }
536
537 /* Don't allow two handlers. */
538
539 if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
540 {
541 Status = AE_ALREADY_EXISTS;
542 goto Cleanup;
543 }
544
545 /* Install the handler before enabling the event */
546
547 AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
548 AcpiGbl_FixedEventHandlers[Event].Context = Context;
549
550 Status = AcpiEnableEvent (Event, 0);
551 if (ACPI_FAILURE (Status))
552 {
553 ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
554
555 /* Remove the handler */
556
557 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
558 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
559 }
560 else
561 {
562 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
563 "Enabled fixed event %X, Handler=%p\n", Event, Handler));
564 }
565
566
567Cleanup:
568 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
569 return_ACPI_STATUS (Status);
570}
571
572ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
573
574
575/*******************************************************************************
576 *
577 * FUNCTION: AcpiRemoveFixedEventHandler
578 *
579 * PARAMETERS: Event - Event type to disable.
580 * Handler - Address of the handler
581 *
582 * RETURN: Status
583 *
584 * DESCRIPTION: Disables the event and unregisters the event handler.
585 *
586 ******************************************************************************/
587
588ACPI_STATUS
589AcpiRemoveFixedEventHandler (
590 UINT32 Event,
591 ACPI_EVENT_HANDLER Handler)
592{
593 ACPI_STATUS Status = AE_OK;
594
595
596 ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
597
598
599 /* Parameter validation */
600
601 if (Event > ACPI_EVENT_MAX)
602 {
603 return_ACPI_STATUS (AE_BAD_PARAMETER);
604 }
605
606 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
607 if (ACPI_FAILURE (Status))
608 {
609 return_ACPI_STATUS (Status);
610 }
611
612 /* Disable the event before removing the handler */
613
614 Status = AcpiDisableEvent (Event, 0);
615
616 /* Always Remove the handler */
617
618 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
619 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
620
621 if (ACPI_FAILURE (Status))
622 {
623 ACPI_WARNING ((AE_INFO,
624 "Could not write to fixed event enable register 0x%X", Event));
625 }
626 else
627 {
628 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
629 }
630
631 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
632 return_ACPI_STATUS (Status);
633}
634
635ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
636
637
638/*******************************************************************************
639 *
640 * FUNCTION: AcpiInstallGpeHandler
641 *
642 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
643 * defined GPEs)
644 * GpeNumber - The GPE number within the GPE block
645 * Type - Whether this GPE should be treated as an
646 * edge- or level-triggered interrupt.
647 * Address - Address of the handler
648 * Context - Value passed to the handler on each GPE
649 *
650 * RETURN: Status
651 *
652 * DESCRIPTION: Install a handler for a General Purpose Event.
653 *
654 ******************************************************************************/
655
656ACPI_STATUS
657AcpiInstallGpeHandler (
658 ACPI_HANDLE GpeDevice,
659 UINT32 GpeNumber,
660 UINT32 Type,
661 ACPI_GPE_HANDLER Address,
662 void *Context)
663{
664 ACPI_GPE_EVENT_INFO *GpeEventInfo;
665 ACPI_GPE_HANDLER_INFO *Handler;
666 ACPI_STATUS Status;
667 ACPI_CPU_FLAGS Flags;
668
669
670 ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
671
672
673 /* Parameter validation */
674
675 if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
676 {
677 return_ACPI_STATUS (AE_BAD_PARAMETER);
678 }
679
680 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
681 if (ACPI_FAILURE (Status))
682 {
683 return_ACPI_STATUS (Status);
684 }
685
686 /* Allocate and init handler object (before lock) */
687
688 Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
689 if (!Handler)
690 {
691 Status = AE_NO_MEMORY;
692 goto UnlockAndExit;
693 }
694
695 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
696
697 /* Ensure that we have a valid GPE number */
698
699 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
700 if (!GpeEventInfo)
701 {
702 Status = AE_BAD_PARAMETER;
703 goto FreeAndExit;
704 }
705
706 /* Make sure that there isn't a handler there already */
707
708 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
709 ACPI_GPE_DISPATCH_HANDLER)
710 {
711 Status = AE_ALREADY_EXISTS;
712 goto FreeAndExit;
713 }
714
715 Handler->Address = Address;
716 Handler->Context = Context;
717 Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
718 Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
719 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
720
721 /*
722 * If the GPE is associated with a method, it may have been enabled
723 * automatically during initialization, in which case it has to be
724 * disabled now to avoid spurious execution of the handler.
725 */
726 if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
727 (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
728 GpeEventInfo->RuntimeCount)
729 {
730 Handler->OriginallyEnabled = TRUE;
731 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
732
733 /* Sanity check of original type against new type */
734
735 if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
736 {
737 ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
738 }
739 }
740
741 /* Install the handler */
742
743 GpeEventInfo->Dispatch.Handler = Handler;
744
745 /* Setup up dispatch flags to indicate handler (vs. method/notify) */
746
747 GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
748 GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
749
750 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
751
752
753UnlockAndExit:
754 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
755 return_ACPI_STATUS (Status);
756
757FreeAndExit:
758 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
759 ACPI_FREE (Handler);
760 goto UnlockAndExit;
761}
762
763ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
764
765
766/*******************************************************************************
767 *
768 * FUNCTION: AcpiRemoveGpeHandler
769 *
770 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
771 * defined GPEs)
772 * GpeNumber - The event to remove a handler
773 * Address - Address of the handler
774 *
775 * RETURN: Status
776 *
777 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
778 *
779 ******************************************************************************/
780
781ACPI_STATUS
782AcpiRemoveGpeHandler (
783 ACPI_HANDLE GpeDevice,
784 UINT32 GpeNumber,
785 ACPI_GPE_HANDLER Address)
786{
787 ACPI_GPE_EVENT_INFO *GpeEventInfo;
788 ACPI_GPE_HANDLER_INFO *Handler;
789 ACPI_STATUS Status;
790 ACPI_CPU_FLAGS Flags;
791
792
793 ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
794
795
796 /* Parameter validation */
797
798 if (!Address)
799 {
800 return_ACPI_STATUS (AE_BAD_PARAMETER);
801 }
802
803 /* Make sure all deferred GPE tasks are completed */
804
805 AcpiOsWaitEventsComplete ();
806
805 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
806 if (ACPI_FAILURE (Status))
807 {
808 return_ACPI_STATUS (Status);
809 }
810
811 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
812
813 /* Ensure that we have a valid GPE number */
814
815 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
816 if (!GpeEventInfo)
817 {
818 Status = AE_BAD_PARAMETER;
819 goto UnlockAndExit;
820 }
821
822 /* Make sure that a handler is indeed installed */
823
824 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
825 ACPI_GPE_DISPATCH_HANDLER)
826 {
827 Status = AE_NOT_EXIST;
828 goto UnlockAndExit;
829 }
830
831 /* Make sure that the installed handler is the same */
832
833 if (GpeEventInfo->Dispatch.Handler->Address != Address)
834 {
835 Status = AE_BAD_PARAMETER;
836 goto UnlockAndExit;
837 }
838
839 /* Remove the handler */
840
841 Handler = GpeEventInfo->Dispatch.Handler;
842
843 /* Restore Method node (if any), set dispatch flags */
844
845 GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
846 GpeEventInfo->Flags &=
847 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
848 GpeEventInfo->Flags |= Handler->OriginalFlags;
849
850 /*
851 * If the GPE was previously associated with a method and it was
852 * enabled, it should be enabled at this point to restore the
853 * post-initialization configuration.
854 */
855 if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
856 Handler->OriginallyEnabled)
857 {
858 (void) AcpiEvAddGpeReference (GpeEventInfo);
859 }
860
861 /* Now we can free the handler object */
862
863 ACPI_FREE (Handler);
864
865
866UnlockAndExit:
867 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
868 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
869 return_ACPI_STATUS (Status);
870}
871
872ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
873
874
875/*******************************************************************************
876 *
877 * FUNCTION: AcpiAcquireGlobalLock
878 *
879 * PARAMETERS: Timeout - How long the caller is willing to wait
880 * Handle - Where the handle to the lock is returned
881 * (if acquired)
882 *
883 * RETURN: Status
884 *
885 * DESCRIPTION: Acquire the ACPI Global Lock
886 *
887 * Note: Allows callers with the same thread ID to acquire the global lock
888 * multiple times. In other words, externally, the behavior of the global lock
889 * is identical to an AML mutex. On the first acquire, a new handle is
890 * returned. On any subsequent calls to acquire by the same thread, the same
891 * handle is returned.
892 *
893 ******************************************************************************/
894
895ACPI_STATUS
896AcpiAcquireGlobalLock (
897 UINT16 Timeout,
898 UINT32 *Handle)
899{
900 ACPI_STATUS Status;
901
902
903 if (!Handle)
904 {
905 return (AE_BAD_PARAMETER);
906 }
907
908 /* Must lock interpreter to prevent race conditions */
909
910 AcpiExEnterInterpreter ();
911
912 Status = AcpiExAcquireMutexObject (Timeout,
913 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
914
915 if (ACPI_SUCCESS (Status))
916 {
917 /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
918
919 *Handle = AcpiGbl_GlobalLockHandle;
920 }
921
922 AcpiExExitInterpreter ();
923 return (Status);
924}
925
926ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
927
928
929/*******************************************************************************
930 *
931 * FUNCTION: AcpiReleaseGlobalLock
932 *
933 * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock
934 *
935 * RETURN: Status
936 *
937 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
938 *
939 ******************************************************************************/
940
941ACPI_STATUS
942AcpiReleaseGlobalLock (
943 UINT32 Handle)
944{
945 ACPI_STATUS Status;
946
947
948 if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
949 {
950 return (AE_NOT_ACQUIRED);
951 }
952
953 Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
954 return (Status);
955}
956
957ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
958
959#endif /* !ACPI_REDUCED_HARDWARE */
807 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
808 if (ACPI_FAILURE (Status))
809 {
810 return_ACPI_STATUS (Status);
811 }
812
813 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
814
815 /* Ensure that we have a valid GPE number */
816
817 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
818 if (!GpeEventInfo)
819 {
820 Status = AE_BAD_PARAMETER;
821 goto UnlockAndExit;
822 }
823
824 /* Make sure that a handler is indeed installed */
825
826 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
827 ACPI_GPE_DISPATCH_HANDLER)
828 {
829 Status = AE_NOT_EXIST;
830 goto UnlockAndExit;
831 }
832
833 /* Make sure that the installed handler is the same */
834
835 if (GpeEventInfo->Dispatch.Handler->Address != Address)
836 {
837 Status = AE_BAD_PARAMETER;
838 goto UnlockAndExit;
839 }
840
841 /* Remove the handler */
842
843 Handler = GpeEventInfo->Dispatch.Handler;
844
845 /* Restore Method node (if any), set dispatch flags */
846
847 GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
848 GpeEventInfo->Flags &=
849 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
850 GpeEventInfo->Flags |= Handler->OriginalFlags;
851
852 /*
853 * If the GPE was previously associated with a method and it was
854 * enabled, it should be enabled at this point to restore the
855 * post-initialization configuration.
856 */
857 if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
858 Handler->OriginallyEnabled)
859 {
860 (void) AcpiEvAddGpeReference (GpeEventInfo);
861 }
862
863 /* Now we can free the handler object */
864
865 ACPI_FREE (Handler);
866
867
868UnlockAndExit:
869 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
870 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
871 return_ACPI_STATUS (Status);
872}
873
874ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
875
876
877/*******************************************************************************
878 *
879 * FUNCTION: AcpiAcquireGlobalLock
880 *
881 * PARAMETERS: Timeout - How long the caller is willing to wait
882 * Handle - Where the handle to the lock is returned
883 * (if acquired)
884 *
885 * RETURN: Status
886 *
887 * DESCRIPTION: Acquire the ACPI Global Lock
888 *
889 * Note: Allows callers with the same thread ID to acquire the global lock
890 * multiple times. In other words, externally, the behavior of the global lock
891 * is identical to an AML mutex. On the first acquire, a new handle is
892 * returned. On any subsequent calls to acquire by the same thread, the same
893 * handle is returned.
894 *
895 ******************************************************************************/
896
897ACPI_STATUS
898AcpiAcquireGlobalLock (
899 UINT16 Timeout,
900 UINT32 *Handle)
901{
902 ACPI_STATUS Status;
903
904
905 if (!Handle)
906 {
907 return (AE_BAD_PARAMETER);
908 }
909
910 /* Must lock interpreter to prevent race conditions */
911
912 AcpiExEnterInterpreter ();
913
914 Status = AcpiExAcquireMutexObject (Timeout,
915 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
916
917 if (ACPI_SUCCESS (Status))
918 {
919 /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
920
921 *Handle = AcpiGbl_GlobalLockHandle;
922 }
923
924 AcpiExExitInterpreter ();
925 return (Status);
926}
927
928ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
929
930
931/*******************************************************************************
932 *
933 * FUNCTION: AcpiReleaseGlobalLock
934 *
935 * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock
936 *
937 * RETURN: Status
938 *
939 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
940 *
941 ******************************************************************************/
942
943ACPI_STATUS
944AcpiReleaseGlobalLock (
945 UINT32 Handle)
946{
947 ACPI_STATUS Status;
948
949
950 if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
951 {
952 return (AE_NOT_ACQUIRED);
953 }
954
955 Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
956 return (Status);
957}
958
959ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
960
961#endif /* !ACPI_REDUCED_HARDWARE */