xref: /freebsd/sys/contrib/dev/acpica/components/events/evxfgpe.c (revision 7750ad47a9a7dbc83f87158464170c8640723293)
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 (AcpiUpdateGpes);
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 = AE_BAD_PARAMETER;
299     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
300     ACPI_NAMESPACE_NODE     *DeviceNode;
301     ACPI_CPU_FLAGS          Flags;
302 
303 
304     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
305 
306 
307     /* Parameter Validation */
308 
309     if (!WakeDevice)
310     {
311         /*
312          * By forcing WakeDevice to be valid, we automatically enable the
313          * implicit notify feature on all hosts.
314          */
315         return_ACPI_STATUS (AE_BAD_PARAMETER);
316     }
317 
318     /* Handle root object case */
319 
320     if (WakeDevice == ACPI_ROOT_OBJECT)
321     {
322         DeviceNode = AcpiGbl_RootNode;
323     }
324     else
325     {
326         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
327     }
328 
329     /* Validate WakeDevice is of type Device */
330 
331     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
332     {
333         return_ACPI_STATUS (AE_BAD_PARAMETER);
334     }
335 
336     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
337 
338     /* Ensure that we have a valid GPE number */
339 
340     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
341     if (GpeEventInfo)
342     {
343         /*
344          * If there is no method or handler for this GPE, then the
345          * WakeDevice will be notified whenever this GPE fires (aka
346          * "implicit notify") Note: The GPE is assumed to be
347          * level-triggered (for windows compatibility).
348          */
349         if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
350                 ACPI_GPE_DISPATCH_NONE)
351         {
352             GpeEventInfo->Flags =
353                 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
354             GpeEventInfo->Dispatch.DeviceNode = DeviceNode;
355         }
356 
357         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
358         Status = AE_OK;
359     }
360 
361     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
362     return_ACPI_STATUS (Status);
363 }
364 
365 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
366 
367 
368 /*******************************************************************************
369  *
370  * FUNCTION:    AcpiSetGpeWakeMask
371  *
372  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
373  *              GpeNumber           - GPE level within the GPE block
374  *              Action              - Enable or Disable
375  *
376  * RETURN:      Status
377  *
378  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
379  *              already be marked as a WAKE GPE.
380  *
381  ******************************************************************************/
382 
383 ACPI_STATUS
384 AcpiSetGpeWakeMask (
385     ACPI_HANDLE             GpeDevice,
386     UINT32                  GpeNumber,
387     UINT8                   Action)
388 {
389     ACPI_STATUS             Status = AE_OK;
390     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
391     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
392     ACPI_CPU_FLAGS          Flags;
393     UINT32                  RegisterBit;
394 
395 
396     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
397 
398 
399     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
400 
401     /*
402      * Ensure that we have a valid GPE number and that this GPE is in
403      * fact a wake GPE
404      */
405     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
406     if (!GpeEventInfo)
407     {
408         Status = AE_BAD_PARAMETER;
409         goto UnlockAndExit;
410     }
411 
412     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
413     {
414         Status = AE_TYPE;
415         goto UnlockAndExit;
416     }
417 
418     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
419     if (!GpeRegisterInfo)
420     {
421         Status = AE_NOT_EXIST;
422         goto UnlockAndExit;
423     }
424 
425     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
426 
427     /* Perform the action */
428 
429     switch (Action)
430     {
431     case ACPI_GPE_ENABLE:
432         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
433         break;
434 
435     case ACPI_GPE_DISABLE:
436         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
437         break;
438 
439     default:
440         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
441         Status = AE_BAD_PARAMETER;
442         break;
443     }
444 
445 UnlockAndExit:
446     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
447     return_ACPI_STATUS (Status);
448 }
449 
450 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
451 
452 
453 /*******************************************************************************
454  *
455  * FUNCTION:    AcpiClearGpe
456  *
457  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
458  *              GpeNumber           - GPE level within the GPE block
459  *
460  * RETURN:      Status
461  *
462  * DESCRIPTION: Clear an ACPI event (general purpose)
463  *
464  ******************************************************************************/
465 
466 ACPI_STATUS
467 AcpiClearGpe (
468     ACPI_HANDLE             GpeDevice,
469     UINT32                  GpeNumber)
470 {
471     ACPI_STATUS             Status = AE_OK;
472     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
473     ACPI_CPU_FLAGS          Flags;
474 
475 
476     ACPI_FUNCTION_TRACE (AcpiClearGpe);
477 
478 
479     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
480 
481     /* Ensure that we have a valid GPE number */
482 
483     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
484     if (!GpeEventInfo)
485     {
486         Status = AE_BAD_PARAMETER;
487         goto UnlockAndExit;
488     }
489 
490     Status = AcpiHwClearGpe (GpeEventInfo);
491 
492 UnlockAndExit:
493     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
494     return_ACPI_STATUS (Status);
495 }
496 
497 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
498 
499 
500 /*******************************************************************************
501  *
502  * FUNCTION:    AcpiGetGpeStatus
503  *
504  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
505  *              GpeNumber           - GPE level within the GPE block
506  *              EventStatus         - Where the current status of the event
507  *                                    will be returned
508  *
509  * RETURN:      Status
510  *
511  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
512  *
513  ******************************************************************************/
514 
515 ACPI_STATUS
516 AcpiGetGpeStatus (
517     ACPI_HANDLE             GpeDevice,
518     UINT32                  GpeNumber,
519     ACPI_EVENT_STATUS       *EventStatus)
520 {
521     ACPI_STATUS             Status = AE_OK;
522     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
523     ACPI_CPU_FLAGS          Flags;
524 
525 
526     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
527 
528 
529     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
530 
531     /* Ensure that we have a valid GPE number */
532 
533     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
534     if (!GpeEventInfo)
535     {
536         Status = AE_BAD_PARAMETER;
537         goto UnlockAndExit;
538     }
539 
540     /* Obtain status on the requested GPE number */
541 
542     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
543 
544 UnlockAndExit:
545     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
546     return_ACPI_STATUS (Status);
547 }
548 
549 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
550 
551 
552 /*******************************************************************************
553  *
554  * FUNCTION:    AcpiFinishGpe
555  *
556  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
557  *                                    (NULL for FADT defined GPEs)
558  *              GpeNumber           - GPE level within the GPE block
559  *
560  * RETURN:      Status
561  *
562  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
563  *              processing. Intended for use by asynchronous host-installed
564  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
565  *              is set in the GPE info.
566  *
567  ******************************************************************************/
568 
569 ACPI_STATUS
570 AcpiFinishGpe (
571     ACPI_HANDLE             GpeDevice,
572     UINT32                  GpeNumber)
573 {
574     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
575     ACPI_STATUS             Status;
576     ACPI_CPU_FLAGS          Flags;
577 
578 
579     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
580 
581 
582     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
583 
584     /* Ensure that we have a valid GPE number */
585 
586     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
587     if (!GpeEventInfo)
588     {
589         Status = AE_BAD_PARAMETER;
590         goto UnlockAndExit;
591     }
592 
593     Status = AcpiEvFinishGpe (GpeEventInfo);
594 
595 UnlockAndExit:
596     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
597     return_ACPI_STATUS (Status);
598 }
599 
600 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
601 
602 
603 /******************************************************************************
604  *
605  * FUNCTION:    AcpiDisableAllGpes
606  *
607  * PARAMETERS:  None
608  *
609  * RETURN:      Status
610  *
611  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
612  *
613  ******************************************************************************/
614 
615 ACPI_STATUS
616 AcpiDisableAllGpes (
617     void)
618 {
619     ACPI_STATUS             Status;
620 
621 
622     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
623 
624 
625     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
626     if (ACPI_FAILURE (Status))
627     {
628         return_ACPI_STATUS (Status);
629     }
630 
631     Status = AcpiHwDisableAllGpes ();
632     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
633 
634     return_ACPI_STATUS (Status);
635 }
636 
637 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
638 
639 
640 /******************************************************************************
641  *
642  * FUNCTION:    AcpiEnableAllRuntimeGpes
643  *
644  * PARAMETERS:  None
645  *
646  * RETURN:      Status
647  *
648  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
649  *
650  ******************************************************************************/
651 
652 ACPI_STATUS
653 AcpiEnableAllRuntimeGpes (
654     void)
655 {
656     ACPI_STATUS             Status;
657 
658 
659     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
660 
661 
662     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
663     if (ACPI_FAILURE (Status))
664     {
665         return_ACPI_STATUS (Status);
666     }
667 
668     Status = AcpiHwEnableAllRuntimeGpes ();
669     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
670 
671     return_ACPI_STATUS (Status);
672 }
673 
674 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
675 
676 
677 /*******************************************************************************
678  *
679  * FUNCTION:    AcpiInstallGpeBlock
680  *
681  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
682  *              GpeBlockAddress     - Address and SpaceID
683  *              RegisterCount       - Number of GPE register pairs in the block
684  *              InterruptNumber     - H/W interrupt for the block
685  *
686  * RETURN:      Status
687  *
688  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
689  *              enabled here.
690  *
691  ******************************************************************************/
692 
693 ACPI_STATUS
694 AcpiInstallGpeBlock (
695     ACPI_HANDLE             GpeDevice,
696     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
697     UINT32                  RegisterCount,
698     UINT32                  InterruptNumber)
699 {
700     ACPI_STATUS             Status;
701     ACPI_OPERAND_OBJECT     *ObjDesc;
702     ACPI_NAMESPACE_NODE     *Node;
703     ACPI_GPE_BLOCK_INFO     *GpeBlock;
704 
705 
706     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
707 
708 
709     if ((!GpeDevice)       ||
710         (!GpeBlockAddress) ||
711         (!RegisterCount))
712     {
713         return_ACPI_STATUS (AE_BAD_PARAMETER);
714     }
715 
716     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
717     if (ACPI_FAILURE (Status))
718     {
719         return (Status);
720     }
721 
722     Node = AcpiNsValidateHandle (GpeDevice);
723     if (!Node)
724     {
725         Status = AE_BAD_PARAMETER;
726         goto UnlockAndExit;
727     }
728 
729     /*
730      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
731      * is always zero
732      */
733     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,
734                 0, InterruptNumber, &GpeBlock);
735     if (ACPI_FAILURE (Status))
736     {
737         goto UnlockAndExit;
738     }
739 
740     /* Install block in the DeviceObject attached to the node */
741 
742     ObjDesc = AcpiNsGetAttachedObject (Node);
743     if (!ObjDesc)
744     {
745         /*
746          * No object, create a new one (Device nodes do not always have
747          * an attached object)
748          */
749         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
750         if (!ObjDesc)
751         {
752             Status = AE_NO_MEMORY;
753             goto UnlockAndExit;
754         }
755 
756         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
757 
758         /* Remove local reference to the object */
759 
760         AcpiUtRemoveReference (ObjDesc);
761         if (ACPI_FAILURE (Status))
762         {
763             goto UnlockAndExit;
764         }
765     }
766 
767     /* Now install the GPE block in the DeviceObject */
768 
769     ObjDesc->Device.GpeBlock = GpeBlock;
770 
771 
772 UnlockAndExit:
773     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
774     return_ACPI_STATUS (Status);
775 }
776 
777 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
778 
779 
780 /*******************************************************************************
781  *
782  * FUNCTION:    AcpiRemoveGpeBlock
783  *
784  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
785  *
786  * RETURN:      Status
787  *
788  * DESCRIPTION: Remove a previously installed block of GPE registers
789  *
790  ******************************************************************************/
791 
792 ACPI_STATUS
793 AcpiRemoveGpeBlock (
794     ACPI_HANDLE             GpeDevice)
795 {
796     ACPI_OPERAND_OBJECT     *ObjDesc;
797     ACPI_STATUS             Status;
798     ACPI_NAMESPACE_NODE     *Node;
799 
800 
801     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
802 
803 
804     if (!GpeDevice)
805     {
806         return_ACPI_STATUS (AE_BAD_PARAMETER);
807     }
808 
809     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
810     if (ACPI_FAILURE (Status))
811     {
812         return (Status);
813     }
814 
815     Node = AcpiNsValidateHandle (GpeDevice);
816     if (!Node)
817     {
818         Status = AE_BAD_PARAMETER;
819         goto UnlockAndExit;
820     }
821 
822     /* Get the DeviceObject attached to the node */
823 
824     ObjDesc = AcpiNsGetAttachedObject (Node);
825     if (!ObjDesc ||
826         !ObjDesc->Device.GpeBlock)
827     {
828         return_ACPI_STATUS (AE_NULL_OBJECT);
829     }
830 
831     /* Delete the GPE block (but not the DeviceObject) */
832 
833     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
834     if (ACPI_SUCCESS (Status))
835     {
836         ObjDesc->Device.GpeBlock = NULL;
837     }
838 
839 UnlockAndExit:
840     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
841     return_ACPI_STATUS (Status);
842 }
843 
844 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
845 
846 
847 /*******************************************************************************
848  *
849  * FUNCTION:    AcpiGetGpeDevice
850  *
851  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
852  *              GpeDevice           - Where the parent GPE Device is returned
853  *
854  * RETURN:      Status
855  *
856  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
857  *              gpe device indicates that the gpe number is contained in one of
858  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
859  *
860  ******************************************************************************/
861 
862 ACPI_STATUS
863 AcpiGetGpeDevice (
864     UINT32                  Index,
865     ACPI_HANDLE             *GpeDevice)
866 {
867     ACPI_GPE_DEVICE_INFO    Info;
868     ACPI_STATUS             Status;
869 
870 
871     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
872 
873 
874     if (!GpeDevice)
875     {
876         return_ACPI_STATUS (AE_BAD_PARAMETER);
877     }
878 
879     if (Index >= AcpiCurrentGpeCount)
880     {
881         return_ACPI_STATUS (AE_NOT_EXIST);
882     }
883 
884     /* Setup and walk the GPE list */
885 
886     Info.Index = Index;
887     Info.Status = AE_NOT_EXIST;
888     Info.GpeDevice = NULL;
889     Info.NextBlockBaseIndex = 0;
890 
891     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
892     if (ACPI_FAILURE (Status))
893     {
894         return_ACPI_STATUS (Status);
895     }
896 
897     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
898     return_ACPI_STATUS (Info.Status);
899 }
900 
901 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
902 
903 #endif /* !ACPI_REDUCED_HARDWARE */
904