xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evxfgpe.c (revision f8da8f3477d3c18142e59d17d05a545982faa5a8)
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 - 2013, 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 
326         Status = AcpiEvEnableGpe (GpeEventInfo);
327         break;
328 
329     case ACPI_GPE_DISABLE:
330 
331         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
332         break;
333 
334     default:
335 
336         Status = AE_BAD_PARAMETER;
337         break;
338     }
339 
340 UnlockAndExit:
341     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
342     return_ACPI_STATUS (Status);
343 }
344 
345 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
346 
347 
348 /*******************************************************************************
349  *
350  * FUNCTION:    AcpiSetupGpeForWake
351  *
352  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
353  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
354  *              GpeNumber           - GPE level within the GPE block
355  *
356  * RETURN:      Status
357  *
358  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
359  *              interface is intended to be used as the host executes the
360  *              _PRW methods (Power Resources for Wake) in the system tables.
361  *              Each _PRW appears under a Device Object (The WakeDevice), and
362  *              contains the info for the wake GPE associated with the
363  *              WakeDevice.
364  *
365  ******************************************************************************/
366 
367 ACPI_STATUS
368 AcpiSetupGpeForWake (
369     ACPI_HANDLE             WakeDevice,
370     ACPI_HANDLE             GpeDevice,
371     UINT32                  GpeNumber)
372 {
373     ACPI_STATUS             Status;
374     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
375     ACPI_NAMESPACE_NODE     *DeviceNode;
376     ACPI_GPE_NOTIFY_INFO    *Notify;
377     ACPI_GPE_NOTIFY_INFO    *NewNotify;
378     ACPI_CPU_FLAGS          Flags;
379 
380 
381     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
382 
383 
384     /* Parameter Validation */
385 
386     if (!WakeDevice)
387     {
388         /*
389          * By forcing WakeDevice to be valid, we automatically enable the
390          * implicit notify feature on all hosts.
391          */
392         return_ACPI_STATUS (AE_BAD_PARAMETER);
393     }
394 
395     /* Handle root object case */
396 
397     if (WakeDevice == ACPI_ROOT_OBJECT)
398     {
399         DeviceNode = AcpiGbl_RootNode;
400     }
401     else
402     {
403         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
404     }
405 
406     /* Validate WakeDevice is of type Device */
407 
408     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
409     {
410         return_ACPI_STATUS (AE_BAD_PARAMETER);
411     }
412 
413     /*
414      * Allocate a new notify object up front, in case it is needed.
415      * Memory allocation while holding a spinlock is a big no-no
416      * on some hosts.
417      */
418     NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
419     if (!NewNotify)
420     {
421         return_ACPI_STATUS (AE_NO_MEMORY);
422     }
423 
424     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
425 
426     /* Ensure that we have a valid GPE number */
427 
428     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
429     if (!GpeEventInfo)
430     {
431         Status = AE_BAD_PARAMETER;
432         goto UnlockAndExit;
433     }
434 
435     /*
436      * If there is no method or handler for this GPE, then the
437      * WakeDevice will be notified whenever this GPE fires. This is
438      * known as an "implicit notify". Note: The GPE is assumed to be
439      * level-triggered (for windows compatibility).
440      */
441     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
442             ACPI_GPE_DISPATCH_NONE)
443     {
444         /*
445          * This is the first device for implicit notify on this GPE.
446          * Just set the flags here, and enter the NOTIFY block below.
447          */
448         GpeEventInfo->Flags =
449             (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
450     }
451 
452     /*
453      * If we already have an implicit notify on this GPE, add
454      * this device to the notify list.
455      */
456     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
457             ACPI_GPE_DISPATCH_NOTIFY)
458     {
459         /* Ensure that the device is not already in the list */
460 
461         Notify = GpeEventInfo->Dispatch.NotifyList;
462         while (Notify)
463         {
464             if (Notify->DeviceNode == DeviceNode)
465             {
466                 Status = AE_ALREADY_EXISTS;
467                 goto UnlockAndExit;
468             }
469             Notify = Notify->Next;
470         }
471 
472         /* Add this device to the notify list for this GPE */
473 
474         NewNotify->DeviceNode = DeviceNode;
475         NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
476         GpeEventInfo->Dispatch.NotifyList = NewNotify;
477         NewNotify = NULL;
478     }
479 
480     /* Mark the GPE as a possible wake event */
481 
482     GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
483     Status = AE_OK;
484 
485 
486 UnlockAndExit:
487     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
488 
489     /* Delete the notify object if it was not used above */
490 
491     if (NewNotify)
492     {
493         ACPI_FREE (NewNotify);
494     }
495     return_ACPI_STATUS (Status);
496 }
497 
498 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
499 
500 
501 /*******************************************************************************
502  *
503  * FUNCTION:    AcpiSetGpeWakeMask
504  *
505  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
506  *              GpeNumber           - GPE level within the GPE block
507  *              Action              - Enable or Disable
508  *
509  * RETURN:      Status
510  *
511  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
512  *              already be marked as a WAKE GPE.
513  *
514  ******************************************************************************/
515 
516 ACPI_STATUS
517 AcpiSetGpeWakeMask (
518     ACPI_HANDLE             GpeDevice,
519     UINT32                  GpeNumber,
520     UINT8                   Action)
521 {
522     ACPI_STATUS             Status = AE_OK;
523     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
524     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
525     ACPI_CPU_FLAGS          Flags;
526     UINT32                  RegisterBit;
527 
528 
529     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
530 
531 
532     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
533 
534     /*
535      * Ensure that we have a valid GPE number and that this GPE is in
536      * fact a wake GPE
537      */
538     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
539     if (!GpeEventInfo)
540     {
541         Status = AE_BAD_PARAMETER;
542         goto UnlockAndExit;
543     }
544 
545     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
546     {
547         Status = AE_TYPE;
548         goto UnlockAndExit;
549     }
550 
551     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
552     if (!GpeRegisterInfo)
553     {
554         Status = AE_NOT_EXIST;
555         goto UnlockAndExit;
556     }
557 
558     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
559 
560     /* Perform the action */
561 
562     switch (Action)
563     {
564     case ACPI_GPE_ENABLE:
565 
566         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
567         break;
568 
569     case ACPI_GPE_DISABLE:
570 
571         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
572         break;
573 
574     default:
575 
576         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
577         Status = AE_BAD_PARAMETER;
578         break;
579     }
580 
581 UnlockAndExit:
582     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
583     return_ACPI_STATUS (Status);
584 }
585 
586 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
587 
588 
589 /*******************************************************************************
590  *
591  * FUNCTION:    AcpiClearGpe
592  *
593  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
594  *              GpeNumber           - GPE level within the GPE block
595  *
596  * RETURN:      Status
597  *
598  * DESCRIPTION: Clear an ACPI event (general purpose)
599  *
600  ******************************************************************************/
601 
602 ACPI_STATUS
603 AcpiClearGpe (
604     ACPI_HANDLE             GpeDevice,
605     UINT32                  GpeNumber)
606 {
607     ACPI_STATUS             Status = AE_OK;
608     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
609     ACPI_CPU_FLAGS          Flags;
610 
611 
612     ACPI_FUNCTION_TRACE (AcpiClearGpe);
613 
614 
615     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
616 
617     /* Ensure that we have a valid GPE number */
618 
619     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
620     if (!GpeEventInfo)
621     {
622         Status = AE_BAD_PARAMETER;
623         goto UnlockAndExit;
624     }
625 
626     Status = AcpiHwClearGpe (GpeEventInfo);
627 
628 UnlockAndExit:
629     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
630     return_ACPI_STATUS (Status);
631 }
632 
633 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
634 
635 
636 /*******************************************************************************
637  *
638  * FUNCTION:    AcpiGetGpeStatus
639  *
640  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
641  *              GpeNumber           - GPE level within the GPE block
642  *              EventStatus         - Where the current status of the event
643  *                                    will be returned
644  *
645  * RETURN:      Status
646  *
647  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
648  *
649  ******************************************************************************/
650 
651 ACPI_STATUS
652 AcpiGetGpeStatus (
653     ACPI_HANDLE             GpeDevice,
654     UINT32                  GpeNumber,
655     ACPI_EVENT_STATUS       *EventStatus)
656 {
657     ACPI_STATUS             Status = AE_OK;
658     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
659     ACPI_CPU_FLAGS          Flags;
660 
661 
662     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
663 
664 
665     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
666 
667     /* Ensure that we have a valid GPE number */
668 
669     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
670     if (!GpeEventInfo)
671     {
672         Status = AE_BAD_PARAMETER;
673         goto UnlockAndExit;
674     }
675 
676     /* Obtain status on the requested GPE number */
677 
678     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
679 
680 UnlockAndExit:
681     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
682     return_ACPI_STATUS (Status);
683 }
684 
685 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
686 
687 
688 /*******************************************************************************
689  *
690  * FUNCTION:    AcpiFinishGpe
691  *
692  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
693  *                                    (NULL for FADT defined GPEs)
694  *              GpeNumber           - GPE level within the GPE block
695  *
696  * RETURN:      Status
697  *
698  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
699  *              processing. Intended for use by asynchronous host-installed
700  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
701  *              is set in the GPE info.
702  *
703  ******************************************************************************/
704 
705 ACPI_STATUS
706 AcpiFinishGpe (
707     ACPI_HANDLE             GpeDevice,
708     UINT32                  GpeNumber)
709 {
710     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
711     ACPI_STATUS             Status;
712     ACPI_CPU_FLAGS          Flags;
713 
714 
715     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
716 
717 
718     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
719 
720     /* Ensure that we have a valid GPE number */
721 
722     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
723     if (!GpeEventInfo)
724     {
725         Status = AE_BAD_PARAMETER;
726         goto UnlockAndExit;
727     }
728 
729     Status = AcpiEvFinishGpe (GpeEventInfo);
730 
731 UnlockAndExit:
732     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
733     return_ACPI_STATUS (Status);
734 }
735 
736 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
737 
738 
739 /******************************************************************************
740  *
741  * FUNCTION:    AcpiDisableAllGpes
742  *
743  * PARAMETERS:  None
744  *
745  * RETURN:      Status
746  *
747  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
748  *
749  ******************************************************************************/
750 
751 ACPI_STATUS
752 AcpiDisableAllGpes (
753     void)
754 {
755     ACPI_STATUS             Status;
756 
757 
758     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
759 
760 
761     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
762     if (ACPI_FAILURE (Status))
763     {
764         return_ACPI_STATUS (Status);
765     }
766 
767     Status = AcpiHwDisableAllGpes ();
768     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
769 
770     return_ACPI_STATUS (Status);
771 }
772 
773 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
774 
775 
776 /******************************************************************************
777  *
778  * FUNCTION:    AcpiEnableAllRuntimeGpes
779  *
780  * PARAMETERS:  None
781  *
782  * RETURN:      Status
783  *
784  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
785  *
786  ******************************************************************************/
787 
788 ACPI_STATUS
789 AcpiEnableAllRuntimeGpes (
790     void)
791 {
792     ACPI_STATUS             Status;
793 
794 
795     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
796 
797 
798     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
799     if (ACPI_FAILURE (Status))
800     {
801         return_ACPI_STATUS (Status);
802     }
803 
804     Status = AcpiHwEnableAllRuntimeGpes ();
805     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
806 
807     return_ACPI_STATUS (Status);
808 }
809 
810 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
811 
812 
813 /*******************************************************************************
814  *
815  * FUNCTION:    AcpiInstallGpeBlock
816  *
817  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
818  *              GpeBlockAddress     - Address and SpaceID
819  *              RegisterCount       - Number of GPE register pairs in the block
820  *              InterruptNumber     - H/W interrupt for the block
821  *
822  * RETURN:      Status
823  *
824  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
825  *              enabled here.
826  *
827  ******************************************************************************/
828 
829 ACPI_STATUS
830 AcpiInstallGpeBlock (
831     ACPI_HANDLE             GpeDevice,
832     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
833     UINT32                  RegisterCount,
834     UINT32                  InterruptNumber)
835 {
836     ACPI_STATUS             Status;
837     ACPI_OPERAND_OBJECT     *ObjDesc;
838     ACPI_NAMESPACE_NODE     *Node;
839     ACPI_GPE_BLOCK_INFO     *GpeBlock;
840 
841 
842     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
843 
844 
845     if ((!GpeDevice)       ||
846         (!GpeBlockAddress) ||
847         (!RegisterCount))
848     {
849         return_ACPI_STATUS (AE_BAD_PARAMETER);
850     }
851 
852     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
853     if (ACPI_FAILURE (Status))
854     {
855         return_ACPI_STATUS (Status);
856     }
857 
858     Node = AcpiNsValidateHandle (GpeDevice);
859     if (!Node)
860     {
861         Status = AE_BAD_PARAMETER;
862         goto UnlockAndExit;
863     }
864 
865     /*
866      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
867      * is always zero
868      */
869     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,
870                 0, InterruptNumber, &GpeBlock);
871     if (ACPI_FAILURE (Status))
872     {
873         goto UnlockAndExit;
874     }
875 
876     /* Install block in the DeviceObject attached to the node */
877 
878     ObjDesc = AcpiNsGetAttachedObject (Node);
879     if (!ObjDesc)
880     {
881         /*
882          * No object, create a new one (Device nodes do not always have
883          * an attached object)
884          */
885         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
886         if (!ObjDesc)
887         {
888             Status = AE_NO_MEMORY;
889             goto UnlockAndExit;
890         }
891 
892         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
893 
894         /* Remove local reference to the object */
895 
896         AcpiUtRemoveReference (ObjDesc);
897         if (ACPI_FAILURE (Status))
898         {
899             goto UnlockAndExit;
900         }
901     }
902 
903     /* Now install the GPE block in the DeviceObject */
904 
905     ObjDesc->Device.GpeBlock = GpeBlock;
906 
907 
908 UnlockAndExit:
909     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
910     return_ACPI_STATUS (Status);
911 }
912 
913 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
914 
915 
916 /*******************************************************************************
917  *
918  * FUNCTION:    AcpiRemoveGpeBlock
919  *
920  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
921  *
922  * RETURN:      Status
923  *
924  * DESCRIPTION: Remove a previously installed block of GPE registers
925  *
926  ******************************************************************************/
927 
928 ACPI_STATUS
929 AcpiRemoveGpeBlock (
930     ACPI_HANDLE             GpeDevice)
931 {
932     ACPI_OPERAND_OBJECT     *ObjDesc;
933     ACPI_STATUS             Status;
934     ACPI_NAMESPACE_NODE     *Node;
935 
936 
937     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
938 
939 
940     if (!GpeDevice)
941     {
942         return_ACPI_STATUS (AE_BAD_PARAMETER);
943     }
944 
945     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
946     if (ACPI_FAILURE (Status))
947     {
948         return_ACPI_STATUS (Status);
949     }
950 
951     Node = AcpiNsValidateHandle (GpeDevice);
952     if (!Node)
953     {
954         Status = AE_BAD_PARAMETER;
955         goto UnlockAndExit;
956     }
957 
958     /* Get the DeviceObject attached to the node */
959 
960     ObjDesc = AcpiNsGetAttachedObject (Node);
961     if (!ObjDesc ||
962         !ObjDesc->Device.GpeBlock)
963     {
964         return_ACPI_STATUS (AE_NULL_OBJECT);
965     }
966 
967     /* Delete the GPE block (but not the DeviceObject) */
968 
969     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
970     if (ACPI_SUCCESS (Status))
971     {
972         ObjDesc->Device.GpeBlock = NULL;
973     }
974 
975 UnlockAndExit:
976     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
977     return_ACPI_STATUS (Status);
978 }
979 
980 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
981 
982 
983 /*******************************************************************************
984  *
985  * FUNCTION:    AcpiGetGpeDevice
986  *
987  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
988  *              GpeDevice           - Where the parent GPE Device is returned
989  *
990  * RETURN:      Status
991  *
992  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
993  *              gpe device indicates that the gpe number is contained in one of
994  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
995  *
996  ******************************************************************************/
997 
998 ACPI_STATUS
999 AcpiGetGpeDevice (
1000     UINT32                  Index,
1001     ACPI_HANDLE             *GpeDevice)
1002 {
1003     ACPI_GPE_DEVICE_INFO    Info;
1004     ACPI_STATUS             Status;
1005 
1006 
1007     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1008 
1009 
1010     if (!GpeDevice)
1011     {
1012         return_ACPI_STATUS (AE_BAD_PARAMETER);
1013     }
1014 
1015     if (Index >= AcpiCurrentGpeCount)
1016     {
1017         return_ACPI_STATUS (AE_NOT_EXIST);
1018     }
1019 
1020     /* Setup and walk the GPE list */
1021 
1022     Info.Index = Index;
1023     Info.Status = AE_NOT_EXIST;
1024     Info.GpeDevice = NULL;
1025     Info.NextBlockBaseIndex = 0;
1026 
1027     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1028     if (ACPI_FAILURE (Status))
1029     {
1030         return_ACPI_STATUS (Status);
1031     }
1032 
1033     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1034     return_ACPI_STATUS (Info.Status);
1035 }
1036 
1037 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1038 
1039 #endif /* !ACPI_REDUCED_HARDWARE */
1040