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