]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/events/evxface.c
Merge ACPICA 20101209.
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / events / evxface.c
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 - 2010, 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
117 #define __EVXFACE_C__
118
119 #include <contrib/dev/acpica/include/acpi.h>
120 #include <contrib/dev/acpica/include/accommon.h>
121 #include <contrib/dev/acpica/include/acnamesp.h>
122 #include <contrib/dev/acpica/include/acevents.h>
123 #include <contrib/dev/acpica/include/acinterp.h>
124
125 #define _COMPONENT          ACPI_EVENTS
126         ACPI_MODULE_NAME    ("evxface")
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiInstallExceptionHandler
132  *
133  * PARAMETERS:  Handler         - Pointer to the handler function for the
134  *                                event
135  *
136  * RETURN:      Status
137  *
138  * DESCRIPTION: Saves the pointer to the handler function
139  *
140  ******************************************************************************/
141
142 ACPI_STATUS
143 AcpiInstallExceptionHandler (
144     ACPI_EXCEPTION_HANDLER  Handler)
145 {
146     ACPI_STATUS             Status;
147
148
149     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
150
151
152     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153     if (ACPI_FAILURE (Status))
154     {
155         return_ACPI_STATUS (Status);
156     }
157
158     /* Don't allow two handlers. */
159
160     if (AcpiGbl_ExceptionHandler)
161     {
162         Status = AE_ALREADY_EXISTS;
163         goto Cleanup;
164     }
165
166     /* Install the handler */
167
168     AcpiGbl_ExceptionHandler = Handler;
169
170 Cleanup:
171     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172     return_ACPI_STATUS (Status);
173 }
174
175 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
176
177
178 /*******************************************************************************
179  *
180  * FUNCTION:    AcpiInstallGlobalEventHandler
181  *
182  * PARAMETERS:  Handler         - Pointer to the global event handler function
183  *              Context         - Value passed to the handler on each event
184  *
185  * RETURN:      Status
186  *
187  * DESCRIPTION: Saves the pointer to the handler function. The global handler
188  *              is invoked upon each incoming GPE and Fixed Event. It is
189  *              invoked at interrupt level at the time of the event dispatch.
190  *              Can be used to update event counters, etc.
191  *
192  ******************************************************************************/
193
194 ACPI_STATUS
195 AcpiInstallGlobalEventHandler (
196     ACPI_GBL_EVENT_HANDLER  Handler,
197     void                    *Context)
198 {
199     ACPI_STATUS             Status;
200
201
202     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
203
204
205     /* Parameter validation */
206
207     if (!Handler)
208     {
209         return_ACPI_STATUS (AE_BAD_PARAMETER);
210     }
211
212     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
213     if (ACPI_FAILURE (Status))
214     {
215         return_ACPI_STATUS (Status);
216     }
217
218     /* Don't allow two handlers. */
219
220     if (AcpiGbl_GlobalEventHandler)
221     {
222         Status = AE_ALREADY_EXISTS;
223         goto Cleanup;
224     }
225
226     AcpiGbl_GlobalEventHandler = Handler;
227     AcpiGbl_GlobalEventHandlerContext = Context;
228
229
230 Cleanup:
231     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
232     return_ACPI_STATUS (Status);
233 }
234
235 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
236
237
238 /*******************************************************************************
239  *
240  * FUNCTION:    AcpiInstallFixedEventHandler
241  *
242  * PARAMETERS:  Event           - Event type to enable.
243  *              Handler         - Pointer to the handler function for the
244  *                                event
245  *              Context         - Value passed to the handler on each GPE
246  *
247  * RETURN:      Status
248  *
249  * DESCRIPTION: Saves the pointer to the handler function and then enables the
250  *              event.
251  *
252  ******************************************************************************/
253
254 ACPI_STATUS
255 AcpiInstallFixedEventHandler (
256     UINT32                  Event,
257     ACPI_EVENT_HANDLER      Handler,
258     void                    *Context)
259 {
260     ACPI_STATUS             Status;
261
262
263     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
264
265
266     /* Parameter validation */
267
268     if (Event > ACPI_EVENT_MAX)
269     {
270         return_ACPI_STATUS (AE_BAD_PARAMETER);
271     }
272
273     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
274     if (ACPI_FAILURE (Status))
275     {
276         return_ACPI_STATUS (Status);
277     }
278
279     /* Don't allow two handlers. */
280
281     if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
282     {
283         Status = AE_ALREADY_EXISTS;
284         goto Cleanup;
285     }
286
287     /* Install the handler before enabling the event */
288
289     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
290     AcpiGbl_FixedEventHandlers[Event].Context = Context;
291
292     Status = AcpiEnableEvent (Event, 0);
293     if (ACPI_FAILURE (Status))
294     {
295         ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
296
297         /* Remove the handler */
298
299         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
300         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
301     }
302     else
303     {
304         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
305             "Enabled fixed event %X, Handler=%p\n", Event, Handler));
306     }
307
308
309 Cleanup:
310     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
311     return_ACPI_STATUS (Status);
312 }
313
314 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
315
316
317 /*******************************************************************************
318  *
319  * FUNCTION:    AcpiRemoveFixedEventHandler
320  *
321  * PARAMETERS:  Event           - Event type to disable.
322  *              Handler         - Address of the handler
323  *
324  * RETURN:      Status
325  *
326  * DESCRIPTION: Disables the event and unregisters the event handler.
327  *
328  ******************************************************************************/
329
330 ACPI_STATUS
331 AcpiRemoveFixedEventHandler (
332     UINT32                  Event,
333     ACPI_EVENT_HANDLER      Handler)
334 {
335     ACPI_STATUS             Status = AE_OK;
336
337
338     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
339
340
341     /* Parameter validation */
342
343     if (Event > ACPI_EVENT_MAX)
344     {
345         return_ACPI_STATUS (AE_BAD_PARAMETER);
346     }
347
348     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
349     if (ACPI_FAILURE (Status))
350     {
351         return_ACPI_STATUS (Status);
352     }
353
354     /* Disable the event before removing the handler */
355
356     Status = AcpiDisableEvent (Event, 0);
357
358     /* Always Remove the handler */
359
360     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
361     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
362
363     if (ACPI_FAILURE (Status))
364     {
365         ACPI_WARNING ((AE_INFO,
366             "Could not write to fixed event enable register 0x%X", Event));
367     }
368     else
369     {
370         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
371     }
372
373     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
374     return_ACPI_STATUS (Status);
375 }
376
377 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
378
379
380 /*******************************************************************************
381  *
382  * FUNCTION:    AcpiInstallNotifyHandler
383  *
384  * PARAMETERS:  Device          - The device for which notifies will be handled
385  *              HandlerType     - The type of handler:
386  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
387  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
388  *                                  ACPI_ALL_NOTIFY:  both system and device
389  *              Handler         - Address of the handler
390  *              Context         - Value passed to the handler on each GPE
391  *
392  * RETURN:      Status
393  *
394  * DESCRIPTION: Install a handler for notifies on an ACPI device
395  *
396  ******************************************************************************/
397
398 ACPI_STATUS
399 AcpiInstallNotifyHandler (
400     ACPI_HANDLE             Device,
401     UINT32                  HandlerType,
402     ACPI_NOTIFY_HANDLER     Handler,
403     void                    *Context)
404 {
405     ACPI_OPERAND_OBJECT     *ObjDesc;
406     ACPI_OPERAND_OBJECT     *NotifyObj;
407     ACPI_NAMESPACE_NODE     *Node;
408     ACPI_STATUS             Status;
409
410
411     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
412
413
414     /* Parameter validation */
415
416     if ((!Device)  ||
417         (!Handler) ||
418         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
419     {
420         return_ACPI_STATUS (AE_BAD_PARAMETER);
421     }
422
423     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
424     if (ACPI_FAILURE (Status))
425     {
426         return_ACPI_STATUS (Status);
427     }
428
429     /* Convert and validate the device handle */
430
431     Node = AcpiNsValidateHandle (Device);
432     if (!Node)
433     {
434         Status = AE_BAD_PARAMETER;
435         goto UnlockAndExit;
436     }
437
438     /*
439      * Root Object:
440      * Registering a notify handler on the root object indicates that the
441      * caller wishes to receive notifications for all objects. Note that
442      * only one <external> global handler can be regsitered (per notify type).
443      */
444     if (Device == ACPI_ROOT_OBJECT)
445     {
446         /* Make sure the handler is not already installed */
447
448         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
449                 AcpiGbl_SystemNotify.Handler)       ||
450             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
451                 AcpiGbl_DeviceNotify.Handler))
452         {
453             Status = AE_ALREADY_EXISTS;
454             goto UnlockAndExit;
455         }
456
457         if (HandlerType & ACPI_SYSTEM_NOTIFY)
458         {
459             AcpiGbl_SystemNotify.Node    = Node;
460             AcpiGbl_SystemNotify.Handler = Handler;
461             AcpiGbl_SystemNotify.Context = Context;
462         }
463
464         if (HandlerType & ACPI_DEVICE_NOTIFY)
465         {
466             AcpiGbl_DeviceNotify.Node    = Node;
467             AcpiGbl_DeviceNotify.Handler = Handler;
468             AcpiGbl_DeviceNotify.Context = Context;
469         }
470
471         /* Global notify handler installed */
472     }
473
474     /*
475      * All Other Objects:
476      * Caller will only receive notifications specific to the target object.
477      * Note that only certain object types can receive notifications.
478      */
479     else
480     {
481         /* Notifies allowed on this object? */
482
483         if (!AcpiEvIsNotifyObject (Node))
484         {
485             Status = AE_TYPE;
486             goto UnlockAndExit;
487         }
488
489         /* Check for an existing internal object */
490
491         ObjDesc = AcpiNsGetAttachedObject (Node);
492         if (ObjDesc)
493         {
494             /* Object exists - make sure there's no handler */
495
496             if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
497                     ObjDesc->CommonNotify.SystemNotify)   ||
498                 ((HandlerType & ACPI_DEVICE_NOTIFY) &&
499                     ObjDesc->CommonNotify.DeviceNotify))
500             {
501                 Status = AE_ALREADY_EXISTS;
502                 goto UnlockAndExit;
503             }
504         }
505         else
506         {
507             /* Create a new object */
508
509             ObjDesc = AcpiUtCreateInternalObject (Node->Type);
510             if (!ObjDesc)
511             {
512                 Status = AE_NO_MEMORY;
513                 goto UnlockAndExit;
514             }
515
516             /* Attach new object to the Node */
517
518             Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
519
520             /* Remove local reference to the object */
521
522             AcpiUtRemoveReference (ObjDesc);
523             if (ACPI_FAILURE (Status))
524             {
525                 goto UnlockAndExit;
526             }
527         }
528
529         /* Install the handler */
530
531         NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
532         if (!NotifyObj)
533         {
534             Status = AE_NO_MEMORY;
535             goto UnlockAndExit;
536         }
537
538         NotifyObj->Notify.Node    = Node;
539         NotifyObj->Notify.Handler = Handler;
540         NotifyObj->Notify.Context = Context;
541
542         if (HandlerType & ACPI_SYSTEM_NOTIFY)
543         {
544             ObjDesc->CommonNotify.SystemNotify = NotifyObj;
545         }
546
547         if (HandlerType & ACPI_DEVICE_NOTIFY)
548         {
549             ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
550         }
551
552         if (HandlerType == ACPI_ALL_NOTIFY)
553         {
554             /* Extra ref if installed in both */
555
556             AcpiUtAddReference (NotifyObj);
557         }
558     }
559
560
561 UnlockAndExit:
562     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
563     return_ACPI_STATUS (Status);
564 }
565
566 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
567
568
569 /*******************************************************************************
570  *
571  * FUNCTION:    AcpiRemoveNotifyHandler
572  *
573  * PARAMETERS:  Device          - The device for which notifies will be handled
574  *              HandlerType     - The type of handler:
575  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
576  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
577  *                                  ACPI_ALL_NOTIFY:  both system and device
578  *              Handler         - Address of the handler
579  *
580  * RETURN:      Status
581  *
582  * DESCRIPTION: Remove a handler for notifies on an ACPI device
583  *
584  ******************************************************************************/
585
586 ACPI_STATUS
587 AcpiRemoveNotifyHandler (
588     ACPI_HANDLE             Device,
589     UINT32                  HandlerType,
590     ACPI_NOTIFY_HANDLER     Handler)
591 {
592     ACPI_OPERAND_OBJECT     *NotifyObj;
593     ACPI_OPERAND_OBJECT     *ObjDesc;
594     ACPI_NAMESPACE_NODE     *Node;
595     ACPI_STATUS             Status;
596
597
598     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
599
600
601     /* Parameter validation */
602
603     if ((!Device)  ||
604         (!Handler) ||
605         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
606     {
607         return_ACPI_STATUS (AE_BAD_PARAMETER);
608     }
609
610     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
611     if (ACPI_FAILURE (Status))
612     {
613         return_ACPI_STATUS (Status);
614     }
615
616     /* Convert and validate the device handle */
617
618     Node = AcpiNsValidateHandle (Device);
619     if (!Node)
620     {
621         Status = AE_BAD_PARAMETER;
622         goto UnlockAndExit;
623     }
624
625     /* Root Object */
626
627     if (Device == ACPI_ROOT_OBJECT)
628     {
629         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
630             "Removing notify handler for namespace root object\n"));
631
632         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
633               !AcpiGbl_SystemNotify.Handler)        ||
634             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
635               !AcpiGbl_DeviceNotify.Handler))
636         {
637             Status = AE_NOT_EXIST;
638             goto UnlockAndExit;
639         }
640
641         if (HandlerType & ACPI_SYSTEM_NOTIFY)
642         {
643             AcpiGbl_SystemNotify.Node    = NULL;
644             AcpiGbl_SystemNotify.Handler = NULL;
645             AcpiGbl_SystemNotify.Context = NULL;
646         }
647
648         if (HandlerType & ACPI_DEVICE_NOTIFY)
649         {
650             AcpiGbl_DeviceNotify.Node    = NULL;
651             AcpiGbl_DeviceNotify.Handler = NULL;
652             AcpiGbl_DeviceNotify.Context = NULL;
653         }
654     }
655
656     /* All Other Objects */
657
658     else
659     {
660         /* Notifies allowed on this object? */
661
662         if (!AcpiEvIsNotifyObject (Node))
663         {
664             Status = AE_TYPE;
665             goto UnlockAndExit;
666         }
667
668         /* Check for an existing internal object */
669
670         ObjDesc = AcpiNsGetAttachedObject (Node);
671         if (!ObjDesc)
672         {
673             Status = AE_NOT_EXIST;
674             goto UnlockAndExit;
675         }
676
677         /* Object exists - make sure there's an existing handler */
678
679         if (HandlerType & ACPI_SYSTEM_NOTIFY)
680         {
681             NotifyObj = ObjDesc->CommonNotify.SystemNotify;
682             if (!NotifyObj)
683             {
684                 Status = AE_NOT_EXIST;
685                 goto UnlockAndExit;
686             }
687
688             if (NotifyObj->Notify.Handler != Handler)
689             {
690                 Status = AE_BAD_PARAMETER;
691                 goto UnlockAndExit;
692             }
693
694             /* Remove the handler */
695
696             ObjDesc->CommonNotify.SystemNotify = NULL;
697             AcpiUtRemoveReference (NotifyObj);
698         }
699
700         if (HandlerType & ACPI_DEVICE_NOTIFY)
701         {
702             NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
703             if (!NotifyObj)
704             {
705                 Status = AE_NOT_EXIST;
706                 goto UnlockAndExit;
707             }
708
709             if (NotifyObj->Notify.Handler != Handler)
710             {
711                 Status = AE_BAD_PARAMETER;
712                 goto UnlockAndExit;
713             }
714
715             /* Remove the handler */
716
717             ObjDesc->CommonNotify.DeviceNotify = NULL;
718             AcpiUtRemoveReference (NotifyObj);
719         }
720     }
721
722
723 UnlockAndExit:
724     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
725     return_ACPI_STATUS (Status);
726 }
727
728 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
729
730
731 /*******************************************************************************
732  *
733  * FUNCTION:    AcpiInstallGpeHandler
734  *
735  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
736  *                                defined GPEs)
737  *              GpeNumber       - The GPE number within the GPE block
738  *              Type            - Whether this GPE should be treated as an
739  *                                edge- or level-triggered interrupt.
740  *              Address         - Address of the handler
741  *              Context         - Value passed to the handler on each GPE
742  *
743  * RETURN:      Status
744  *
745  * DESCRIPTION: Install a handler for a General Purpose Event.
746  *
747  ******************************************************************************/
748
749 ACPI_STATUS
750 AcpiInstallGpeHandler (
751     ACPI_HANDLE             GpeDevice,
752     UINT32                  GpeNumber,
753     UINT32                  Type,
754     ACPI_GPE_HANDLER        Address,
755     void                    *Context)
756 {
757     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
758     ACPI_GPE_HANDLER_INFO   *Handler;
759     ACPI_STATUS             Status;
760     ACPI_CPU_FLAGS          Flags;
761
762
763     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
764
765
766     /* Parameter validation */
767
768     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
769     {
770         return_ACPI_STATUS (AE_BAD_PARAMETER);
771     }
772
773     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
774     if (ACPI_FAILURE (Status))
775     {
776         return_ACPI_STATUS (Status);
777     }
778
779     /* Allocate and init handler object (before lock) */
780
781     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
782     if (!Handler)
783     {
784         Status = AE_NO_MEMORY;
785         goto UnlockAndExit;
786     }
787
788     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
789
790     /* Ensure that we have a valid GPE number */
791
792     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
793     if (!GpeEventInfo)
794     {
795         Status = AE_BAD_PARAMETER;
796         goto FreeAndExit;
797     }
798
799     /* Make sure that there isn't a handler there already */
800
801     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
802             ACPI_GPE_DISPATCH_HANDLER)
803     {
804         Status = AE_ALREADY_EXISTS;
805         goto FreeAndExit;
806     }
807
808     Handler->Address = Address;
809     Handler->Context = Context;
810     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
811     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
812         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
813
814     /*
815      * If the GPE is associated with a method, it may have been enabled
816      * automatically during initialization, in which case it has to be
817      * disabled now to avoid spurious execution of the handler.
818      */
819     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
820          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
821         GpeEventInfo->RuntimeCount)
822     {
823         Handler->OriginallyEnabled = TRUE;
824         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
825
826         /* Sanity check of original type against new type */
827
828         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
829         {
830             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
831         }
832     }
833
834     /* Install the handler */
835
836     GpeEventInfo->Dispatch.Handler = Handler;
837
838     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
839
840     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
841     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
842
843     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
844
845
846 UnlockAndExit:
847     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
848     return_ACPI_STATUS (Status);
849
850 FreeAndExit:
851     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
852     ACPI_FREE (Handler);
853     goto UnlockAndExit;
854 }
855
856 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
857
858
859 /*******************************************************************************
860  *
861  * FUNCTION:    AcpiRemoveGpeHandler
862  *
863  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
864  *                                defined GPEs)
865  *              GpeNumber       - The event to remove a handler
866  *              Address         - Address of the handler
867  *
868  * RETURN:      Status
869  *
870  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
871  *
872  ******************************************************************************/
873
874 ACPI_STATUS
875 AcpiRemoveGpeHandler (
876     ACPI_HANDLE             GpeDevice,
877     UINT32                  GpeNumber,
878     ACPI_GPE_HANDLER        Address)
879 {
880     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
881     ACPI_GPE_HANDLER_INFO   *Handler;
882     ACPI_STATUS             Status;
883     ACPI_CPU_FLAGS          Flags;
884
885
886     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
887
888
889     /* Parameter validation */
890
891     if (!Address)
892     {
893         return_ACPI_STATUS (AE_BAD_PARAMETER);
894     }
895
896     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
897     if (ACPI_FAILURE (Status))
898     {
899         return_ACPI_STATUS (Status);
900     }
901
902     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
903
904     /* Ensure that we have a valid GPE number */
905
906     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
907     if (!GpeEventInfo)
908     {
909         Status = AE_BAD_PARAMETER;
910         goto UnlockAndExit;
911     }
912
913     /* Make sure that a handler is indeed installed */
914
915     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
916             ACPI_GPE_DISPATCH_HANDLER)
917     {
918         Status = AE_NOT_EXIST;
919         goto UnlockAndExit;
920     }
921
922     /* Make sure that the installed handler is the same */
923
924     if (GpeEventInfo->Dispatch.Handler->Address != Address)
925     {
926         Status = AE_BAD_PARAMETER;
927         goto UnlockAndExit;
928     }
929
930     /* Remove the handler */
931
932     Handler = GpeEventInfo->Dispatch.Handler;
933
934     /* Restore Method node (if any), set dispatch flags */
935
936     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
937     GpeEventInfo->Flags &=
938         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
939     GpeEventInfo->Flags |= Handler->OriginalFlags;
940
941     /*
942      * If the GPE was previously associated with a method and it was
943      * enabled, it should be enabled at this point to restore the
944      * post-initialization configuration.
945      */
946     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
947         Handler->OriginallyEnabled)
948     {
949         (void) AcpiEvAddGpeReference (GpeEventInfo);
950     }
951
952     /* Now we can free the handler object */
953
954     ACPI_FREE (Handler);
955
956
957 UnlockAndExit:
958     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
959     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
960     return_ACPI_STATUS (Status);
961 }
962
963 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
964
965
966 /*******************************************************************************
967  *
968  * FUNCTION:    AcpiAcquireGlobalLock
969  *
970  * PARAMETERS:  Timeout         - How long the caller is willing to wait
971  *              Handle          - Where the handle to the lock is returned
972  *                                (if acquired)
973  *
974  * RETURN:      Status
975  *
976  * DESCRIPTION: Acquire the ACPI Global Lock
977  *
978  * Note: Allows callers with the same thread ID to acquire the global lock
979  * multiple times. In other words, externally, the behavior of the global lock
980  * is identical to an AML mutex. On the first acquire, a new handle is
981  * returned. On any subsequent calls to acquire by the same thread, the same
982  * handle is returned.
983  *
984  ******************************************************************************/
985
986 ACPI_STATUS
987 AcpiAcquireGlobalLock (
988     UINT16                  Timeout,
989     UINT32                  *Handle)
990 {
991     ACPI_STATUS             Status;
992
993
994     if (!Handle)
995     {
996         return (AE_BAD_PARAMETER);
997     }
998
999     /* Must lock interpreter to prevent race conditions */
1000
1001     AcpiExEnterInterpreter ();
1002
1003     Status = AcpiExAcquireMutexObject (Timeout,
1004                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1005
1006     if (ACPI_SUCCESS (Status))
1007     {
1008         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1009
1010         *Handle = AcpiGbl_GlobalLockHandle;
1011     }
1012
1013     AcpiExExitInterpreter ();
1014     return (Status);
1015 }
1016
1017 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1018
1019
1020 /*******************************************************************************
1021  *
1022  * FUNCTION:    AcpiReleaseGlobalLock
1023  *
1024  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1025  *
1026  * RETURN:      Status
1027  *
1028  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1029  *
1030  ******************************************************************************/
1031
1032 ACPI_STATUS
1033 AcpiReleaseGlobalLock (
1034     UINT32                  Handle)
1035 {
1036     ACPI_STATUS             Status;
1037
1038
1039     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1040     {
1041         return (AE_NOT_ACQUIRED);
1042     }
1043
1044     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1045     return (Status);
1046 }
1047
1048 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1049