1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2014, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
45 #define EXPORT_ACPI_INTERFACES
53 #define _COMPONENT ACPI_EVENTS
54 ACPI_MODULE_NAME ("evxface")
57 /*******************************************************************************
59 * FUNCTION: AcpiInstallNotifyHandler
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
71 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
72 * ThermalZone, or Processor object.
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
79 ******************************************************************************/
82 AcpiInstallNotifyHandler (
85 ACPI_NOTIFY_HANDLER Handler,
88 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
89 ACPI_OPERAND_OBJECT *ObjDesc;
90 ACPI_OPERAND_OBJECT *HandlerObj;
95 ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
98 /* Parameter validation */
100 if ((!Device) || (!Handler) || (!HandlerType) ||
101 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
103 return_ACPI_STATUS (AE_BAD_PARAMETER);
106 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
107 if (ACPI_FAILURE (Status))
109 return_ACPI_STATUS (Status);
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.
119 if (Device == ACPI_ROOT_OBJECT)
121 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
123 if (HandlerType & (i+1))
125 if (AcpiGbl_GlobalNotify[i].Handler)
127 Status = AE_ALREADY_EXISTS;
131 AcpiGbl_GlobalNotify[i].Handler = Handler;
132 AcpiGbl_GlobalNotify[i].Context = Context;
136 goto UnlockAndExit; /* Global notify handler installed, all done */
141 * Caller will only receive notifications specific to the target
142 * object. Note that only certain object types are allowed to
143 * receive notifications.
146 /* Are Notifies allowed on this object? */
148 if (!AcpiEvIsNotifyObject (Node))
154 /* Check for an existing internal object, might not exist */
156 ObjDesc = AcpiNsGetAttachedObject (Node);
159 /* Create a new object */
161 ObjDesc = AcpiUtCreateInternalObject (Node->Type);
164 Status = AE_NO_MEMORY;
168 /* Attach new object to the Node, remove local reference */
170 Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
171 AcpiUtRemoveReference (ObjDesc);
172 if (ACPI_FAILURE (Status))
178 /* Ensure that the handler is not already installed in the lists */
180 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
182 if (HandlerType & (i+1))
184 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
187 if (HandlerObj->Notify.Handler == Handler)
189 Status = AE_ALREADY_EXISTS;
193 HandlerObj = HandlerObj->Notify.Next[i];
198 /* Create and populate a new notify handler object */
200 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
203 Status = AE_NO_MEMORY;
207 HandlerObj->Notify.Node = Node;
208 HandlerObj->Notify.HandlerType = HandlerType;
209 HandlerObj->Notify.Handler = Handler;
210 HandlerObj->Notify.Context = Context;
212 /* Install the handler at the list head(s) */
214 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
216 if (HandlerType & (i+1))
218 HandlerObj->Notify.Next[i] =
219 ObjDesc->CommonNotify.NotifyList[i];
221 ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
225 /* Add an extra reference if handler was installed in both lists */
227 if (HandlerType == ACPI_ALL_NOTIFY)
229 AcpiUtAddReference (HandlerObj);
234 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
235 return_ACPI_STATUS (Status);
238 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
241 /*******************************************************************************
243 * FUNCTION: AcpiRemoveNotifyHandler
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
254 * DESCRIPTION: Remove a handler for notifies on an ACPI device
256 ******************************************************************************/
259 AcpiRemoveNotifyHandler (
262 ACPI_NOTIFY_HANDLER Handler)
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 = AE_OK;
272 ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
275 /* Parameter validation */
277 if ((!Device) || (!Handler) || (!HandlerType) ||
278 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
280 return_ACPI_STATUS (AE_BAD_PARAMETER);
283 /* Root Object. Global handlers are removed here */
285 if (Device == ACPI_ROOT_OBJECT)
287 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
289 if (HandlerType & (i+1))
291 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
292 if (ACPI_FAILURE (Status))
294 return_ACPI_STATUS (Status);
297 if (!AcpiGbl_GlobalNotify[i].Handler ||
298 (AcpiGbl_GlobalNotify[i].Handler != Handler))
300 Status = AE_NOT_EXIST;
304 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
305 "Removing global notify handler\n"));
307 AcpiGbl_GlobalNotify[i].Handler = NULL;
308 AcpiGbl_GlobalNotify[i].Context = NULL;
310 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
312 /* Make sure all deferred notify tasks are completed */
314 AcpiOsWaitEventsComplete ();
318 return_ACPI_STATUS (AE_OK);
321 /* All other objects: Are Notifies allowed on this object? */
323 if (!AcpiEvIsNotifyObject (Node))
325 return_ACPI_STATUS (AE_TYPE);
328 /* Must have an existing internal object */
330 ObjDesc = AcpiNsGetAttachedObject (Node);
333 return_ACPI_STATUS (AE_NOT_EXIST);
336 /* Internal object exists. Find the handler and remove it */
338 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
340 if (HandlerType & (i+1))
342 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
343 if (ACPI_FAILURE (Status))
345 return_ACPI_STATUS (Status);
348 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
349 PreviousHandlerObj = NULL;
351 /* Attempt to find the handler in the handler list */
354 (HandlerObj->Notify.Handler != Handler))
356 PreviousHandlerObj = HandlerObj;
357 HandlerObj = HandlerObj->Notify.Next[i];
362 Status = AE_NOT_EXIST;
366 /* Remove the handler object from the list */
368 if (PreviousHandlerObj) /* Handler is not at the list head */
370 PreviousHandlerObj->Notify.Next[i] =
371 HandlerObj->Notify.Next[i];
373 else /* Handler is at the list head */
375 ObjDesc->CommonNotify.NotifyList[i] =
376 HandlerObj->Notify.Next[i];
379 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
381 /* Make sure all deferred notify tasks are completed */
383 AcpiOsWaitEventsComplete ();
384 AcpiUtRemoveReference (HandlerObj);
388 return_ACPI_STATUS (Status);
392 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
393 return_ACPI_STATUS (Status);
396 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
399 /*******************************************************************************
401 * FUNCTION: AcpiInstallExceptionHandler
403 * PARAMETERS: Handler - Pointer to the handler function for the
408 * DESCRIPTION: Saves the pointer to the handler function
410 ******************************************************************************/
413 AcpiInstallExceptionHandler (
414 ACPI_EXCEPTION_HANDLER Handler)
419 ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
422 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
423 if (ACPI_FAILURE (Status))
425 return_ACPI_STATUS (Status);
428 /* Don't allow two handlers. */
430 if (AcpiGbl_ExceptionHandler)
432 Status = AE_ALREADY_EXISTS;
436 /* Install the handler */
438 AcpiGbl_ExceptionHandler = Handler;
441 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
442 return_ACPI_STATUS (Status);
445 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
448 #if (!ACPI_REDUCED_HARDWARE)
449 /*******************************************************************************
451 * FUNCTION: AcpiInstallSciHandler
453 * PARAMETERS: Address - Address of the handler
454 * Context - Value passed to the handler on each SCI
458 * DESCRIPTION: Install a handler for a System Control Interrupt.
460 ******************************************************************************/
463 AcpiInstallSciHandler (
464 ACPI_SCI_HANDLER Address,
467 ACPI_SCI_HANDLER_INFO *NewSciHandler;
468 ACPI_SCI_HANDLER_INFO *SciHandler;
469 ACPI_CPU_FLAGS Flags;
473 ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
478 return_ACPI_STATUS (AE_BAD_PARAMETER);
481 /* Allocate and init a handler object */
483 NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
486 return_ACPI_STATUS (AE_NO_MEMORY);
489 NewSciHandler->Address = Address;
490 NewSciHandler->Context = Context;
492 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
493 if (ACPI_FAILURE (Status))
498 /* Lock list during installation */
500 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
501 SciHandler = AcpiGbl_SciHandlerList;
503 /* Ensure handler does not already exist */
507 if (Address == SciHandler->Address)
509 Status = AE_ALREADY_EXISTS;
513 SciHandler = SciHandler->Next;
516 /* Install the new handler into the global list (at head) */
518 NewSciHandler->Next = AcpiGbl_SciHandlerList;
519 AcpiGbl_SciHandlerList = NewSciHandler;
524 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
525 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
528 if (ACPI_FAILURE (Status))
530 ACPI_FREE (NewSciHandler);
532 return_ACPI_STATUS (Status);
535 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
538 /*******************************************************************************
540 * FUNCTION: AcpiRemoveSciHandler
542 * PARAMETERS: Address - Address of the handler
546 * DESCRIPTION: Remove a handler for a System Control Interrupt.
548 ******************************************************************************/
551 AcpiRemoveSciHandler (
552 ACPI_SCI_HANDLER Address)
554 ACPI_SCI_HANDLER_INFO *PrevSciHandler;
555 ACPI_SCI_HANDLER_INFO *NextSciHandler;
556 ACPI_CPU_FLAGS Flags;
560 ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
565 return_ACPI_STATUS (AE_BAD_PARAMETER);
568 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
569 if (ACPI_FAILURE (Status))
571 return_ACPI_STATUS (Status);
574 /* Remove the SCI handler with lock */
576 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
578 PrevSciHandler = NULL;
579 NextSciHandler = AcpiGbl_SciHandlerList;
580 while (NextSciHandler)
582 if (NextSciHandler->Address == Address)
584 /* Unlink and free the SCI handler info block */
588 PrevSciHandler->Next = NextSciHandler->Next;
592 AcpiGbl_SciHandlerList = NextSciHandler->Next;
595 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
596 ACPI_FREE (NextSciHandler);
600 PrevSciHandler = NextSciHandler;
601 NextSciHandler = NextSciHandler->Next;
604 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
605 Status = AE_NOT_EXIST;
609 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
610 return_ACPI_STATUS (Status);
613 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
616 /*******************************************************************************
618 * FUNCTION: AcpiInstallGlobalEventHandler
620 * PARAMETERS: Handler - Pointer to the global event handler function
621 * Context - Value passed to the handler on each event
625 * DESCRIPTION: Saves the pointer to the handler function. The global handler
626 * is invoked upon each incoming GPE and Fixed Event. It is
627 * invoked at interrupt level at the time of the event dispatch.
628 * Can be used to update event counters, etc.
630 ******************************************************************************/
633 AcpiInstallGlobalEventHandler (
634 ACPI_GBL_EVENT_HANDLER Handler,
640 ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
643 /* Parameter validation */
647 return_ACPI_STATUS (AE_BAD_PARAMETER);
650 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
651 if (ACPI_FAILURE (Status))
653 return_ACPI_STATUS (Status);
656 /* Don't allow two handlers. */
658 if (AcpiGbl_GlobalEventHandler)
660 Status = AE_ALREADY_EXISTS;
664 AcpiGbl_GlobalEventHandler = Handler;
665 AcpiGbl_GlobalEventHandlerContext = Context;
669 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
670 return_ACPI_STATUS (Status);
673 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
676 /*******************************************************************************
678 * FUNCTION: AcpiInstallFixedEventHandler
680 * PARAMETERS: Event - Event type to enable.
681 * Handler - Pointer to the handler function for the
683 * Context - Value passed to the handler on each GPE
687 * DESCRIPTION: Saves the pointer to the handler function and then enables the
690 ******************************************************************************/
693 AcpiInstallFixedEventHandler (
695 ACPI_EVENT_HANDLER Handler,
701 ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
704 /* Parameter validation */
706 if (Event > ACPI_EVENT_MAX)
708 return_ACPI_STATUS (AE_BAD_PARAMETER);
711 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
712 if (ACPI_FAILURE (Status))
714 return_ACPI_STATUS (Status);
717 /* Do not allow multiple handlers */
719 if (AcpiGbl_FixedEventHandlers[Event].Handler)
721 Status = AE_ALREADY_EXISTS;
725 /* Install the handler before enabling the event */
727 AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
728 AcpiGbl_FixedEventHandlers[Event].Context = Context;
730 Status = AcpiEnableEvent (Event, 0);
731 if (ACPI_FAILURE (Status))
733 ACPI_WARNING ((AE_INFO,
734 "Could not enable fixed event - %s (%u)",
735 AcpiUtGetEventName (Event), Event));
737 /* Remove the handler */
739 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
740 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
744 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
745 "Enabled fixed event %s (%X), Handler=%p\n",
746 AcpiUtGetEventName (Event), Event, Handler));
751 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
752 return_ACPI_STATUS (Status);
755 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
758 /*******************************************************************************
760 * FUNCTION: AcpiRemoveFixedEventHandler
762 * PARAMETERS: Event - Event type to disable.
763 * Handler - Address of the handler
767 * DESCRIPTION: Disables the event and unregisters the event handler.
769 ******************************************************************************/
772 AcpiRemoveFixedEventHandler (
774 ACPI_EVENT_HANDLER Handler)
776 ACPI_STATUS Status = AE_OK;
779 ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
782 /* Parameter validation */
784 if (Event > ACPI_EVENT_MAX)
786 return_ACPI_STATUS (AE_BAD_PARAMETER);
789 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
790 if (ACPI_FAILURE (Status))
792 return_ACPI_STATUS (Status);
795 /* Disable the event before removing the handler */
797 Status = AcpiDisableEvent (Event, 0);
799 /* Always Remove the handler */
801 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
802 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
804 if (ACPI_FAILURE (Status))
806 ACPI_WARNING ((AE_INFO,
807 "Could not disable fixed event - %s (%u)",
808 AcpiUtGetEventName (Event), Event));
812 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
813 "Disabled fixed event - %s (%X)\n",
814 AcpiUtGetEventName (Event), Event));
817 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
818 return_ACPI_STATUS (Status);
821 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
824 /*******************************************************************************
826 * FUNCTION: AcpiInstallGpeHandler
828 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
830 * GpeNumber - The GPE number within the GPE block
831 * Type - Whether this GPE should be treated as an
832 * edge- or level-triggered interrupt.
833 * Address - Address of the handler
834 * Context - Value passed to the handler on each GPE
838 * DESCRIPTION: Install a handler for a General Purpose Event.
840 ******************************************************************************/
843 AcpiInstallGpeHandler (
844 ACPI_HANDLE GpeDevice,
847 ACPI_GPE_HANDLER Address,
850 ACPI_GPE_EVENT_INFO *GpeEventInfo;
851 ACPI_GPE_HANDLER_INFO *Handler;
853 ACPI_CPU_FLAGS Flags;
856 ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
859 /* Parameter validation */
861 if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
863 return_ACPI_STATUS (AE_BAD_PARAMETER);
866 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
867 if (ACPI_FAILURE (Status))
869 return_ACPI_STATUS (Status);
872 /* Allocate and init handler object (before lock) */
874 Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
877 Status = AE_NO_MEMORY;
881 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
883 /* Ensure that we have a valid GPE number */
885 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
888 Status = AE_BAD_PARAMETER;
892 /* Make sure that there isn't a handler there already */
894 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
895 ACPI_GPE_DISPATCH_HANDLER)
897 Status = AE_ALREADY_EXISTS;
901 Handler->Address = Address;
902 Handler->Context = Context;
903 Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
904 Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
905 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
908 * If the GPE is associated with a method, it may have been enabled
909 * automatically during initialization, in which case it has to be
910 * disabled now to avoid spurious execution of the handler.
912 if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
913 (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
914 GpeEventInfo->RuntimeCount)
916 Handler->OriginallyEnabled = TRUE;
917 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
919 /* Sanity check of original type against new type */
921 if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
923 ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
927 /* Install the handler */
929 GpeEventInfo->Dispatch.Handler = Handler;
931 /* Setup up dispatch flags to indicate handler (vs. method/notify) */
933 GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
934 GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
936 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
940 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
941 return_ACPI_STATUS (Status);
944 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
949 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
952 /*******************************************************************************
954 * FUNCTION: AcpiRemoveGpeHandler
956 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
958 * GpeNumber - The event to remove a handler
959 * Address - Address of the handler
963 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
965 ******************************************************************************/
968 AcpiRemoveGpeHandler (
969 ACPI_HANDLE GpeDevice,
971 ACPI_GPE_HANDLER Address)
973 ACPI_GPE_EVENT_INFO *GpeEventInfo;
974 ACPI_GPE_HANDLER_INFO *Handler;
976 ACPI_CPU_FLAGS Flags;
979 ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
982 /* Parameter validation */
986 return_ACPI_STATUS (AE_BAD_PARAMETER);
989 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
990 if (ACPI_FAILURE (Status))
992 return_ACPI_STATUS (Status);
995 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
997 /* Ensure that we have a valid GPE number */
999 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1002 Status = AE_BAD_PARAMETER;
1006 /* Make sure that a handler is indeed installed */
1008 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
1009 ACPI_GPE_DISPATCH_HANDLER)
1011 Status = AE_NOT_EXIST;
1015 /* Make sure that the installed handler is the same */
1017 if (GpeEventInfo->Dispatch.Handler->Address != Address)
1019 Status = AE_BAD_PARAMETER;
1023 /* Remove the handler */
1025 Handler = GpeEventInfo->Dispatch.Handler;
1027 /* Restore Method node (if any), set dispatch flags */
1029 GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1030 GpeEventInfo->Flags &=
1031 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1032 GpeEventInfo->Flags |= Handler->OriginalFlags;
1035 * If the GPE was previously associated with a method and it was
1036 * enabled, it should be enabled at this point to restore the
1037 * post-initialization configuration.
1039 if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
1040 Handler->OriginallyEnabled)
1042 (void) AcpiEvAddGpeReference (GpeEventInfo);
1045 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1046 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1048 /* Make sure all deferred GPE tasks are completed */
1050 AcpiOsWaitEventsComplete ();
1052 /* Now we can free the handler object */
1054 ACPI_FREE (Handler);
1055 return_ACPI_STATUS (Status);
1058 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1059 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1060 return_ACPI_STATUS (Status);
1063 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1066 /*******************************************************************************
1068 * FUNCTION: AcpiAcquireGlobalLock
1070 * PARAMETERS: Timeout - How long the caller is willing to wait
1071 * Handle - Where the handle to the lock is returned
1076 * DESCRIPTION: Acquire the ACPI Global Lock
1078 * Note: Allows callers with the same thread ID to acquire the global lock
1079 * multiple times. In other words, externally, the behavior of the global lock
1080 * is identical to an AML mutex. On the first acquire, a new handle is
1081 * returned. On any subsequent calls to acquire by the same thread, the same
1082 * handle is returned.
1084 ******************************************************************************/
1087 AcpiAcquireGlobalLock (
1096 return (AE_BAD_PARAMETER);
1099 /* Must lock interpreter to prevent race conditions */
1101 AcpiExEnterInterpreter ();
1103 Status = AcpiExAcquireMutexObject (Timeout,
1104 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1106 if (ACPI_SUCCESS (Status))
1108 /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1110 *Handle = AcpiGbl_GlobalLockHandle;
1113 AcpiExExitInterpreter ();
1117 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1120 /*******************************************************************************
1122 * FUNCTION: AcpiReleaseGlobalLock
1124 * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock
1128 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1130 ******************************************************************************/
1133 AcpiReleaseGlobalLock (
1139 if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1141 return (AE_NOT_ACQUIRED);
1144 Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1148 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1150 #endif /* !ACPI_REDUCED_HARDWARE */