No empty .Rs/.Re
[netbsd-mini2440.git] / sys / external / intel-public / acpica / dist / events / evgpeblk.c
blob343a31d28efd4b0448d87f75d41adb4223199948
1 /******************************************************************************
3 * Module Name: evgpeblk - GPE block creation and initialization.
5 *****************************************************************************/
7 /******************************************************************************
9 * 1. Copyright Notice
11 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12 * All rights reserved.
14 * 2. License
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
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
38 * conditions are met:
40 * 3. Conditions
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
64 * make.
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
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
88 * PARTICULAR PURPOSE.
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
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 *****************************************************************************/
116 #include "acpi.h"
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 */
126 static ACPI_STATUS
127 AcpiEvSaveMethodInfo (
128 ACPI_HANDLE ObjHandle,
129 UINT32 Level,
130 void *ObjDesc,
131 void **ReturnValue);
133 static ACPI_STATUS
134 AcpiEvMatchPrwAndGpe (
135 ACPI_HANDLE ObjHandle,
136 UINT32 Level,
137 void *Info,
138 void **ReturnValue);
140 static ACPI_GPE_XRUPT_INFO *
141 AcpiEvGetGpeXruptBlock (
142 UINT32 InterruptNumber);
144 static ACPI_STATUS
145 AcpiEvDeleteGpeXrupt (
146 ACPI_GPE_XRUPT_INFO *GpeXrupt);
148 static ACPI_STATUS
149 AcpiEvInstallGpeBlock (
150 ACPI_GPE_BLOCK_INFO *GpeBlock,
151 UINT32 InterruptNumber);
153 static ACPI_STATUS
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 ******************************************************************************/
172 BOOLEAN
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 */
194 while (GpeBlock)
196 if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) &&
197 (&GpeBlock->EventInfo[((ACPI_SIZE)
198 GpeBlock->RegisterCount) * 8] > GpeEventInfo))
200 return (TRUE);
203 GpeBlock = GpeBlock->Next;
206 GpeXruptBlock = GpeXruptBlock->Next;
209 return (FALSE);
213 /*******************************************************************************
215 * FUNCTION: AcpiEvWalkGpeList
217 * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
218 * Context - Value passed to callback
220 * RETURN: Status
222 * DESCRIPTION: Walk the GPE lists.
224 ******************************************************************************/
226 ACPI_STATUS
227 AcpiEvWalkGpeList (
228 ACPI_GPE_CALLBACK GpeWalkCallback,
229 void *Context)
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;
245 while (GpeXruptInfo)
247 /* Walk all Gpe Blocks attached to this interrupt level */
249 GpeBlock = GpeXruptInfo->GpeBlockListHead;
250 while (GpeBlock)
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 */
259 Status = AE_OK;
261 goto UnlockAndExit;
264 GpeBlock = GpeBlock->Next;
267 GpeXruptInfo = GpeXruptInfo->Next;
270 UnlockAndExit:
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
283 * RETURN: Status
285 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
286 * Used only prior to termination.
288 ******************************************************************************/
290 ACPI_STATUS
291 AcpiEvDeleteGpeHandlers (
292 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
293 ACPI_GPE_BLOCK_INFO *GpeBlock,
294 void *Context)
296 ACPI_GPE_EVENT_INFO *GpeEventInfo;
297 UINT32 i;
298 UINT32 j;
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
335 * RETURN: Status
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:
343 * "_Lxx" or "_Exx"
344 * Where:
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 ******************************************************************************/
351 static ACPI_STATUS
352 AcpiEvSaveMethodInfo (
353 ACPI_HANDLE ObjHandle,
354 UINT32 Level,
355 void *ObjDesc,
356 void **ReturnValue)
358 ACPI_GPE_BLOCK_INFO *GpeBlock = (void *) ObjDesc;
359 ACPI_GPE_EVENT_INFO *GpeEventInfo;
360 UINT32 GpeNumber;
361 char Name[ACPI_NAME_SIZE + 1];
362 UINT8 Type;
363 ACPI_STATUS Status;
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
374 ACPI_MOVE_32_TO_32 (
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
380 * of the method name
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.
385 switch (Name[1])
387 case 'L':
388 Type = ACPI_GPE_LEVEL_TRIGGERED;
389 break;
391 case 'E':
392 Type = ACPI_GPE_EDGE_TRIGGERED;
393 break;
395 default:
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)",
401 Name));
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)",
415 Name));
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",
451 Name, GpeNumber));
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 ******************************************************************************/
471 static ACPI_STATUS
472 AcpiEvMatchPrwAndGpe (
473 ACPI_HANDLE ObjHandle,
474 UINT32 Level,
475 void *Info,
476 void **ReturnValue)
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;
485 UINT32 GpeNumber;
486 ACPI_STATUS Status;
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)
507 goto Cleanup;
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
517 * first element
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 !=
539 ACPI_TYPE_INTEGER))
541 goto Cleanup;
544 /* Get GPE block reference and decode */
546 TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
547 GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
549 else
551 /* Unknown type, just ignore it */
553 goto Cleanup;
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))
579 goto Cleanup;
582 Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
585 Cleanup:
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
602 * subject to change.
604 ******************************************************************************/
606 static ACPI_GPE_XRUPT_INFO *
607 AcpiEvGetGpeXruptBlock (
608 UINT32 InterruptNumber)
610 ACPI_GPE_XRUPT_INFO *NextGpeXrupt;
611 ACPI_GPE_XRUPT_INFO *GpeXrupt;
612 ACPI_STATUS Status;
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;
622 while (NextGpeXrupt)
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));
635 if (!GpeXrupt)
637 return_PTR (NULL);
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;
656 else
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",
672 InterruptNumber));
673 return_PTR (NULL);
677 return_PTR (GpeXrupt);
681 /*******************************************************************************
683 * FUNCTION: AcpiEvDeleteGpeXrupt
685 * PARAMETERS: GpeXrupt - A GPE interrupt info block
687 * RETURN: Status
689 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
690 * interrupt handler if not the SCI interrupt.
692 ******************************************************************************/
694 static ACPI_STATUS
695 AcpiEvDeleteGpeXrupt (
696 ACPI_GPE_XRUPT_INFO *GpeXrupt)
698 ACPI_STATUS Status;
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;
729 else
731 /* No previous, update list head */
733 AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
736 if (GpeXrupt->Next)
738 GpeXrupt->Next->Previous = GpeXrupt->Previous;
740 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
742 /* Free the block */
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
755 * GPE block
757 * RETURN: Status
759 * DESCRIPTION: Install new GPE block with mutex support
761 ******************************************************************************/
763 static ACPI_STATUS
764 AcpiEvInstallGpeBlock (
765 ACPI_GPE_BLOCK_INFO *GpeBlock,
766 UINT32 InterruptNumber)
768 ACPI_GPE_BLOCK_INFO *NextGpeBlock;
769 ACPI_GPE_XRUPT_INFO *GpeXruptBlock;
770 ACPI_STATUS Status;
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);
784 if (!GpeXruptBlock)
786 Status = AE_NO_MEMORY;
787 goto UnlockAndExit;
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;
804 else
806 GpeXruptBlock->GpeBlockListHead = GpeBlock;
809 GpeBlock->XruptBlock = GpeXruptBlock;
810 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
813 UnlockAndExit:
814 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
815 return_ACPI_STATUS (Status);
819 /*******************************************************************************
821 * FUNCTION: AcpiEvDeleteGpeBlock
823 * PARAMETERS: GpeBlock - Existing GPE block
825 * RETURN: Status
827 * DESCRIPTION: Remove a GPE block
829 ******************************************************************************/
831 ACPI_STATUS
832 AcpiEvDeleteGpeBlock (
833 ACPI_GPE_BLOCK_INFO *GpeBlock)
835 ACPI_STATUS Status;
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))
859 goto UnlockAndExit;
862 else
864 /* Remove the block on this interrupt with lock */
866 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
867 if (GpeBlock->Previous)
869 GpeBlock->Previous->Next = GpeBlock->Next;
871 else
873 GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next;
876 if (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);
891 UnlockAndExit:
892 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
893 return_ACPI_STATUS (Status);
897 /*******************************************************************************
899 * FUNCTION: AcpiEvCreateGpeInfoBlocks
901 * PARAMETERS: GpeBlock - New GPE block
903 * RETURN: Status
905 * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block
907 ******************************************************************************/
909 static ACPI_STATUS
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;
917 UINT32 i;
918 UINT32 j;
919 ACPI_STATUS Status;
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));
945 if (!GpeEventInfo)
947 ACPI_ERROR ((AE_INFO,
948 "Could not allocate the GpeEventInfo table"));
949 Status = AE_NO_MEMORY;
950 goto ErrorExit;
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;
993 ThisEvent++;
996 /* Disable all GPEs within this register */
998 Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress);
999 if (ACPI_FAILURE (Status))
1001 goto ErrorExit;
1004 /* Clear any pending GPE events within this register */
1006 Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress);
1007 if (ACPI_FAILURE (Status))
1009 goto ErrorExit;
1012 ThisRegister++;
1015 return_ACPI_STATUS (AE_OK);
1018 ErrorExit:
1019 if (GpeRegisterInfo)
1021 ACPI_FREE (GpeRegisterInfo);
1023 if (GpeEventInfo)
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
1043 * RETURN: Status
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 ******************************************************************************/
1051 ACPI_STATUS
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)
1060 ACPI_STATUS Status;
1061 ACPI_GPE_BLOCK_INFO *GpeBlock;
1064 ACPI_FUNCTION_TRACE (EvCreateGpeBlock);
1067 if (!RegisterCount)
1069 return_ACPI_STATUS (AE_OK);
1072 /* Allocate a new GPE block */
1074 GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO));
1075 if (!GpeBlock)
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 */
1117 if (ReturnGpeBlock)
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,
1129 InterruptNumber));
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
1145 * RETURN: Status
1147 * DESCRIPTION: Initialize and enable a GPE block. First find and run any
1148 * _PRT methods associated with the block, then enable the
1149 * appropriate GPEs.
1150 * Note: Assumes namespace is locked.
1152 ******************************************************************************/
1154 ACPI_STATUS
1155 AcpiEvInitializeGpeBlock (
1156 ACPI_NAMESPACE_NODE *GpeDevice,
1157 ACPI_GPE_BLOCK_INFO *GpeBlock)
1159 ACPI_STATUS Status;
1160 ACPI_GPE_EVENT_INFO *GpeEventInfo;
1161 ACPI_GPE_WALK_INFO GpeInfo;
1162 UINT32 WakeGpeCount;
1163 UINT32 GpeEnabledCount;
1164 UINT32 i;
1165 UINT32 j;
1168 ACPI_FUNCTION_TRACE (EvInitializeGpeBlock);
1171 /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
1173 if (!GpeBlock)
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
1188 * is running.
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.
1206 WakeGpeCount = 0;
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))
1222 GpeEnabledCount++;
1225 if (GpeEventInfo->Flags & ACPI_GPE_TYPE_WAKE)
1227 WakeGpeCount++;
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",
1242 GpeBlock));
1245 return_ACPI_STATUS (Status);
1249 /*******************************************************************************
1251 * FUNCTION: AcpiEvGpeInitialize
1253 * PARAMETERS: None
1255 * RETURN: Status
1257 * DESCRIPTION: Initialize the GPE data structures
1259 ******************************************************************************/
1261 ACPI_STATUS
1262 AcpiEvGpeInitialize (
1263 void)
1265 UINT32 RegisterCount0 = 0;
1266 UINT32 RegisterCount1 = 0;
1267 UINT32 GpeNumberMax = 0;
1268 ACPI_STATUS Status;
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
1300 * the other.
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 */
1348 RegisterCount1 = 0;
1350 else
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"));
1382 Status = AE_OK;
1383 goto Cleanup;
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",
1392 GpeNumberMax));
1393 Status = AE_BAD_VALUE;
1394 goto Cleanup;
1397 Cleanup:
1398 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1399 return_ACPI_STATUS (AE_OK);