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