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