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