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