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