]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/evgpe.c
This commit was generated by cvs2svn to compensate for changes in r151208,
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / evgpe.c
1 /******************************************************************************
2  *
3  * Module Name: evgpe - General Purpose Event handling and dispatch
4  *              $Revision: 44 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2004, 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
125 /*******************************************************************************
126  *
127  * FUNCTION:    AcpiEvSetGpeType
128  *
129  * PARAMETERS:  GpeEventInfo            - GPE to set
130  *              Type                    - New type
131  *
132  * RETURN:      Status
133  *
134  * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
135  *
136  ******************************************************************************/
137
138 ACPI_STATUS
139 AcpiEvSetGpeType (
140     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
141     UINT8                   Type)
142 {
143     ACPI_STATUS             Status;
144
145
146     ACPI_FUNCTION_TRACE ("EvSetGpeType");
147
148
149     /* Validate type and update register enable masks */
150
151     switch (Type)
152     {
153     case ACPI_GPE_TYPE_WAKE:
154     case ACPI_GPE_TYPE_RUNTIME:
155     case ACPI_GPE_TYPE_WAKE_RUN:
156         break;
157
158     default:
159         return_ACPI_STATUS (AE_BAD_PARAMETER);
160     }
161
162     /* Disable the GPE if currently enabled */
163
164     Status = AcpiEvDisableGpe (GpeEventInfo);
165
166     /* Type was validated above */
167
168     GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
169     GpeEventInfo->Flags |= Type;                /* Insert type */
170     return_ACPI_STATUS (Status);
171 }
172
173
174 /*******************************************************************************
175  *
176  * FUNCTION:    AcpiEvUpdateGpeEnableMasks
177  *
178  * PARAMETERS:  GpeEventInfo            - GPE to update
179  *              Type                    - What to do: ACPI_GPE_DISABLE or
180  *                                        ACPI_GPE_ENABLE
181  *
182  * RETURN:      Status
183  *
184  * DESCRIPTION: Updates GPE register enable masks based on the GPE type
185  *
186  ******************************************************************************/
187
188 ACPI_STATUS
189 AcpiEvUpdateGpeEnableMasks (
190     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
191     UINT8                   Type)
192 {
193     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
194     UINT8                   RegisterBit;
195
196
197     ACPI_FUNCTION_TRACE ("EvUpdateGpeEnableMasks");
198
199
200     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
201     if (!GpeRegisterInfo)
202     {
203         return_ACPI_STATUS (AE_NOT_EXIST);
204     }
205     RegisterBit = GpeEventInfo->RegisterBit;
206
207     /* 1) Disable case.  Simply clear all enable bits */
208
209     if (Type == ACPI_GPE_DISABLE)
210     {
211         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
212         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
213         return_ACPI_STATUS (AE_OK);
214     }
215
216     /* 2) Enable case.  Set/Clear the appropriate enable bits */
217
218     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
219     {
220     case ACPI_GPE_TYPE_WAKE:
221         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
222         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
223         break;
224
225     case ACPI_GPE_TYPE_RUNTIME:
226         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
227         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
228         break;
229
230     case ACPI_GPE_TYPE_WAKE_RUN:
231         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
232         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
233         break;
234
235     default:
236         return_ACPI_STATUS (AE_BAD_PARAMETER);
237     }
238
239     return_ACPI_STATUS (AE_OK);
240 }
241
242
243 /*******************************************************************************
244  *
245  * FUNCTION:    AcpiEvEnableGpe
246  *
247  * PARAMETERS:  GpeEventInfo            - GPE to enable
248  *              WriteToHardware         - Enable now, or just mark data structs
249  *                                        (WAKE GPEs should be deferred)
250  *
251  * RETURN:      Status
252  *
253  * DESCRIPTION: Enable a GPE based on the GPE type
254  *
255  ******************************************************************************/
256
257 ACPI_STATUS
258 AcpiEvEnableGpe (
259     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
260     BOOLEAN                 WriteToHardware)
261 {
262     ACPI_STATUS             Status;
263
264
265     ACPI_FUNCTION_TRACE ("EvEnableGpe");
266
267
268     /* Make sure HW enable masks are updated */
269
270     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
271     if (ACPI_FAILURE (Status))
272     {
273         return_ACPI_STATUS (Status);
274     }
275
276     /* Mark wake-enabled or HW enable, or both */
277
278     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
279     {
280     case ACPI_GPE_TYPE_WAKE:
281
282         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
283         break;
284
285     case ACPI_GPE_TYPE_WAKE_RUN:
286
287         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
288
289         /*lint -fallthrough */
290
291     case ACPI_GPE_TYPE_RUNTIME:
292
293         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
294
295         if (WriteToHardware)
296         {
297             /* Clear the GPE (of stale events), then enable it */
298
299             Status = AcpiHwClearGpe (GpeEventInfo);
300             if (ACPI_FAILURE (Status))
301             {
302                 return_ACPI_STATUS (Status);
303             }
304
305             /* Enable the requested runtime GPE */
306
307             Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
308         }
309         break;
310
311     default:
312         return_ACPI_STATUS (AE_BAD_PARAMETER);
313     }
314
315     return_ACPI_STATUS (AE_OK);
316 }
317
318
319 /*******************************************************************************
320  *
321  * FUNCTION:    AcpiEvDisableGpe
322  *
323  * PARAMETERS:  GpeEventInfo            - GPE to disable
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Disable a GPE based on the GPE type
328  *
329  ******************************************************************************/
330
331 ACPI_STATUS
332 AcpiEvDisableGpe (
333     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
334 {
335     ACPI_STATUS             Status;
336
337
338     ACPI_FUNCTION_TRACE ("EvDisableGpe");
339
340
341     if (!(GpeEventInfo->Flags & ACPI_GPE_ENABLE_MASK))
342     {
343         return_ACPI_STATUS (AE_OK);
344     }
345
346     /* Make sure HW enable masks are updated */
347
348     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
349     if (ACPI_FAILURE (Status))
350     {
351         return_ACPI_STATUS (Status);
352     }
353
354     /* Mark wake-disabled or HW disable, or both */
355
356     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
357     {
358     case ACPI_GPE_TYPE_WAKE:
359         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
360         break;
361
362     case ACPI_GPE_TYPE_WAKE_RUN:
363         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
364
365         /*lint -fallthrough */
366
367     case ACPI_GPE_TYPE_RUNTIME:
368
369         /* Disable the requested runtime GPE */
370
371         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
372         Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
373         break;
374
375     default:
376         return_ACPI_STATUS (AE_BAD_PARAMETER);
377     }
378
379     return_ACPI_STATUS (AE_OK);
380 }
381
382
383 /*******************************************************************************
384  *
385  * FUNCTION:    AcpiEvGetGpeEventInfo
386  *
387  * PARAMETERS:  GpeDevice           - Device node.  NULL for GPE0/GPE1
388  *              GpeNumber           - Raw GPE number
389  *
390  * RETURN:      A GPE EventInfo struct.  NULL if not a valid GPE
391  *
392  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
393  *              Validates the GpeBlock and the GpeNumber
394  *
395  *              Should be called only when the GPE lists are semaphore locked
396  *              and not subject to change.
397  *
398  ******************************************************************************/
399
400 ACPI_GPE_EVENT_INFO *
401 AcpiEvGetGpeEventInfo (
402     ACPI_HANDLE             GpeDevice,
403     UINT32                  GpeNumber)
404 {
405     ACPI_OPERAND_OBJECT     *ObjDesc;
406     ACPI_GPE_BLOCK_INFO     *GpeBlock;
407     ACPI_NATIVE_UINT        i;
408
409
410     ACPI_FUNCTION_ENTRY ();
411
412
413     /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
414
415     if (!GpeDevice)
416     {
417         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
418
419         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
420         {
421             GpeBlock = AcpiGbl_GpeFadtBlocks[i];
422             if (GpeBlock)
423             {
424                 if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
425                     (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
426                 {
427                     return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
428                 }
429             }
430         }
431
432         /* The GpeNumber was not in the range of either FADT GPE block */
433
434         return (NULL);
435     }
436
437     /* A Non-NULL GpeDevice means this is a GPE Block Device */
438
439     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
440     if (!ObjDesc ||
441         !ObjDesc->Device.GpeBlock)
442     {
443         return (NULL);
444     }
445
446     GpeBlock = ObjDesc->Device.GpeBlock;
447
448     if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
449         (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
450     {
451         return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
452     }
453
454     return (NULL);
455 }
456
457
458 /*******************************************************************************
459  *
460  * FUNCTION:    AcpiEvGpeDetect
461  *
462  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
463  *                                    Can have multiple GPE blocks attached.
464  *
465  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
466  *
467  * DESCRIPTION: Detect if any GP events have occurred.  This function is
468  *              executed at interrupt level.
469  *
470  ******************************************************************************/
471
472 UINT32
473 AcpiEvGpeDetect (
474     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
475 {
476     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
477     UINT8                   EnabledStatusByte;
478     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
479     UINT32                  StatusReg;
480     UINT32                  EnableReg;
481     ACPI_STATUS             Status;
482     ACPI_GPE_BLOCK_INFO     *GpeBlock;
483     ACPI_NATIVE_UINT        i;
484     ACPI_NATIVE_UINT        j;
485
486
487     ACPI_FUNCTION_NAME ("EvGpeDetect");
488
489     /* Check for the case where there are no GPEs */
490
491     if (!GpeXruptList)
492     {
493         return (IntStatus);
494     }
495
496     /* Examine all GPE blocks attached to this interrupt level */
497
498     AcpiOsAcquireLock (AcpiGbl_GpeLock, ACPI_ISR);
499     GpeBlock = GpeXruptList->GpeBlockListHead;
500     while (GpeBlock)
501     {
502         /*
503          * Read all of the 8-bit GPE status and enable registers
504          * in this GPE block, saving all of them.
505          * Find all currently active GP events.
506          */
507         for (i = 0; i < GpeBlock->RegisterCount; i++)
508         {
509             /* Get the next status/enable pair */
510
511             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
512
513             /* Read the Status Register */
514
515             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &StatusReg,
516                         &GpeRegisterInfo->StatusAddress);
517             if (ACPI_FAILURE (Status))
518             {
519                 goto UnlockAndExit;
520             }
521
522             /* Read the Enable Register */
523
524             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &EnableReg,
525                         &GpeRegisterInfo->EnableAddress);
526             if (ACPI_FAILURE (Status))
527             {
528                 goto UnlockAndExit;
529             }
530
531             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
532                 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
533                 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
534
535             /* First check if there is anything active at all in this register */
536
537             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
538             if (!EnabledStatusByte)
539             {
540                 /* No active GPEs in this register, move on */
541
542                 continue;
543             }
544
545             /* Now look at the individual GPEs in this byte register */
546
547             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
548             {
549                 /* Examine one GPE bit */
550
551                 if (EnabledStatusByte & AcpiGbl_DecodeTo8bit[j])
552                 {
553                     /*
554                      * Found an active GPE. Dispatch the event to a handler
555                      * or method.
556                      */
557                     IntStatus |= AcpiEvGpeDispatch (
558                                     &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j],
559                                     (UINT32) j + GpeRegisterInfo->BaseGpeNumber);
560                 }
561             }
562         }
563
564         GpeBlock = GpeBlock->Next;
565     }
566
567 UnlockAndExit:
568
569     AcpiOsReleaseLock (AcpiGbl_GpeLock, ACPI_ISR);
570     return (IntStatus);
571 }
572
573
574 /*******************************************************************************
575  *
576  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
577  *
578  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
579  *
580  * RETURN:      None
581  *
582  * DESCRIPTION: Perform the actual execution of a GPE control method.  This
583  *              function is called from an invocation of AcpiOsQueueForExecution
584  *              (and therefore does NOT execute at interrupt level) so that
585  *              the control method itself is not executed in the context of
586  *              an interrupt handler.
587  *
588  ******************************************************************************/
589
590 static void ACPI_SYSTEM_XFACE
591 AcpiEvAsynchExecuteGpeMethod (
592     void                    *Context)
593 {
594     ACPI_GPE_EVENT_INFO     *GpeEventInfo = (void *) Context;
595     UINT32                  GpeNumber = 0;
596     ACPI_STATUS             Status;
597     ACPI_GPE_EVENT_INFO     LocalGpeEventInfo;
598     ACPI_PARAMETER_INFO     Info;
599
600
601     ACPI_FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
602
603
604     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
605     if (ACPI_FAILURE (Status))
606     {
607         return_VOID;
608     }
609
610     /* Must revalidate the GpeNumber/GpeBlock */
611
612     if (!AcpiEvValidGpeEvent (GpeEventInfo))
613     {
614         Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
615         return_VOID;
616     }
617
618     /* Set the GPE flags for return to enabled state */
619
620     (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
621
622     /*
623      * Take a snapshot of the GPE info for this level - we copy the
624      * info to prevent a race condition with RemoveHandler/RemoveBlock.
625      */
626     ACPI_MEMCPY (&LocalGpeEventInfo, GpeEventInfo, sizeof (ACPI_GPE_EVENT_INFO));
627
628     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
629     if (ACPI_FAILURE (Status))
630     {
631         return_VOID;
632     }
633
634     /*
635      * Must check for control method type dispatch one more
636      * time to avoid race with EvGpeInstallHandler
637      */
638     if ((LocalGpeEventInfo.Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD)
639     {
640         /*
641          * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
642          * control method that corresponds to this GPE
643          */
644         Info.Node = LocalGpeEventInfo.Dispatch.MethodNode;
645         Info.Parameters = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT *, GpeEventInfo);
646         Info.ParameterType = ACPI_PARAM_GPE;
647
648         Status = AcpiNsEvaluateByHandle (&Info);
649         if (ACPI_FAILURE (Status))
650         {
651             ACPI_REPORT_ERROR ((
652                 "%s while evaluating method [%4.4s] for GPE[%2X]\n",
653                 AcpiFormatException (Status),
654                 AcpiUtGetNodeName (LocalGpeEventInfo.Dispatch.MethodNode),
655                 GpeNumber));
656         }
657     }
658
659     if ((LocalGpeEventInfo.Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED)
660     {
661         /*
662          * GPE is level-triggered, we clear the GPE status bit after
663          * handling the event.
664          */
665         Status = AcpiHwClearGpe (&LocalGpeEventInfo);
666         if (ACPI_FAILURE (Status))
667         {
668             return_VOID;
669         }
670     }
671
672     /* Enable this GPE */
673
674     (void) AcpiHwWriteGpeEnableReg (&LocalGpeEventInfo);
675     return_VOID;
676 }
677
678
679 /*******************************************************************************
680  *
681  * FUNCTION:    AcpiEvGpeDispatch
682  *
683  * PARAMETERS:  GpeEventInfo    - info for this GPE
684  *              GpeNumber       - Number relative to the parent GPE block
685  *
686  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
687  *
688  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
689  *              or method (e.g. _Lxx/_Exx) handler.
690  *
691  *              This function executes at interrupt level.
692  *
693  ******************************************************************************/
694
695 UINT32
696 AcpiEvGpeDispatch (
697     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
698     UINT32                  GpeNumber)
699 {
700     ACPI_STATUS             Status;
701
702
703     ACPI_FUNCTION_TRACE ("EvGpeDispatch");
704
705
706     /*
707      * If edge-triggered, clear the GPE status bit now.  Note that
708      * level-triggered events are cleared after the GPE is serviced.
709      */
710     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED)
711     {
712         Status = AcpiHwClearGpe (GpeEventInfo);
713         if (ACPI_FAILURE (Status))
714         {
715             ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to clear GPE[%2X]\n",
716                 GpeNumber));
717             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
718         }
719     }
720
721     /* Save current system state */
722
723     if (AcpiGbl_SystemAwakeAndRunning)
724     {
725         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_SYSTEM_RUNNING);
726     }
727     else
728     {
729         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_SYSTEM_RUNNING);
730     }
731
732     /*
733      * Dispatch the GPE to either an installed handler, or the control
734      * method associated with this GPE (_Lxx or _Exx).
735      * If a handler exists, we invoke it and do not attempt to run the method.
736      * If there is neither a handler nor a method, we disable the level to
737      * prevent further events from coming in here.
738      */
739     switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
740     {
741     case ACPI_GPE_DISPATCH_HANDLER:
742
743         /*
744          * Invoke the installed handler (at interrupt level)
745          * Ignore return status for now.  TBD: leave GPE disabled on error?
746          */
747         (void) GpeEventInfo->Dispatch.Handler->Address (
748                         GpeEventInfo->Dispatch.Handler->Context);
749
750         /* It is now safe to clear level-triggered events. */
751
752         if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED)
753         {
754             Status = AcpiHwClearGpe (GpeEventInfo);
755             if (ACPI_FAILURE (Status))
756             {
757                 ACPI_REPORT_ERROR ((
758                     "AcpiEvGpeDispatch: Unable to clear GPE[%2X]\n",
759                     GpeNumber));
760                 return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
761             }
762         }
763         break;
764
765     case ACPI_GPE_DISPATCH_METHOD:
766
767         /*
768          * Disable GPE, so it doesn't keep firing before the method has a
769          * chance to run.
770          */
771         Status = AcpiEvDisableGpe (GpeEventInfo);
772         if (ACPI_FAILURE (Status))
773         {
774             ACPI_REPORT_ERROR ((
775                 "AcpiEvGpeDispatch: Unable to disable GPE[%2X]\n",
776                 GpeNumber));
777             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
778         }
779
780         /*
781          * Execute the method associated with the GPE
782          * NOTE: Level-triggered GPEs are cleared after the method completes.
783          */
784         if (ACPI_FAILURE (AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
785                                 AcpiEvAsynchExecuteGpeMethod,
786                                 GpeEventInfo)))
787         {
788             ACPI_REPORT_ERROR ((
789                 "AcpiEvGpeDispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
790                 GpeNumber));
791         }
792         break;
793
794     default:
795
796         /* No handler or method to run! */
797
798         ACPI_REPORT_ERROR ((
799             "AcpiEvGpeDispatch: No handler or method for GPE[%2X], disabling event\n",
800             GpeNumber));
801
802         /*
803          * Disable the GPE.  The GPE will remain disabled until the ACPI
804          * Core Subsystem is restarted, or a handler is installed.
805          */
806         Status = AcpiEvDisableGpe (GpeEventInfo);
807         if (ACPI_FAILURE (Status))
808         {
809             ACPI_REPORT_ERROR ((
810                 "AcpiEvGpeDispatch: Unable to disable GPE[%2X]\n",
811                 GpeNumber));
812             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
813         }
814         break;
815     }
816
817     return_VALUE (ACPI_INTERRUPT_HANDLED);
818 }
819
820
821 #ifdef ACPI_GPE_NOTIFY_CHECK
822
823 /*******************************************************************************
824  * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
825  *
826  * FUNCTION:    AcpiEvCheckForWakeOnlyGpe
827  *
828  * PARAMETERS:  GpeEventInfo    - info for this GPE
829  *
830  * RETURN:      Status
831  *
832  * DESCRIPTION: Determine if a a GPE is "wake-only".
833  *
834  *              Called from Notify() code in interpreter when a "DeviceWake"
835  *              Notify comes in.
836  *
837  ******************************************************************************/
838
839 ACPI_STATUS
840 AcpiEvCheckForWakeOnlyGpe (
841     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
842 {
843     ACPI_STATUS             Status;
844
845
846     ACPI_FUNCTION_TRACE ("EvCheckForWakeOnlyGpe");
847
848
849     if ((GpeEventInfo)   &&  /* Only >0 for _Lxx/_Exx */
850        ((GpeEventInfo->Flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */
851     {
852         /* This must be a wake-only GPE, disable it */
853
854         Status = AcpiEvDisableGpe (GpeEventInfo);
855
856         /* Set GPE to wake-only.  Do not change wake disabled/enabled status */
857
858         AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE);
859
860         ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
861                 GpeEventInfo));
862
863         /* This was a wake-only GPE */
864
865         return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
866     }
867
868     return_ACPI_STATUS (AE_OK);
869 }
870 #endif
871
872