1 /******************************************************************************
3 * Module Name: evgpeblk - GPE block creation and initialization.
6 *****************************************************************************/
8 /******************************************************************************
12 * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13 * All rights reserved.
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
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
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;
38 * The above copyright and patent license is granted only if the following
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.
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
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
73 * 3.4. Intel retains all right, title, and interest in and to the Original
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.
81 * 4. Disclaimer and Export Compliance
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
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
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.
115 *****************************************************************************/
118 #include "acevents.h"
119 #include "acnamesp.h"
121 #define _COMPONENT ACPI_EVENTS
122 ACPI_MODULE_NAME ("evgpeblk")
125 /*******************************************************************************
127 * FUNCTION: AcpiEvValidGpeEvent
129 * PARAMETERS: GpeEventInfo - Info for this GPE
131 * RETURN: TRUE if the GpeEvent is valid
133 * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
134 * Should be called only when the GPE lists are semaphore locked
135 * and not subject to change.
137 ******************************************************************************/
140 AcpiEvValidGpeEvent (
141 ACPI_GPE_EVENT_INFO
*GpeEventInfo
)
143 ACPI_GPE_XRUPT_INFO
*GpeXruptBlock
;
144 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
147 ACPI_FUNCTION_ENTRY ();
150 /* No need for spin lock since we are not changing any list elements */
152 /* Walk the GPE interrupt levels */
154 GpeXruptBlock
= AcpiGbl_GpeXruptListHead
;
155 while (GpeXruptBlock
)
157 GpeBlock
= GpeXruptBlock
->GpeBlockListHead
;
159 /* Walk the GPE blocks on this interrupt level */
163 if ((&GpeBlock
->EventInfo
[0] <= GpeEventInfo
) &&
164 (&GpeBlock
->EventInfo
[((ACPI_SIZE
) GpeBlock
->RegisterCount
) * 8] > GpeEventInfo
))
169 GpeBlock
= GpeBlock
->Next
;
172 GpeXruptBlock
= GpeXruptBlock
->Next
;
179 /*******************************************************************************
181 * FUNCTION: AcpiEvWalkGpeList
183 * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
184 * Flags - ACPI_NOT_ISR or ACPI_ISR
188 * DESCRIPTION: Walk the GPE lists.
190 ******************************************************************************/
194 ACPI_GPE_CALLBACK GpeWalkCallback
,
197 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
198 ACPI_GPE_XRUPT_INFO
*GpeXruptInfo
;
199 ACPI_STATUS Status
= AE_OK
;
202 ACPI_FUNCTION_TRACE ("EvWalkGpeList");
205 AcpiOsAcquireLock (AcpiGbl_GpeLock
, Flags
);
207 /* Walk the interrupt level descriptor list */
209 GpeXruptInfo
= AcpiGbl_GpeXruptListHead
;
212 /* Walk all Gpe Blocks attached to this interrupt level */
214 GpeBlock
= GpeXruptInfo
->GpeBlockListHead
;
217 /* One callback per GPE block */
219 Status
= GpeWalkCallback (GpeXruptInfo
, GpeBlock
);
220 if (ACPI_FAILURE (Status
))
225 GpeBlock
= GpeBlock
->Next
;
228 GpeXruptInfo
= GpeXruptInfo
->Next
;
232 AcpiOsReleaseLock (AcpiGbl_GpeLock
, Flags
);
233 return_ACPI_STATUS (Status
);
237 /******************************************************************************
239 * FUNCTION: AcpiEvDeleteGpeHandlers
241 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
242 * GpeBlock - Gpe Block info
246 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
247 * Used only prior to termination.
249 ******************************************************************************/
252 AcpiEvDeleteGpeHandlers (
253 ACPI_GPE_XRUPT_INFO
*GpeXruptInfo
,
254 ACPI_GPE_BLOCK_INFO
*GpeBlock
)
256 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
261 ACPI_FUNCTION_TRACE ("EvDeleteGpeHandlers");
264 /* Examine each GPE Register within the block */
266 for (i
= 0; i
< GpeBlock
->RegisterCount
; i
++)
268 /* Now look at the individual GPEs in this byte register */
270 for (j
= 0; j
< ACPI_GPE_REGISTER_WIDTH
; j
++)
272 GpeEventInfo
= &GpeBlock
->EventInfo
[(i
* ACPI_GPE_REGISTER_WIDTH
) + j
];
274 if ((GpeEventInfo
->Flags
& ACPI_GPE_DISPATCH_MASK
) == ACPI_GPE_DISPATCH_HANDLER
)
276 ACPI_MEM_FREE (GpeEventInfo
->Dispatch
.Handler
);
277 GpeEventInfo
->Dispatch
.Handler
= NULL
;
278 GpeEventInfo
->Flags
&= ~ACPI_GPE_DISPATCH_MASK
;
283 return_ACPI_STATUS (AE_OK
);
287 /*******************************************************************************
289 * FUNCTION: AcpiEvSaveMethodInfo
291 * PARAMETERS: Callback from WalkNamespace
295 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
296 * control method under the _GPE portion of the namespace.
297 * Extract the name and GPE type from the object, saving this
298 * information for quick lookup during GPE dispatch
300 * The name of each GPE control method is of the form:
303 * L - means that the GPE is level triggered
304 * E - means that the GPE is edge triggered
305 * xx - is the GPE number [in HEX]
307 ******************************************************************************/
310 AcpiEvSaveMethodInfo (
311 ACPI_HANDLE ObjHandle
,
316 ACPI_GPE_BLOCK_INFO
*GpeBlock
= (void *) ObjDesc
;
317 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
319 char Name
[ACPI_NAME_SIZE
+ 1];
324 ACPI_FUNCTION_TRACE ("EvSaveMethodInfo");
328 * _Lxx and _Exx GPE method support
330 * 1) Extract the name from the object and convert to a string
332 ACPI_MOVE_32_TO_32 (Name
,
333 &((ACPI_NAMESPACE_NODE
*) ObjHandle
)->Name
.Integer
);
334 Name
[ACPI_NAME_SIZE
] = 0;
337 * 2) Edge/Level determination is based on the 2nd character
340 * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
341 * if a _PRW object is found that points to this GPE.
346 Type
= ACPI_GPE_LEVEL_TRIGGERED
;
350 Type
= ACPI_GPE_EDGE_TRIGGERED
;
354 /* Unknown method type, just ignore it! */
356 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
357 "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
359 return_ACPI_STATUS (AE_OK
);
362 /* Convert the last two characters of the name to the GPE Number */
364 GpeNumber
= ACPI_STRTOUL (&Name
[2], NULL
, 16);
365 if (GpeNumber
== ACPI_UINT32_MAX
)
367 /* Conversion failed; invalid method, just ignore it */
369 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
370 "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
372 return_ACPI_STATUS (AE_OK
);
375 /* Ensure that we have a valid GPE number for this GPE block */
377 if ((GpeNumber
< GpeBlock
->BlockBaseNumber
) ||
378 (GpeNumber
>= (GpeBlock
->BlockBaseNumber
+ (GpeBlock
->RegisterCount
* 8))))
381 * Not valid for this GPE block, just ignore it
382 * However, it may be valid for a different GPE block, since GPE0 and GPE1
383 * methods both appear under \_GPE.
385 return_ACPI_STATUS (AE_OK
);
389 * Now we can add this information to the GpeEventInfo block
390 * for use during dispatch of this GPE. Default type is RUNTIME, although
391 * this may change when the _PRW methods are executed later.
393 GpeEventInfo
= &GpeBlock
->EventInfo
[GpeNumber
- GpeBlock
->BlockBaseNumber
];
395 GpeEventInfo
->Flags
= (UINT8
) (Type
| ACPI_GPE_DISPATCH_METHOD
|
396 ACPI_GPE_TYPE_RUNTIME
);
398 GpeEventInfo
->Dispatch
.MethodNode
= (ACPI_NAMESPACE_NODE
*) ObjHandle
;
400 /* Update enable mask, but don't enable the HW GPE as of yet */
402 Status
= AcpiEvEnableGpe (GpeEventInfo
, FALSE
);
404 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD
,
405 "Registered GPE method %s as GPE number 0x%.2X\n",
407 return_ACPI_STATUS (Status
);
411 /*******************************************************************************
413 * FUNCTION: AcpiEvMatchPrwAndGpe
415 * PARAMETERS: Callback from WalkNamespace
417 * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
418 * not aborted on a single _PRW failure.
420 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
421 * Device. Run the _PRW method. If present, extract the GPE
422 * number and mark the GPE as a WAKE GPE.
424 ******************************************************************************/
427 AcpiEvMatchPrwAndGpe (
428 ACPI_HANDLE ObjHandle
,
433 ACPI_GPE_WALK_INFO
*GpeInfo
= (void *) Info
;
434 ACPI_NAMESPACE_NODE
*GpeDevice
;
435 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
436 ACPI_NAMESPACE_NODE
*TargetGpeDevice
;
437 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
438 ACPI_OPERAND_OBJECT
*PkgDesc
;
439 ACPI_OPERAND_OBJECT
*ObjDesc
;
444 ACPI_FUNCTION_TRACE ("EvMatchPrwAndGpe");
447 /* Check for a _PRW method under this device */
449 Status
= AcpiUtEvaluateObject (ObjHandle
, METHOD_NAME__PRW
,
450 ACPI_BTYPE_PACKAGE
, &PkgDesc
);
451 if (ACPI_FAILURE (Status
))
453 /* Ignore all errors from _PRW, we don't want to abort the subsystem */
455 return_ACPI_STATUS (AE_OK
);
458 /* The returned _PRW package must have at least two elements */
460 if (PkgDesc
->Package
.Count
< 2)
465 /* Extract pointers from the input context */
467 GpeDevice
= GpeInfo
->GpeDevice
;
468 GpeBlock
= GpeInfo
->GpeBlock
;
471 * The _PRW object must return a package, we are only interested
472 * in the first element
474 ObjDesc
= PkgDesc
->Package
.Elements
[0];
476 if (ACPI_GET_OBJECT_TYPE (ObjDesc
) == ACPI_TYPE_INTEGER
)
478 /* Use FADT-defined GPE device (from definition of _PRW) */
480 TargetGpeDevice
= AcpiGbl_FadtGpeDevice
;
482 /* Integer is the GPE number in the FADT described GPE blocks */
484 GpeNumber
= (UINT32
) ObjDesc
->Integer
.Value
;
486 else if (ACPI_GET_OBJECT_TYPE (ObjDesc
) == ACPI_TYPE_PACKAGE
)
488 /* Package contains a GPE reference and GPE number within a GPE block */
490 if ((ObjDesc
->Package
.Count
< 2) ||
491 (ACPI_GET_OBJECT_TYPE (ObjDesc
->Package
.Elements
[0]) != ACPI_TYPE_LOCAL_REFERENCE
) ||
492 (ACPI_GET_OBJECT_TYPE (ObjDesc
->Package
.Elements
[1]) != ACPI_TYPE_INTEGER
))
497 /* Get GPE block reference and decode */
499 TargetGpeDevice
= ObjDesc
->Package
.Elements
[0]->Reference
.Node
;
500 GpeNumber
= (UINT32
) ObjDesc
->Package
.Elements
[1]->Integer
.Value
;
504 /* Unknown type, just ignore it */
510 * Is this GPE within this block?
512 * TRUE iff these conditions are true:
513 * 1) The GPE devices match.
514 * 2) The GPE index(number) is within the range of the Gpe Block
515 * associated with the GPE device.
517 if ((GpeDevice
== TargetGpeDevice
) &&
518 (GpeNumber
>= GpeBlock
->BlockBaseNumber
) &&
519 (GpeNumber
< GpeBlock
->BlockBaseNumber
+ (GpeBlock
->RegisterCount
* 8)))
521 GpeEventInfo
= &GpeBlock
->EventInfo
[GpeNumber
- GpeBlock
->BlockBaseNumber
];
523 /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
525 GpeEventInfo
->Flags
&= ~(ACPI_GPE_WAKE_ENABLED
| ACPI_GPE_RUN_ENABLED
);
526 Status
= AcpiEvSetGpeType (GpeEventInfo
, ACPI_GPE_TYPE_WAKE
);
527 if (ACPI_FAILURE (Status
))
531 Status
= AcpiEvUpdateGpeEnableMasks (GpeEventInfo
, ACPI_GPE_DISABLE
);
535 AcpiUtRemoveReference (PkgDesc
);
536 return_ACPI_STATUS (AE_OK
);
540 /*******************************************************************************
542 * FUNCTION: AcpiEvGetGpeXruptBlock
544 * PARAMETERS: InterruptLevel - Interrupt for a GPE block
546 * RETURN: A GPE interrupt block
548 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
549 * block per unique interrupt level used for GPEs.
550 * Should be called only when the GPE lists are semaphore locked
551 * and not subject to change.
553 ******************************************************************************/
555 static ACPI_GPE_XRUPT_INFO
*
556 AcpiEvGetGpeXruptBlock (
557 UINT32 InterruptLevel
)
559 ACPI_GPE_XRUPT_INFO
*NextGpeXrupt
;
560 ACPI_GPE_XRUPT_INFO
*GpeXrupt
;
564 ACPI_FUNCTION_TRACE ("EvGetGpeXruptBlock");
567 /* No need for spin lock since we are not changing any list elements here */
569 NextGpeXrupt
= AcpiGbl_GpeXruptListHead
;
572 if (NextGpeXrupt
->InterruptLevel
== InterruptLevel
)
574 return_PTR (NextGpeXrupt
);
577 NextGpeXrupt
= NextGpeXrupt
->Next
;
580 /* Not found, must allocate a new xrupt descriptor */
582 GpeXrupt
= ACPI_MEM_CALLOCATE (sizeof (ACPI_GPE_XRUPT_INFO
));
588 GpeXrupt
->InterruptLevel
= InterruptLevel
;
590 /* Install new interrupt descriptor with spin lock */
592 AcpiOsAcquireLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
593 if (AcpiGbl_GpeXruptListHead
)
595 NextGpeXrupt
= AcpiGbl_GpeXruptListHead
;
596 while (NextGpeXrupt
->Next
)
598 NextGpeXrupt
= NextGpeXrupt
->Next
;
601 NextGpeXrupt
->Next
= GpeXrupt
;
602 GpeXrupt
->Previous
= NextGpeXrupt
;
606 AcpiGbl_GpeXruptListHead
= GpeXrupt
;
608 AcpiOsReleaseLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
610 /* Install new interrupt handler if not SCI_INT */
612 if (InterruptLevel
!= AcpiGbl_FADT
->SciInt
)
614 Status
= AcpiOsInstallInterruptHandler (InterruptLevel
,
615 AcpiEvGpeXruptHandler
, GpeXrupt
);
616 if (ACPI_FAILURE (Status
))
618 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
619 "Could not install GPE interrupt handler at level 0x%X\n",
625 return_PTR (GpeXrupt
);
629 /*******************************************************************************
631 * FUNCTION: AcpiEvDeleteGpeXrupt
633 * PARAMETERS: GpeXrupt - A GPE interrupt info block
637 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
638 * interrupt handler if not the SCI interrupt.
640 ******************************************************************************/
643 AcpiEvDeleteGpeXrupt (
644 ACPI_GPE_XRUPT_INFO
*GpeXrupt
)
649 ACPI_FUNCTION_TRACE ("EvDeleteGpeXrupt");
652 /* We never want to remove the SCI interrupt handler */
654 if (GpeXrupt
->InterruptLevel
== AcpiGbl_FADT
->SciInt
)
656 GpeXrupt
->GpeBlockListHead
= NULL
;
657 return_ACPI_STATUS (AE_OK
);
660 /* Disable this interrupt */
662 Status
= AcpiOsRemoveInterruptHandler (GpeXrupt
->InterruptLevel
,
663 AcpiEvGpeXruptHandler
);
664 if (ACPI_FAILURE (Status
))
666 return_ACPI_STATUS (Status
);
669 /* Unlink the interrupt block with lock */
671 AcpiOsAcquireLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
672 if (GpeXrupt
->Previous
)
674 GpeXrupt
->Previous
->Next
= GpeXrupt
->Next
;
679 GpeXrupt
->Next
->Previous
= GpeXrupt
->Previous
;
681 AcpiOsReleaseLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
685 ACPI_MEM_FREE (GpeXrupt
);
686 return_ACPI_STATUS (AE_OK
);
690 /*******************************************************************************
692 * FUNCTION: AcpiEvInstallGpeBlock
694 * PARAMETERS: GpeBlock - New GPE block
695 * InterruptLevel - Level to be associated with this GPE block
699 * DESCRIPTION: Install new GPE block with mutex support
701 ******************************************************************************/
704 AcpiEvInstallGpeBlock (
705 ACPI_GPE_BLOCK_INFO
*GpeBlock
,
706 UINT32 InterruptLevel
)
708 ACPI_GPE_BLOCK_INFO
*NextGpeBlock
;
709 ACPI_GPE_XRUPT_INFO
*GpeXruptBlock
;
713 ACPI_FUNCTION_TRACE ("EvInstallGpeBlock");
716 Status
= AcpiUtAcquireMutex (ACPI_MTX_EVENTS
);
717 if (ACPI_FAILURE (Status
))
719 return_ACPI_STATUS (Status
);
722 GpeXruptBlock
= AcpiEvGetGpeXruptBlock (InterruptLevel
);
725 Status
= AE_NO_MEMORY
;
729 /* Install the new block at the end of the list for this interrupt with lock */
731 AcpiOsAcquireLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
732 if (GpeXruptBlock
->GpeBlockListHead
)
734 NextGpeBlock
= GpeXruptBlock
->GpeBlockListHead
;
735 while (NextGpeBlock
->Next
)
737 NextGpeBlock
= NextGpeBlock
->Next
;
740 NextGpeBlock
->Next
= GpeBlock
;
741 GpeBlock
->Previous
= NextGpeBlock
;
745 GpeXruptBlock
->GpeBlockListHead
= GpeBlock
;
748 GpeBlock
->XruptBlock
= GpeXruptBlock
;
749 AcpiOsReleaseLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
752 Status
= AcpiUtReleaseMutex (ACPI_MTX_EVENTS
);
753 return_ACPI_STATUS (Status
);
757 /*******************************************************************************
759 * FUNCTION: AcpiEvDeleteGpeBlock
761 * PARAMETERS: GpeBlock - Existing GPE block
765 * DESCRIPTION: Remove a GPE block
767 ******************************************************************************/
770 AcpiEvDeleteGpeBlock (
771 ACPI_GPE_BLOCK_INFO
*GpeBlock
)
776 ACPI_FUNCTION_TRACE ("EvInstallGpeBlock");
779 Status
= AcpiUtAcquireMutex (ACPI_MTX_EVENTS
);
780 if (ACPI_FAILURE (Status
))
782 return_ACPI_STATUS (Status
);
785 /* Disable all GPEs in this block */
787 Status
= AcpiHwDisableGpeBlock (GpeBlock
->XruptBlock
, GpeBlock
);
789 if (!GpeBlock
->Previous
&& !GpeBlock
->Next
)
791 /* This is the last GpeBlock on this interrupt */
793 Status
= AcpiEvDeleteGpeXrupt (GpeBlock
->XruptBlock
);
794 if (ACPI_FAILURE (Status
))
801 /* Remove the block on this interrupt with lock */
803 AcpiOsAcquireLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
804 if (GpeBlock
->Previous
)
806 GpeBlock
->Previous
->Next
= GpeBlock
->Next
;
810 GpeBlock
->XruptBlock
->GpeBlockListHead
= GpeBlock
->Next
;
815 GpeBlock
->Next
->Previous
= GpeBlock
->Previous
;
817 AcpiOsReleaseLock (AcpiGbl_GpeLock
, ACPI_NOT_ISR
);
820 /* Free the GpeBlock */
822 ACPI_MEM_FREE (GpeBlock
->RegisterInfo
);
823 ACPI_MEM_FREE (GpeBlock
->EventInfo
);
824 ACPI_MEM_FREE (GpeBlock
);
827 Status
= AcpiUtReleaseMutex (ACPI_MTX_EVENTS
);
828 return_ACPI_STATUS (Status
);
832 /*******************************************************************************
834 * FUNCTION: AcpiEvCreateGpeInfoBlocks
836 * PARAMETERS: GpeBlock - New GPE block
840 * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block
842 ******************************************************************************/
845 AcpiEvCreateGpeInfoBlocks (
846 ACPI_GPE_BLOCK_INFO
*GpeBlock
)
848 ACPI_GPE_REGISTER_INFO
*GpeRegisterInfo
= NULL
;
849 ACPI_GPE_EVENT_INFO
*GpeEventInfo
= NULL
;
850 ACPI_GPE_EVENT_INFO
*ThisEvent
;
851 ACPI_GPE_REGISTER_INFO
*ThisRegister
;
857 ACPI_FUNCTION_TRACE ("EvCreateGpeInfoBlocks");
860 /* Allocate the GPE register information block */
862 GpeRegisterInfo
= ACPI_MEM_CALLOCATE (
863 (ACPI_SIZE
) GpeBlock
->RegisterCount
*
864 sizeof (ACPI_GPE_REGISTER_INFO
));
865 if (!GpeRegisterInfo
)
867 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
868 "Could not allocate the GpeRegisterInfo table\n"));
869 return_ACPI_STATUS (AE_NO_MEMORY
);
873 * Allocate the GPE EventInfo block. There are eight distinct GPEs
874 * per register. Initialization to zeros is sufficient.
876 GpeEventInfo
= ACPI_MEM_CALLOCATE (
877 ((ACPI_SIZE
) GpeBlock
->RegisterCount
* ACPI_GPE_REGISTER_WIDTH
) *
878 sizeof (ACPI_GPE_EVENT_INFO
));
881 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
, "Could not allocate the GpeEventInfo table\n"));
882 Status
= AE_NO_MEMORY
;
886 /* Save the new Info arrays in the GPE block */
888 GpeBlock
->RegisterInfo
= GpeRegisterInfo
;
889 GpeBlock
->EventInfo
= GpeEventInfo
;
892 * Initialize the GPE Register and Event structures. A goal of these
893 * tables is to hide the fact that there are two separate GPE register sets
894 * in a given gpe hardware block, the status registers occupy the first half,
895 * and the enable registers occupy the second half.
897 ThisRegister
= GpeRegisterInfo
;
898 ThisEvent
= GpeEventInfo
;
900 for (i
= 0; i
< GpeBlock
->RegisterCount
; i
++)
902 /* Init the RegisterInfo for this GPE register (8 GPEs) */
904 ThisRegister
->BaseGpeNumber
= (UINT8
) (GpeBlock
->BlockBaseNumber
+
905 (i
* ACPI_GPE_REGISTER_WIDTH
));
907 ACPI_STORE_ADDRESS (ThisRegister
->StatusAddress
.Address
,
908 (ACPI_GET_ADDRESS (GpeBlock
->BlockAddress
.Address
)
911 ACPI_STORE_ADDRESS (ThisRegister
->EnableAddress
.Address
,
912 (ACPI_GET_ADDRESS (GpeBlock
->BlockAddress
.Address
)
914 + GpeBlock
->RegisterCount
));
916 ThisRegister
->StatusAddress
.AddressSpaceId
= GpeBlock
->BlockAddress
.AddressSpaceId
;
917 ThisRegister
->EnableAddress
.AddressSpaceId
= GpeBlock
->BlockAddress
.AddressSpaceId
;
918 ThisRegister
->StatusAddress
.RegisterBitWidth
= ACPI_GPE_REGISTER_WIDTH
;
919 ThisRegister
->EnableAddress
.RegisterBitWidth
= ACPI_GPE_REGISTER_WIDTH
;
920 ThisRegister
->StatusAddress
.RegisterBitOffset
= ACPI_GPE_REGISTER_WIDTH
;
921 ThisRegister
->EnableAddress
.RegisterBitOffset
= ACPI_GPE_REGISTER_WIDTH
;
923 /* Init the EventInfo for each GPE within this register */
925 for (j
= 0; j
< ACPI_GPE_REGISTER_WIDTH
; j
++)
927 ThisEvent
->RegisterBit
= AcpiGbl_DecodeTo8bit
[j
];
928 ThisEvent
->RegisterInfo
= ThisRegister
;
933 * Clear the status/enable registers. Note that status registers
934 * are cleared by writing a '1', while enable registers are cleared
937 Status
= AcpiHwLowLevelWrite (ACPI_GPE_REGISTER_WIDTH
, 0x00,
938 &ThisRegister
->EnableAddress
);
939 if (ACPI_FAILURE (Status
))
944 Status
= AcpiHwLowLevelWrite (ACPI_GPE_REGISTER_WIDTH
, 0xFF,
945 &ThisRegister
->StatusAddress
);
946 if (ACPI_FAILURE (Status
))
954 return_ACPI_STATUS (AE_OK
);
960 ACPI_MEM_FREE (GpeRegisterInfo
);
964 ACPI_MEM_FREE (GpeEventInfo
);
967 return_ACPI_STATUS (Status
);
971 /*******************************************************************************
973 * FUNCTION: AcpiEvCreateGpeBlock
975 * PARAMETERS: GpeDevice - Handle to the parent GPE block
976 * GpeBlockAddress - Address and SpaceID
977 * RegisterCount - Number of GPE register pairs in the block
978 * GpeBlockBaseNumber - Starting GPE number for the block
979 * InterruptLevel - H/W interrupt for the block
980 * ReturnGpeBlock - Where the new block descriptor is returned
984 * DESCRIPTION: Create and Install a block of GPE registers
986 ******************************************************************************/
989 AcpiEvCreateGpeBlock (
990 ACPI_NAMESPACE_NODE
*GpeDevice
,
991 ACPI_GENERIC_ADDRESS
*GpeBlockAddress
,
992 UINT32 RegisterCount
,
993 UINT8 GpeBlockBaseNumber
,
994 UINT32 InterruptLevel
,
995 ACPI_GPE_BLOCK_INFO
**ReturnGpeBlock
)
997 ACPI_GPE_BLOCK_INFO
*GpeBlock
;
998 ACPI_GPE_EVENT_INFO
*GpeEventInfo
;
1001 UINT32 WakeGpeCount
;
1002 UINT32 GpeEnabledCount
;
1004 ACPI_GPE_WALK_INFO GpeInfo
;
1007 ACPI_FUNCTION_TRACE ("EvCreateGpeBlock");
1012 return_ACPI_STATUS (AE_OK
);
1015 /* Allocate a new GPE block */
1017 GpeBlock
= ACPI_MEM_CALLOCATE (sizeof (ACPI_GPE_BLOCK_INFO
));
1020 return_ACPI_STATUS (AE_NO_MEMORY
);
1023 /* Initialize the new GPE block */
1025 GpeBlock
->RegisterCount
= RegisterCount
;
1026 GpeBlock
->BlockBaseNumber
= GpeBlockBaseNumber
;
1027 GpeBlock
->Node
= GpeDevice
;
1029 ACPI_MEMCPY (&GpeBlock
->BlockAddress
, GpeBlockAddress
, sizeof (ACPI_GENERIC_ADDRESS
));
1031 /* Create the RegisterInfo and EventInfo sub-structures */
1033 Status
= AcpiEvCreateGpeInfoBlocks (GpeBlock
);
1034 if (ACPI_FAILURE (Status
))
1036 ACPI_MEM_FREE (GpeBlock
);
1037 return_ACPI_STATUS (Status
);
1040 /* Install the new block in the global list(s) */
1042 Status
= AcpiEvInstallGpeBlock (GpeBlock
, InterruptLevel
);
1043 if (ACPI_FAILURE (Status
))
1045 ACPI_MEM_FREE (GpeBlock
);
1046 return_ACPI_STATUS (Status
);
1049 /* Find all GPE methods (_Lxx, _Exx) for this block */
1051 Status
= AcpiNsWalkNamespace (ACPI_TYPE_METHOD
, GpeDevice
,
1052 ACPI_UINT32_MAX
, ACPI_NS_WALK_NO_UNLOCK
, AcpiEvSaveMethodInfo
,
1056 * Runtime option: Should Wake GPEs be enabled at runtime? The default
1057 * is No,they should only be enabled just as the machine goes to sleep.
1059 if (AcpiGbl_LeaveWakeGpesDisabled
)
1062 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
1063 * (Each GPE that has one or more _PRWs that reference it is by
1064 * definition a WAKE GPE and will not be enabled while the machine
1067 GpeInfo
.GpeBlock
= GpeBlock
;
1068 GpeInfo
.GpeDevice
= GpeDevice
;
1070 Status
= AcpiNsWalkNamespace (ACPI_TYPE_DEVICE
, ACPI_ROOT_OBJECT
,
1071 ACPI_UINT32_MAX
, ACPI_NS_WALK_UNLOCK
, AcpiEvMatchPrwAndGpe
,
1076 * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
1077 * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must
1078 * be enabled via the AcpiEnableGpe() external interface.
1081 GpeEnabledCount
= 0;
1083 for (i
= 0; i
< GpeBlock
->RegisterCount
; i
++)
1085 for (j
= 0; j
< 8; j
++)
1087 /* Get the info block for this particular GPE */
1089 GpeEventInfo
= &GpeBlock
->EventInfo
[(i
* ACPI_GPE_REGISTER_WIDTH
) + j
];
1091 if (((GpeEventInfo
->Flags
& ACPI_GPE_DISPATCH_MASK
) == ACPI_GPE_DISPATCH_METHOD
) &&
1092 (GpeEventInfo
->Flags
& ACPI_GPE_TYPE_RUNTIME
))
1097 if (GpeEventInfo
->Flags
& ACPI_GPE_TYPE_WAKE
)
1104 /* Dump info about this GPE block */
1106 ACPI_DEBUG_PRINT ((ACPI_DB_INIT
,
1107 "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
1108 (UINT32
) GpeBlock
->BlockBaseNumber
,
1109 (UINT32
) (GpeBlock
->BlockBaseNumber
+
1110 ((GpeBlock
->RegisterCount
* ACPI_GPE_REGISTER_WIDTH
) -1)),
1111 GpeDevice
->Name
.Ascii
,
1112 GpeBlock
->RegisterCount
,
1115 /* Enable all valid GPEs found above */
1117 Status
= AcpiHwEnableRuntimeGpeBlock (NULL
, GpeBlock
);
1119 ACPI_DEBUG_PRINT ((ACPI_DB_INIT
,
1120 "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
1121 WakeGpeCount
, GpeEnabledCount
));
1123 /* Return the new block */
1127 (*ReturnGpeBlock
) = GpeBlock
;
1130 return_ACPI_STATUS (AE_OK
);
1134 /*******************************************************************************
1136 * FUNCTION: AcpiEvGpeInitialize
1142 * DESCRIPTION: Initialize the GPE data structures
1144 ******************************************************************************/
1147 AcpiEvGpeInitialize (
1150 UINT32 RegisterCount0
= 0;
1151 UINT32 RegisterCount1
= 0;
1152 UINT32 GpeNumberMax
= 0;
1156 ACPI_FUNCTION_TRACE ("EvGpeInitialize");
1159 Status
= AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE
);
1160 if (ACPI_FAILURE (Status
))
1162 return_ACPI_STATUS (Status
);
1166 * Initialize the GPE Block(s) defined in the FADT
1168 * Why the GPE register block lengths are divided by 2: From the ACPI Spec,
1169 * section "General-Purpose Event Registers", we have:
1171 * "Each register block contains two registers of equal length
1172 * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
1173 * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
1174 * The length of the GPE1_STS and GPE1_EN registers is equal to
1175 * half the GPE1_LEN. If a generic register block is not supported
1176 * then its respective block pointer and block length values in the
1177 * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
1178 * to be the same size."
1182 * Determine the maximum GPE number for this machine.
1184 * Note: both GPE0 and GPE1 are optional, and either can exist without
1187 * If EITHER the register length OR the block address are zero, then that
1188 * particular block is not supported.
1190 if (AcpiGbl_FADT
->Gpe0BlkLen
&&
1191 ACPI_GET_ADDRESS (AcpiGbl_FADT
->XGpe0Blk
.Address
))
1193 /* GPE block 0 exists (has both length and address > 0) */
1195 RegisterCount0
= (UINT16
) (AcpiGbl_FADT
->Gpe0BlkLen
/ 2);
1197 GpeNumberMax
= (RegisterCount0
* ACPI_GPE_REGISTER_WIDTH
) - 1;
1199 /* Install GPE Block 0 */
1201 Status
= AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice
, &AcpiGbl_FADT
->XGpe0Blk
,
1202 RegisterCount0
, 0, AcpiGbl_FADT
->SciInt
, &AcpiGbl_GpeFadtBlocks
[0]);
1204 if (ACPI_FAILURE (Status
))
1206 ACPI_REPORT_ERROR ((
1207 "Could not create GPE Block 0, %s\n",
1208 AcpiFormatException (Status
)));
1212 if (AcpiGbl_FADT
->Gpe1BlkLen
&&
1213 ACPI_GET_ADDRESS (AcpiGbl_FADT
->XGpe1Blk
.Address
))
1215 /* GPE block 1 exists (has both length and address > 0) */
1217 RegisterCount1
= (UINT16
) (AcpiGbl_FADT
->Gpe1BlkLen
/ 2);
1219 /* Check for GPE0/GPE1 overlap (if both banks exist) */
1221 if ((RegisterCount0
) &&
1222 (GpeNumberMax
>= AcpiGbl_FADT
->Gpe1Base
))
1224 ACPI_REPORT_ERROR ((
1225 "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n",
1226 GpeNumberMax
, AcpiGbl_FADT
->Gpe1Base
,
1227 AcpiGbl_FADT
->Gpe1Base
+
1228 ((RegisterCount1
* ACPI_GPE_REGISTER_WIDTH
) - 1)));
1230 /* Ignore GPE1 block by setting the register count to zero */
1236 /* Install GPE Block 1 */
1238 Status
= AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice
, &AcpiGbl_FADT
->XGpe1Blk
,
1239 RegisterCount1
, AcpiGbl_FADT
->Gpe1Base
,
1240 AcpiGbl_FADT
->SciInt
, &AcpiGbl_GpeFadtBlocks
[1]);
1242 if (ACPI_FAILURE (Status
))
1244 ACPI_REPORT_ERROR ((
1245 "Could not create GPE Block 1, %s\n",
1246 AcpiFormatException (Status
)));
1250 * GPE0 and GPE1 do not have to be contiguous in the GPE number
1251 * space. However, GPE0 always starts at GPE number zero.
1253 GpeNumberMax
= AcpiGbl_FADT
->Gpe1Base
+
1254 ((RegisterCount1
* ACPI_GPE_REGISTER_WIDTH
) - 1);
1258 /* Exit if there are no GPE registers */
1260 if ((RegisterCount0
+ RegisterCount1
) == 0)
1262 /* GPEs are not required by ACPI, this is OK */
1264 ACPI_DEBUG_PRINT ((ACPI_DB_INIT
,
1265 "There are no GPE blocks defined in the FADT\n"));
1270 /* Check for Max GPE number out-of-range */
1272 if (GpeNumberMax
> ACPI_GPE_MAX
)
1274 ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
1276 Status
= AE_BAD_VALUE
;
1281 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE
);
1282 return_ACPI_STATUS (AE_OK
);