Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/evgpeblk.c need to be fixed.

0001 /******************************************************************************
0002  *
0003  * Module Name: evgpeblk - GPE block creation and initialization.
0004  *
0005  *****************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights.  You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code.  No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision.  In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change.  Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee.  Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution.  In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government.  In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************/
0115 
0116 #include "acpi.h"
0117 #include "accommon.h"
0118 #include "acevents.h"
0119 #include "acnamesp.h"
0120 
0121 #define _COMPONENT          ACPI_EVENTS
0122         ACPI_MODULE_NAME    ("evgpeblk")
0123 
0124 /* Local prototypes */
0125 
0126 static ACPI_STATUS
0127 AcpiEvSaveMethodInfo (
0128     ACPI_HANDLE             ObjHandle,
0129     UINT32                  Level,
0130     void                    *ObjDesc,
0131     void                    **ReturnValue);
0132 
0133 static ACPI_STATUS
0134 AcpiEvMatchPrwAndGpe (
0135     ACPI_HANDLE             ObjHandle,
0136     UINT32                  Level,
0137     void                    *Info,
0138     void                    **ReturnValue);
0139 
0140 static ACPI_GPE_XRUPT_INFO *
0141 AcpiEvGetGpeXruptBlock (
0142     UINT32                  InterruptNumber);
0143 
0144 static ACPI_STATUS
0145 AcpiEvDeleteGpeXrupt (
0146     ACPI_GPE_XRUPT_INFO     *GpeXrupt);
0147 
0148 static ACPI_STATUS
0149 AcpiEvInstallGpeBlock (
0150     ACPI_GPE_BLOCK_INFO     *GpeBlock,
0151     UINT32                  InterruptNumber);
0152 
0153 static ACPI_STATUS
0154 AcpiEvCreateGpeInfoBlocks (
0155     ACPI_GPE_BLOCK_INFO     *GpeBlock);
0156 
0157 
0158 /*******************************************************************************
0159  *
0160  * FUNCTION:    AcpiEvValidGpeEvent
0161  *
0162  * PARAMETERS:  GpeEventInfo                - Info for this GPE
0163  *
0164  * RETURN:      TRUE if the GpeEvent is valid
0165  *
0166  * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
0167  *              Should be called only when the GPE lists are semaphore locked
0168  *              and not subject to change.
0169  *
0170  ******************************************************************************/
0171 
0172 BOOLEAN
0173 AcpiEvValidGpeEvent (
0174     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
0175 {
0176     ACPI_GPE_XRUPT_INFO     *GpeXruptBlock;
0177     ACPI_GPE_BLOCK_INFO     *GpeBlock;
0178 
0179 
0180     ACPI_FUNCTION_ENTRY ();
0181 
0182 
0183     /* No need for spin lock since we are not changing any list elements */
0184 
0185     /* Walk the GPE interrupt levels */
0186 
0187     GpeXruptBlock = AcpiGbl_GpeXruptListHead;
0188     while (GpeXruptBlock)
0189     {
0190         GpeBlock = GpeXruptBlock->GpeBlockListHead;
0191 
0192         /* Walk the GPE blocks on this interrupt level */
0193 
0194         while (GpeBlock)
0195         {
0196             if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) &&
0197                 (&GpeBlock->EventInfo[((ACPI_SIZE)
0198                     GpeBlock->RegisterCount) * 8] > GpeEventInfo))
0199             {
0200                 return (TRUE);
0201             }
0202 
0203             GpeBlock = GpeBlock->Next;
0204         }
0205 
0206         GpeXruptBlock = GpeXruptBlock->Next;
0207     }
0208 
0209     return (FALSE);
0210 }
0211 
0212 
0213 /*******************************************************************************
0214  *
0215  * FUNCTION:    AcpiEvWalkGpeList
0216  *
0217  * PARAMETERS:  GpeWalkCallback     - Routine called for each GPE block
0218  *              Context             - Value passed to callback
0219  *
0220  * RETURN:      Status
0221  *
0222  * DESCRIPTION: Walk the GPE lists.
0223  *
0224  ******************************************************************************/
0225 
0226 ACPI_STATUS
0227 AcpiEvWalkGpeList (
0228     ACPI_GPE_CALLBACK       GpeWalkCallback,
0229     void                    *Context)
0230 {
0231     ACPI_GPE_BLOCK_INFO     *GpeBlock;
0232     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
0233     ACPI_STATUS             Status = AE_OK;
0234     ACPI_CPU_FLAGS          Flags;
0235 
0236 
0237     ACPI_FUNCTION_TRACE (EvWalkGpeList);
0238 
0239 
0240     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
0241 
0242     /* Walk the interrupt level descriptor list */
0243 
0244     GpeXruptInfo = AcpiGbl_GpeXruptListHead;
0245     while (GpeXruptInfo)
0246     {
0247         /* Walk all Gpe Blocks attached to this interrupt level */
0248 
0249         GpeBlock = GpeXruptInfo->GpeBlockListHead;
0250         while (GpeBlock)
0251         {
0252             /* One callback per GPE block */
0253 
0254             Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context);
0255             if (ACPI_FAILURE (Status))
0256             {
0257                 if (Status == AE_CTRL_END) /* Callback abort */
0258                 {
0259                     Status = AE_OK;
0260                 }
0261                 goto UnlockAndExit;
0262             }
0263 
0264             GpeBlock = GpeBlock->Next;
0265         }
0266 
0267         GpeXruptInfo = GpeXruptInfo->Next;
0268     }
0269 
0270 UnlockAndExit:
0271     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
0272     return_ACPI_STATUS (Status);
0273 }
0274 
0275 
0276 /*******************************************************************************
0277  *
0278  * FUNCTION:    AcpiEvDeleteGpeHandlers
0279  *
0280  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
0281  *              GpeBlock            - Gpe Block info
0282  *
0283  * RETURN:      Status
0284  *
0285  * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
0286  *              Used only prior to termination.
0287  *
0288  ******************************************************************************/
0289 
0290 ACPI_STATUS
0291 AcpiEvDeleteGpeHandlers (
0292     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
0293     ACPI_GPE_BLOCK_INFO     *GpeBlock,
0294     void                    *Context)
0295 {
0296     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
0297     UINT32                  i;
0298     UINT32                  j;
0299 
0300 
0301     ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
0302 
0303 
0304     /* Examine each GPE Register within the block */
0305 
0306     for (i = 0; i < GpeBlock->RegisterCount; i++)
0307     {
0308         /* Now look at the individual GPEs in this byte register */
0309 
0310         for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
0311         {
0312             GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
0313                 ACPI_GPE_REGISTER_WIDTH) + j];
0314 
0315             if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
0316                     ACPI_GPE_DISPATCH_HANDLER)
0317             {
0318                 ACPI_FREE (GpeEventInfo->Dispatch.Handler);
0319                 GpeEventInfo->Dispatch.Handler = NULL;
0320                 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
0321             }
0322         }
0323     }
0324 
0325     return_ACPI_STATUS (AE_OK);
0326 }
0327 
0328 
0329 /*******************************************************************************
0330  *
0331  * FUNCTION:    AcpiEvSaveMethodInfo
0332  *
0333  * PARAMETERS:  Callback from WalkNamespace
0334  *
0335  * RETURN:      Status
0336  *
0337  * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
0338  *              control method under the _GPE portion of the namespace.
0339  *              Extract the name and GPE type from the object, saving this
0340  *              information for quick lookup during GPE dispatch
0341  *
0342  *              The name of each GPE control method is of the form:
0343  *              "_Lxx" or "_Exx"
0344  *              Where:
0345  *                  L      - means that the GPE is level triggered
0346  *                  E      - means that the GPE is edge triggered
0347  *                  xx     - is the GPE number [in HEX]
0348  *
0349  ******************************************************************************/
0350 
0351 static ACPI_STATUS
0352 AcpiEvSaveMethodInfo (
0353     ACPI_HANDLE             ObjHandle,
0354     UINT32                  Level,
0355     void                    *ObjDesc,
0356     void                    **ReturnValue)
0357 {
0358     ACPI_GPE_BLOCK_INFO     *GpeBlock = (void *) ObjDesc;
0359     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
0360     UINT32                  GpeNumber;
0361     char                    Name[ACPI_NAME_SIZE + 1];
0362     UINT8                   Type;
0363     ACPI_STATUS             Status;
0364 
0365 
0366     ACPI_FUNCTION_TRACE (EvSaveMethodInfo);
0367 
0368 
0369     /*
0370      * _Lxx and _Exx GPE method support
0371      *
0372      * 1) Extract the name from the object and convert to a string
0373      */
0374     ACPI_MOVE_32_TO_32 (
0375         Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer);
0376     Name[ACPI_NAME_SIZE] = 0;
0377 
0378     /*
0379      * 2) Edge/Level determination is based on the 2nd character
0380      *    of the method name
0381      *
0382      * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
0383      * if a _PRW object is found that points to this GPE.
0384      */
0385     switch (Name[1])
0386     {
0387     case 'L':
0388         Type = ACPI_GPE_LEVEL_TRIGGERED;
0389         break;
0390 
0391     case 'E':
0392         Type = ACPI_GPE_EDGE_TRIGGERED;
0393         break;
0394 
0395     default:
0396         /* Unknown method type, just ignore it! */
0397 
0398         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
0399             "Ignoring unknown GPE method type: %s "
0400             "(name not of form _Lxx or _Exx)",
0401             Name));
0402         return_ACPI_STATUS (AE_OK);
0403     }
0404 
0405     /* Convert the last two characters of the name to the GPE Number */
0406 
0407     GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
0408     if (GpeNumber == ACPI_UINT32_MAX)
0409     {
0410         /* Conversion failed; invalid method, just ignore it */
0411 
0412         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
0413             "Could not extract GPE number from name: %s "
0414             "(name is not of form _Lxx or _Exx)",
0415             Name));
0416         return_ACPI_STATUS (AE_OK);
0417     }
0418 
0419     /* Ensure that we have a valid GPE number for this GPE block */
0420 
0421     if ((GpeNumber < GpeBlock->BlockBaseNumber) ||
0422         (GpeNumber >= (GpeBlock->BlockBaseNumber +
0423             (GpeBlock->RegisterCount * 8))))
0424     {
0425         /*
0426          * Not valid for this GPE block, just ignore it. However, it may be
0427          * valid for a different GPE block, since GPE0 and GPE1 methods both
0428          * appear under \_GPE.
0429          */
0430         return_ACPI_STATUS (AE_OK);
0431     }
0432 
0433     /*
0434      * Now we can add this information to the GpeEventInfo block for use
0435      * during dispatch of this GPE. Default type is RUNTIME, although this may
0436      * change when the _PRW methods are executed later.
0437      */
0438     GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber];
0439 
0440     GpeEventInfo->Flags = (UINT8)
0441         (Type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
0442 
0443     GpeEventInfo->Dispatch.MethodNode = (ACPI_NAMESPACE_NODE *) ObjHandle;
0444 
0445     /* Update enable mask, but don't enable the HW GPE as of yet */
0446 
0447     Status = AcpiEvEnableGpe (GpeEventInfo, FALSE);
0448 
0449     ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
0450         "Registered GPE method %s as GPE number 0x%.2X\n",
0451         Name, GpeNumber));
0452     return_ACPI_STATUS (Status);
0453 }
0454 
0455 
0456 /*******************************************************************************
0457  *
0458  * FUNCTION:    AcpiEvMatchPrwAndGpe
0459  *
0460  * PARAMETERS:  Callback from WalkNamespace
0461  *
0462  * RETURN:      Status. NOTE: We ignore errors so that the _PRW walk is
0463  *              not aborted on a single _PRW failure.
0464  *
0465  * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
0466  *              Device. Run the _PRW method. If present, extract the GPE
0467  *              number and mark the GPE as a WAKE GPE.
0468  *
0469  ******************************************************************************/
0470 
0471 static ACPI_STATUS
0472 AcpiEvMatchPrwAndGpe (
0473     ACPI_HANDLE             ObjHandle,
0474     UINT32                  Level,
0475     void                    *Info,
0476     void                    **ReturnValue)
0477 {
0478     ACPI_GPE_WALK_INFO      *GpeInfo = (void *) Info;
0479     ACPI_NAMESPACE_NODE     *GpeDevice;
0480     ACPI_GPE_BLOCK_INFO     *GpeBlock;
0481     ACPI_NAMESPACE_NODE     *TargetGpeDevice;
0482     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
0483     ACPI_OPERAND_OBJECT     *PkgDesc;
0484     ACPI_OPERAND_OBJECT     *ObjDesc;
0485     UINT32                  GpeNumber;
0486     ACPI_STATUS             Status;
0487 
0488 
0489     ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);
0490 
0491 
0492     /* Check for a _PRW method under this device */
0493 
0494     Status = AcpiUtEvaluateObject (ObjHandle, METHOD_NAME__PRW,
0495                 ACPI_BTYPE_PACKAGE, &PkgDesc);
0496     if (ACPI_FAILURE (Status))
0497     {
0498         /* Ignore all errors from _PRW, we don't want to abort the subsystem */
0499 
0500         return_ACPI_STATUS (AE_OK);
0501     }
0502 
0503     /* The returned _PRW package must have at least two elements */
0504 
0505     if (PkgDesc->Package.Count < 2)
0506     {
0507         goto Cleanup;
0508     }
0509 
0510     /* Extract pointers from the input context */
0511 
0512     GpeDevice = GpeInfo->GpeDevice;
0513     GpeBlock = GpeInfo->GpeBlock;
0514 
0515     /*
0516      * The _PRW object must return a package, we are only interested in the
0517      * first element
0518      */
0519     ObjDesc = PkgDesc->Package.Elements[0];
0520 
0521     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
0522     {
0523         /* Use FADT-defined GPE device (from definition of _PRW) */
0524 
0525         TargetGpeDevice = AcpiGbl_FadtGpeDevice;
0526 
0527         /* Integer is the GPE number in the FADT described GPE blocks */
0528 
0529         GpeNumber = (UINT32) ObjDesc->Integer.Value;
0530     }
0531     else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
0532     {
0533         /* Package contains a GPE reference and GPE number within a GPE block */
0534 
0535         if ((ObjDesc->Package.Count < 2) ||
0536             ((ObjDesc->Package.Elements[0])->Common.Type !=
0537                 ACPI_TYPE_LOCAL_REFERENCE) ||
0538             ((ObjDesc->Package.Elements[1])->Common.Type !=
0539                 ACPI_TYPE_INTEGER))
0540         {
0541             goto Cleanup;
0542         }
0543 
0544         /* Get GPE block reference and decode */
0545 
0546         TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
0547         GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
0548     }
0549     else
0550     {
0551         /* Unknown type, just ignore it */
0552 
0553         goto Cleanup;
0554     }
0555 
0556     /*
0557      * Is this GPE within this block?
0558      *
0559      * TRUE if and only if these conditions are true:
0560      *     1) The GPE devices match.
0561      *     2) The GPE index(number) is within the range of the Gpe Block
0562      *          associated with the GPE device.
0563      */
0564     if ((GpeDevice == TargetGpeDevice) &&
0565         (GpeNumber >= GpeBlock->BlockBaseNumber) &&
0566         (GpeNumber < GpeBlock->BlockBaseNumber +
0567             (GpeBlock->RegisterCount * 8)))
0568     {
0569         GpeEventInfo = &GpeBlock->EventInfo[GpeNumber -
0570             GpeBlock->BlockBaseNumber];
0571 
0572         /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
0573 
0574         GpeEventInfo->Flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
0575 
0576         Status = AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE);
0577         if (ACPI_FAILURE (Status))
0578         {
0579             goto Cleanup;
0580         }
0581 
0582         Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
0583     }
0584 
0585 Cleanup:
0586     AcpiUtRemoveReference (PkgDesc);
0587     return_ACPI_STATUS (AE_OK);
0588 }
0589 
0590 
0591 /*******************************************************************************
0592  *
0593  * FUNCTION:    AcpiEvGetGpeXruptBlock
0594  *
0595  * PARAMETERS:  InterruptNumber      - Interrupt for a GPE block
0596  *
0597  * RETURN:      A GPE interrupt block
0598  *
0599  * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
0600  *              block per unique interrupt level used for GPEs. Should be
0601  *              called only when the GPE lists are semaphore locked and not
0602  *              subject to change.
0603  *
0604  ******************************************************************************/
0605 
0606 static ACPI_GPE_XRUPT_INFO *
0607 AcpiEvGetGpeXruptBlock (
0608     UINT32                  InterruptNumber)
0609 {
0610     ACPI_GPE_XRUPT_INFO     *NextGpeXrupt;
0611     ACPI_GPE_XRUPT_INFO     *GpeXrupt;
0612     ACPI_STATUS             Status;
0613     ACPI_CPU_FLAGS          Flags;
0614 
0615 
0616     ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
0617 
0618 
0619     /* No need for lock since we are not changing any list elements here */
0620 
0621     NextGpeXrupt = AcpiGbl_GpeXruptListHead;
0622     while (NextGpeXrupt)
0623     {
0624         if (NextGpeXrupt->InterruptNumber == InterruptNumber)
0625         {
0626             return_PTR (NextGpeXrupt);
0627         }
0628 
0629         NextGpeXrupt = NextGpeXrupt->Next;
0630     }
0631 
0632     /* Not found, must allocate a new xrupt descriptor */
0633 
0634     GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
0635     if (!GpeXrupt)
0636     {
0637         return_PTR (NULL);
0638     }
0639 
0640     GpeXrupt->InterruptNumber = InterruptNumber;
0641 
0642     /* Install new interrupt descriptor with spin lock */
0643 
0644     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
0645     if (AcpiGbl_GpeXruptListHead)
0646     {
0647         NextGpeXrupt = AcpiGbl_GpeXruptListHead;
0648         while (NextGpeXrupt->Next)
0649         {
0650             NextGpeXrupt = NextGpeXrupt->Next;
0651         }
0652 
0653         NextGpeXrupt->Next = GpeXrupt;
0654         GpeXrupt->Previous = NextGpeXrupt;
0655     }
0656     else
0657     {
0658         AcpiGbl_GpeXruptListHead = GpeXrupt;
0659     }
0660     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
0661 
0662     /* Install new interrupt handler if not SCI_INT */
0663 
0664     if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
0665     {
0666         Status = AcpiOsInstallInterruptHandler (InterruptNumber,
0667                     AcpiEvGpeXruptHandler, GpeXrupt);
0668         if (ACPI_FAILURE (Status))
0669         {
0670             ACPI_ERROR ((AE_INFO,
0671                 "Could not install GPE interrupt handler at level 0x%X",
0672                 InterruptNumber));
0673             return_PTR (NULL);
0674         }
0675     }
0676 
0677     return_PTR (GpeXrupt);
0678 }
0679 
0680 
0681 /*******************************************************************************
0682  *
0683  * FUNCTION:    AcpiEvDeleteGpeXrupt
0684  *
0685  * PARAMETERS:  GpeXrupt        - A GPE interrupt info block
0686  *
0687  * RETURN:      Status
0688  *
0689  * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
0690  *              interrupt handler if not the SCI interrupt.
0691  *
0692  ******************************************************************************/
0693 
0694 static ACPI_STATUS
0695 AcpiEvDeleteGpeXrupt (
0696     ACPI_GPE_XRUPT_INFO     *GpeXrupt)
0697 {
0698     ACPI_STATUS             Status;
0699     ACPI_CPU_FLAGS          Flags;
0700 
0701 
0702     ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt);
0703 
0704 
0705     /* We never want to remove the SCI interrupt handler */
0706 
0707     if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt)
0708     {
0709         GpeXrupt->GpeBlockListHead = NULL;
0710         return_ACPI_STATUS (AE_OK);
0711     }
0712 
0713     /* Disable this interrupt */
0714 
0715     Status = AcpiOsRemoveInterruptHandler (
0716                 GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler);
0717     if (ACPI_FAILURE (Status))
0718     {
0719         return_ACPI_STATUS (Status);
0720     }
0721 
0722     /* Unlink the interrupt block with lock */
0723 
0724     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
0725     if (GpeXrupt->Previous)
0726     {
0727         GpeXrupt->Previous->Next = GpeXrupt->Next;
0728     }
0729     else
0730     {
0731         /* No previous, update list head */
0732 
0733         AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
0734     }
0735 
0736     if (GpeXrupt->Next)
0737     {
0738         GpeXrupt->Next->Previous = GpeXrupt->Previous;
0739     }
0740     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
0741 
0742     /* Free the block */
0743 
0744     ACPI_FREE (GpeXrupt);
0745     return_ACPI_STATUS (AE_OK);
0746 }
0747 
0748 
0749 /*******************************************************************************
0750  *
0751  * FUNCTION:    AcpiEvInstallGpeBlock
0752  *
0753  * PARAMETERS:  GpeBlock                - New GPE block
0754  *              InterruptNumber         - Xrupt to be associated with this
0755  *                                        GPE block
0756  *
0757  * RETURN:      Status
0758  *
0759  * DESCRIPTION: Install new GPE block with mutex support
0760  *
0761  ******************************************************************************/
0762 
0763 static ACPI_STATUS
0764 AcpiEvInstallGpeBlock (
0765     ACPI_GPE_BLOCK_INFO     *GpeBlock,
0766     UINT32                  InterruptNumber)
0767 {
0768     ACPI_GPE_BLOCK_INFO     *NextGpeBlock;
0769     ACPI_GPE_XRUPT_INFO     *GpeXruptBlock;
0770     ACPI_STATUS             Status;
0771     ACPI_CPU_FLAGS          Flags;
0772 
0773 
0774     ACPI_FUNCTION_TRACE (EvInstallGpeBlock);
0775 
0776 
0777     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
0778     if (ACPI_FAILURE (Status))
0779     {
0780         return_ACPI_STATUS (Status);
0781     }
0782 
0783     GpeXruptBlock = AcpiEvGetGpeXruptBlock (InterruptNumber);
0784     if (!GpeXruptBlock)
0785     {
0786         Status = AE_NO_MEMORY;
0787         goto UnlockAndExit;
0788     }
0789 
0790     /* Install the new block at the end of the list with lock */
0791 
0792     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
0793     if (GpeXruptBlock->GpeBlockListHead)
0794     {
0795         NextGpeBlock = GpeXruptBlock->GpeBlockListHead;
0796         while (NextGpeBlock->Next)
0797         {
0798             NextGpeBlock = NextGpeBlock->Next;
0799         }
0800 
0801         NextGpeBlock->Next = GpeBlock;
0802         GpeBlock->Previous = NextGpeBlock;
0803     }
0804     else
0805     {
0806         GpeXruptBlock->GpeBlockListHead = GpeBlock;
0807     }
0808 
0809     GpeBlock->XruptBlock = GpeXruptBlock;
0810     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
0811 
0812 
0813 UnlockAndExit:
0814     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
0815     return_ACPI_STATUS (Status);
0816 }
0817 
0818 
0819 /*******************************************************************************
0820  *
0821  * FUNCTION:    AcpiEvDeleteGpeBlock
0822  *
0823  * PARAMETERS:  GpeBlock            - Existing GPE block
0824  *
0825  * RETURN:      Status
0826  *
0827  * DESCRIPTION: Remove a GPE block
0828  *
0829  ******************************************************************************/
0830 
0831 ACPI_STATUS
0832 AcpiEvDeleteGpeBlock (
0833     ACPI_GPE_BLOCK_INFO     *GpeBlock)
0834 {
0835     ACPI_STATUS             Status;
0836     ACPI_CPU_FLAGS          Flags;
0837 
0838 
0839     ACPI_FUNCTION_TRACE (EvInstallGpeBlock);
0840 
0841 
0842     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
0843     if (ACPI_FAILURE (Status))
0844     {
0845         return_ACPI_STATUS (Status);
0846     }
0847 
0848     /* Disable all GPEs in this block */
0849 
0850     Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL);
0851 
0852     if (!GpeBlock->Previous && !GpeBlock->Next)
0853     {
0854         /* This is the last GpeBlock on this interrupt */
0855 
0856         Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock);
0857         if (ACPI_FAILURE (Status))
0858         {
0859             goto UnlockAndExit;
0860         }
0861     }
0862     else
0863     {
0864         /* Remove the block on this interrupt with lock */
0865 
0866         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
0867         if (GpeBlock->Previous)
0868         {
0869             GpeBlock->Previous->Next = GpeBlock->Next;
0870         }
0871         else
0872         {
0873             GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next;
0874         }
0875 
0876         if (GpeBlock->Next)
0877         {
0878             GpeBlock->Next->Previous = GpeBlock->Previous;
0879         }
0880         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
0881     }
0882 
0883     AcpiCurrentGpeCount -= GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH;
0884 
0885     /* Free the GpeBlock */
0886 
0887     ACPI_FREE (GpeBlock->RegisterInfo);
0888     ACPI_FREE (GpeBlock->EventInfo);
0889     ACPI_FREE (GpeBlock);
0890 
0891 UnlockAndExit:
0892     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
0893     return_ACPI_STATUS (Status);
0894 }
0895 
0896 
0897 /*******************************************************************************
0898  *
0899  * FUNCTION:    AcpiEvCreateGpeInfoBlocks
0900  *
0901  * PARAMETERS:  GpeBlock    - New GPE block
0902  *
0903  * RETURN:      Status
0904  *
0905  * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block
0906  *
0907  ******************************************************************************/
0908 
0909 static ACPI_STATUS
0910 AcpiEvCreateGpeInfoBlocks (
0911     ACPI_GPE_BLOCK_INFO     *GpeBlock)
0912 {
0913     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo = NULL;
0914     ACPI_GPE_EVENT_INFO     *GpeEventInfo = NULL;
0915     ACPI_GPE_EVENT_INFO     *ThisEvent;
0916     ACPI_GPE_REGISTER_INFO  *ThisRegister;
0917     UINT32                  i;
0918     UINT32                  j;
0919     ACPI_STATUS             Status;
0920 
0921 
0922     ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks);
0923 
0924 
0925     /* Allocate the GPE register information block */
0926 
0927     GpeRegisterInfo = ACPI_ALLOCATE_ZEROED (
0928                             (ACPI_SIZE) GpeBlock->RegisterCount *
0929                             sizeof (ACPI_GPE_REGISTER_INFO));
0930     if (!GpeRegisterInfo)
0931     {
0932         ACPI_ERROR ((AE_INFO,
0933             "Could not allocate the GpeRegisterInfo table"));
0934         return_ACPI_STATUS (AE_NO_MEMORY);
0935     }
0936 
0937     /*
0938      * Allocate the GPE EventInfo block. There are eight distinct GPEs
0939      * per register. Initialization to zeros is sufficient.
0940      */
0941     GpeEventInfo = ACPI_ALLOCATE_ZEROED (
0942                         ((ACPI_SIZE) GpeBlock->RegisterCount *
0943                         ACPI_GPE_REGISTER_WIDTH) *
0944                         sizeof (ACPI_GPE_EVENT_INFO));
0945     if (!GpeEventInfo)
0946     {
0947         ACPI_ERROR ((AE_INFO,
0948             "Could not allocate the GpeEventInfo table"));
0949         Status = AE_NO_MEMORY;
0950         goto ErrorExit;
0951     }
0952 
0953     /* Save the new Info arrays in the GPE block */
0954 
0955     GpeBlock->RegisterInfo = GpeRegisterInfo;
0956     GpeBlock->EventInfo    = GpeEventInfo;
0957 
0958     /*
0959      * Initialize the GPE Register and Event structures. A goal of these
0960      * tables is to hide the fact that there are two separate GPE register
0961      * sets in a given GPE hardware block, the status registers occupy the
0962      * first half, and the enable registers occupy the second half.
0963      */
0964     ThisRegister = GpeRegisterInfo;
0965     ThisEvent    = GpeEventInfo;
0966 
0967     for (i = 0; i < GpeBlock->RegisterCount; i++)
0968     {
0969         /* Init the RegisterInfo for this GPE register (8 GPEs) */
0970 
0971         ThisRegister->BaseGpeNumber = (UINT8) (GpeBlock->BlockBaseNumber +
0972                                              (i * ACPI_GPE_REGISTER_WIDTH));
0973 
0974         ThisRegister->StatusAddress.Address =
0975             GpeBlock->BlockAddress.Address + i;
0976 
0977         ThisRegister->EnableAddress.Address =
0978             GpeBlock->BlockAddress.Address + i + GpeBlock->RegisterCount;
0979 
0980         ThisRegister->StatusAddress.SpaceId   = GpeBlock->BlockAddress.SpaceId;
0981         ThisRegister->EnableAddress.SpaceId   = GpeBlock->BlockAddress.SpaceId;
0982         ThisRegister->StatusAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
0983         ThisRegister->EnableAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
0984         ThisRegister->StatusAddress.BitOffset = 0;
0985         ThisRegister->EnableAddress.BitOffset = 0;
0986 
0987         /* Init the EventInfo for each GPE within this register */
0988 
0989         for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
0990         {
0991             ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j);
0992             ThisEvent->RegisterInfo = ThisRegister;
0993             ThisEvent++;
0994         }
0995 
0996         /* Disable all GPEs within this register */
0997 
0998         Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress);
0999         if (ACPI_FAILURE (Status))
1000         {
1001             goto ErrorExit;
1002         }
1003 
1004         /* Clear any pending GPE events within this register */
1005 
1006         Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress);
1007         if (ACPI_FAILURE (Status))
1008         {
1009             goto ErrorExit;
1010         }
1011 
1012         ThisRegister++;
1013     }
1014 
1015     return_ACPI_STATUS (AE_OK);
1016 
1017 
1018 ErrorExit:
1019     if (GpeRegisterInfo)
1020     {
1021         ACPI_FREE (GpeRegisterInfo);
1022     }
1023     if (GpeEventInfo)
1024     {
1025         ACPI_FREE (GpeEventInfo);
1026     }
1027 
1028     return_ACPI_STATUS (Status);
1029 }
1030 
1031 
1032 /*******************************************************************************
1033  *
1034  * FUNCTION:    AcpiEvCreateGpeBlock
1035  *
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
1042  *
1043  * RETURN:      Status
1044  *
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.
1048  *
1049  ******************************************************************************/
1050 
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)
1059 {
1060     ACPI_STATUS             Status;
1061     ACPI_GPE_BLOCK_INFO     *GpeBlock;
1062 
1063 
1064     ACPI_FUNCTION_TRACE (EvCreateGpeBlock);
1065 
1066 
1067     if (!RegisterCount)
1068     {
1069         return_ACPI_STATUS (AE_OK);
1070     }
1071 
1072     /* Allocate a new GPE block */
1073 
1074     GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO));
1075     if (!GpeBlock)
1076     {
1077         return_ACPI_STATUS (AE_NO_MEMORY);
1078     }
1079 
1080     /* Initialize the new GPE block */
1081 
1082     GpeBlock->Node = GpeDevice;
1083     GpeBlock->RegisterCount = RegisterCount;
1084     GpeBlock->BlockBaseNumber = GpeBlockBaseNumber;
1085 
1086     ACPI_MEMCPY (&GpeBlock->BlockAddress, GpeBlockAddress,
1087         sizeof (ACPI_GENERIC_ADDRESS));
1088 
1089     /*
1090      * Create the RegisterInfo and EventInfo sub-structures
1091      * Note: disables and clears all GPEs in the block
1092      */
1093     Status = AcpiEvCreateGpeInfoBlocks (GpeBlock);
1094     if (ACPI_FAILURE (Status))
1095     {
1096         ACPI_FREE (GpeBlock);
1097         return_ACPI_STATUS (Status);
1098     }
1099 
1100     /* Install the new block in the global lists */
1101 
1102     Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber);
1103     if (ACPI_FAILURE (Status))
1104     {
1105         ACPI_FREE (GpeBlock);
1106         return_ACPI_STATUS (Status);
1107     }
1108 
1109     /* Find all GPE methods (_Lxx, _Exx) for this block */
1110 
1111     Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
1112                 ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
1113                 AcpiEvSaveMethodInfo, GpeBlock, NULL);
1114 
1115     /* Return the new block */
1116 
1117     if (ReturnGpeBlock)
1118     {
1119         (*ReturnGpeBlock) = GpeBlock;
1120     }
1121 
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));
1130 
1131     /* Update global count of currently available GPEs */
1132 
1133     AcpiCurrentGpeCount += RegisterCount * ACPI_GPE_REGISTER_WIDTH;
1134     return_ACPI_STATUS (AE_OK);
1135 }
1136 
1137 
1138 /*******************************************************************************
1139  *
1140  * FUNCTION:    AcpiEvInitializeGpeBlock
1141  *
1142  * PARAMETERS:  GpeDevice           - Handle to the parent GPE block
1143  *              GpeBlock            - Gpe Block info
1144  *
1145  * RETURN:      Status
1146  *
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.
1151  *
1152  ******************************************************************************/
1153 
1154 ACPI_STATUS
1155 AcpiEvInitializeGpeBlock (
1156     ACPI_NAMESPACE_NODE     *GpeDevice,
1157     ACPI_GPE_BLOCK_INFO     *GpeBlock)
1158 {
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;
1166 
1167 
1168     ACPI_FUNCTION_TRACE (EvInitializeGpeBlock);
1169 
1170 
1171     /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
1172 
1173     if (!GpeBlock)
1174     {
1175         return_ACPI_STATUS (AE_OK);
1176     }
1177 
1178     /*
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.
1181      */
1182     if (AcpiGbl_LeaveWakeGpesDisabled)
1183     {
1184         /*
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.
1189          */
1190         GpeInfo.GpeBlock = GpeBlock;
1191         GpeInfo.GpeDevice = GpeDevice;
1192 
1193         Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1194                     ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
1195                     AcpiEvMatchPrwAndGpe, &GpeInfo, NULL);
1196     }
1197 
1198     /*
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
1202      *
1203      * Any other GPEs within this block must be enabled via the
1204      * AcpiEnableGpe() external interface.
1205      */
1206     WakeGpeCount = 0;
1207     GpeEnabledCount = 0;
1208 
1209     for (i = 0; i < GpeBlock->RegisterCount; i++)
1210     {
1211         for (j = 0; j < 8; j++)
1212         {
1213             /* Get the info block for this particular GPE */
1214 
1215             GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
1216                 ACPI_GPE_REGISTER_WIDTH) + j];
1217 
1218             if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
1219                     ACPI_GPE_DISPATCH_METHOD) &&
1220                  (GpeEventInfo->Flags & ACPI_GPE_TYPE_RUNTIME))
1221             {
1222                 GpeEnabledCount++;
1223             }
1224 
1225             if (GpeEventInfo->Flags & ACPI_GPE_TYPE_WAKE)
1226             {
1227                 WakeGpeCount++;
1228             }
1229         }
1230     }
1231 
1232     ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
1233         "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
1234         WakeGpeCount, GpeEnabledCount));
1235 
1236     /* Enable all valid runtime GPEs found above */
1237 
1238     Status = AcpiHwEnableRuntimeGpeBlock (NULL, GpeBlock, NULL);
1239     if (ACPI_FAILURE (Status))
1240     {
1241         ACPI_ERROR ((AE_INFO, "Could not enable GPEs in GpeBlock %p",
1242             GpeBlock));
1243     }
1244 
1245     return_ACPI_STATUS (Status);
1246 }
1247 
1248 
1249 /*******************************************************************************
1250  *
1251  * FUNCTION:    AcpiEvGpeInitialize
1252  *
1253  * PARAMETERS:  None
1254  *
1255  * RETURN:      Status
1256  *
1257  * DESCRIPTION: Initialize the GPE data structures
1258  *
1259  ******************************************************************************/
1260 
1261 ACPI_STATUS
1262 AcpiEvGpeInitialize (
1263     void)
1264 {
1265     UINT32                  RegisterCount0 = 0;
1266     UINT32                  RegisterCount1 = 0;
1267     UINT32                  GpeNumberMax = 0;
1268     ACPI_STATUS             Status;
1269 
1270 
1271     ACPI_FUNCTION_TRACE (EvGpeInitialize);
1272 
1273 
1274     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1275     if (ACPI_FAILURE (Status))
1276     {
1277         return_ACPI_STATUS (Status);
1278     }
1279 
1280     /*
1281      * Initialize the GPE Block(s) defined in the FADT
1282      *
1283      * Why the GPE register block lengths are divided by 2:  From the ACPI
1284      * Spec, section "General-Purpose Event Registers", we have:
1285      *
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."
1294      */
1295 
1296     /*
1297      * Determine the maximum GPE number for this machine.
1298      *
1299      * Note: both GPE0 and GPE1 are optional, and either can exist without
1300      * the other.
1301      *
1302      * If EITHER the register length OR the block address are zero, then that
1303      * particular block is not supported.
1304      */
1305     if (AcpiGbl_FADT.Gpe0BlockLength &&
1306         AcpiGbl_FADT.XGpe0Block.Address)
1307     {
1308         /* GPE block 0 exists (has both length and address > 0) */
1309 
1310         RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2);
1311 
1312         GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1;
1313 
1314         /* Install GPE Block 0 */
1315 
1316         Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
1317                     &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0,
1318                     AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]);
1319 
1320         if (ACPI_FAILURE (Status))
1321         {
1322             ACPI_EXCEPTION ((AE_INFO, Status,
1323                 "Could not create GPE Block 0"));
1324         }
1325     }
1326 
1327     if (AcpiGbl_FADT.Gpe1BlockLength &&
1328         AcpiGbl_FADT.XGpe1Block.Address)
1329     {
1330         /* GPE block 1 exists (has both length and address > 0) */
1331 
1332         RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2);
1333 
1334         /* Check for GPE0/GPE1 overlap (if both banks exist) */
1335 
1336         if ((RegisterCount0) &&
1337             (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base))
1338         {
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)));
1345 
1346             /* Ignore GPE1 block by setting the register count to zero */
1347 
1348             RegisterCount1 = 0;
1349         }
1350         else
1351         {
1352             /* Install GPE Block 1 */
1353 
1354             Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
1355                         &AcpiGbl_FADT.XGpe1Block, RegisterCount1,
1356                         AcpiGbl_FADT.Gpe1Base,
1357                         AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]);
1358 
1359             if (ACPI_FAILURE (Status))
1360             {
1361                 ACPI_EXCEPTION ((AE_INFO, Status,
1362                     "Could not create GPE Block 1"));
1363             }
1364 
1365             /*
1366              * GPE0 and GPE1 do not have to be contiguous in the GPE number
1367              * space. However, GPE0 always starts at GPE number zero.
1368              */
1369             GpeNumberMax = AcpiGbl_FADT.Gpe1Base +
1370                             ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1);
1371         }
1372     }
1373 
1374     /* Exit if there are no GPE registers */
1375 
1376     if ((RegisterCount0 + RegisterCount1) == 0)
1377     {
1378         /* GPEs are not required by ACPI, this is OK */
1379 
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;
1384     }
1385 
1386     /* Check for Max GPE number out-of-range */
1387 
1388     if (GpeNumberMax > ACPI_GPE_MAX)
1389     {
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;
1395     }
1396 
1397 Cleanup:
1398     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1399     return_ACPI_STATUS (AE_OK);
1400 }
1401 
1402