1 /******************************************************************************
3 * Module Name: evgpeblk - GPE block creation and initialization.
5 *****************************************************************************/
7 /******************************************************************************
11 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12 * All rights reserved.
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
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
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;
37 * The above copyright and patent license is granted only if the following
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.
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
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
72 * 3.4. Intel retains all right, title, and interest in and to the Original
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.
80 * 4. Disclaimer and Export Compliance
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
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
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.
114 *****************************************************************************/
117 #include "accommon.h"
118 #include "acevents.h"
119 #include "acnamesp.h"
121 #define _COMPONENT ACPI_EVENTS
122 ACPI_MODULE_NAME ("evgpeblk")
124 /* Local prototypes */
127 AcpiEvSaveMethodInfo (
128 ACPI_HANDLE ObjHandle
,
134 AcpiEvMatchPrwAndGpe (
135 ACPI_HANDLE ObjHandle
,
140 static ACPI_GPE_XRUPT_INFO
*
141 AcpiEvGetGpeXruptBlock (
142 UINT32 InterruptNumber
);
145 AcpiEvDeleteGpeXrupt (
146 ACPI_GPE_XRUPT_INFO
*GpeXrupt
);
149 AcpiEvInstallGpeBlock (
150 ACPI_GPE_BLOCK_INFO
*GpeBlock
,
151 UINT32 InterruptNumber
);
154 AcpiEvCreateGpeInfoBlocks (
155 ACPI_GPE_BLOCK_INFO
*GpeBlock
);
158 /*******************************************************************************
160 * FUNCTION: AcpiEvValidGpeEvent
162 * PARAMETERS: GpeEventInfo - Info for this GPE
164 * RETURN: TRUE if the GpeEvent is valid
166 * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
167 * Should be called only when the GPE lists are semaphore locked
168 * and not subject to change.
170 ******************************************************************************/
173 AcpiEvValidGpeEvent (
174 ACPI_GPE_EVENT_INFO
*GpeEventInfo
)
176 ACPI_GPE_XRUPT_INFO
*GpeXruptBlock
;
177 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
180 ACPI_FUNCTION_ENTRY ();
183 /* No need for spin lock since we are not changing any list elements */
185 /* Walk the GPE interrupt levels */
187 GpeXruptBlock
= AcpiGbl_GpeXruptListHead
;
188 while (GpeXruptBlock
)
190 GpeBlock
= GpeXruptBlock
->GpeBlockListHead
;
192 /* Walk the GPE blocks on this interrupt level */
196 if ((&GpeBlock
->EventInfo
[0] <= GpeEventInfo
) &&
197 (&GpeBlock
->EventInfo
[((ACPI_SIZE
)
198 GpeBlock
->RegisterCount
) * 8] > GpeEventInfo
))
203 GpeBlock
= GpeBlock
->Next
;
206 GpeXruptBlock
= GpeXruptBlock
->Next
;
213 /*******************************************************************************
215 * FUNCTION: AcpiEvWalkGpeList
217 * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
218 * Context - Value passed to callback
222 * DESCRIPTION: Walk the GPE lists.
224 ******************************************************************************/
228 ACPI_GPE_CALLBACK GpeWalkCallback
,
231 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
232 ACPI_GPE_XRUPT_INFO
*GpeXruptInfo
;
233 ACPI_STATUS Status
= AE_OK
;
234 ACPI_CPU_FLAGS Flags
;
237 ACPI_FUNCTION_TRACE (EvWalkGpeList
);
240 Flags
= AcpiOsAcquireLock (AcpiGbl_GpeLock
);
242 /* Walk the interrupt level descriptor list */
244 GpeXruptInfo
= AcpiGbl_GpeXruptListHead
;
247 /* Walk all Gpe Blocks attached to this interrupt level */
249 GpeBlock
= GpeXruptInfo
->GpeBlockListHead
;
252 /* One callback per GPE block */
254 Status
= GpeWalkCallback (GpeXruptInfo
, GpeBlock
, Context
);
255 if (ACPI_FAILURE (Status
))
257 if (Status
== AE_CTRL_END
) /* Callback abort */
264 GpeBlock
= GpeBlock
->Next
;
267 GpeXruptInfo
= GpeXruptInfo
->Next
;
271 AcpiOsReleaseLock (AcpiGbl_GpeLock
, Flags
);
272 return_ACPI_STATUS (Status
);
276 /*******************************************************************************
278 * FUNCTION: AcpiEvDeleteGpeHandlers
280 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
281 * GpeBlock - Gpe Block info
285 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
286 * Used only prior to termination.
288 ******************************************************************************/
291 AcpiEvDeleteGpeHandlers (
292 ACPI_GPE_XRUPT_INFO
*GpeXruptInfo
,
293 ACPI_GPE_BLOCK_INFO
*GpeBlock
,
296 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
301 ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers
);
304 /* Examine each GPE Register within the block */
306 for (i
= 0; i
< GpeBlock
->RegisterCount
; i
++)
308 /* Now look at the individual GPEs in this byte register */
310 for (j
= 0; j
< ACPI_GPE_REGISTER_WIDTH
; j
++)
312 GpeEventInfo
= &GpeBlock
->EventInfo
[((ACPI_SIZE
) i
*
313 ACPI_GPE_REGISTER_WIDTH
) + j
];
315 if ((GpeEventInfo
->Flags
& ACPI_GPE_DISPATCH_MASK
) ==
316 ACPI_GPE_DISPATCH_HANDLER
)
318 ACPI_FREE (GpeEventInfo
->Dispatch
.Handler
);
319 GpeEventInfo
->Dispatch
.Handler
= NULL
;
320 GpeEventInfo
->Flags
&= ~ACPI_GPE_DISPATCH_MASK
;
325 return_ACPI_STATUS (AE_OK
);
329 /*******************************************************************************
331 * FUNCTION: AcpiEvSaveMethodInfo
333 * PARAMETERS: Callback from WalkNamespace
337 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
338 * control method under the _GPE portion of the namespace.
339 * Extract the name and GPE type from the object, saving this
340 * information for quick lookup during GPE dispatch
342 * The name of each GPE control method is of the form:
345 * L - means that the GPE is level triggered
346 * E - means that the GPE is edge triggered
347 * xx - is the GPE number [in HEX]
349 ******************************************************************************/
352 AcpiEvSaveMethodInfo (
353 ACPI_HANDLE ObjHandle
,
358 ACPI_GPE_BLOCK_INFO
*GpeBlock
= (void *) ObjDesc
;
359 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
361 char Name
[ACPI_NAME_SIZE
+ 1];
366 ACPI_FUNCTION_TRACE (EvSaveMethodInfo
);
370 * _Lxx and _Exx GPE method support
372 * 1) Extract the name from the object and convert to a string
375 Name
, &((ACPI_NAMESPACE_NODE
*) ObjHandle
)->Name
.Integer
);
376 Name
[ACPI_NAME_SIZE
] = 0;
379 * 2) Edge/Level determination is based on the 2nd character
382 * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
383 * if a _PRW object is found that points to this GPE.
388 Type
= ACPI_GPE_LEVEL_TRIGGERED
;
392 Type
= ACPI_GPE_EDGE_TRIGGERED
;
396 /* Unknown method type, just ignore it! */
398 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD
,
399 "Ignoring unknown GPE method type: %s "
400 "(name not of form _Lxx or _Exx)",
402 return_ACPI_STATUS (AE_OK
);
405 /* Convert the last two characters of the name to the GPE Number */
407 GpeNumber
= ACPI_STRTOUL (&Name
[2], NULL
, 16);
408 if (GpeNumber
== ACPI_UINT32_MAX
)
410 /* Conversion failed; invalid method, just ignore it */
412 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD
,
413 "Could not extract GPE number from name: %s "
414 "(name is not of form _Lxx or _Exx)",
416 return_ACPI_STATUS (AE_OK
);
419 /* Ensure that we have a valid GPE number for this GPE block */
421 if ((GpeNumber
< GpeBlock
->BlockBaseNumber
) ||
422 (GpeNumber
>= (GpeBlock
->BlockBaseNumber
+
423 (GpeBlock
->RegisterCount
* 8))))
426 * Not valid for this GPE block, just ignore it. However, it may be
427 * valid for a different GPE block, since GPE0 and GPE1 methods both
428 * appear under \_GPE.
430 return_ACPI_STATUS (AE_OK
);
434 * Now we can add this information to the GpeEventInfo block for use
435 * during dispatch of this GPE. Default type is RUNTIME, although this may
436 * change when the _PRW methods are executed later.
438 GpeEventInfo
= &GpeBlock
->EventInfo
[GpeNumber
- GpeBlock
->BlockBaseNumber
];
440 GpeEventInfo
->Flags
= (UINT8
)
441 (Type
| ACPI_GPE_DISPATCH_METHOD
| ACPI_GPE_TYPE_RUNTIME
);
443 GpeEventInfo
->Dispatch
.MethodNode
= (ACPI_NAMESPACE_NODE
*) ObjHandle
;
445 /* Update enable mask, but don't enable the HW GPE as of yet */
447 Status
= AcpiEvEnableGpe (GpeEventInfo
, FALSE
);
449 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD
,
450 "Registered GPE method %s as GPE number 0x%.2X\n",
452 return_ACPI_STATUS (Status
);
456 /*******************************************************************************
458 * FUNCTION: AcpiEvMatchPrwAndGpe
460 * PARAMETERS: Callback from WalkNamespace
462 * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
463 * not aborted on a single _PRW failure.
465 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
466 * Device. Run the _PRW method. If present, extract the GPE
467 * number and mark the GPE as a WAKE GPE.
469 ******************************************************************************/
472 AcpiEvMatchPrwAndGpe (
473 ACPI_HANDLE ObjHandle
,
478 ACPI_GPE_WALK_INFO
*GpeInfo
= (void *) Info
;
479 ACPI_NAMESPACE_NODE
*GpeDevice
;
480 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
481 ACPI_NAMESPACE_NODE
*TargetGpeDevice
;
482 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
483 ACPI_OPERAND_OBJECT
*PkgDesc
;
484 ACPI_OPERAND_OBJECT
*ObjDesc
;
489 ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe
);
492 /* Check for a _PRW method under this device */
494 Status
= AcpiUtEvaluateObject (ObjHandle
, METHOD_NAME__PRW
,
495 ACPI_BTYPE_PACKAGE
, &PkgDesc
);
496 if (ACPI_FAILURE (Status
))
498 /* Ignore all errors from _PRW, we don't want to abort the subsystem */
500 return_ACPI_STATUS (AE_OK
);
503 /* The returned _PRW package must have at least two elements */
505 if (PkgDesc
->Package
.Count
< 2)
510 /* Extract pointers from the input context */
512 GpeDevice
= GpeInfo
->GpeDevice
;
513 GpeBlock
= GpeInfo
->GpeBlock
;
516 * The _PRW object must return a package, we are only interested in the
519 ObjDesc
= PkgDesc
->Package
.Elements
[0];
521 if (ObjDesc
->Common
.Type
== ACPI_TYPE_INTEGER
)
523 /* Use FADT-defined GPE device (from definition of _PRW) */
525 TargetGpeDevice
= AcpiGbl_FadtGpeDevice
;
527 /* Integer is the GPE number in the FADT described GPE blocks */
529 GpeNumber
= (UINT32
) ObjDesc
->Integer
.Value
;
531 else if (ObjDesc
->Common
.Type
== ACPI_TYPE_PACKAGE
)
533 /* Package contains a GPE reference and GPE number within a GPE block */
535 if ((ObjDesc
->Package
.Count
< 2) ||
536 ((ObjDesc
->Package
.Elements
[0])->Common
.Type
!=
537 ACPI_TYPE_LOCAL_REFERENCE
) ||
538 ((ObjDesc
->Package
.Elements
[1])->Common
.Type
!=
544 /* Get GPE block reference and decode */
546 TargetGpeDevice
= ObjDesc
->Package
.Elements
[0]->Reference
.Node
;
547 GpeNumber
= (UINT32
) ObjDesc
->Package
.Elements
[1]->Integer
.Value
;
551 /* Unknown type, just ignore it */
557 * Is this GPE within this block?
559 * TRUE if and only if these conditions are true:
560 * 1) The GPE devices match.
561 * 2) The GPE index(number) is within the range of the Gpe Block
562 * associated with the GPE device.
564 if ((GpeDevice
== TargetGpeDevice
) &&
565 (GpeNumber
>= GpeBlock
->BlockBaseNumber
) &&
566 (GpeNumber
< GpeBlock
->BlockBaseNumber
+
567 (GpeBlock
->RegisterCount
* 8)))
569 GpeEventInfo
= &GpeBlock
->EventInfo
[GpeNumber
-
570 GpeBlock
->BlockBaseNumber
];
572 /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
574 GpeEventInfo
->Flags
&= ~(ACPI_GPE_WAKE_ENABLED
| ACPI_GPE_RUN_ENABLED
);
576 Status
= AcpiEvSetGpeType (GpeEventInfo
, ACPI_GPE_TYPE_WAKE
);
577 if (ACPI_FAILURE (Status
))
582 Status
= AcpiEvUpdateGpeEnableMasks (GpeEventInfo
, ACPI_GPE_DISABLE
);
586 AcpiUtRemoveReference (PkgDesc
);
587 return_ACPI_STATUS (AE_OK
);
591 /*******************************************************************************
593 * FUNCTION: AcpiEvGetGpeXruptBlock
595 * PARAMETERS: InterruptNumber - Interrupt for a GPE block
597 * RETURN: A GPE interrupt block
599 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
600 * block per unique interrupt level used for GPEs. Should be
601 * called only when the GPE lists are semaphore locked and not
604 ******************************************************************************/
606 static ACPI_GPE_XRUPT_INFO
*
607 AcpiEvGetGpeXruptBlock (
608 UINT32 InterruptNumber
)
610 ACPI_GPE_XRUPT_INFO
*NextGpeXrupt
;
611 ACPI_GPE_XRUPT_INFO
*GpeXrupt
;
613 ACPI_CPU_FLAGS Flags
;
616 ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock
);
619 /* No need for lock since we are not changing any list elements here */
621 NextGpeXrupt
= AcpiGbl_GpeXruptListHead
;
624 if (NextGpeXrupt
->InterruptNumber
== InterruptNumber
)
626 return_PTR (NextGpeXrupt
);
629 NextGpeXrupt
= NextGpeXrupt
->Next
;
632 /* Not found, must allocate a new xrupt descriptor */
634 GpeXrupt
= ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO
));
640 GpeXrupt
->InterruptNumber
= InterruptNumber
;
642 /* Install new interrupt descriptor with spin lock */
644 Flags
= AcpiOsAcquireLock (AcpiGbl_GpeLock
);
645 if (AcpiGbl_GpeXruptListHead
)
647 NextGpeXrupt
= AcpiGbl_GpeXruptListHead
;
648 while (NextGpeXrupt
->Next
)
650 NextGpeXrupt
= NextGpeXrupt
->Next
;
653 NextGpeXrupt
->Next
= GpeXrupt
;
654 GpeXrupt
->Previous
= NextGpeXrupt
;
658 AcpiGbl_GpeXruptListHead
= GpeXrupt
;
660 AcpiOsReleaseLock (AcpiGbl_GpeLock
, Flags
);
662 /* Install new interrupt handler if not SCI_INT */
664 if (InterruptNumber
!= AcpiGbl_FADT
.SciInterrupt
)
666 Status
= AcpiOsInstallInterruptHandler (InterruptNumber
,
667 AcpiEvGpeXruptHandler
, GpeXrupt
);
668 if (ACPI_FAILURE (Status
))
670 ACPI_ERROR ((AE_INFO
,
671 "Could not install GPE interrupt handler at level 0x%X",
677 return_PTR (GpeXrupt
);
681 /*******************************************************************************
683 * FUNCTION: AcpiEvDeleteGpeXrupt
685 * PARAMETERS: GpeXrupt - A GPE interrupt info block
689 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
690 * interrupt handler if not the SCI interrupt.
692 ******************************************************************************/
695 AcpiEvDeleteGpeXrupt (
696 ACPI_GPE_XRUPT_INFO
*GpeXrupt
)
699 ACPI_CPU_FLAGS Flags
;
702 ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt
);
705 /* We never want to remove the SCI interrupt handler */
707 if (GpeXrupt
->InterruptNumber
== AcpiGbl_FADT
.SciInterrupt
)
709 GpeXrupt
->GpeBlockListHead
= NULL
;
710 return_ACPI_STATUS (AE_OK
);
713 /* Disable this interrupt */
715 Status
= AcpiOsRemoveInterruptHandler (
716 GpeXrupt
->InterruptNumber
, AcpiEvGpeXruptHandler
);
717 if (ACPI_FAILURE (Status
))
719 return_ACPI_STATUS (Status
);
722 /* Unlink the interrupt block with lock */
724 Flags
= AcpiOsAcquireLock (AcpiGbl_GpeLock
);
725 if (GpeXrupt
->Previous
)
727 GpeXrupt
->Previous
->Next
= GpeXrupt
->Next
;
731 /* No previous, update list head */
733 AcpiGbl_GpeXruptListHead
= GpeXrupt
->Next
;
738 GpeXrupt
->Next
->Previous
= GpeXrupt
->Previous
;
740 AcpiOsReleaseLock (AcpiGbl_GpeLock
, Flags
);
744 ACPI_FREE (GpeXrupt
);
745 return_ACPI_STATUS (AE_OK
);
749 /*******************************************************************************
751 * FUNCTION: AcpiEvInstallGpeBlock
753 * PARAMETERS: GpeBlock - New GPE block
754 * InterruptNumber - Xrupt to be associated with this
759 * DESCRIPTION: Install new GPE block with mutex support
761 ******************************************************************************/
764 AcpiEvInstallGpeBlock (
765 ACPI_GPE_BLOCK_INFO
*GpeBlock
,
766 UINT32 InterruptNumber
)
768 ACPI_GPE_BLOCK_INFO
*NextGpeBlock
;
769 ACPI_GPE_XRUPT_INFO
*GpeXruptBlock
;
771 ACPI_CPU_FLAGS Flags
;
774 ACPI_FUNCTION_TRACE (EvInstallGpeBlock
);
777 Status
= AcpiUtAcquireMutex (ACPI_MTX_EVENTS
);
778 if (ACPI_FAILURE (Status
))
780 return_ACPI_STATUS (Status
);
783 GpeXruptBlock
= AcpiEvGetGpeXruptBlock (InterruptNumber
);
786 Status
= AE_NO_MEMORY
;
790 /* Install the new block at the end of the list with lock */
792 Flags
= AcpiOsAcquireLock (AcpiGbl_GpeLock
);
793 if (GpeXruptBlock
->GpeBlockListHead
)
795 NextGpeBlock
= GpeXruptBlock
->GpeBlockListHead
;
796 while (NextGpeBlock
->Next
)
798 NextGpeBlock
= NextGpeBlock
->Next
;
801 NextGpeBlock
->Next
= GpeBlock
;
802 GpeBlock
->Previous
= NextGpeBlock
;
806 GpeXruptBlock
->GpeBlockListHead
= GpeBlock
;
809 GpeBlock
->XruptBlock
= GpeXruptBlock
;
810 AcpiOsReleaseLock (AcpiGbl_GpeLock
, Flags
);
814 Status
= AcpiUtReleaseMutex (ACPI_MTX_EVENTS
);
815 return_ACPI_STATUS (Status
);
819 /*******************************************************************************
821 * FUNCTION: AcpiEvDeleteGpeBlock
823 * PARAMETERS: GpeBlock - Existing GPE block
827 * DESCRIPTION: Remove a GPE block
829 ******************************************************************************/
832 AcpiEvDeleteGpeBlock (
833 ACPI_GPE_BLOCK_INFO
*GpeBlock
)
836 ACPI_CPU_FLAGS Flags
;
839 ACPI_FUNCTION_TRACE (EvInstallGpeBlock
);
842 Status
= AcpiUtAcquireMutex (ACPI_MTX_EVENTS
);
843 if (ACPI_FAILURE (Status
))
845 return_ACPI_STATUS (Status
);
848 /* Disable all GPEs in this block */
850 Status
= AcpiHwDisableGpeBlock (GpeBlock
->XruptBlock
, GpeBlock
, NULL
);
852 if (!GpeBlock
->Previous
&& !GpeBlock
->Next
)
854 /* This is the last GpeBlock on this interrupt */
856 Status
= AcpiEvDeleteGpeXrupt (GpeBlock
->XruptBlock
);
857 if (ACPI_FAILURE (Status
))
864 /* Remove the block on this interrupt with lock */
866 Flags
= AcpiOsAcquireLock (AcpiGbl_GpeLock
);
867 if (GpeBlock
->Previous
)
869 GpeBlock
->Previous
->Next
= GpeBlock
->Next
;
873 GpeBlock
->XruptBlock
->GpeBlockListHead
= GpeBlock
->Next
;
878 GpeBlock
->Next
->Previous
= GpeBlock
->Previous
;
880 AcpiOsReleaseLock (AcpiGbl_GpeLock
, Flags
);
883 AcpiCurrentGpeCount
-= GpeBlock
->RegisterCount
* ACPI_GPE_REGISTER_WIDTH
;
885 /* Free the GpeBlock */
887 ACPI_FREE (GpeBlock
->RegisterInfo
);
888 ACPI_FREE (GpeBlock
->EventInfo
);
889 ACPI_FREE (GpeBlock
);
892 Status
= AcpiUtReleaseMutex (ACPI_MTX_EVENTS
);
893 return_ACPI_STATUS (Status
);
897 /*******************************************************************************
899 * FUNCTION: AcpiEvCreateGpeInfoBlocks
901 * PARAMETERS: GpeBlock - New GPE block
905 * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block
907 ******************************************************************************/
910 AcpiEvCreateGpeInfoBlocks (
911 ACPI_GPE_BLOCK_INFO
*GpeBlock
)
913 ACPI_GPE_REGISTER_INFO
*GpeRegisterInfo
= NULL
;
914 ACPI_GPE_EVENT_INFO
*GpeEventInfo
= NULL
;
915 ACPI_GPE_EVENT_INFO
*ThisEvent
;
916 ACPI_GPE_REGISTER_INFO
*ThisRegister
;
922 ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks
);
925 /* Allocate the GPE register information block */
927 GpeRegisterInfo
= ACPI_ALLOCATE_ZEROED (
928 (ACPI_SIZE
) GpeBlock
->RegisterCount
*
929 sizeof (ACPI_GPE_REGISTER_INFO
));
930 if (!GpeRegisterInfo
)
932 ACPI_ERROR ((AE_INFO
,
933 "Could not allocate the GpeRegisterInfo table"));
934 return_ACPI_STATUS (AE_NO_MEMORY
);
938 * Allocate the GPE EventInfo block. There are eight distinct GPEs
939 * per register. Initialization to zeros is sufficient.
941 GpeEventInfo
= ACPI_ALLOCATE_ZEROED (
942 ((ACPI_SIZE
) GpeBlock
->RegisterCount
*
943 ACPI_GPE_REGISTER_WIDTH
) *
944 sizeof (ACPI_GPE_EVENT_INFO
));
947 ACPI_ERROR ((AE_INFO
,
948 "Could not allocate the GpeEventInfo table"));
949 Status
= AE_NO_MEMORY
;
953 /* Save the new Info arrays in the GPE block */
955 GpeBlock
->RegisterInfo
= GpeRegisterInfo
;
956 GpeBlock
->EventInfo
= GpeEventInfo
;
959 * Initialize the GPE Register and Event structures. A goal of these
960 * tables is to hide the fact that there are two separate GPE register
961 * sets in a given GPE hardware block, the status registers occupy the
962 * first half, and the enable registers occupy the second half.
964 ThisRegister
= GpeRegisterInfo
;
965 ThisEvent
= GpeEventInfo
;
967 for (i
= 0; i
< GpeBlock
->RegisterCount
; i
++)
969 /* Init the RegisterInfo for this GPE register (8 GPEs) */
971 ThisRegister
->BaseGpeNumber
= (UINT8
) (GpeBlock
->BlockBaseNumber
+
972 (i
* ACPI_GPE_REGISTER_WIDTH
));
974 ThisRegister
->StatusAddress
.Address
=
975 GpeBlock
->BlockAddress
.Address
+ i
;
977 ThisRegister
->EnableAddress
.Address
=
978 GpeBlock
->BlockAddress
.Address
+ i
+ GpeBlock
->RegisterCount
;
980 ThisRegister
->StatusAddress
.SpaceId
= GpeBlock
->BlockAddress
.SpaceId
;
981 ThisRegister
->EnableAddress
.SpaceId
= GpeBlock
->BlockAddress
.SpaceId
;
982 ThisRegister
->StatusAddress
.BitWidth
= ACPI_GPE_REGISTER_WIDTH
;
983 ThisRegister
->EnableAddress
.BitWidth
= ACPI_GPE_REGISTER_WIDTH
;
984 ThisRegister
->StatusAddress
.BitOffset
= 0;
985 ThisRegister
->EnableAddress
.BitOffset
= 0;
987 /* Init the EventInfo for each GPE within this register */
989 for (j
= 0; j
< ACPI_GPE_REGISTER_WIDTH
; j
++)
991 ThisEvent
->GpeNumber
= (UINT8
) (ThisRegister
->BaseGpeNumber
+ j
);
992 ThisEvent
->RegisterInfo
= ThisRegister
;
996 /* Disable all GPEs within this register */
998 Status
= AcpiHwWrite (0x00, &ThisRegister
->EnableAddress
);
999 if (ACPI_FAILURE (Status
))
1004 /* Clear any pending GPE events within this register */
1006 Status
= AcpiHwWrite (0xFF, &ThisRegister
->StatusAddress
);
1007 if (ACPI_FAILURE (Status
))
1015 return_ACPI_STATUS (AE_OK
);
1019 if (GpeRegisterInfo
)
1021 ACPI_FREE (GpeRegisterInfo
);
1025 ACPI_FREE (GpeEventInfo
);
1028 return_ACPI_STATUS (Status
);
1032 /*******************************************************************************
1034 * FUNCTION: AcpiEvCreateGpeBlock
1036 * PARAMETERS: GpeDevice - Handle to the parent GPE block
1037 * GpeBlockAddress - Address and SpaceID
1038 * RegisterCount - Number of GPE register pairs in the block
1039 * GpeBlockBaseNumber - Starting GPE number for the block
1040 * InterruptNumber - H/W interrupt for the block
1041 * ReturnGpeBlock - Where the new block descriptor is returned
1045 * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
1046 * the block are disabled at exit.
1047 * Note: Assumes namespace is locked.
1049 ******************************************************************************/
1052 AcpiEvCreateGpeBlock (
1053 ACPI_NAMESPACE_NODE
*GpeDevice
,
1054 ACPI_GENERIC_ADDRESS
*GpeBlockAddress
,
1055 UINT32 RegisterCount
,
1056 UINT8 GpeBlockBaseNumber
,
1057 UINT32 InterruptNumber
,
1058 ACPI_GPE_BLOCK_INFO
**ReturnGpeBlock
)
1061 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
1064 ACPI_FUNCTION_TRACE (EvCreateGpeBlock
);
1069 return_ACPI_STATUS (AE_OK
);
1072 /* Allocate a new GPE block */
1074 GpeBlock
= ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO
));
1077 return_ACPI_STATUS (AE_NO_MEMORY
);
1080 /* Initialize the new GPE block */
1082 GpeBlock
->Node
= GpeDevice
;
1083 GpeBlock
->RegisterCount
= RegisterCount
;
1084 GpeBlock
->BlockBaseNumber
= GpeBlockBaseNumber
;
1086 ACPI_MEMCPY (&GpeBlock
->BlockAddress
, GpeBlockAddress
,
1087 sizeof (ACPI_GENERIC_ADDRESS
));
1090 * Create the RegisterInfo and EventInfo sub-structures
1091 * Note: disables and clears all GPEs in the block
1093 Status
= AcpiEvCreateGpeInfoBlocks (GpeBlock
);
1094 if (ACPI_FAILURE (Status
))
1096 ACPI_FREE (GpeBlock
);
1097 return_ACPI_STATUS (Status
);
1100 /* Install the new block in the global lists */
1102 Status
= AcpiEvInstallGpeBlock (GpeBlock
, InterruptNumber
);
1103 if (ACPI_FAILURE (Status
))
1105 ACPI_FREE (GpeBlock
);
1106 return_ACPI_STATUS (Status
);
1109 /* Find all GPE methods (_Lxx, _Exx) for this block */
1111 Status
= AcpiNsWalkNamespace (ACPI_TYPE_METHOD
, GpeDevice
,
1112 ACPI_UINT32_MAX
, ACPI_NS_WALK_NO_UNLOCK
,
1113 AcpiEvSaveMethodInfo
, GpeBlock
, NULL
);
1115 /* Return the new block */
1119 (*ReturnGpeBlock
) = GpeBlock
;
1122 ACPI_DEBUG_PRINT ((ACPI_DB_INIT
,
1123 "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
1124 (UINT32
) GpeBlock
->BlockBaseNumber
,
1125 (UINT32
) (GpeBlock
->BlockBaseNumber
+
1126 ((GpeBlock
->RegisterCount
* ACPI_GPE_REGISTER_WIDTH
) -1)),
1127 GpeDevice
->Name
.Ascii
,
1128 GpeBlock
->RegisterCount
,
1131 /* Update global count of currently available GPEs */
1133 AcpiCurrentGpeCount
+= RegisterCount
* ACPI_GPE_REGISTER_WIDTH
;
1134 return_ACPI_STATUS (AE_OK
);
1138 /*******************************************************************************
1140 * FUNCTION: AcpiEvInitializeGpeBlock
1142 * PARAMETERS: GpeDevice - Handle to the parent GPE block
1143 * GpeBlock - Gpe Block info
1147 * DESCRIPTION: Initialize and enable a GPE block. First find and run any
1148 * _PRT methods associated with the block, then enable the
1150 * Note: Assumes namespace is locked.
1152 ******************************************************************************/
1155 AcpiEvInitializeGpeBlock (
1156 ACPI_NAMESPACE_NODE
*GpeDevice
,
1157 ACPI_GPE_BLOCK_INFO
*GpeBlock
)
1160 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
1161 ACPI_GPE_WALK_INFO GpeInfo
;
1162 UINT32 WakeGpeCount
;
1163 UINT32 GpeEnabledCount
;
1168 ACPI_FUNCTION_TRACE (EvInitializeGpeBlock
);
1171 /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
1175 return_ACPI_STATUS (AE_OK
);
1179 * Runtime option: Should wake GPEs be enabled at runtime? The default
1180 * is no, they should only be enabled just as the machine goes to sleep.
1182 if (AcpiGbl_LeaveWakeGpesDisabled
)
1185 * Differentiate runtime vs wake GPEs, via the _PRW control methods.
1186 * Each GPE that has one or more _PRWs that reference it is by
1187 * definition a wake GPE and will not be enabled while the machine
1190 GpeInfo
.GpeBlock
= GpeBlock
;
1191 GpeInfo
.GpeDevice
= GpeDevice
;
1193 Status
= AcpiNsWalkNamespace (ACPI_TYPE_DEVICE
, ACPI_ROOT_OBJECT
,
1194 ACPI_UINT32_MAX
, ACPI_NS_WALK_UNLOCK
,
1195 AcpiEvMatchPrwAndGpe
, &GpeInfo
, NULL
);
1199 * Enable all GPEs in this block that have these attributes:
1200 * 1) are "runtime" or "run/wake" GPEs, and
1201 * 2) have a corresponding _Lxx or _Exx method
1203 * Any other GPEs within this block must be enabled via the
1204 * AcpiEnableGpe() external interface.
1207 GpeEnabledCount
= 0;
1209 for (i
= 0; i
< GpeBlock
->RegisterCount
; i
++)
1211 for (j
= 0; j
< 8; j
++)
1213 /* Get the info block for this particular GPE */
1215 GpeEventInfo
= &GpeBlock
->EventInfo
[((ACPI_SIZE
) i
*
1216 ACPI_GPE_REGISTER_WIDTH
) + j
];
1218 if (((GpeEventInfo
->Flags
& ACPI_GPE_DISPATCH_MASK
) ==
1219 ACPI_GPE_DISPATCH_METHOD
) &&
1220 (GpeEventInfo
->Flags
& ACPI_GPE_TYPE_RUNTIME
))
1225 if (GpeEventInfo
->Flags
& ACPI_GPE_TYPE_WAKE
)
1232 ACPI_DEBUG_PRINT ((ACPI_DB_INIT
,
1233 "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
1234 WakeGpeCount
, GpeEnabledCount
));
1236 /* Enable all valid runtime GPEs found above */
1238 Status
= AcpiHwEnableRuntimeGpeBlock (NULL
, GpeBlock
, NULL
);
1239 if (ACPI_FAILURE (Status
))
1241 ACPI_ERROR ((AE_INFO
, "Could not enable GPEs in GpeBlock %p",
1245 return_ACPI_STATUS (Status
);
1249 /*******************************************************************************
1251 * FUNCTION: AcpiEvGpeInitialize
1257 * DESCRIPTION: Initialize the GPE data structures
1259 ******************************************************************************/
1262 AcpiEvGpeInitialize (
1265 UINT32 RegisterCount0
= 0;
1266 UINT32 RegisterCount1
= 0;
1267 UINT32 GpeNumberMax
= 0;
1271 ACPI_FUNCTION_TRACE (EvGpeInitialize
);
1274 Status
= AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE
);
1275 if (ACPI_FAILURE (Status
))
1277 return_ACPI_STATUS (Status
);
1281 * Initialize the GPE Block(s) defined in the FADT
1283 * Why the GPE register block lengths are divided by 2: From the ACPI
1284 * Spec, section "General-Purpose Event Registers", we have:
1286 * "Each register block contains two registers of equal length
1287 * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
1288 * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
1289 * The length of the GPE1_STS and GPE1_EN registers is equal to
1290 * half the GPE1_LEN. If a generic register block is not supported
1291 * then its respective block pointer and block length values in the
1292 * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
1293 * to be the same size."
1297 * Determine the maximum GPE number for this machine.
1299 * Note: both GPE0 and GPE1 are optional, and either can exist without
1302 * If EITHER the register length OR the block address are zero, then that
1303 * particular block is not supported.
1305 if (AcpiGbl_FADT
.Gpe0BlockLength
&&
1306 AcpiGbl_FADT
.XGpe0Block
.Address
)
1308 /* GPE block 0 exists (has both length and address > 0) */
1310 RegisterCount0
= (UINT16
) (AcpiGbl_FADT
.Gpe0BlockLength
/ 2);
1312 GpeNumberMax
= (RegisterCount0
* ACPI_GPE_REGISTER_WIDTH
) - 1;
1314 /* Install GPE Block 0 */
1316 Status
= AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice
,
1317 &AcpiGbl_FADT
.XGpe0Block
, RegisterCount0
, 0,
1318 AcpiGbl_FADT
.SciInterrupt
, &AcpiGbl_GpeFadtBlocks
[0]);
1320 if (ACPI_FAILURE (Status
))
1322 ACPI_EXCEPTION ((AE_INFO
, Status
,
1323 "Could not create GPE Block 0"));
1327 if (AcpiGbl_FADT
.Gpe1BlockLength
&&
1328 AcpiGbl_FADT
.XGpe1Block
.Address
)
1330 /* GPE block 1 exists (has both length and address > 0) */
1332 RegisterCount1
= (UINT16
) (AcpiGbl_FADT
.Gpe1BlockLength
/ 2);
1334 /* Check for GPE0/GPE1 overlap (if both banks exist) */
1336 if ((RegisterCount0
) &&
1337 (GpeNumberMax
>= AcpiGbl_FADT
.Gpe1Base
))
1339 ACPI_ERROR ((AE_INFO
,
1340 "GPE0 block (GPE 0 to %d) overlaps the GPE1 block "
1341 "(GPE %d to %d) - Ignoring GPE1",
1342 GpeNumberMax
, AcpiGbl_FADT
.Gpe1Base
,
1343 AcpiGbl_FADT
.Gpe1Base
+
1344 ((RegisterCount1
* ACPI_GPE_REGISTER_WIDTH
) - 1)));
1346 /* Ignore GPE1 block by setting the register count to zero */
1352 /* Install GPE Block 1 */
1354 Status
= AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice
,
1355 &AcpiGbl_FADT
.XGpe1Block
, RegisterCount1
,
1356 AcpiGbl_FADT
.Gpe1Base
,
1357 AcpiGbl_FADT
.SciInterrupt
, &AcpiGbl_GpeFadtBlocks
[1]);
1359 if (ACPI_FAILURE (Status
))
1361 ACPI_EXCEPTION ((AE_INFO
, Status
,
1362 "Could not create GPE Block 1"));
1366 * GPE0 and GPE1 do not have to be contiguous in the GPE number
1367 * space. However, GPE0 always starts at GPE number zero.
1369 GpeNumberMax
= AcpiGbl_FADT
.Gpe1Base
+
1370 ((RegisterCount1
* ACPI_GPE_REGISTER_WIDTH
) - 1);
1374 /* Exit if there are no GPE registers */
1376 if ((RegisterCount0
+ RegisterCount1
) == 0)
1378 /* GPEs are not required by ACPI, this is OK */
1380 ACPI_DEBUG_PRINT ((ACPI_DB_INIT
,
1381 "There are no GPE blocks defined in the FADT\n"));
1386 /* Check for Max GPE number out-of-range */
1388 if (GpeNumberMax
> ACPI_GPE_MAX
)
1390 ACPI_ERROR ((AE_INFO
,
1391 "Maximum GPE number from FADT is too large: 0x%X",
1393 Status
= AE_BAD_VALUE
;
1398 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE
);
1399 return_ACPI_STATUS (AE_OK
);