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