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