ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

evgpeinit.c
Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * Module Name: evgpeinit - System GPE initialization and update
00004  *
00005  *****************************************************************************/
00006 
00007 /******************************************************************************
00008  *
00009  * 1. Copyright Notice
00010  *
00011  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
00012  * All rights reserved.
00013  *
00014  * 2. License
00015  *
00016  * 2.1. This is your license from Intel Corp. under its intellectual property
00017  * rights.  You may have additional license terms from the party that provided
00018  * you this software, covering your right to use that party's intellectual
00019  * property rights.
00020  *
00021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
00022  * copy of the source code appearing in this file ("Covered Code") an
00023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
00024  * base code distributed originally by Intel ("Original Intel Code") to copy,
00025  * make derivatives, distribute, use and display any portion of the Covered
00026  * Code in any form, with the right to sublicense such rights; and
00027  *
00028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
00029  * license (with the right to sublicense), under only those claims of Intel
00030  * patents that are infringed by the Original Intel Code, to make, use, sell,
00031  * offer to sell, and import the Covered Code and derivative works thereof
00032  * solely to the minimum extent necessary to exercise the above copyright
00033  * license, and in no event shall the patent license extend to any additions
00034  * to or modifications of the Original Intel Code.  No other license or right
00035  * is granted directly or by implication, estoppel or otherwise;
00036  *
00037  * The above copyright and patent license is granted only if the following
00038  * conditions are met:
00039  *
00040  * 3. Conditions
00041  *
00042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
00043  * Redistribution of source code of any substantial portion of the Covered
00044  * Code or modification with rights to further distribute source must include
00045  * the above Copyright Notice, the above License, this list of Conditions,
00046  * and the following Disclaimer and Export Compliance provision.  In addition,
00047  * Licensee must cause all Covered Code to which Licensee contributes to
00048  * contain a file documenting the changes Licensee made to create that Covered
00049  * Code and the date of any change.  Licensee must include in that file the
00050  * documentation of any changes made by any predecessor Licensee.  Licensee
00051  * must include a prominent statement that the modification is derived,
00052  * directly or indirectly, from Original Intel Code.
00053  *
00054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
00055  * Redistribution of source code of any substantial portion of the Covered
00056  * Code or modification without rights to further distribute source must
00057  * include the following Disclaimer and Export Compliance provision in the
00058  * documentation and/or other materials provided with distribution.  In
00059  * addition, Licensee may not authorize further sublicense of source of any
00060  * portion of the Covered Code, and must include terms to the effect that the
00061  * license from Licensee to its licensee is limited to the intellectual
00062  * property embodied in the software Licensee provides to its licensee, and
00063  * not to intellectual property embodied in modifications its licensee may
00064  * make.
00065  *
00066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
00067  * substantial portion of the Covered Code or modification must reproduce the
00068  * above Copyright Notice, and the following Disclaimer and Export Compliance
00069  * provision in the documentation and/or other materials provided with the
00070  * distribution.
00071  *
00072  * 3.4. Intel retains all right, title, and interest in and to the Original
00073  * Intel Code.
00074  *
00075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
00076  * Intel shall be used in advertising or otherwise to promote the sale, use or
00077  * other dealings in products derived from or relating to the Covered Code
00078  * without prior written authorization from Intel.
00079  *
00080  * 4. Disclaimer and Export Compliance
00081  *
00082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
00083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
00084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
00085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
00086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
00087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
00088  * PARTICULAR PURPOSE.
00089  *
00090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
00091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
00092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
00093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
00094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
00095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
00096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
00097  * LIMITED REMEDY.
00098  *
00099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
00100  * software or system incorporating such software without first obtaining any
00101  * required license or other approval from the U. S. Department of Commerce or
00102  * any other agency or department of the United States Government.  In the
00103  * event Licensee exports any such software from the United States or
00104  * re-exports any such software from a foreign destination, Licensee shall
00105  * ensure that the distribution and export/re-export of the software is in
00106  * compliance with all laws, regulations, orders, or other restrictions of the
00107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
00108  * any of its subsidiaries will export/re-export any technical data, process,
00109  * software, or service, directly or indirectly, to any country for which the
00110  * United States government or any agency thereof requires an export license,
00111  * other governmental approval, or letter of assurance, without first obtaining
00112  * such license, approval or letter.
00113  *
00114  *****************************************************************************/
00115 
00116 
00117 #include "acpi.h"
00118 #include "accommon.h"
00119 #include "acevents.h"
00120 #include "acnamesp.h"
00121 
00122 #define _COMPONENT          ACPI_EVENTS
00123         ACPI_MODULE_NAME    ("evgpeinit")
00124 
00125 
00126 /*
00127  * Note: History of _PRW support in ACPICA
00128  *
00129  * Originally (2000 - 2010), the GPE initialization code performed a walk of
00130  * the entire namespace to execute the _PRW methods and detect all GPEs
00131  * capable of waking the system.
00132  *
00133  * As of 10/2010, the _PRW method execution has been removed since it is
00134  * actually unnecessary. The host OS must in fact execute all _PRW methods
00135  * in order to identify the device/power-resource dependencies. We now put
00136  * the onus on the host OS to identify the wake GPEs as part of this process
00137  * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This
00138  * not only reduces the complexity of the ACPICA initialization code, but in
00139  * some cases (on systems with very large namespaces) it should reduce the
00140  * kernel boot time as well.
00141  */
00142 
00143 /*******************************************************************************
00144  *
00145  * FUNCTION:    AcpiEvGpeInitialize
00146  *
00147  * PARAMETERS:  None
00148  *
00149  * RETURN:      Status
00150  *
00151  * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks
00152  *
00153  ******************************************************************************/
00154 
00155 ACPI_STATUS
00156 AcpiEvGpeInitialize (
00157     void)
00158 {
00159     UINT32                  RegisterCount0 = 0;
00160     UINT32                  RegisterCount1 = 0;
00161     UINT32                  GpeNumberMax = 0;
00162     ACPI_STATUS             Status;
00163 
00164 
00165     ACPI_FUNCTION_TRACE (EvGpeInitialize);
00166 
00167 
00168     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
00169     if (ACPI_FAILURE (Status))
00170     {
00171         return_ACPI_STATUS (Status);
00172     }
00173 
00174     /*
00175      * Initialize the GPE Block(s) defined in the FADT
00176      *
00177      * Why the GPE register block lengths are divided by 2:  From the ACPI
00178      * Spec, section "General-Purpose Event Registers", we have:
00179      *
00180      * "Each register block contains two registers of equal length
00181      *  GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
00182      *  GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
00183      *  The length of the GPE1_STS and GPE1_EN registers is equal to
00184      *  half the GPE1_LEN. If a generic register block is not supported
00185      *  then its respective block pointer and block length values in the
00186      *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
00187      *  to be the same size."
00188      */
00189 
00190     /*
00191      * Determine the maximum GPE number for this machine.
00192      *
00193      * Note: both GPE0 and GPE1 are optional, and either can exist without
00194      * the other.
00195      *
00196      * If EITHER the register length OR the block address are zero, then that
00197      * particular block is not supported.
00198      */
00199     if (AcpiGbl_FADT.Gpe0BlockLength &&
00200         AcpiGbl_FADT.XGpe0Block.Address)
00201     {
00202         /* GPE block 0 exists (has both length and address > 0) */
00203 
00204         RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2);
00205 
00206         GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1;
00207 
00208         /* Install GPE Block 0 */
00209 
00210         Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
00211                     &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0,
00212                     AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]);
00213 
00214         if (ACPI_FAILURE (Status))
00215         {
00216             ACPI_EXCEPTION ((AE_INFO, Status,
00217                 "Could not create GPE Block 0"));
00218         }
00219     }
00220 
00221     if (AcpiGbl_FADT.Gpe1BlockLength &&
00222         AcpiGbl_FADT.XGpe1Block.Address)
00223     {
00224         /* GPE block 1 exists (has both length and address > 0) */
00225 
00226         RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2);
00227 
00228         /* Check for GPE0/GPE1 overlap (if both banks exist) */
00229 
00230         if ((RegisterCount0) &&
00231             (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base))
00232         {
00233             ACPI_ERROR ((AE_INFO,
00234                 "GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
00235                 "(GPE %u to %u) - Ignoring GPE1",
00236                 GpeNumberMax, AcpiGbl_FADT.Gpe1Base,
00237                 AcpiGbl_FADT.Gpe1Base +
00238                 ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
00239 
00240             /* Ignore GPE1 block by setting the register count to zero */
00241 
00242             RegisterCount1 = 0;
00243         }
00244         else
00245         {
00246             /* Install GPE Block 1 */
00247 
00248             Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
00249                         &AcpiGbl_FADT.XGpe1Block, RegisterCount1,
00250                         AcpiGbl_FADT.Gpe1Base,
00251                         AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]);
00252 
00253             if (ACPI_FAILURE (Status))
00254             {
00255                 ACPI_EXCEPTION ((AE_INFO, Status,
00256                     "Could not create GPE Block 1"));
00257             }
00258 
00259             /*
00260              * GPE0 and GPE1 do not have to be contiguous in the GPE number
00261              * space. However, GPE0 always starts at GPE number zero.
00262              */
00263             GpeNumberMax = AcpiGbl_FADT.Gpe1Base +
00264                             ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1);
00265         }
00266     }
00267 
00268     /* Exit if there are no GPE registers */
00269 
00270     if ((RegisterCount0 + RegisterCount1) == 0)
00271     {
00272         /* GPEs are not required by ACPI, this is OK */
00273 
00274         ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
00275             "There are no GPE blocks defined in the FADT\n"));
00276         Status = AE_OK;
00277         goto Cleanup;
00278     }
00279 
00280     /* Check for Max GPE number out-of-range */
00281 
00282     if (GpeNumberMax > ACPI_GPE_MAX)
00283     {
00284         ACPI_ERROR ((AE_INFO,
00285             "Maximum GPE number from FADT is too large: 0x%X",
00286             GpeNumberMax));
00287         Status = AE_BAD_VALUE;
00288         goto Cleanup;
00289     }
00290 
00291 Cleanup:
00292     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
00293     return_ACPI_STATUS (AE_OK);
00294 }
00295 
00296 
00297 /*******************************************************************************
00298  *
00299  * FUNCTION:    AcpiEvUpdateGpes
00300  *
00301  * PARAMETERS:  TableOwnerId        - ID of the newly-loaded ACPI table
00302  *
00303  * RETURN:      None
00304  *
00305  * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
00306  *              result of a Load() or LoadTable() operation. If new GPE
00307  *              methods have been installed, register the new methods.
00308  *
00309  ******************************************************************************/
00310 
00311 void
00312 AcpiEvUpdateGpes (
00313     ACPI_OWNER_ID           TableOwnerId)
00314 {
00315     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
00316     ACPI_GPE_BLOCK_INFO     *GpeBlock;
00317     ACPI_GPE_WALK_INFO      WalkInfo;
00318     ACPI_STATUS             Status = AE_OK;
00319 
00320 
00321     /*
00322      * Find any _Lxx/_Exx GPE methods that have just been loaded.
00323      *
00324      * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
00325      * enabled.
00326      *
00327      * Examine the namespace underneath each GpeDevice within the
00328      * GpeBlock lists.
00329      */
00330     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
00331     if (ACPI_FAILURE (Status))
00332     {
00333         return;
00334     }
00335 
00336     WalkInfo.Count = 0;
00337     WalkInfo.OwnerId = TableOwnerId;
00338     WalkInfo.ExecuteByOwnerId = TRUE;
00339 
00340     /* Walk the interrupt level descriptor list */
00341 
00342     GpeXruptInfo = AcpiGbl_GpeXruptListHead;
00343     while (GpeXruptInfo)
00344     {
00345         /* Walk all Gpe Blocks attached to this interrupt level */
00346 
00347         GpeBlock = GpeXruptInfo->GpeBlockListHead;
00348         while (GpeBlock)
00349         {
00350             WalkInfo.GpeBlock = GpeBlock;
00351             WalkInfo.GpeDevice = GpeBlock->Node;
00352 
00353             Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD,
00354                         WalkInfo.GpeDevice, ACPI_UINT32_MAX,
00355                         ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod,
00356                         NULL, &WalkInfo, NULL);
00357             if (ACPI_FAILURE (Status))
00358             {
00359                 ACPI_EXCEPTION ((AE_INFO, Status,
00360                     "While decoding _Lxx/_Exx methods"));
00361             }
00362 
00363             GpeBlock = GpeBlock->Next;
00364         }
00365 
00366         GpeXruptInfo = GpeXruptInfo->Next;
00367     }
00368 
00369     if (WalkInfo.Count)
00370     {
00371         ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count));
00372     }
00373 
00374     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
00375     return;
00376 }
00377 
00378 
00379 /*******************************************************************************
00380  *
00381  * FUNCTION:    AcpiEvMatchGpeMethod
00382  *
00383  * PARAMETERS:  Callback from WalkNamespace
00384  *
00385  * RETURN:      Status
00386  *
00387  * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
00388  *              control method under the _GPE portion of the namespace.
00389  *              Extract the name and GPE type from the object, saving this
00390  *              information for quick lookup during GPE dispatch. Allows a
00391  *              per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the
00392  *              WalkInfo parameter block.
00393  *
00394  *              The name of each GPE control method is of the form:
00395  *              "_Lxx" or "_Exx", where:
00396  *                  L      - means that the GPE is level triggered
00397  *                  E      - means that the GPE is edge triggered
00398  *                  xx     - is the GPE number [in HEX]
00399  *
00400  * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods
00401  * with that owner.
00402  *
00403  ******************************************************************************/
00404 
00405 ACPI_STATUS
00406 AcpiEvMatchGpeMethod (
00407     ACPI_HANDLE             ObjHandle,
00408     UINT32                  Level,
00409     void                    *Context,
00410     void                    **ReturnValue)
00411 {
00412     ACPI_NAMESPACE_NODE     *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
00413     ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
00414     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
00415     UINT32                  GpeNumber;
00416     char                    Name[ACPI_NAME_SIZE + 1];
00417     UINT8                   Type;
00418 
00419 
00420     ACPI_FUNCTION_TRACE (EvMatchGpeMethod);
00421 
00422 
00423     /* Check if requested OwnerId matches this OwnerId */
00424 
00425     if ((WalkInfo->ExecuteByOwnerId) &&
00426         (MethodNode->OwnerId != WalkInfo->OwnerId))
00427     {
00428         return_ACPI_STATUS (AE_OK);
00429     }
00430 
00431     /*
00432      * Match and decode the _Lxx and _Exx GPE method names
00433      *
00434      * 1) Extract the method name and null terminate it
00435      */
00436     ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer);
00437     Name[ACPI_NAME_SIZE] = 0;
00438 
00439     /* 2) Name must begin with an underscore */
00440 
00441     if (Name[0] != '_')
00442     {
00443         return_ACPI_STATUS (AE_OK); /* Ignore this method */
00444     }
00445 
00446     /*
00447      * 3) Edge/Level determination is based on the 2nd character
00448      *    of the method name
00449      */
00450     switch (Name[1])
00451     {
00452     case 'L':
00453         Type = ACPI_GPE_LEVEL_TRIGGERED;
00454         break;
00455 
00456     case 'E':
00457         Type = ACPI_GPE_EDGE_TRIGGERED;
00458         break;
00459 
00460     default:
00461         /* Unknown method type, just ignore it */
00462 
00463         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
00464             "Ignoring unknown GPE method type: %s "
00465             "(name not of form _Lxx or _Exx)", Name));
00466         return_ACPI_STATUS (AE_OK);
00467     }
00468 
00469     /* 4) The last two characters of the name are the hex GPE Number */
00470 
00471     GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
00472     if (GpeNumber == ACPI_UINT32_MAX)
00473     {
00474         /* Conversion failed; invalid method, just ignore it */
00475 
00476         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
00477             "Could not extract GPE number from name: %s "
00478             "(name is not of form _Lxx or _Exx)", Name));
00479         return_ACPI_STATUS (AE_OK);
00480     }
00481 
00482     /* Ensure that we have a valid GPE number for this GPE block */
00483 
00484     GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock);
00485     if (!GpeEventInfo)
00486     {
00487         /*
00488          * This GpeNumber is not valid for this GPE block, just ignore it.
00489          * However, it may be valid for a different GPE block, since GPE0
00490          * and GPE1 methods both appear under \_GPE.
00491          */
00492         return_ACPI_STATUS (AE_OK);
00493     }
00494 
00495     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
00496             ACPI_GPE_DISPATCH_HANDLER)
00497     {
00498         /* If there is already a handler, ignore this GPE method */
00499 
00500         return_ACPI_STATUS (AE_OK);
00501     }
00502 
00503     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
00504             ACPI_GPE_DISPATCH_METHOD)
00505     {
00506         /*
00507          * If there is already a method, ignore this method. But check
00508          * for a type mismatch (if both the _Lxx AND _Exx exist)
00509          */
00510         if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
00511         {
00512             ACPI_ERROR ((AE_INFO,
00513                 "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods",
00514                 GpeNumber, GpeNumber, GpeNumber));
00515         }
00516         return_ACPI_STATUS (AE_OK);
00517     }
00518 
00519     /*
00520      * Add the GPE information from above to the GpeEventInfo block for
00521      * use during dispatch of this GPE.
00522      */
00523     GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK);
00524     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD);
00525     GpeEventInfo->Dispatch.MethodNode = MethodNode;
00526 
00527     ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
00528         "Registered GPE method %s as GPE number 0x%.2X\n",
00529         Name, GpeNumber));
00530     return_ACPI_STATUS (AE_OK);
00531 }

Generated on Sun May 27 2012 04:27:15 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.