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