dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / uts / intel / io / acpica / events / evxface.c
blobedace796492894c4895ba0847d86691470b1a3ca
1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
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.
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.
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.
44 #define EXPORT_ACPI_INTERFACES
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acnamesp.h"
49 #include "acevents.h"
50 #include "acinterp.h"
52 #define _COMPONENT ACPI_EVENTS
53 ACPI_MODULE_NAME ("evxface")
55 #if (!ACPI_REDUCED_HARDWARE)
57 /* Local prototypes */
59 static ACPI_STATUS
60 AcpiEvInstallGpeHandler (
61 ACPI_HANDLE GpeDevice,
62 UINT32 GpeNumber,
63 UINT32 Type,
64 BOOLEAN IsRawHandler,
65 ACPI_GPE_HANDLER Address,
66 void *Context);
68 #endif
71 /*******************************************************************************
73 * FUNCTION: AcpiInstallNotifyHandler
75 * PARAMETERS: Device - The device for which notifies will be handled
76 * HandlerType - The type of handler:
77 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
78 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
79 * ACPI_ALL_NOTIFY: Both System and Device
80 * Handler - Address of the handler
81 * Context - Value passed to the handler on each GPE
83 * RETURN: Status
85 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
86 * ThermalZone, or Processor object.
88 * NOTES: The Root namespace object may have only one handler for each
89 * type of notify (System/Device). Device/Thermal/Processor objects
90 * may have one device notify handler, and multiple system notify
91 * handlers.
93 ******************************************************************************/
95 ACPI_STATUS
96 AcpiInstallNotifyHandler (
97 ACPI_HANDLE Device,
98 UINT32 HandlerType,
99 ACPI_NOTIFY_HANDLER Handler,
100 void *Context)
102 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
103 ACPI_OPERAND_OBJECT *ObjDesc;
104 ACPI_OPERAND_OBJECT *HandlerObj;
105 ACPI_STATUS Status;
106 UINT32 i;
109 ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
112 /* Parameter validation */
114 if ((!Device) || (!Handler) || (!HandlerType) ||
115 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
117 return_ACPI_STATUS (AE_BAD_PARAMETER);
120 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
121 if (ACPI_FAILURE (Status))
123 return_ACPI_STATUS (Status);
127 * Root Object:
128 * Registering a notify handler on the root object indicates that the
129 * caller wishes to receive notifications for all objects. Note that
130 * only one global handler can be registered per notify type.
131 * Ensure that a handler is not already installed.
133 if (Device == ACPI_ROOT_OBJECT)
135 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
137 if (HandlerType & (i+1))
139 if (AcpiGbl_GlobalNotify[i].Handler)
141 Status = AE_ALREADY_EXISTS;
142 goto UnlockAndExit;
145 AcpiGbl_GlobalNotify[i].Handler = Handler;
146 AcpiGbl_GlobalNotify[i].Context = Context;
150 goto UnlockAndExit; /* Global notify handler installed, all done */
154 * All Other Objects:
155 * Caller will only receive notifications specific to the target
156 * object. Note that only certain object types are allowed to
157 * receive notifications.
160 /* Are Notifies allowed on this object? */
162 if (!AcpiEvIsNotifyObject (Node))
164 Status = AE_TYPE;
165 goto UnlockAndExit;
168 /* Check for an existing internal object, might not exist */
170 ObjDesc = AcpiNsGetAttachedObject (Node);
171 if (!ObjDesc)
173 /* Create a new object */
175 ObjDesc = AcpiUtCreateInternalObject (Node->Type);
176 if (!ObjDesc)
178 Status = AE_NO_MEMORY;
179 goto UnlockAndExit;
182 /* Attach new object to the Node, remove local reference */
184 Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
185 AcpiUtRemoveReference (ObjDesc);
186 if (ACPI_FAILURE (Status))
188 goto UnlockAndExit;
192 /* Ensure that the handler is not already installed in the lists */
194 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
196 if (HandlerType & (i+1))
198 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
199 while (HandlerObj)
201 if (HandlerObj->Notify.Handler == Handler)
203 Status = AE_ALREADY_EXISTS;
204 goto UnlockAndExit;
207 HandlerObj = HandlerObj->Notify.Next[i];
212 /* Create and populate a new notify handler object */
214 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
215 if (!HandlerObj)
217 Status = AE_NO_MEMORY;
218 goto UnlockAndExit;
221 HandlerObj->Notify.Node = Node;
222 HandlerObj->Notify.HandlerType = HandlerType;
223 HandlerObj->Notify.Handler = Handler;
224 HandlerObj->Notify.Context = Context;
226 /* Install the handler at the list head(s) */
228 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
230 if (HandlerType & (i+1))
232 HandlerObj->Notify.Next[i] =
233 ObjDesc->CommonNotify.NotifyList[i];
235 ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
239 /* Add an extra reference if handler was installed in both lists */
241 if (HandlerType == ACPI_ALL_NOTIFY)
243 AcpiUtAddReference (HandlerObj);
247 UnlockAndExit:
248 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
249 return_ACPI_STATUS (Status);
252 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
255 /*******************************************************************************
257 * FUNCTION: AcpiRemoveNotifyHandler
259 * PARAMETERS: Device - The device for which the handler is installed
260 * HandlerType - The type of handler:
261 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
262 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
263 * ACPI_ALL_NOTIFY: Both System and Device
264 * Handler - Address of the handler
266 * RETURN: Status
268 * DESCRIPTION: Remove a handler for notifies on an ACPI device
270 ******************************************************************************/
272 ACPI_STATUS
273 AcpiRemoveNotifyHandler (
274 ACPI_HANDLE Device,
275 UINT32 HandlerType,
276 ACPI_NOTIFY_HANDLER Handler)
278 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
279 ACPI_OPERAND_OBJECT *ObjDesc;
280 ACPI_OPERAND_OBJECT *HandlerObj;
281 ACPI_OPERAND_OBJECT *PreviousHandlerObj;
282 ACPI_STATUS Status = AE_OK;
283 UINT32 i;
286 ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
289 /* Parameter validation */
291 if ((!Device) || (!Handler) || (!HandlerType) ||
292 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
294 return_ACPI_STATUS (AE_BAD_PARAMETER);
297 /* Root Object. Global handlers are removed here */
299 if (Device == ACPI_ROOT_OBJECT)
301 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
303 if (HandlerType & (i+1))
305 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
306 if (ACPI_FAILURE (Status))
308 return_ACPI_STATUS (Status);
311 if (!AcpiGbl_GlobalNotify[i].Handler ||
312 (AcpiGbl_GlobalNotify[i].Handler != Handler))
314 Status = AE_NOT_EXIST;
315 goto UnlockAndExit;
318 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
319 "Removing global notify handler\n"));
321 AcpiGbl_GlobalNotify[i].Handler = NULL;
322 AcpiGbl_GlobalNotify[i].Context = NULL;
324 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
326 /* Make sure all deferred notify tasks are completed */
328 AcpiOsWaitEventsComplete ();
332 return_ACPI_STATUS (AE_OK);
335 /* All other objects: Are Notifies allowed on this object? */
337 if (!AcpiEvIsNotifyObject (Node))
339 return_ACPI_STATUS (AE_TYPE);
342 /* Must have an existing internal object */
344 ObjDesc = AcpiNsGetAttachedObject (Node);
345 if (!ObjDesc)
347 return_ACPI_STATUS (AE_NOT_EXIST);
350 /* Internal object exists. Find the handler and remove it */
352 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
354 if (HandlerType & (i+1))
356 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
357 if (ACPI_FAILURE (Status))
359 return_ACPI_STATUS (Status);
362 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
363 PreviousHandlerObj = NULL;
365 /* Attempt to find the handler in the handler list */
367 while (HandlerObj &&
368 (HandlerObj->Notify.Handler != Handler))
370 PreviousHandlerObj = HandlerObj;
371 HandlerObj = HandlerObj->Notify.Next[i];
374 if (!HandlerObj)
376 Status = AE_NOT_EXIST;
377 goto UnlockAndExit;
380 /* Remove the handler object from the list */
382 if (PreviousHandlerObj) /* Handler is not at the list head */
384 PreviousHandlerObj->Notify.Next[i] =
385 HandlerObj->Notify.Next[i];
387 else /* Handler is at the list head */
389 ObjDesc->CommonNotify.NotifyList[i] =
390 HandlerObj->Notify.Next[i];
393 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
395 /* Make sure all deferred notify tasks are completed */
397 AcpiOsWaitEventsComplete ();
398 AcpiUtRemoveReference (HandlerObj);
402 return_ACPI_STATUS (Status);
405 UnlockAndExit:
406 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
407 return_ACPI_STATUS (Status);
410 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
413 /*******************************************************************************
415 * FUNCTION: AcpiInstallExceptionHandler
417 * PARAMETERS: Handler - Pointer to the handler function for the
418 * event
420 * RETURN: Status
422 * DESCRIPTION: Saves the pointer to the handler function
424 ******************************************************************************/
426 ACPI_STATUS
427 AcpiInstallExceptionHandler (
428 ACPI_EXCEPTION_HANDLER Handler)
430 ACPI_STATUS Status;
433 ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
436 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
437 if (ACPI_FAILURE (Status))
439 return_ACPI_STATUS (Status);
442 /* Don't allow two handlers. */
444 if (AcpiGbl_ExceptionHandler)
446 Status = AE_ALREADY_EXISTS;
447 goto Cleanup;
450 /* Install the handler */
452 AcpiGbl_ExceptionHandler = Handler;
454 Cleanup:
455 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
456 return_ACPI_STATUS (Status);
459 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
462 #if (!ACPI_REDUCED_HARDWARE)
463 /*******************************************************************************
465 * FUNCTION: AcpiInstallSciHandler
467 * PARAMETERS: Address - Address of the handler
468 * Context - Value passed to the handler on each SCI
470 * RETURN: Status
472 * DESCRIPTION: Install a handler for a System Control Interrupt.
474 ******************************************************************************/
476 ACPI_STATUS
477 AcpiInstallSciHandler (
478 ACPI_SCI_HANDLER Address,
479 void *Context)
481 ACPI_SCI_HANDLER_INFO *NewSciHandler;
482 ACPI_SCI_HANDLER_INFO *SciHandler;
483 ACPI_CPU_FLAGS Flags;
484 ACPI_STATUS Status;
487 ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
490 if (!Address)
492 return_ACPI_STATUS (AE_BAD_PARAMETER);
495 /* Allocate and init a handler object */
497 NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
498 if (!NewSciHandler)
500 return_ACPI_STATUS (AE_NO_MEMORY);
503 NewSciHandler->Address = Address;
504 NewSciHandler->Context = Context;
506 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
507 if (ACPI_FAILURE (Status))
509 goto Exit;
512 /* Lock list during installation */
514 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
515 SciHandler = AcpiGbl_SciHandlerList;
517 /* Ensure handler does not already exist */
519 while (SciHandler)
521 if (Address == SciHandler->Address)
523 Status = AE_ALREADY_EXISTS;
524 goto UnlockAndExit;
527 SciHandler = SciHandler->Next;
530 /* Install the new handler into the global list (at head) */
532 NewSciHandler->Next = AcpiGbl_SciHandlerList;
533 AcpiGbl_SciHandlerList = NewSciHandler;
536 UnlockAndExit:
538 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
539 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
541 Exit:
542 if (ACPI_FAILURE (Status))
544 ACPI_FREE (NewSciHandler);
546 return_ACPI_STATUS (Status);
549 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
552 /*******************************************************************************
554 * FUNCTION: AcpiRemoveSciHandler
556 * PARAMETERS: Address - Address of the handler
558 * RETURN: Status
560 * DESCRIPTION: Remove a handler for a System Control Interrupt.
562 ******************************************************************************/
564 ACPI_STATUS
565 AcpiRemoveSciHandler (
566 ACPI_SCI_HANDLER Address)
568 ACPI_SCI_HANDLER_INFO *PrevSciHandler;
569 ACPI_SCI_HANDLER_INFO *NextSciHandler;
570 ACPI_CPU_FLAGS Flags;
571 ACPI_STATUS Status;
574 ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
577 if (!Address)
579 return_ACPI_STATUS (AE_BAD_PARAMETER);
582 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
583 if (ACPI_FAILURE (Status))
585 return_ACPI_STATUS (Status);
588 /* Remove the SCI handler with lock */
590 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
592 PrevSciHandler = NULL;
593 NextSciHandler = AcpiGbl_SciHandlerList;
594 while (NextSciHandler)
596 if (NextSciHandler->Address == Address)
598 /* Unlink and free the SCI handler info block */
600 if (PrevSciHandler)
602 PrevSciHandler->Next = NextSciHandler->Next;
604 else
606 AcpiGbl_SciHandlerList = NextSciHandler->Next;
609 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
610 ACPI_FREE (NextSciHandler);
611 goto UnlockAndExit;
614 PrevSciHandler = NextSciHandler;
615 NextSciHandler = NextSciHandler->Next;
618 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
619 Status = AE_NOT_EXIST;
622 UnlockAndExit:
623 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
624 return_ACPI_STATUS (Status);
627 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
630 /*******************************************************************************
632 * FUNCTION: AcpiInstallGlobalEventHandler
634 * PARAMETERS: Handler - Pointer to the global event handler function
635 * Context - Value passed to the handler on each event
637 * RETURN: Status
639 * DESCRIPTION: Saves the pointer to the handler function. The global handler
640 * is invoked upon each incoming GPE and Fixed Event. It is
641 * invoked at interrupt level at the time of the event dispatch.
642 * Can be used to update event counters, etc.
644 ******************************************************************************/
646 ACPI_STATUS
647 AcpiInstallGlobalEventHandler (
648 ACPI_GBL_EVENT_HANDLER Handler,
649 void *Context)
651 ACPI_STATUS Status;
654 ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
657 /* Parameter validation */
659 if (!Handler)
661 return_ACPI_STATUS (AE_BAD_PARAMETER);
664 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
665 if (ACPI_FAILURE (Status))
667 return_ACPI_STATUS (Status);
670 /* Don't allow two handlers. */
672 if (AcpiGbl_GlobalEventHandler)
674 Status = AE_ALREADY_EXISTS;
675 goto Cleanup;
678 AcpiGbl_GlobalEventHandler = Handler;
679 AcpiGbl_GlobalEventHandlerContext = Context;
682 Cleanup:
683 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
684 return_ACPI_STATUS (Status);
687 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
690 /*******************************************************************************
692 * FUNCTION: AcpiInstallFixedEventHandler
694 * PARAMETERS: Event - Event type to enable.
695 * Handler - Pointer to the handler function for the
696 * event
697 * Context - Value passed to the handler on each GPE
699 * RETURN: Status
701 * DESCRIPTION: Saves the pointer to the handler function and then enables the
702 * event.
704 ******************************************************************************/
706 ACPI_STATUS
707 AcpiInstallFixedEventHandler (
708 UINT32 Event,
709 ACPI_EVENT_HANDLER Handler,
710 void *Context)
712 ACPI_STATUS Status;
715 ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
718 /* Parameter validation */
720 if (Event > ACPI_EVENT_MAX)
722 return_ACPI_STATUS (AE_BAD_PARAMETER);
725 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
726 if (ACPI_FAILURE (Status))
728 return_ACPI_STATUS (Status);
731 /* Do not allow multiple handlers */
733 if (AcpiGbl_FixedEventHandlers[Event].Handler)
735 Status = AE_ALREADY_EXISTS;
736 goto Cleanup;
739 /* Install the handler before enabling the event */
741 AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
742 AcpiGbl_FixedEventHandlers[Event].Context = Context;
744 Status = AcpiEnableEvent (Event, 0);
745 if (ACPI_FAILURE (Status))
747 ACPI_WARNING ((AE_INFO,
748 "Could not enable fixed event - %s (%u)",
749 AcpiUtGetEventName (Event), Event));
751 /* Remove the handler */
753 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
754 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
756 else
758 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
759 "Enabled fixed event %s (%X), Handler=%p\n",
760 AcpiUtGetEventName (Event), Event, Handler));
764 Cleanup:
765 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
766 return_ACPI_STATUS (Status);
769 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
772 /*******************************************************************************
774 * FUNCTION: AcpiRemoveFixedEventHandler
776 * PARAMETERS: Event - Event type to disable.
777 * Handler - Address of the handler
779 * RETURN: Status
781 * DESCRIPTION: Disables the event and unregisters the event handler.
783 ******************************************************************************/
785 ACPI_STATUS
786 AcpiRemoveFixedEventHandler (
787 UINT32 Event,
788 ACPI_EVENT_HANDLER Handler)
790 ACPI_STATUS Status = AE_OK;
793 ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
796 /* Parameter validation */
798 if (Event > ACPI_EVENT_MAX)
800 return_ACPI_STATUS (AE_BAD_PARAMETER);
803 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
804 if (ACPI_FAILURE (Status))
806 return_ACPI_STATUS (Status);
809 /* Disable the event before removing the handler */
811 Status = AcpiDisableEvent (Event, 0);
813 /* Always Remove the handler */
815 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
816 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
818 if (ACPI_FAILURE (Status))
820 ACPI_WARNING ((AE_INFO,
821 "Could not disable fixed event - %s (%u)",
822 AcpiUtGetEventName (Event), Event));
824 else
826 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
827 "Disabled fixed event - %s (%X)\n",
828 AcpiUtGetEventName (Event), Event));
831 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
832 return_ACPI_STATUS (Status);
835 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
838 /*******************************************************************************
840 * FUNCTION: AcpiEvInstallGpeHandler
842 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
843 * defined GPEs)
844 * GpeNumber - The GPE number within the GPE block
845 * Type - Whether this GPE should be treated as an
846 * edge- or level-triggered interrupt.
847 * IsRawHandler - Whether this GPE should be handled using
848 * the special GPE handler mode.
849 * Address - Address of the handler
850 * Context - Value passed to the handler on each GPE
852 * RETURN: Status
854 * DESCRIPTION: Internal function to install a handler for a General Purpose
855 * Event.
857 ******************************************************************************/
859 static ACPI_STATUS
860 AcpiEvInstallGpeHandler (
861 ACPI_HANDLE GpeDevice,
862 UINT32 GpeNumber,
863 UINT32 Type,
864 BOOLEAN IsRawHandler,
865 ACPI_GPE_HANDLER Address,
866 void *Context)
868 ACPI_GPE_EVENT_INFO *GpeEventInfo;
869 ACPI_GPE_HANDLER_INFO *Handler;
870 ACPI_STATUS Status;
871 ACPI_CPU_FLAGS Flags;
874 ACPI_FUNCTION_TRACE (EvInstallGpeHandler);
877 /* Parameter validation */
879 if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
881 return_ACPI_STATUS (AE_BAD_PARAMETER);
884 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
885 if (ACPI_FAILURE (Status))
887 return_ACPI_STATUS (Status);
890 /* Allocate and init handler object (before lock) */
892 Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
893 if (!Handler)
895 Status = AE_NO_MEMORY;
896 goto UnlockAndExit;
899 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
901 /* Ensure that we have a valid GPE number */
903 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
904 if (!GpeEventInfo)
906 Status = AE_BAD_PARAMETER;
907 goto FreeAndExit;
910 /* Make sure that there isn't a handler there already */
912 if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
913 ACPI_GPE_DISPATCH_HANDLER) ||
914 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
915 ACPI_GPE_DISPATCH_RAW_HANDLER))
917 Status = AE_ALREADY_EXISTS;
918 goto FreeAndExit;
921 Handler->Address = Address;
922 Handler->Context = Context;
923 Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
924 Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
925 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
928 * If the GPE is associated with a method, it may have been enabled
929 * automatically during initialization, in which case it has to be
930 * disabled now to avoid spurious execution of the handler.
932 if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
933 ACPI_GPE_DISPATCH_METHOD) ||
934 (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
935 ACPI_GPE_DISPATCH_NOTIFY)) &&
936 GpeEventInfo->RuntimeCount)
938 Handler->OriginallyEnabled = TRUE;
939 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
941 /* Sanity check of original type against new type */
943 if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
945 ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
949 /* Install the handler */
951 GpeEventInfo->Dispatch.Handler = Handler;
953 /* Setup up dispatch flags to indicate handler (vs. method/notify) */
955 GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
956 GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ?
957 ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER));
959 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
962 UnlockAndExit:
963 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
964 return_ACPI_STATUS (Status);
966 FreeAndExit:
967 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
968 ACPI_FREE (Handler);
969 goto UnlockAndExit;
973 /*******************************************************************************
975 * FUNCTION: AcpiInstallGpeHandler
977 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
978 * defined GPEs)
979 * GpeNumber - The GPE number within the GPE block
980 * Type - Whether this GPE should be treated as an
981 * edge- or level-triggered interrupt.
982 * Address - Address of the handler
983 * Context - Value passed to the handler on each GPE
985 * RETURN: Status
987 * DESCRIPTION: Install a handler for a General Purpose Event.
989 ******************************************************************************/
991 ACPI_STATUS
992 AcpiInstallGpeHandler (
993 ACPI_HANDLE GpeDevice,
994 UINT32 GpeNumber,
995 UINT32 Type,
996 ACPI_GPE_HANDLER Address,
997 void *Context)
999 ACPI_STATUS Status;
1002 ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
1005 Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1006 FALSE, Address, Context);
1008 return_ACPI_STATUS (Status);
1011 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
1014 /*******************************************************************************
1016 * FUNCTION: AcpiInstallGpeRawHandler
1018 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
1019 * defined GPEs)
1020 * GpeNumber - The GPE number within the GPE block
1021 * Type - Whether this GPE should be treated as an
1022 * edge- or level-triggered interrupt.
1023 * Address - Address of the handler
1024 * Context - Value passed to the handler on each GPE
1026 * RETURN: Status
1028 * DESCRIPTION: Install a handler for a General Purpose Event.
1030 ******************************************************************************/
1032 ACPI_STATUS
1033 AcpiInstallGpeRawHandler (
1034 ACPI_HANDLE GpeDevice,
1035 UINT32 GpeNumber,
1036 UINT32 Type,
1037 ACPI_GPE_HANDLER Address,
1038 void *Context)
1040 ACPI_STATUS Status;
1043 ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler);
1046 Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1047 TRUE, Address, Context);
1049 return_ACPI_STATUS (Status);
1052 ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler)
1055 /*******************************************************************************
1057 * FUNCTION: AcpiRemoveGpeHandler
1059 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
1060 * defined GPEs)
1061 * GpeNumber - The event to remove a handler
1062 * Address - Address of the handler
1064 * RETURN: Status
1066 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
1068 ******************************************************************************/
1070 ACPI_STATUS
1071 AcpiRemoveGpeHandler (
1072 ACPI_HANDLE GpeDevice,
1073 UINT32 GpeNumber,
1074 ACPI_GPE_HANDLER Address)
1076 ACPI_GPE_EVENT_INFO *GpeEventInfo;
1077 ACPI_GPE_HANDLER_INFO *Handler;
1078 ACPI_STATUS Status;
1079 ACPI_CPU_FLAGS Flags;
1082 ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
1085 /* Parameter validation */
1087 if (!Address)
1089 return_ACPI_STATUS (AE_BAD_PARAMETER);
1092 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1093 if (ACPI_FAILURE (Status))
1095 return_ACPI_STATUS (Status);
1098 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1100 /* Ensure that we have a valid GPE number */
1102 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1103 if (!GpeEventInfo)
1105 Status = AE_BAD_PARAMETER;
1106 goto UnlockAndExit;
1109 /* Make sure that a handler is indeed installed */
1111 if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1112 ACPI_GPE_DISPATCH_HANDLER) &&
1113 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1114 ACPI_GPE_DISPATCH_RAW_HANDLER))
1116 Status = AE_NOT_EXIST;
1117 goto UnlockAndExit;
1120 /* Make sure that the installed handler is the same */
1122 if (GpeEventInfo->Dispatch.Handler->Address != Address)
1124 Status = AE_BAD_PARAMETER;
1125 goto UnlockAndExit;
1128 /* Remove the handler */
1130 Handler = GpeEventInfo->Dispatch.Handler;
1131 GpeEventInfo->Dispatch.Handler = NULL;
1133 /* Restore Method node (if any), set dispatch flags */
1135 GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1136 GpeEventInfo->Flags &=
1137 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1138 GpeEventInfo->Flags |= Handler->OriginalFlags;
1141 * If the GPE was previously associated with a method and it was
1142 * enabled, it should be enabled at this point to restore the
1143 * post-initialization configuration.
1145 if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1146 ACPI_GPE_DISPATCH_METHOD) ||
1147 (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1148 ACPI_GPE_DISPATCH_NOTIFY)) &&
1149 Handler->OriginallyEnabled)
1151 (void) AcpiEvAddGpeReference (GpeEventInfo);
1154 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1155 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1157 /* Make sure all deferred GPE tasks are completed */
1159 AcpiOsWaitEventsComplete ();
1161 /* Now we can free the handler object */
1163 ACPI_FREE (Handler);
1164 return_ACPI_STATUS (Status);
1166 UnlockAndExit:
1167 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1168 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1169 return_ACPI_STATUS (Status);
1172 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1175 /*******************************************************************************
1177 * FUNCTION: AcpiAcquireGlobalLock
1179 * PARAMETERS: Timeout - How long the caller is willing to wait
1180 * Handle - Where the handle to the lock is returned
1181 * (if acquired)
1183 * RETURN: Status
1185 * DESCRIPTION: Acquire the ACPI Global Lock
1187 * Note: Allows callers with the same thread ID to acquire the global lock
1188 * multiple times. In other words, externally, the behavior of the global lock
1189 * is identical to an AML mutex. On the first acquire, a new handle is
1190 * returned. On any subsequent calls to acquire by the same thread, the same
1191 * handle is returned.
1193 ******************************************************************************/
1195 ACPI_STATUS
1196 AcpiAcquireGlobalLock (
1197 UINT16 Timeout,
1198 UINT32 *Handle)
1200 ACPI_STATUS Status;
1203 if (!Handle)
1205 return (AE_BAD_PARAMETER);
1208 /* Must lock interpreter to prevent race conditions */
1210 AcpiExEnterInterpreter ();
1212 Status = AcpiExAcquireMutexObject (Timeout,
1213 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1215 if (ACPI_SUCCESS (Status))
1217 /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1219 *Handle = AcpiGbl_GlobalLockHandle;
1222 AcpiExExitInterpreter ();
1223 return (Status);
1226 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1229 /*******************************************************************************
1231 * FUNCTION: AcpiReleaseGlobalLock
1233 * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock
1235 * RETURN: Status
1237 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1239 ******************************************************************************/
1241 ACPI_STATUS
1242 AcpiReleaseGlobalLock (
1243 UINT32 Handle)
1245 ACPI_STATUS Status;
1248 if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1250 return (AE_NOT_ACQUIRED);
1253 Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1254 return (Status);
1257 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1259 #endif /* !ACPI_REDUCED_HARDWARE */