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