xref: /freebsd/sys/contrib/dev/acpica/components/events/evxface.c (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2022, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #define EXPORT_ACPI_INTERFACES
153 
154 #include <contrib/dev/acpica/include/acpi.h>
155 #include <contrib/dev/acpica/include/accommon.h>
156 #include <contrib/dev/acpica/include/acnamesp.h>
157 #include <contrib/dev/acpica/include/acevents.h>
158 #include <contrib/dev/acpica/include/acinterp.h>
159 
160 #define _COMPONENT          ACPI_EVENTS
161         ACPI_MODULE_NAME    ("evxface")
162 
163 #if (!ACPI_REDUCED_HARDWARE)
164 
165 /* Local prototypes */
166 
167 static ACPI_STATUS
168 AcpiEvInstallGpeHandler (
169     ACPI_HANDLE             GpeDevice,
170     UINT32                  GpeNumber,
171     UINT32                  Type,
172     BOOLEAN                 IsRawHandler,
173     ACPI_GPE_HANDLER        Address,
174     void                    *Context);
175 
176 #endif
177 
178 
179 /*******************************************************************************
180  *
181  * FUNCTION:    AcpiInstallNotifyHandler
182  *
183  * PARAMETERS:  Device          - The device for which notifies will be handled
184  *              HandlerType     - The type of handler:
185  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
186  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
187  *                                  ACPI_ALL_NOTIFY:    Both System and Device
188  *              Handler         - Address of the handler
189  *              Context         - Value passed to the handler on each GPE
190  *
191  * RETURN:      Status
192  *
193  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
194  *              ThermalZone, or Processor object.
195  *
196  * NOTES:       The Root namespace object may have only one handler for each
197  *              type of notify (System/Device). Device/Thermal/Processor objects
198  *              may have one device notify handler, and multiple system notify
199  *              handlers.
200  *
201  ******************************************************************************/
202 
203 ACPI_STATUS
204 AcpiInstallNotifyHandler (
205     ACPI_HANDLE             Device,
206     UINT32                  HandlerType,
207     ACPI_NOTIFY_HANDLER     Handler,
208     void                    *Context)
209 {
210     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
211     ACPI_OPERAND_OBJECT     *ObjDesc;
212     ACPI_OPERAND_OBJECT     *HandlerObj;
213     ACPI_STATUS             Status;
214     UINT32                  i;
215 
216 
217     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
218 
219 
220     /* Parameter validation */
221 
222     if ((!Device) || (!Handler) || (!HandlerType) ||
223         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
224     {
225         return_ACPI_STATUS (AE_BAD_PARAMETER);
226     }
227 
228     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
229     if (ACPI_FAILURE (Status))
230     {
231         return_ACPI_STATUS (Status);
232     }
233 
234     /*
235      * Root Object:
236      * Registering a notify handler on the root object indicates that the
237      * caller wishes to receive notifications for all objects. Note that
238      * only one global handler can be registered per notify type.
239      * Ensure that a handler is not already installed.
240      */
241     if (Device == ACPI_ROOT_OBJECT)
242     {
243         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
244         {
245             if (HandlerType & (i+1))
246             {
247                 if (AcpiGbl_GlobalNotify[i].Handler)
248                 {
249                     Status = AE_ALREADY_EXISTS;
250                     goto UnlockAndExit;
251                 }
252 
253                 AcpiGbl_GlobalNotify[i].Handler = Handler;
254                 AcpiGbl_GlobalNotify[i].Context = Context;
255             }
256         }
257 
258         goto UnlockAndExit; /* Global notify handler installed, all done */
259     }
260 
261     /*
262      * All Other Objects:
263      * Caller will only receive notifications specific to the target
264      * object. Note that only certain object types are allowed to
265      * receive notifications.
266      */
267 
268     /* Are Notifies allowed on this object? */
269 
270     if (!AcpiEvIsNotifyObject (Node))
271     {
272         Status = AE_TYPE;
273         goto UnlockAndExit;
274     }
275 
276     /* Check for an existing internal object, might not exist */
277 
278     ObjDesc = AcpiNsGetAttachedObject (Node);
279     if (!ObjDesc)
280     {
281         /* Create a new object */
282 
283         ObjDesc = AcpiUtCreateInternalObject (Node->Type);
284         if (!ObjDesc)
285         {
286             Status = AE_NO_MEMORY;
287             goto UnlockAndExit;
288         }
289 
290         /* Attach new object to the Node, remove local reference */
291 
292         Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
293         AcpiUtRemoveReference (ObjDesc);
294         if (ACPI_FAILURE (Status))
295         {
296             goto UnlockAndExit;
297         }
298     }
299 
300     /* Ensure that the handler is not already installed in the lists */
301 
302     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
303     {
304         if (HandlerType & (i+1))
305         {
306             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
307             while (HandlerObj)
308             {
309                 if (HandlerObj->Notify.Handler == Handler)
310                 {
311                     Status = AE_ALREADY_EXISTS;
312                     goto UnlockAndExit;
313                 }
314 
315                 HandlerObj = HandlerObj->Notify.Next[i];
316             }
317         }
318     }
319 
320     /* Create and populate a new notify handler object */
321 
322     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
323     if (!HandlerObj)
324     {
325         Status = AE_NO_MEMORY;
326         goto UnlockAndExit;
327     }
328 
329     HandlerObj->Notify.Node = Node;
330     HandlerObj->Notify.HandlerType = HandlerType;
331     HandlerObj->Notify.Handler = Handler;
332     HandlerObj->Notify.Context = Context;
333 
334     /* Install the handler at the list head(s) */
335 
336     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
337     {
338         if (HandlerType & (i+1))
339         {
340             HandlerObj->Notify.Next[i] =
341                 ObjDesc->CommonNotify.NotifyList[i];
342 
343             ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
344         }
345     }
346 
347     /* Add an extra reference if handler was installed in both lists */
348 
349     if (HandlerType == ACPI_ALL_NOTIFY)
350     {
351         AcpiUtAddReference (HandlerObj);
352     }
353 
354 
355 UnlockAndExit:
356     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
357     return_ACPI_STATUS (Status);
358 }
359 
360 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
361 
362 
363 /*******************************************************************************
364  *
365  * FUNCTION:    AcpiRemoveNotifyHandler
366  *
367  * PARAMETERS:  Device          - The device for which the handler is installed
368  *              HandlerType     - The type of handler:
369  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
370  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
371  *                                  ACPI_ALL_NOTIFY:    Both System and Device
372  *              Handler         - Address of the handler
373  *
374  * RETURN:      Status
375  *
376  * DESCRIPTION: Remove a handler for notifies on an ACPI device
377  *
378  ******************************************************************************/
379 
380 ACPI_STATUS
381 AcpiRemoveNotifyHandler (
382     ACPI_HANDLE             Device,
383     UINT32                  HandlerType,
384     ACPI_NOTIFY_HANDLER     Handler)
385 {
386     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
387     ACPI_OPERAND_OBJECT     *ObjDesc;
388     ACPI_OPERAND_OBJECT     *HandlerObj;
389     ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
390     ACPI_STATUS             Status = AE_OK;
391     UINT32                  i;
392 
393 
394     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
395 
396 
397     /* Parameter validation */
398 
399     if ((!Device) || (!Handler) || (!HandlerType) ||
400         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
401     {
402         return_ACPI_STATUS (AE_BAD_PARAMETER);
403     }
404 
405     /* Root Object. Global handlers are removed here */
406 
407     if (Device == ACPI_ROOT_OBJECT)
408     {
409         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
410         {
411             if (HandlerType & (i+1))
412             {
413                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
414                 if (ACPI_FAILURE (Status))
415                 {
416                     return_ACPI_STATUS (Status);
417                 }
418 
419                 if (!AcpiGbl_GlobalNotify[i].Handler ||
420                     (AcpiGbl_GlobalNotify[i].Handler != Handler))
421                 {
422                     Status = AE_NOT_EXIST;
423                     goto UnlockAndExit;
424                 }
425 
426                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
427                     "Removing global notify handler\n"));
428 
429                 AcpiGbl_GlobalNotify[i].Handler = NULL;
430                 AcpiGbl_GlobalNotify[i].Context = NULL;
431 
432                 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
433 
434                 /* Make sure all deferred notify tasks are completed */
435 
436                 AcpiOsWaitEventsComplete ();
437             }
438         }
439 
440         return_ACPI_STATUS (AE_OK);
441     }
442 
443     /* All other objects: Are Notifies allowed on this object? */
444 
445     if (!AcpiEvIsNotifyObject (Node))
446     {
447         return_ACPI_STATUS (AE_TYPE);
448     }
449 
450     /* Must have an existing internal object */
451 
452     ObjDesc = AcpiNsGetAttachedObject (Node);
453     if (!ObjDesc)
454     {
455         return_ACPI_STATUS (AE_NOT_EXIST);
456     }
457 
458     /* Internal object exists. Find the handler and remove it */
459 
460     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
461     {
462         if (HandlerType & (i+1))
463         {
464             Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
465             if (ACPI_FAILURE (Status))
466             {
467                 return_ACPI_STATUS (Status);
468             }
469 
470             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
471             PreviousHandlerObj = NULL;
472 
473             /* Attempt to find the handler in the handler list */
474 
475             while (HandlerObj &&
476                   (HandlerObj->Notify.Handler != Handler))
477             {
478                 PreviousHandlerObj = HandlerObj;
479                 HandlerObj = HandlerObj->Notify.Next[i];
480             }
481 
482             if (!HandlerObj)
483             {
484                 Status = AE_NOT_EXIST;
485                 goto UnlockAndExit;
486             }
487 
488             /* Remove the handler object from the list */
489 
490             if (PreviousHandlerObj) /* Handler is not at the list head */
491             {
492                 PreviousHandlerObj->Notify.Next[i] =
493                     HandlerObj->Notify.Next[i];
494             }
495             else /* Handler is at the list head */
496             {
497                 ObjDesc->CommonNotify.NotifyList[i] =
498                     HandlerObj->Notify.Next[i];
499             }
500 
501             (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
502 
503             /* Make sure all deferred notify tasks are completed */
504 
505             AcpiOsWaitEventsComplete ();
506             AcpiUtRemoveReference (HandlerObj);
507         }
508     }
509 
510     return_ACPI_STATUS (Status);
511 
512 
513 UnlockAndExit:
514     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
515     return_ACPI_STATUS (Status);
516 }
517 
518 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
519 
520 
521 /*******************************************************************************
522  *
523  * FUNCTION:    AcpiInstallExceptionHandler
524  *
525  * PARAMETERS:  Handler         - Pointer to the handler function for the
526  *                                event
527  *
528  * RETURN:      Status
529  *
530  * DESCRIPTION: Saves the pointer to the handler function
531  *
532  ******************************************************************************/
533 
534 ACPI_STATUS
535 AcpiInstallExceptionHandler (
536     ACPI_EXCEPTION_HANDLER  Handler)
537 {
538     ACPI_STATUS             Status;
539 
540 
541     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
542 
543 
544     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
545     if (ACPI_FAILURE (Status))
546     {
547         return_ACPI_STATUS (Status);
548     }
549 
550     /* Don't allow two handlers. */
551 
552     if (AcpiGbl_ExceptionHandler)
553     {
554         Status = AE_ALREADY_EXISTS;
555         goto Cleanup;
556     }
557 
558     /* Install the handler */
559 
560     AcpiGbl_ExceptionHandler = Handler;
561 
562 Cleanup:
563     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
564     return_ACPI_STATUS (Status);
565 }
566 
567 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
568 
569 
570 #if (!ACPI_REDUCED_HARDWARE)
571 /*******************************************************************************
572  *
573  * FUNCTION:    AcpiInstallSciHandler
574  *
575  * PARAMETERS:  Address             - Address of the handler
576  *              Context             - Value passed to the handler on each SCI
577  *
578  * RETURN:      Status
579  *
580  * DESCRIPTION: Install a handler for a System Control Interrupt.
581  *
582  ******************************************************************************/
583 
584 ACPI_STATUS
585 AcpiInstallSciHandler (
586     ACPI_SCI_HANDLER        Address,
587     void                    *Context)
588 {
589     ACPI_SCI_HANDLER_INFO   *NewSciHandler;
590     ACPI_SCI_HANDLER_INFO   *SciHandler;
591     ACPI_CPU_FLAGS          Flags;
592     ACPI_STATUS             Status;
593 
594 
595     ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
596 
597 
598     if (!Address)
599     {
600         return_ACPI_STATUS (AE_BAD_PARAMETER);
601     }
602 
603     /* Allocate and init a handler object */
604 
605     NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
606     if (!NewSciHandler)
607     {
608         return_ACPI_STATUS (AE_NO_MEMORY);
609     }
610 
611     NewSciHandler->Address = Address;
612     NewSciHandler->Context = Context;
613 
614     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
615     if (ACPI_FAILURE (Status))
616     {
617         goto Exit;
618     }
619 
620     /* Lock list during installation */
621 
622     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
623     SciHandler = AcpiGbl_SciHandlerList;
624 
625     /* Ensure handler does not already exist */
626 
627     while (SciHandler)
628     {
629         if (Address == SciHandler->Address)
630         {
631             Status = AE_ALREADY_EXISTS;
632             goto UnlockAndExit;
633         }
634 
635         SciHandler = SciHandler->Next;
636     }
637 
638     /* Install the new handler into the global list (at head) */
639 
640     NewSciHandler->Next = AcpiGbl_SciHandlerList;
641     AcpiGbl_SciHandlerList = NewSciHandler;
642 
643 
644 UnlockAndExit:
645 
646     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
647     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
648 
649 Exit:
650     if (ACPI_FAILURE (Status))
651     {
652         ACPI_FREE (NewSciHandler);
653     }
654     return_ACPI_STATUS (Status);
655 }
656 
657 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
658 
659 
660 /*******************************************************************************
661  *
662  * FUNCTION:    AcpiRemoveSciHandler
663  *
664  * PARAMETERS:  Address             - Address of the handler
665  *
666  * RETURN:      Status
667  *
668  * DESCRIPTION: Remove a handler for a System Control Interrupt.
669  *
670  ******************************************************************************/
671 
672 ACPI_STATUS
673 AcpiRemoveSciHandler (
674     ACPI_SCI_HANDLER        Address)
675 {
676     ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
677     ACPI_SCI_HANDLER_INFO   *NextSciHandler;
678     ACPI_CPU_FLAGS          Flags;
679     ACPI_STATUS             Status;
680 
681 
682     ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
683 
684 
685     if (!Address)
686     {
687         return_ACPI_STATUS (AE_BAD_PARAMETER);
688     }
689 
690     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
691     if (ACPI_FAILURE (Status))
692     {
693         return_ACPI_STATUS (Status);
694     }
695 
696     /* Remove the SCI handler with lock */
697 
698     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
699 
700     PrevSciHandler = NULL;
701     NextSciHandler = AcpiGbl_SciHandlerList;
702     while (NextSciHandler)
703     {
704         if (NextSciHandler->Address == Address)
705         {
706             /* Unlink and free the SCI handler info block */
707 
708             if (PrevSciHandler)
709             {
710                 PrevSciHandler->Next = NextSciHandler->Next;
711             }
712             else
713             {
714                 AcpiGbl_SciHandlerList = NextSciHandler->Next;
715             }
716 
717             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
718             ACPI_FREE (NextSciHandler);
719             goto UnlockAndExit;
720         }
721 
722         PrevSciHandler = NextSciHandler;
723         NextSciHandler = NextSciHandler->Next;
724     }
725 
726     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
727     Status = AE_NOT_EXIST;
728 
729 
730 UnlockAndExit:
731     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
732     return_ACPI_STATUS (Status);
733 }
734 
735 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
736 
737 
738 /*******************************************************************************
739  *
740  * FUNCTION:    AcpiInstallGlobalEventHandler
741  *
742  * PARAMETERS:  Handler         - Pointer to the global event handler function
743  *              Context         - Value passed to the handler on each event
744  *
745  * RETURN:      Status
746  *
747  * DESCRIPTION: Saves the pointer to the handler function. The global handler
748  *              is invoked upon each incoming GPE and Fixed Event. It is
749  *              invoked at interrupt level at the time of the event dispatch.
750  *              Can be used to update event counters, etc.
751  *
752  ******************************************************************************/
753 
754 ACPI_STATUS
755 AcpiInstallGlobalEventHandler (
756     ACPI_GBL_EVENT_HANDLER  Handler,
757     void                    *Context)
758 {
759     ACPI_STATUS             Status;
760 
761 
762     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
763 
764 
765     /* Parameter validation */
766 
767     if (!Handler)
768     {
769         return_ACPI_STATUS (AE_BAD_PARAMETER);
770     }
771 
772     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
773     if (ACPI_FAILURE (Status))
774     {
775         return_ACPI_STATUS (Status);
776     }
777 
778     /* Don't allow two handlers. */
779 
780     if (AcpiGbl_GlobalEventHandler)
781     {
782         Status = AE_ALREADY_EXISTS;
783         goto Cleanup;
784     }
785 
786     AcpiGbl_GlobalEventHandler = Handler;
787     AcpiGbl_GlobalEventHandlerContext = Context;
788 
789 
790 Cleanup:
791     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
792     return_ACPI_STATUS (Status);
793 }
794 
795 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
796 
797 
798 /*******************************************************************************
799  *
800  * FUNCTION:    AcpiInstallFixedEventHandler
801  *
802  * PARAMETERS:  Event           - Event type to enable.
803  *              Handler         - Pointer to the handler function for the
804  *                                event
805  *              Context         - Value passed to the handler on each GPE
806  *
807  * RETURN:      Status
808  *
809  * DESCRIPTION: Saves the pointer to the handler function and then enables the
810  *              event.
811  *
812  ******************************************************************************/
813 
814 ACPI_STATUS
815 AcpiInstallFixedEventHandler (
816     UINT32                  Event,
817     ACPI_EVENT_HANDLER      Handler,
818     void                    *Context)
819 {
820     ACPI_STATUS             Status;
821 
822 
823     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
824 
825 
826     /* Parameter validation */
827 
828     if (Event > ACPI_EVENT_MAX)
829     {
830         return_ACPI_STATUS (AE_BAD_PARAMETER);
831     }
832 
833     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
834     if (ACPI_FAILURE (Status))
835     {
836         return_ACPI_STATUS (Status);
837     }
838 
839     /* Do not allow multiple handlers */
840 
841     if (AcpiGbl_FixedEventHandlers[Event].Handler)
842     {
843         Status = AE_ALREADY_EXISTS;
844         goto Cleanup;
845     }
846 
847     /* Install the handler before enabling the event */
848 
849     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
850     AcpiGbl_FixedEventHandlers[Event].Context = Context;
851 
852     Status = AcpiEnableEvent (Event, 0);
853     if (ACPI_FAILURE (Status))
854     {
855         ACPI_WARNING ((AE_INFO,
856             "Could not enable fixed event - %s (%u)",
857             AcpiUtGetEventName (Event), Event));
858 
859         /* Remove the handler */
860 
861         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
862         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
863     }
864     else
865     {
866         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
867             "Enabled fixed event %s (%X), Handler=%p\n",
868             AcpiUtGetEventName (Event), Event, Handler));
869     }
870 
871 
872 Cleanup:
873     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
874     return_ACPI_STATUS (Status);
875 }
876 
877 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
878 
879 
880 /*******************************************************************************
881  *
882  * FUNCTION:    AcpiRemoveFixedEventHandler
883  *
884  * PARAMETERS:  Event           - Event type to disable.
885  *              Handler         - Address of the handler
886  *
887  * RETURN:      Status
888  *
889  * DESCRIPTION: Disables the event and unregisters the event handler.
890  *
891  ******************************************************************************/
892 
893 ACPI_STATUS
894 AcpiRemoveFixedEventHandler (
895     UINT32                  Event,
896     ACPI_EVENT_HANDLER      Handler)
897 {
898     ACPI_STATUS             Status = AE_OK;
899 
900 
901     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
902 
903 
904     /* Parameter validation */
905 
906     if (Event > ACPI_EVENT_MAX)
907     {
908         return_ACPI_STATUS (AE_BAD_PARAMETER);
909     }
910 
911     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
912     if (ACPI_FAILURE (Status))
913     {
914         return_ACPI_STATUS (Status);
915     }
916 
917     /* Disable the event before removing the handler */
918 
919     Status = AcpiDisableEvent (Event, 0);
920 
921     /* Always Remove the handler */
922 
923     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
924     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
925 
926     if (ACPI_FAILURE (Status))
927     {
928         ACPI_WARNING ((AE_INFO,
929             "Could not disable fixed event - %s (%u)",
930             AcpiUtGetEventName (Event), Event));
931     }
932     else
933     {
934         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
935             "Disabled fixed event - %s (%X)\n",
936             AcpiUtGetEventName (Event), Event));
937     }
938 
939     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
940     return_ACPI_STATUS (Status);
941 }
942 
943 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
944 
945 
946 /*******************************************************************************
947  *
948  * FUNCTION:    AcpiEvInstallGpeHandler
949  *
950  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
951  *                                defined GPEs)
952  *              GpeNumber       - The GPE number within the GPE block
953  *              Type            - Whether this GPE should be treated as an
954  *                                edge- or level-triggered interrupt.
955  *              IsRawHandler    - Whether this GPE should be handled using
956  *                                the special GPE handler mode.
957  *              Address         - Address of the handler
958  *              Context         - Value passed to the handler on each GPE
959  *
960  * RETURN:      Status
961  *
962  * DESCRIPTION: Internal function to install a handler for a General Purpose
963  *              Event.
964  *
965  ******************************************************************************/
966 
967 static ACPI_STATUS
968 AcpiEvInstallGpeHandler (
969     ACPI_HANDLE             GpeDevice,
970     UINT32                  GpeNumber,
971     UINT32                  Type,
972     BOOLEAN                 IsRawHandler,
973     ACPI_GPE_HANDLER        Address,
974     void                    *Context)
975 {
976     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
977     ACPI_GPE_HANDLER_INFO   *Handler;
978     ACPI_STATUS             Status;
979     ACPI_CPU_FLAGS          Flags;
980 
981 
982     ACPI_FUNCTION_TRACE (EvInstallGpeHandler);
983 
984 
985     /* Parameter validation */
986 
987     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
988     {
989         return_ACPI_STATUS (AE_BAD_PARAMETER);
990     }
991 
992     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
993     if (ACPI_FAILURE (Status))
994     {
995         return_ACPI_STATUS (Status);
996     }
997 
998     /* Allocate and init handler object (before lock) */
999 
1000     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
1001     if (!Handler)
1002     {
1003         Status = AE_NO_MEMORY;
1004         goto UnlockAndExit;
1005     }
1006 
1007     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1008 
1009     /* Ensure that we have a valid GPE number */
1010 
1011     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1012     if (!GpeEventInfo)
1013     {
1014         Status = AE_BAD_PARAMETER;
1015         goto FreeAndExit;
1016     }
1017 
1018     /* Make sure that there isn't a handler there already */
1019 
1020     if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
1021             ACPI_GPE_DISPATCH_HANDLER) ||
1022         (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
1023             ACPI_GPE_DISPATCH_RAW_HANDLER))
1024     {
1025         Status = AE_ALREADY_EXISTS;
1026         goto FreeAndExit;
1027     }
1028 
1029     Handler->Address = Address;
1030     Handler->Context = Context;
1031     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
1032     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
1033         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
1034 
1035     /*
1036      * If the GPE is associated with a method, it may have been enabled
1037      * automatically during initialization, in which case it has to be
1038      * disabled now to avoid spurious execution of the handler.
1039      */
1040     if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1041             ACPI_GPE_DISPATCH_METHOD) ||
1042          (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1043             ACPI_GPE_DISPATCH_NOTIFY)) &&
1044         GpeEventInfo->RuntimeCount)
1045     {
1046         Handler->OriginallyEnabled = TRUE;
1047         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
1048 
1049         /* Sanity check of original type against new type */
1050 
1051         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
1052         {
1053             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
1054         }
1055     }
1056 
1057     /* Install the handler */
1058 
1059     GpeEventInfo->Dispatch.Handler = Handler;
1060 
1061     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
1062 
1063     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1064     GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ?
1065         ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER));
1066 
1067     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1068 
1069 
1070 UnlockAndExit:
1071     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1072     return_ACPI_STATUS (Status);
1073 
1074 FreeAndExit:
1075     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1076     ACPI_FREE (Handler);
1077     goto UnlockAndExit;
1078 }
1079 
1080 
1081 /*******************************************************************************
1082  *
1083  * FUNCTION:    AcpiInstallGpeHandler
1084  *
1085  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1086  *                                defined GPEs)
1087  *              GpeNumber       - The GPE number within the GPE block
1088  *              Type            - Whether this GPE should be treated as an
1089  *                                edge- or level-triggered interrupt.
1090  *              Address         - Address of the handler
1091  *              Context         - Value passed to the handler on each GPE
1092  *
1093  * RETURN:      Status
1094  *
1095  * DESCRIPTION: Install a handler for a General Purpose Event.
1096  *
1097  ******************************************************************************/
1098 
1099 ACPI_STATUS
1100 AcpiInstallGpeHandler (
1101     ACPI_HANDLE             GpeDevice,
1102     UINT32                  GpeNumber,
1103     UINT32                  Type,
1104     ACPI_GPE_HANDLER        Address,
1105     void                    *Context)
1106 {
1107     ACPI_STATUS             Status;
1108 
1109 
1110     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
1111 
1112 
1113     Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1114         FALSE, Address, Context);
1115 
1116     return_ACPI_STATUS (Status);
1117 }
1118 
1119 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
1120 
1121 
1122 /*******************************************************************************
1123  *
1124  * FUNCTION:    AcpiInstallGpeRawHandler
1125  *
1126  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1127  *                                defined GPEs)
1128  *              GpeNumber       - The GPE number within the GPE block
1129  *              Type            - Whether this GPE should be treated as an
1130  *                                edge- or level-triggered interrupt.
1131  *              Address         - Address of the handler
1132  *              Context         - Value passed to the handler on each GPE
1133  *
1134  * RETURN:      Status
1135  *
1136  * DESCRIPTION: Install a handler for a General Purpose Event.
1137  *
1138  ******************************************************************************/
1139 
1140 ACPI_STATUS
1141 AcpiInstallGpeRawHandler (
1142     ACPI_HANDLE             GpeDevice,
1143     UINT32                  GpeNumber,
1144     UINT32                  Type,
1145     ACPI_GPE_HANDLER        Address,
1146     void                    *Context)
1147 {
1148     ACPI_STATUS             Status;
1149 
1150 
1151     ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler);
1152 
1153 
1154     Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1155         TRUE, Address, Context);
1156 
1157     return_ACPI_STATUS (Status);
1158 }
1159 
1160 ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler)
1161 
1162 
1163 /*******************************************************************************
1164  *
1165  * FUNCTION:    AcpiRemoveGpeHandler
1166  *
1167  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1168  *                                defined GPEs)
1169  *              GpeNumber       - The event to remove a handler
1170  *              Address         - Address of the handler
1171  *
1172  * RETURN:      Status
1173  *
1174  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
1175  *
1176  ******************************************************************************/
1177 
1178 ACPI_STATUS
1179 AcpiRemoveGpeHandler (
1180     ACPI_HANDLE             GpeDevice,
1181     UINT32                  GpeNumber,
1182     ACPI_GPE_HANDLER        Address)
1183 {
1184     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1185     ACPI_GPE_HANDLER_INFO   *Handler;
1186     ACPI_STATUS             Status;
1187     ACPI_CPU_FLAGS          Flags;
1188 
1189 
1190     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
1191 
1192 
1193     /* Parameter validation */
1194 
1195     if (!Address)
1196     {
1197         return_ACPI_STATUS (AE_BAD_PARAMETER);
1198     }
1199 
1200     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1201     if (ACPI_FAILURE (Status))
1202     {
1203         return_ACPI_STATUS (Status);
1204     }
1205 
1206     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1207 
1208     /* Ensure that we have a valid GPE number */
1209 
1210     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1211     if (!GpeEventInfo)
1212     {
1213         Status = AE_BAD_PARAMETER;
1214         goto UnlockAndExit;
1215     }
1216 
1217     /* Make sure that a handler is indeed installed */
1218 
1219     if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1220             ACPI_GPE_DISPATCH_HANDLER) &&
1221         (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1222             ACPI_GPE_DISPATCH_RAW_HANDLER))
1223     {
1224         Status = AE_NOT_EXIST;
1225         goto UnlockAndExit;
1226     }
1227 
1228     /* Make sure that the installed handler is the same */
1229 
1230     if (GpeEventInfo->Dispatch.Handler->Address != Address)
1231     {
1232         Status = AE_BAD_PARAMETER;
1233         goto UnlockAndExit;
1234     }
1235 
1236     /* Remove the handler */
1237 
1238     Handler = GpeEventInfo->Dispatch.Handler;
1239     GpeEventInfo->Dispatch.Handler = NULL;
1240 
1241     /* Restore Method node (if any), set dispatch flags */
1242 
1243     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1244     GpeEventInfo->Flags &=
1245         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1246     GpeEventInfo->Flags |= Handler->OriginalFlags;
1247 
1248     /*
1249      * If the GPE was previously associated with a method and it was
1250      * enabled, it should be enabled at this point to restore the
1251      * post-initialization configuration.
1252      */
1253     if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1254             ACPI_GPE_DISPATCH_METHOD) ||
1255          (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1256             ACPI_GPE_DISPATCH_NOTIFY)) &&
1257         Handler->OriginallyEnabled)
1258     {
1259         (void) AcpiEvAddGpeReference (GpeEventInfo, FALSE);
1260         if (ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))
1261         {
1262             /* Poll edge triggered GPEs to handle existing events */
1263 
1264             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1265             (void) AcpiEvDetectGpe (
1266                 GpeDevice, GpeEventInfo, GpeNumber);
1267             Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1268         }
1269     }
1270 
1271     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1272     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1273 
1274     /* Make sure all deferred GPE tasks are completed */
1275 
1276     AcpiOsWaitEventsComplete ();
1277 
1278     /* Now we can free the handler object */
1279 
1280     ACPI_FREE (Handler);
1281     return_ACPI_STATUS (Status);
1282 
1283 UnlockAndExit:
1284     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1285     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1286     return_ACPI_STATUS (Status);
1287 }
1288 
1289 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1290 
1291 
1292 /*******************************************************************************
1293  *
1294  * FUNCTION:    AcpiAcquireGlobalLock
1295  *
1296  * PARAMETERS:  Timeout         - How long the caller is willing to wait
1297  *              Handle          - Where the handle to the lock is returned
1298  *                                (if acquired)
1299  *
1300  * RETURN:      Status
1301  *
1302  * DESCRIPTION: Acquire the ACPI Global Lock
1303  *
1304  * Note: Allows callers with the same thread ID to acquire the global lock
1305  * multiple times. In other words, externally, the behavior of the global lock
1306  * is identical to an AML mutex. On the first acquire, a new handle is
1307  * returned. On any subsequent calls to acquire by the same thread, the same
1308  * handle is returned.
1309  *
1310  ******************************************************************************/
1311 
1312 ACPI_STATUS
1313 AcpiAcquireGlobalLock (
1314     UINT16                  Timeout,
1315     UINT32                  *Handle)
1316 {
1317     ACPI_STATUS             Status;
1318 
1319 
1320     if (!Handle)
1321     {
1322         return (AE_BAD_PARAMETER);
1323     }
1324 
1325     /* Must lock interpreter to prevent race conditions */
1326 
1327     AcpiExEnterInterpreter ();
1328 
1329     Status = AcpiExAcquireMutexObject (Timeout,
1330         AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1331 
1332     if (ACPI_SUCCESS (Status))
1333     {
1334         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1335 
1336         *Handle = AcpiGbl_GlobalLockHandle;
1337     }
1338 
1339     AcpiExExitInterpreter ();
1340     return (Status);
1341 }
1342 
1343 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1344 
1345 
1346 /*******************************************************************************
1347  *
1348  * FUNCTION:    AcpiReleaseGlobalLock
1349  *
1350  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1351  *
1352  * RETURN:      Status
1353  *
1354  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1355  *
1356  ******************************************************************************/
1357 
1358 ACPI_STATUS
1359 AcpiReleaseGlobalLock (
1360     UINT32                  Handle)
1361 {
1362     ACPI_STATUS             Status;
1363 
1364 
1365     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1366     {
1367         return (AE_NOT_ACQUIRED);
1368     }
1369 
1370     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1371     return (Status);
1372 }
1373 
1374 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1375 
1376 #endif /* !ACPI_REDUCED_HARDWARE */
1377