Import acpica-unix-20061109 from Intel.
[dragonfly.git] / sys / contrib / dev / acpica-unix-20061109 / events / evgpe.c
1 /******************************************************************************
2  *
3  * Module Name: evgpe - General Purpose Event handling and dispatch
4  *              $Revision: 1.67 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2006, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117 #include "acpi.h"
118 #include "acevents.h"
119 #include "acnamesp.h"
120
121 #define _COMPONENT          ACPI_EVENTS
122         ACPI_MODULE_NAME    ("evgpe")
123
124 /* Local prototypes */
125
126 static void ACPI_SYSTEM_XFACE
127 AcpiEvAsynchExecuteGpeMethod (
128     void                    *Context);
129
130
131 /*******************************************************************************
132  *
133  * FUNCTION:    AcpiEvSetGpeType
134  *
135  * PARAMETERS:  GpeEventInfo            - GPE to set
136  *              Type                    - New type
137  *
138  * RETURN:      Status
139  *
140  * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
141  *
142  ******************************************************************************/
143
144 ACPI_STATUS
145 AcpiEvSetGpeType (
146     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
147     UINT8                   Type)
148 {
149     ACPI_STATUS             Status;
150
151
152     ACPI_FUNCTION_TRACE (EvSetGpeType);
153
154
155     /* Validate type and update register enable masks */
156
157     switch (Type)
158     {
159     case ACPI_GPE_TYPE_WAKE:
160     case ACPI_GPE_TYPE_RUNTIME:
161     case ACPI_GPE_TYPE_WAKE_RUN:
162         break;
163
164     default:
165         return_ACPI_STATUS (AE_BAD_PARAMETER);
166     }
167
168     /* Disable the GPE if currently enabled */
169
170     Status = AcpiEvDisableGpe (GpeEventInfo);
171
172     /* Type was validated above */
173
174     GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
175     GpeEventInfo->Flags |= Type;                /* Insert type */
176     return_ACPI_STATUS (Status);
177 }
178
179
180 /*******************************************************************************
181  *
182  * FUNCTION:    AcpiEvUpdateGpeEnableMasks
183  *
184  * PARAMETERS:  GpeEventInfo            - GPE to update
185  *              Type                    - What to do: ACPI_GPE_DISABLE or
186  *                                        ACPI_GPE_ENABLE
187  *
188  * RETURN:      Status
189  *
190  * DESCRIPTION: Updates GPE register enable masks based on the GPE type
191  *
192  ******************************************************************************/
193
194 ACPI_STATUS
195 AcpiEvUpdateGpeEnableMasks (
196     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
197     UINT8                   Type)
198 {
199     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
200     UINT8                   RegisterBit;
201
202
203     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
204
205
206     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
207     if (!GpeRegisterInfo)
208     {
209         return_ACPI_STATUS (AE_NOT_EXIST);
210     }
211     RegisterBit = (UINT8)
212         (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
213
214     /* 1) Disable case.  Simply clear all enable bits */
215
216     if (Type == ACPI_GPE_DISABLE)
217     {
218         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
219         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
220         return_ACPI_STATUS (AE_OK);
221     }
222
223     /* 2) Enable case.  Set/Clear the appropriate enable bits */
224
225     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
226     {
227     case ACPI_GPE_TYPE_WAKE:
228         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
229         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
230         break;
231
232     case ACPI_GPE_TYPE_RUNTIME:
233         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
234         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
235         break;
236
237     case ACPI_GPE_TYPE_WAKE_RUN:
238         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
239         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
240         break;
241
242     default:
243         return_ACPI_STATUS (AE_BAD_PARAMETER);
244     }
245
246     return_ACPI_STATUS (AE_OK);
247 }
248
249
250 /*******************************************************************************
251  *
252  * FUNCTION:    AcpiEvEnableGpe
253  *
254  * PARAMETERS:  GpeEventInfo            - GPE to enable
255  *              WriteToHardware         - Enable now, or just mark data structs
256  *                                        (WAKE GPEs should be deferred)
257  *
258  * RETURN:      Status
259  *
260  * DESCRIPTION: Enable a GPE based on the GPE type
261  *
262  ******************************************************************************/
263
264 ACPI_STATUS
265 AcpiEvEnableGpe (
266     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
267     BOOLEAN                 WriteToHardware)
268 {
269     ACPI_STATUS             Status;
270
271
272     ACPI_FUNCTION_TRACE (EvEnableGpe);
273
274
275     /* Make sure HW enable masks are updated */
276
277     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
278     if (ACPI_FAILURE (Status))
279     {
280         return_ACPI_STATUS (Status);
281     }
282
283     /* Mark wake-enabled or HW enable, or both */
284
285     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
286     {
287     case ACPI_GPE_TYPE_WAKE:
288
289         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
290         break;
291
292     case ACPI_GPE_TYPE_WAKE_RUN:
293
294         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
295
296         /*lint -fallthrough */
297
298     case ACPI_GPE_TYPE_RUNTIME:
299
300         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
301
302         if (WriteToHardware)
303         {
304             /* Clear the GPE (of stale events), then enable it */
305
306             Status = AcpiHwClearGpe (GpeEventInfo);
307             if (ACPI_FAILURE (Status))
308             {
309                 return_ACPI_STATUS (Status);
310             }
311
312             /* Enable the requested runtime GPE */
313
314             Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
315         }
316         break;
317
318     default:
319         return_ACPI_STATUS (AE_BAD_PARAMETER);
320     }
321
322     return_ACPI_STATUS (AE_OK);
323 }
324
325
326 /*******************************************************************************
327  *
328  * FUNCTION:    AcpiEvDisableGpe
329  *
330  * PARAMETERS:  GpeEventInfo            - GPE to disable
331  *
332  * RETURN:      Status
333  *
334  * DESCRIPTION: Disable a GPE based on the GPE type
335  *
336  ******************************************************************************/
337
338 ACPI_STATUS
339 AcpiEvDisableGpe (
340     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
341 {
342     ACPI_STATUS             Status;
343
344
345     ACPI_FUNCTION_TRACE (EvDisableGpe);
346
347
348     if (!(GpeEventInfo->Flags & ACPI_GPE_ENABLE_MASK))
349     {
350         return_ACPI_STATUS (AE_OK);
351     }
352
353     /* Make sure HW enable masks are updated */
354
355     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
356     if (ACPI_FAILURE (Status))
357     {
358         return_ACPI_STATUS (Status);
359     }
360
361     /* Mark wake-disabled or HW disable, or both */
362
363     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
364     {
365     case ACPI_GPE_TYPE_WAKE:
366         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
367         break;
368
369     case ACPI_GPE_TYPE_WAKE_RUN:
370         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
371
372         /*lint -fallthrough */
373
374     case ACPI_GPE_TYPE_RUNTIME:
375
376         /* Disable the requested runtime GPE */
377
378         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
379         Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
380         break;
381
382     default:
383         return_ACPI_STATUS (AE_BAD_PARAMETER);
384     }
385
386     return_ACPI_STATUS (AE_OK);
387 }
388
389
390 /*******************************************************************************
391  *
392  * FUNCTION:    AcpiEvGetGpeEventInfo
393  *
394  * PARAMETERS:  GpeDevice           - Device node.  NULL for GPE0/GPE1
395  *              GpeNumber           - Raw GPE number
396  *
397  * RETURN:      A GPE EventInfo struct.  NULL if not a valid GPE
398  *
399  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
400  *              Validates the GpeBlock and the GpeNumber
401  *
402  *              Should be called only when the GPE lists are semaphore locked
403  *              and not subject to change.
404  *
405  ******************************************************************************/
406
407 ACPI_GPE_EVENT_INFO *
408 AcpiEvGetGpeEventInfo (
409     ACPI_HANDLE             GpeDevice,
410     UINT32                  GpeNumber)
411 {
412     ACPI_OPERAND_OBJECT     *ObjDesc;
413     ACPI_GPE_BLOCK_INFO     *GpeBlock;
414     ACPI_NATIVE_UINT        i;
415
416
417     ACPI_FUNCTION_ENTRY ();
418
419
420     /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
421
422     if (!GpeDevice)
423     {
424         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
425
426         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
427         {
428             GpeBlock = AcpiGbl_GpeFadtBlocks[i];
429             if (GpeBlock)
430             {
431                 if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
432                     (GpeNumber < GpeBlock->BlockBaseNumber +
433                         (GpeBlock->RegisterCount * 8)))
434                 {
435                     return (&GpeBlock->EventInfo[GpeNumber -
436                         GpeBlock->BlockBaseNumber]);
437                 }
438             }
439         }
440
441         /* The GpeNumber was not in the range of either FADT GPE block */
442
443         return (NULL);
444     }
445
446     /* A Non-NULL GpeDevice means this is a GPE Block Device */
447
448     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
449     if (!ObjDesc ||
450         !ObjDesc->Device.GpeBlock)
451     {
452         return (NULL);
453     }
454
455     GpeBlock = ObjDesc->Device.GpeBlock;
456
457     if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
458         (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
459     {
460         return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
461     }
462
463     return (NULL);
464 }
465
466
467 /*******************************************************************************
468  *
469  * FUNCTION:    AcpiEvGpeDetect
470  *
471  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
472  *                                    Can have multiple GPE blocks attached.
473  *
474  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
475  *
476  * DESCRIPTION: Detect if any GP events have occurred.  This function is
477  *              executed at interrupt level.
478  *
479  ******************************************************************************/
480
481 UINT32
482 AcpiEvGpeDetect (
483     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
484 {
485     ACPI_STATUS             Status;
486     ACPI_GPE_BLOCK_INFO     *GpeBlock;
487     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
488     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
489     UINT8                   EnabledStatusByte;
490     UINT32                  StatusReg;
491     UINT32                  EnableReg;
492     ACPI_CPU_FLAGS          Flags;
493     ACPI_NATIVE_UINT        i;
494     ACPI_NATIVE_UINT        j;
495
496
497     ACPI_FUNCTION_NAME (EvGpeDetect);
498
499     /* Check for the case where there are no GPEs */
500
501     if (!GpeXruptList)
502     {
503         return (IntStatus);
504     }
505
506     /*
507      * We need to obtain the GPE lock for both the data structs and registers
508      * Note: Not necessary to obtain the hardware lock, since the GPE registers
509      * are owned by the GpeLock.
510      */
511     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
512
513     /* Examine all GPE blocks attached to this interrupt level */
514
515     GpeBlock = GpeXruptList->GpeBlockListHead;
516     while (GpeBlock)
517     {
518         /*
519          * Read all of the 8-bit GPE status and enable registers
520          * in this GPE block, saving all of them.
521          * Find all currently active GP events.
522          */
523         for (i = 0; i < GpeBlock->RegisterCount; i++)
524         {
525             /* Get the next status/enable pair */
526
527             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
528
529             /* Read the Status Register */
530
531             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &StatusReg,
532                         &GpeRegisterInfo->StatusAddress);
533             if (ACPI_FAILURE (Status))
534             {
535                 goto UnlockAndExit;
536             }
537
538             /* Read the Enable Register */
539
540             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &EnableReg,
541                         &GpeRegisterInfo->EnableAddress);
542             if (ACPI_FAILURE (Status))
543             {
544                 goto UnlockAndExit;
545             }
546
547             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
548                 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
549                 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
550
551             /* Check if there is anything active at all in this register */
552
553             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
554             if (!EnabledStatusByte)
555             {
556                 /* No active GPEs in this register, move on */
557
558                 continue;
559             }
560
561             /* Now look at the individual GPEs in this byte register */
562
563             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
564             {
565                 /* Examine one GPE bit */
566
567                 if (EnabledStatusByte & (1 << j))
568                 {
569                     /*
570                      * Found an active GPE. Dispatch the event to a handler
571                      * or method.
572                      */
573                     IntStatus |= AcpiEvGpeDispatch (
574                         &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j],
575                         (UINT32) j + GpeRegisterInfo->BaseGpeNumber);
576                 }
577             }
578         }
579
580         GpeBlock = GpeBlock->Next;
581     }
582
583 UnlockAndExit:
584
585     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
586     return (IntStatus);
587 }
588
589
590 /*******************************************************************************
591  *
592  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
593  *
594  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
595  *
596  * RETURN:      None
597  *
598  * DESCRIPTION: Perform the actual execution of a GPE control method. This
599  *              function is called from an invocation of AcpiOsExecute and
600  *              therefore does NOT execute at interrupt level - so that
601  *              the control method itself is not executed in the context of
602  *              an interrupt handler.
603  *
604  ******************************************************************************/
605
606 static void ACPI_SYSTEM_XFACE
607 AcpiEvAsynchExecuteGpeMethod (
608     void                    *Context)
609 {
610     ACPI_GPE_EVENT_INFO     *GpeEventInfo = (void *) Context;
611     ACPI_STATUS             Status;
612     ACPI_GPE_EVENT_INFO     LocalGpeEventInfo;
613     ACPI_EVALUATE_INFO      *Info;
614
615
616     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
617
618
619     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
620     if (ACPI_FAILURE (Status))
621     {
622         return_VOID;
623     }
624
625     /* Must revalidate the GpeNumber/GpeBlock */
626
627     if (!AcpiEvValidGpeEvent (GpeEventInfo))
628     {
629         Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
630         return_VOID;
631     }
632
633     /* Set the GPE flags for return to enabled state */
634
635     (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
636
637     /*
638      * Take a snapshot of the GPE info for this level - we copy the
639      * info to prevent a race condition with RemoveHandler/RemoveBlock.
640      */
641     ACPI_MEMCPY (&LocalGpeEventInfo, GpeEventInfo,
642         sizeof (ACPI_GPE_EVENT_INFO));
643
644     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
645     if (ACPI_FAILURE (Status))
646     {
647         return_VOID;
648     }
649
650     /*
651      * Must check for control method type dispatch one more
652      * time to avoid race with EvGpeInstallHandler
653      */
654     if ((LocalGpeEventInfo.Flags & ACPI_GPE_DISPATCH_MASK) ==
655             ACPI_GPE_DISPATCH_METHOD)
656     {
657         /* Allocate the evaluation information block */
658
659         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
660         if (!Info)
661         {
662             Status = AE_NO_MEMORY;
663         }
664         else
665         {
666             /*
667              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
668              * control method that corresponds to this GPE
669              */
670             Info->PrefixNode = LocalGpeEventInfo.Dispatch.MethodNode;
671             Info->Parameters = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT *, GpeEventInfo);
672             Info->ParameterType = ACPI_PARAM_GPE;
673             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
674
675             Status = AcpiNsEvaluate (Info);
676             ACPI_FREE (Info);
677         }
678
679         if (ACPI_FAILURE (Status))
680         {
681             ACPI_EXCEPTION ((AE_INFO, Status,
682                 "while evaluating GPE method [%4.4s]",
683                 AcpiUtGetNodeName (LocalGpeEventInfo.Dispatch.MethodNode)));
684         }
685     }
686
687     if ((LocalGpeEventInfo.Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
688             ACPI_GPE_LEVEL_TRIGGERED)
689     {
690         /*
691          * GPE is level-triggered, we clear the GPE status bit after
692          * handling the event.
693          */
694         Status = AcpiHwClearGpe (&LocalGpeEventInfo);
695         if (ACPI_FAILURE (Status))
696         {
697             return_VOID;
698         }
699     }
700
701     /* Enable this GPE */
702
703     (void) AcpiHwWriteGpeEnableReg (&LocalGpeEventInfo);
704     return_VOID;
705 }
706
707
708 /*******************************************************************************
709  *
710  * FUNCTION:    AcpiEvGpeDispatch
711  *
712  * PARAMETERS:  GpeEventInfo    - Info for this GPE
713  *              GpeNumber       - Number relative to the parent GPE block
714  *
715  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
716  *
717  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
718  *              or method (e.g. _Lxx/_Exx) handler.
719  *
720  *              This function executes at interrupt level.
721  *
722  ******************************************************************************/
723
724 UINT32
725 AcpiEvGpeDispatch (
726     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
727     UINT32                  GpeNumber)
728 {
729     ACPI_STATUS             Status;
730
731
732     ACPI_FUNCTION_TRACE (EvGpeDispatch);
733
734
735     AcpiGpeCount++;
736
737     /*
738      * If edge-triggered, clear the GPE status bit now.  Note that
739      * level-triggered events are cleared after the GPE is serviced.
740      */
741     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
742             ACPI_GPE_EDGE_TRIGGERED)
743     {
744         Status = AcpiHwClearGpe (GpeEventInfo);
745         if (ACPI_FAILURE (Status))
746         {
747             ACPI_EXCEPTION ((AE_INFO, Status,
748                 "Unable to clear GPE[%2X]", GpeNumber));
749             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
750         }
751     }
752
753     if (!AcpiGbl_SystemAwakeAndRunning)
754     {
755         /*
756          * We just woke up because of a wake GPE. Disable any further GPEs
757          * until we are fully up and running (Only wake GPEs should be enabled
758          * at this time, but we just brute-force disable them all.)
759          * 1) We must disable this particular wake GPE so it won't fire again
760          * 2) We want to disable all wake GPEs, since we are now awake
761          */
762         (void) AcpiHwDisableAllGpes ();
763     }
764
765     /*
766      * Dispatch the GPE to either an installed handler, or the control method
767      * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
768      * it and do not attempt to run the method. If there is neither a handler
769      * nor a method, we disable this GPE to prevent further such pointless
770      * events from firing.
771      */
772     switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
773     {
774     case ACPI_GPE_DISPATCH_HANDLER:
775
776         /*
777          * Invoke the installed handler (at interrupt level)
778          * Ignore return status for now.  TBD: leave GPE disabled on error?
779          */
780         (void) GpeEventInfo->Dispatch.Handler->Address (
781                         GpeEventInfo->Dispatch.Handler->Context);
782
783         /* It is now safe to clear level-triggered events. */
784
785         if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
786                 ACPI_GPE_LEVEL_TRIGGERED)
787         {
788             Status = AcpiHwClearGpe (GpeEventInfo);
789             if (ACPI_FAILURE (Status))
790             {
791                 ACPI_EXCEPTION ((AE_INFO, Status,
792                     "Unable to clear GPE[%2X]", GpeNumber));
793                 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
794             }
795         }
796         break;
797
798     case ACPI_GPE_DISPATCH_METHOD:
799
800         /*
801          * Disable the GPE, so it doesn't keep firing before the method has a
802          * chance to run (it runs asynchronously with interrupts enabled).
803          */
804         Status = AcpiEvDisableGpe (GpeEventInfo);
805         if (ACPI_FAILURE (Status))
806         {
807             ACPI_EXCEPTION ((AE_INFO, Status,
808                 "Unable to disable GPE[%2X]", GpeNumber));
809             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
810         }
811
812         /*
813          * Execute the method associated with the GPE
814          * NOTE: Level-triggered GPEs are cleared after the method completes.
815          */
816         Status = AcpiOsExecute (OSL_GPE_HANDLER,
817                     AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
818         if (ACPI_FAILURE (Status))
819         {
820             ACPI_EXCEPTION ((AE_INFO, Status,
821                 "Unable to queue handler for GPE[%2X] - event disabled",
822                 GpeNumber));
823         }
824         break;
825
826     default:
827
828         /* No handler or method to run! */
829
830         ACPI_ERROR ((AE_INFO,
831             "No handler or method for GPE[%2X], disabling event",
832             GpeNumber));
833
834         /*
835          * Disable the GPE. The GPE will remain disabled until the ACPI
836          * Core Subsystem is restarted, or a handler is installed.
837          */
838         Status = AcpiEvDisableGpe (GpeEventInfo);
839         if (ACPI_FAILURE (Status))
840         {
841             ACPI_EXCEPTION ((AE_INFO, Status,
842                 "Unable to disable GPE[%2X]", GpeNumber));
843             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
844         }
845         break;
846     }
847
848     return_UINT32 (ACPI_INTERRUPT_HANDLED);
849 }
850