Sync ACPICA with Intel's version 20141107.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / events / evxfgpe.c
1 /******************************************************************************
2  *
3  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, 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 #define EXPORT_ACPI_INTERFACES
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acevents.h"
49 #include "acnamesp.h"
50
51 #define _COMPONENT          ACPI_EVENTS
52         ACPI_MODULE_NAME    ("evxfgpe")
53
54
55 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56 /*******************************************************************************
57  *
58  * FUNCTION:    AcpiUpdateAllGpes
59  *
60  * PARAMETERS:  None
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65  *              associated _Lxx or _Exx methods and are not pointed to by any
66  *              device _PRW methods (this indicates that these GPEs are
67  *              generally intended for system or device wakeup. Such GPEs
68  *              have to be enabled directly when the devices whose _PRW
69  *              methods point to them are set up for wakeup signaling.)
70  *
71  * NOTE: Should be called after any GPEs are added to the system. Primarily,
72  * after the system _PRW methods have been run, but also after a GPE Block
73  * Device has been added or if any new GPE methods have been added via a
74  * dynamic table load.
75  *
76  ******************************************************************************/
77
78 ACPI_STATUS
79 AcpiUpdateAllGpes (
80     void)
81 {
82     ACPI_STATUS             Status;
83
84
85     ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
86
87
88     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
89     if (ACPI_FAILURE (Status))
90     {
91         return_ACPI_STATUS (Status);
92     }
93
94     if (AcpiGbl_AllGpesInitialized)
95     {
96         goto UnlockAndExit;
97     }
98
99     Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
100     if (ACPI_SUCCESS (Status))
101     {
102         AcpiGbl_AllGpesInitialized = TRUE;
103     }
104
105 UnlockAndExit:
106     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
107     return_ACPI_STATUS (Status);
108 }
109
110 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
111
112
113 /*******************************************************************************
114  *
115  * FUNCTION:    AcpiEnableGpe
116  *
117  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
118  *              GpeNumber           - GPE level within the GPE block
119  *
120  * RETURN:      Status
121  *
122  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
123  *              hardware-enabled.
124  *
125  ******************************************************************************/
126
127 ACPI_STATUS
128 AcpiEnableGpe (
129     ACPI_HANDLE             GpeDevice,
130     UINT32                  GpeNumber)
131 {
132     ACPI_STATUS             Status = AE_BAD_PARAMETER;
133     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
134     ACPI_CPU_FLAGS          Flags;
135
136
137     ACPI_FUNCTION_TRACE (AcpiEnableGpe);
138
139
140     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
141
142     /*
143      * Ensure that we have a valid GPE number and that there is some way
144      * of handling the GPE (handler or a GPE method). In other words, we
145      * won't allow a valid GPE to be enabled if there is no way to handle it.
146      */
147     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
148     if (GpeEventInfo)
149     {
150         if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
151             ACPI_GPE_DISPATCH_NONE)
152         {
153             Status = AcpiEvAddGpeReference (GpeEventInfo);
154         }
155         else
156         {
157             Status = AE_NO_HANDLER;
158         }
159     }
160
161     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
162     return_ACPI_STATUS (Status);
163 }
164
165 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
166
167
168 /*******************************************************************************
169  *
170  * FUNCTION:    AcpiDisableGpe
171  *
172  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
173  *              GpeNumber           - GPE level within the GPE block
174  *
175  * RETURN:      Status
176  *
177  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
178  *              removed, only then is the GPE disabled (for runtime GPEs), or
179  *              the GPE mask bit disabled (for wake GPEs)
180  *
181  ******************************************************************************/
182
183 ACPI_STATUS
184 AcpiDisableGpe (
185     ACPI_HANDLE             GpeDevice,
186     UINT32                  GpeNumber)
187 {
188     ACPI_STATUS             Status = AE_BAD_PARAMETER;
189     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
190     ACPI_CPU_FLAGS          Flags;
191
192
193     ACPI_FUNCTION_TRACE (AcpiDisableGpe);
194
195
196     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
197
198     /* Ensure that we have a valid GPE number */
199
200     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
201     if (GpeEventInfo)
202     {
203         Status = AcpiEvRemoveGpeReference (GpeEventInfo);
204     }
205
206     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
207     return_ACPI_STATUS (Status);
208 }
209
210 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
211
212
213 /*******************************************************************************
214  *
215  * FUNCTION:    AcpiSetGpe
216  *
217  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
218  *              GpeNumber           - GPE level within the GPE block
219  *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
220  *
221  * RETURN:      Status
222  *
223  * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
224  *              the reference count mechanism used in the AcpiEnableGpe and
225  *              AcpiDisableGpe interfaces -- and should be used with care.
226  *
227  * Note: Typically used to disable a runtime GPE for short period of time,
228  * then re-enable it, without disturbing the existing reference counts. This
229  * is useful, for example, in the Embedded Controller (EC) driver.
230  *
231  ******************************************************************************/
232
233 ACPI_STATUS
234 AcpiSetGpe (
235     ACPI_HANDLE             GpeDevice,
236     UINT32                  GpeNumber,
237     UINT8                   Action)
238 {
239     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
240     ACPI_STATUS             Status;
241     ACPI_CPU_FLAGS          Flags;
242
243
244     ACPI_FUNCTION_TRACE (AcpiSetGpe);
245
246
247     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
248
249     /* Ensure that we have a valid GPE number */
250
251     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
252     if (!GpeEventInfo)
253     {
254         Status = AE_BAD_PARAMETER;
255         goto UnlockAndExit;
256     }
257
258     /* Perform the action */
259
260     switch (Action)
261     {
262     case ACPI_GPE_ENABLE:
263
264         Status = AcpiEvEnableGpe (GpeEventInfo);
265         break;
266
267     case ACPI_GPE_DISABLE:
268
269         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
270         break;
271
272     default:
273
274         Status = AE_BAD_PARAMETER;
275         break;
276     }
277
278 UnlockAndExit:
279     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
280     return_ACPI_STATUS (Status);
281 }
282
283 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
284
285
286 /*******************************************************************************
287  *
288  * FUNCTION:    AcpiMarkGpeForWake
289  *
290  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
291  *              GpeNumber           - GPE level within the GPE block
292  *
293  * RETURN:      Status
294  *
295  * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
296  *              sets the ACPI_GPE_CAN_WAKE flag.
297  *
298  * Some potential callers of AcpiSetupGpeForWake may know in advance that
299  * there won't be any notify handlers installed for device wake notifications
300  * from the given GPE (one example is a button GPE in Linux). For these cases,
301  * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
302  * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
303  * setup implicit wake notification for it (since there's no handler method).
304  *
305  ******************************************************************************/
306
307 ACPI_STATUS
308 AcpiMarkGpeForWake (
309     ACPI_HANDLE             GpeDevice,
310     UINT32                  GpeNumber)
311 {
312     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
313     ACPI_STATUS             Status = AE_BAD_PARAMETER;
314     ACPI_CPU_FLAGS          Flags;
315
316
317     ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
318
319
320     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
321
322     /* Ensure that we have a valid GPE number */
323
324     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
325     if (GpeEventInfo)
326     {
327         /* Mark the GPE as a possible wake event */
328
329         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
330         Status = AE_OK;
331     }
332
333     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
334     return_ACPI_STATUS (Status);
335 }
336
337 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
338
339
340 /*******************************************************************************
341  *
342  * FUNCTION:    AcpiSetupGpeForWake
343  *
344  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
345  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
346  *              GpeNumber           - GPE level within the GPE block
347  *
348  * RETURN:      Status
349  *
350  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
351  *              interface is intended to be used as the host executes the
352  *              _PRW methods (Power Resources for Wake) in the system tables.
353  *              Each _PRW appears under a Device Object (The WakeDevice), and
354  *              contains the info for the wake GPE associated with the
355  *              WakeDevice.
356  *
357  ******************************************************************************/
358
359 ACPI_STATUS
360 AcpiSetupGpeForWake (
361     ACPI_HANDLE             WakeDevice,
362     ACPI_HANDLE             GpeDevice,
363     UINT32                  GpeNumber)
364 {
365     ACPI_STATUS             Status;
366     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
367     ACPI_NAMESPACE_NODE     *DeviceNode;
368     ACPI_GPE_NOTIFY_INFO    *Notify;
369     ACPI_GPE_NOTIFY_INFO    *NewNotify;
370     ACPI_CPU_FLAGS          Flags;
371
372
373     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
374
375
376     /* Parameter Validation */
377
378     if (!WakeDevice)
379     {
380         /*
381          * By forcing WakeDevice to be valid, we automatically enable the
382          * implicit notify feature on all hosts.
383          */
384         return_ACPI_STATUS (AE_BAD_PARAMETER);
385     }
386
387     /* Handle root object case */
388
389     if (WakeDevice == ACPI_ROOT_OBJECT)
390     {
391         DeviceNode = AcpiGbl_RootNode;
392     }
393     else
394     {
395         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
396     }
397
398     /* Validate WakeDevice is of type Device */
399
400     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
401     {
402         return_ACPI_STATUS (AE_BAD_PARAMETER);
403     }
404
405     /*
406      * Allocate a new notify object up front, in case it is needed.
407      * Memory allocation while holding a spinlock is a big no-no
408      * on some hosts.
409      */
410     NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
411     if (!NewNotify)
412     {
413         return_ACPI_STATUS (AE_NO_MEMORY);
414     }
415
416     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
417
418     /* Ensure that we have a valid GPE number */
419
420     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
421     if (!GpeEventInfo)
422     {
423         Status = AE_BAD_PARAMETER;
424         goto UnlockAndExit;
425     }
426
427     /*
428      * If there is no method or handler for this GPE, then the
429      * WakeDevice will be notified whenever this GPE fires. This is
430      * known as an "implicit notify". Note: The GPE is assumed to be
431      * level-triggered (for windows compatibility).
432      */
433     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
434             ACPI_GPE_DISPATCH_NONE)
435     {
436         /*
437          * This is the first device for implicit notify on this GPE.
438          * Just set the flags here, and enter the NOTIFY block below.
439          */
440         GpeEventInfo->Flags =
441             (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
442     }
443
444     /*
445      * If we already have an implicit notify on this GPE, add
446      * this device to the notify list.
447      */
448     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
449             ACPI_GPE_DISPATCH_NOTIFY)
450     {
451         /* Ensure that the device is not already in the list */
452
453         Notify = GpeEventInfo->Dispatch.NotifyList;
454         while (Notify)
455         {
456             if (Notify->DeviceNode == DeviceNode)
457             {
458                 Status = AE_ALREADY_EXISTS;
459                 goto UnlockAndExit;
460             }
461             Notify = Notify->Next;
462         }
463
464         /* Add this device to the notify list for this GPE */
465
466         NewNotify->DeviceNode = DeviceNode;
467         NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
468         GpeEventInfo->Dispatch.NotifyList = NewNotify;
469         NewNotify = NULL;
470     }
471
472     /* Mark the GPE as a possible wake event */
473
474     GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
475     Status = AE_OK;
476
477
478 UnlockAndExit:
479     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
480
481     /* Delete the notify object if it was not used above */
482
483     if (NewNotify)
484     {
485         ACPI_FREE (NewNotify);
486     }
487     return_ACPI_STATUS (Status);
488 }
489
490 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
491
492
493 /*******************************************************************************
494  *
495  * FUNCTION:    AcpiSetGpeWakeMask
496  *
497  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
498  *              GpeNumber           - GPE level within the GPE block
499  *              Action              - Enable or Disable
500  *
501  * RETURN:      Status
502  *
503  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
504  *              already be marked as a WAKE GPE.
505  *
506  ******************************************************************************/
507
508 ACPI_STATUS
509 AcpiSetGpeWakeMask (
510     ACPI_HANDLE             GpeDevice,
511     UINT32                  GpeNumber,
512     UINT8                   Action)
513 {
514     ACPI_STATUS             Status = AE_OK;
515     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
516     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
517     ACPI_CPU_FLAGS          Flags;
518     UINT32                  RegisterBit;
519
520
521     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
522
523
524     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
525
526     /*
527      * Ensure that we have a valid GPE number and that this GPE is in
528      * fact a wake GPE
529      */
530     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
531     if (!GpeEventInfo)
532     {
533         Status = AE_BAD_PARAMETER;
534         goto UnlockAndExit;
535     }
536
537     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
538     {
539         Status = AE_TYPE;
540         goto UnlockAndExit;
541     }
542
543     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
544     if (!GpeRegisterInfo)
545     {
546         Status = AE_NOT_EXIST;
547         goto UnlockAndExit;
548     }
549
550     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
551
552     /* Perform the action */
553
554     switch (Action)
555     {
556     case ACPI_GPE_ENABLE:
557
558         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
559         break;
560
561     case ACPI_GPE_DISABLE:
562
563         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
564         break;
565
566     default:
567
568         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
569         Status = AE_BAD_PARAMETER;
570         break;
571     }
572
573 UnlockAndExit:
574     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
575     return_ACPI_STATUS (Status);
576 }
577
578 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
579
580
581 /*******************************************************************************
582  *
583  * FUNCTION:    AcpiClearGpe
584  *
585  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
586  *              GpeNumber           - GPE level within the GPE block
587  *
588  * RETURN:      Status
589  *
590  * DESCRIPTION: Clear an ACPI event (general purpose)
591  *
592  ******************************************************************************/
593
594 ACPI_STATUS
595 AcpiClearGpe (
596     ACPI_HANDLE             GpeDevice,
597     UINT32                  GpeNumber)
598 {
599     ACPI_STATUS             Status = AE_OK;
600     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
601     ACPI_CPU_FLAGS          Flags;
602
603
604     ACPI_FUNCTION_TRACE (AcpiClearGpe);
605
606
607     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
608
609     /* Ensure that we have a valid GPE number */
610
611     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
612     if (!GpeEventInfo)
613     {
614         Status = AE_BAD_PARAMETER;
615         goto UnlockAndExit;
616     }
617
618     Status = AcpiHwClearGpe (GpeEventInfo);
619
620 UnlockAndExit:
621     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
622     return_ACPI_STATUS (Status);
623 }
624
625 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
626
627
628 /*******************************************************************************
629  *
630  * FUNCTION:    AcpiGetGpeStatus
631  *
632  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
633  *              GpeNumber           - GPE level within the GPE block
634  *              EventStatus         - Where the current status of the event
635  *                                    will be returned
636  *
637  * RETURN:      Status
638  *
639  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
640  *
641  ******************************************************************************/
642
643 ACPI_STATUS
644 AcpiGetGpeStatus (
645     ACPI_HANDLE             GpeDevice,
646     UINT32                  GpeNumber,
647     ACPI_EVENT_STATUS       *EventStatus)
648 {
649     ACPI_STATUS             Status = AE_OK;
650     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
651     ACPI_CPU_FLAGS          Flags;
652
653
654     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
655
656
657     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
658
659     /* Ensure that we have a valid GPE number */
660
661     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
662     if (!GpeEventInfo)
663     {
664         Status = AE_BAD_PARAMETER;
665         goto UnlockAndExit;
666     }
667
668     /* Obtain status on the requested GPE number */
669
670     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
671
672 UnlockAndExit:
673     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
674     return_ACPI_STATUS (Status);
675 }
676
677 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
678
679
680 /*******************************************************************************
681  *
682  * FUNCTION:    AcpiFinishGpe
683  *
684  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
685  *                                    (NULL for FADT defined GPEs)
686  *              GpeNumber           - GPE level within the GPE block
687  *
688  * RETURN:      Status
689  *
690  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
691  *              processing. Intended for use by asynchronous host-installed
692  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
693  *              is set in the GPE info.
694  *
695  ******************************************************************************/
696
697 ACPI_STATUS
698 AcpiFinishGpe (
699     ACPI_HANDLE             GpeDevice,
700     UINT32                  GpeNumber)
701 {
702     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
703     ACPI_STATUS             Status;
704     ACPI_CPU_FLAGS          Flags;
705
706
707     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
708
709
710     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
711
712     /* Ensure that we have a valid GPE number */
713
714     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
715     if (!GpeEventInfo)
716     {
717         Status = AE_BAD_PARAMETER;
718         goto UnlockAndExit;
719     }
720
721     Status = AcpiEvFinishGpe (GpeEventInfo);
722
723 UnlockAndExit:
724     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
725     return_ACPI_STATUS (Status);
726 }
727
728 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
729
730
731 /******************************************************************************
732  *
733  * FUNCTION:    AcpiDisableAllGpes
734  *
735  * PARAMETERS:  None
736  *
737  * RETURN:      Status
738  *
739  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
740  *
741  ******************************************************************************/
742
743 ACPI_STATUS
744 AcpiDisableAllGpes (
745     void)
746 {
747     ACPI_STATUS             Status;
748
749
750     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
751
752
753     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
754     if (ACPI_FAILURE (Status))
755     {
756         return_ACPI_STATUS (Status);
757     }
758
759     Status = AcpiHwDisableAllGpes ();
760     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
761
762     return_ACPI_STATUS (Status);
763 }
764
765 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
766
767
768 /******************************************************************************
769  *
770  * FUNCTION:    AcpiEnableAllRuntimeGpes
771  *
772  * PARAMETERS:  None
773  *
774  * RETURN:      Status
775  *
776  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
777  *
778  ******************************************************************************/
779
780 ACPI_STATUS
781 AcpiEnableAllRuntimeGpes (
782     void)
783 {
784     ACPI_STATUS             Status;
785
786
787     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
788
789
790     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
791     if (ACPI_FAILURE (Status))
792     {
793         return_ACPI_STATUS (Status);
794     }
795
796     Status = AcpiHwEnableAllRuntimeGpes ();
797     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
798
799     return_ACPI_STATUS (Status);
800 }
801
802 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
803
804
805 /*******************************************************************************
806  *
807  * FUNCTION:    AcpiInstallGpeBlock
808  *
809  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
810  *              GpeBlockAddress     - Address and SpaceID
811  *              RegisterCount       - Number of GPE register pairs in the block
812  *              InterruptNumber     - H/W interrupt for the block
813  *
814  * RETURN:      Status
815  *
816  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
817  *              enabled here.
818  *
819  ******************************************************************************/
820
821 ACPI_STATUS
822 AcpiInstallGpeBlock (
823     ACPI_HANDLE             GpeDevice,
824     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
825     UINT32                  RegisterCount,
826     UINT32                  InterruptNumber)
827 {
828     ACPI_STATUS             Status;
829     ACPI_OPERAND_OBJECT     *ObjDesc;
830     ACPI_NAMESPACE_NODE     *Node;
831     ACPI_GPE_BLOCK_INFO     *GpeBlock;
832
833
834     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
835
836
837     if ((!GpeDevice)       ||
838         (!GpeBlockAddress) ||
839         (!RegisterCount))
840     {
841         return_ACPI_STATUS (AE_BAD_PARAMETER);
842     }
843
844     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
845     if (ACPI_FAILURE (Status))
846     {
847         return_ACPI_STATUS (Status);
848     }
849
850     Node = AcpiNsValidateHandle (GpeDevice);
851     if (!Node)
852     {
853         Status = AE_BAD_PARAMETER;
854         goto UnlockAndExit;
855     }
856
857     /* Validate the parent device */
858
859     if (Node->Type != ACPI_TYPE_DEVICE)
860     {
861         Status = AE_TYPE;
862         goto UnlockAndExit;
863     }
864
865     if (Node->Object)
866     {
867         Status = AE_ALREADY_EXISTS;
868         goto UnlockAndExit;
869     }
870
871     /*
872      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
873      * is always zero
874      */
875     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
876                 GpeBlockAddress->SpaceId, RegisterCount,
877                 0, InterruptNumber, &GpeBlock);
878     if (ACPI_FAILURE (Status))
879     {
880         goto UnlockAndExit;
881     }
882
883     /* Install block in the DeviceObject attached to the node */
884
885     ObjDesc = AcpiNsGetAttachedObject (Node);
886     if (!ObjDesc)
887     {
888         /*
889          * No object, create a new one (Device nodes do not always have
890          * an attached object)
891          */
892         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
893         if (!ObjDesc)
894         {
895             Status = AE_NO_MEMORY;
896             goto UnlockAndExit;
897         }
898
899         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
900
901         /* Remove local reference to the object */
902
903         AcpiUtRemoveReference (ObjDesc);
904         if (ACPI_FAILURE (Status))
905         {
906             goto UnlockAndExit;
907         }
908     }
909
910     /* Now install the GPE block in the DeviceObject */
911
912     ObjDesc->Device.GpeBlock = GpeBlock;
913
914
915 UnlockAndExit:
916     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
917     return_ACPI_STATUS (Status);
918 }
919
920 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
921
922
923 /*******************************************************************************
924  *
925  * FUNCTION:    AcpiRemoveGpeBlock
926  *
927  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
928  *
929  * RETURN:      Status
930  *
931  * DESCRIPTION: Remove a previously installed block of GPE registers
932  *
933  ******************************************************************************/
934
935 ACPI_STATUS
936 AcpiRemoveGpeBlock (
937     ACPI_HANDLE             GpeDevice)
938 {
939     ACPI_OPERAND_OBJECT     *ObjDesc;
940     ACPI_STATUS             Status;
941     ACPI_NAMESPACE_NODE     *Node;
942
943
944     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
945
946
947     if (!GpeDevice)
948     {
949         return_ACPI_STATUS (AE_BAD_PARAMETER);
950     }
951
952     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
953     if (ACPI_FAILURE (Status))
954     {
955         return_ACPI_STATUS (Status);
956     }
957
958     Node = AcpiNsValidateHandle (GpeDevice);
959     if (!Node)
960     {
961         Status = AE_BAD_PARAMETER;
962         goto UnlockAndExit;
963     }
964
965     /* Validate the parent device */
966
967     if (Node->Type != ACPI_TYPE_DEVICE)
968     {
969         Status = AE_TYPE;
970         goto UnlockAndExit;
971     }
972
973     /* Get the DeviceObject attached to the node */
974
975     ObjDesc = AcpiNsGetAttachedObject (Node);
976     if (!ObjDesc ||
977         !ObjDesc->Device.GpeBlock)
978     {
979         return_ACPI_STATUS (AE_NULL_OBJECT);
980     }
981
982     /* Delete the GPE block (but not the DeviceObject) */
983
984     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
985     if (ACPI_SUCCESS (Status))
986     {
987         ObjDesc->Device.GpeBlock = NULL;
988     }
989
990 UnlockAndExit:
991     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
992     return_ACPI_STATUS (Status);
993 }
994
995 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
996
997
998 /*******************************************************************************
999  *
1000  * FUNCTION:    AcpiGetGpeDevice
1001  *
1002  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1003  *              GpeDevice           - Where the parent GPE Device is returned
1004  *
1005  * RETURN:      Status
1006  *
1007  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1008  *              gpe device indicates that the gpe number is contained in one of
1009  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1010  *
1011  ******************************************************************************/
1012
1013 ACPI_STATUS
1014 AcpiGetGpeDevice (
1015     UINT32                  Index,
1016     ACPI_HANDLE             *GpeDevice)
1017 {
1018     ACPI_GPE_DEVICE_INFO    Info;
1019     ACPI_STATUS             Status;
1020
1021
1022     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1023
1024
1025     if (!GpeDevice)
1026     {
1027         return_ACPI_STATUS (AE_BAD_PARAMETER);
1028     }
1029
1030     if (Index >= AcpiCurrentGpeCount)
1031     {
1032         return_ACPI_STATUS (AE_NOT_EXIST);
1033     }
1034
1035     /* Setup and walk the GPE list */
1036
1037     Info.Index = Index;
1038     Info.Status = AE_NOT_EXIST;
1039     Info.GpeDevice = NULL;
1040     Info.NextBlockBaseIndex = 0;
1041
1042     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1043     if (ACPI_FAILURE (Status))
1044     {
1045         return_ACPI_STATUS (Status);
1046     }
1047
1048     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1049     return_ACPI_STATUS (Info.Status);
1050 }
1051
1052 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1053
1054 #endif /* !ACPI_REDUCED_HARDWARE */