Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenevgpe.c
Go to the documentation of this file.
00001 /****************************************************************************** 00002 * 00003 * Module Name: evgpe - General Purpose Event handling and dispatch 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 #include "acpi.h" 00117 #include "accommon.h" 00118 #include "acevents.h" 00119 #include "acnamesp.h" 00120 00121 #define _COMPONENT ACPI_EVENTS 00122 ACPI_MODULE_NAME ("evgpe") 00123 00124 /* Local prototypes */ 00125 00126 static void ACPI_SYSTEM_XFACE 00127 AcpiEvAsynchExecuteGpeMethod ( 00128 void *Context); 00129 00130 static void ACPI_SYSTEM_XFACE 00131 AcpiEvAsynchEnableGpe ( 00132 void *Context); 00133 00134 00135 /******************************************************************************* 00136 * 00137 * FUNCTION: AcpiEvUpdateGpeEnableMask 00138 * 00139 * PARAMETERS: GpeEventInfo - GPE to update 00140 * 00141 * RETURN: Status 00142 * 00143 * DESCRIPTION: Updates GPE register enable mask based upon whether there are 00144 * runtime references to this GPE 00145 * 00146 ******************************************************************************/ 00147 00148 ACPI_STATUS 00149 AcpiEvUpdateGpeEnableMask ( 00150 ACPI_GPE_EVENT_INFO *GpeEventInfo) 00151 { 00152 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 00153 UINT32 RegisterBit; 00154 00155 00156 ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask); 00157 00158 00159 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 00160 if (!GpeRegisterInfo) 00161 { 00162 return_ACPI_STATUS (AE_NOT_EXIST); 00163 } 00164 00165 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 00166 00167 /* Clear the run bit up front */ 00168 00169 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 00170 00171 /* Set the mask bit only if there are references to this GPE */ 00172 00173 if (GpeEventInfo->RuntimeCount) 00174 { 00175 ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit); 00176 } 00177 00178 return_ACPI_STATUS (AE_OK); 00179 } 00180 00181 00182 /******************************************************************************* 00183 * 00184 * FUNCTION: AcpiEvEnableGpe 00185 * 00186 * PARAMETERS: GpeEventInfo - GPE to enable 00187 * 00188 * RETURN: Status 00189 * 00190 * DESCRIPTION: Clear a GPE of stale events and enable it. 00191 * 00192 ******************************************************************************/ 00193 00194 ACPI_STATUS 00195 AcpiEvEnableGpe ( 00196 ACPI_GPE_EVENT_INFO *GpeEventInfo) 00197 { 00198 ACPI_STATUS Status; 00199 00200 00201 ACPI_FUNCTION_TRACE (EvEnableGpe); 00202 00203 00204 /* 00205 * We will only allow a GPE to be enabled if it has either an associated 00206 * method (_Lxx/_Exx) or a handler, or is using the implicit notify 00207 * feature. Otherwise, the GPE will be immediately disabled by 00208 * AcpiEvGpeDispatch the first time it fires. 00209 */ 00210 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 00211 ACPI_GPE_DISPATCH_NONE) 00212 { 00213 return_ACPI_STATUS (AE_NO_HANDLER); 00214 } 00215 00216 /* Clear the GPE (of stale events) */ 00217 00218 Status = AcpiHwClearGpe (GpeEventInfo); 00219 if (ACPI_FAILURE (Status)) 00220 { 00221 return_ACPI_STATUS (Status); 00222 } 00223 00224 /* Enable the requested GPE */ 00225 00226 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); 00227 return_ACPI_STATUS (Status); 00228 } 00229 00230 00231 /******************************************************************************* 00232 * 00233 * FUNCTION: AcpiEvAddGpeReference 00234 * 00235 * PARAMETERS: GpeEventInfo - Add a reference to this GPE 00236 * 00237 * RETURN: Status 00238 * 00239 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 00240 * hardware-enabled. 00241 * 00242 ******************************************************************************/ 00243 00244 ACPI_STATUS 00245 AcpiEvAddGpeReference ( 00246 ACPI_GPE_EVENT_INFO *GpeEventInfo) 00247 { 00248 ACPI_STATUS Status = AE_OK; 00249 00250 00251 ACPI_FUNCTION_TRACE (EvAddGpeReference); 00252 00253 00254 if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) 00255 { 00256 return_ACPI_STATUS (AE_LIMIT); 00257 } 00258 00259 GpeEventInfo->RuntimeCount++; 00260 if (GpeEventInfo->RuntimeCount == 1) 00261 { 00262 /* Enable on first reference */ 00263 00264 Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 00265 if (ACPI_SUCCESS (Status)) 00266 { 00267 Status = AcpiEvEnableGpe (GpeEventInfo); 00268 } 00269 00270 if (ACPI_FAILURE (Status)) 00271 { 00272 GpeEventInfo->RuntimeCount--; 00273 } 00274 } 00275 00276 return_ACPI_STATUS (Status); 00277 } 00278 00279 00280 /******************************************************************************* 00281 * 00282 * FUNCTION: AcpiEvRemoveGpeReference 00283 * 00284 * PARAMETERS: GpeEventInfo - Remove a reference to this GPE 00285 * 00286 * RETURN: Status 00287 * 00288 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 00289 * removed, the GPE is hardware-disabled. 00290 * 00291 ******************************************************************************/ 00292 00293 ACPI_STATUS 00294 AcpiEvRemoveGpeReference ( 00295 ACPI_GPE_EVENT_INFO *GpeEventInfo) 00296 { 00297 ACPI_STATUS Status = AE_OK; 00298 00299 00300 ACPI_FUNCTION_TRACE (EvRemoveGpeReference); 00301 00302 00303 if (!GpeEventInfo->RuntimeCount) 00304 { 00305 return_ACPI_STATUS (AE_LIMIT); 00306 } 00307 00308 GpeEventInfo->RuntimeCount--; 00309 if (!GpeEventInfo->RuntimeCount) 00310 { 00311 /* Disable on last reference */ 00312 00313 Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 00314 if (ACPI_SUCCESS (Status)) 00315 { 00316 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 00317 } 00318 00319 if (ACPI_FAILURE (Status)) 00320 { 00321 GpeEventInfo->RuntimeCount++; 00322 } 00323 } 00324 00325 return_ACPI_STATUS (Status); 00326 } 00327 00328 00329 /******************************************************************************* 00330 * 00331 * FUNCTION: AcpiEvLowGetGpeInfo 00332 * 00333 * PARAMETERS: GpeNumber - Raw GPE number 00334 * GpeBlock - A GPE info block 00335 * 00336 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber 00337 * is not within the specified GPE block) 00338 * 00339 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is 00340 * the low-level implementation of EvGetGpeEventInfo. 00341 * 00342 ******************************************************************************/ 00343 00344 ACPI_GPE_EVENT_INFO * 00345 AcpiEvLowGetGpeInfo ( 00346 UINT32 GpeNumber, 00347 ACPI_GPE_BLOCK_INFO *GpeBlock) 00348 { 00349 UINT32 GpeIndex; 00350 00351 00352 /* 00353 * Validate that the GpeNumber is within the specified GpeBlock. 00354 * (Two steps) 00355 */ 00356 if (!GpeBlock || 00357 (GpeNumber < GpeBlock->BlockBaseNumber)) 00358 { 00359 return (NULL); 00360 } 00361 00362 GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; 00363 if (GpeIndex >= GpeBlock->GpeCount) 00364 { 00365 return (NULL); 00366 } 00367 00368 return (&GpeBlock->EventInfo[GpeIndex]); 00369 } 00370 00371 00372 /******************************************************************************* 00373 * 00374 * FUNCTION: AcpiEvGetGpeEventInfo 00375 * 00376 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 00377 * GpeNumber - Raw GPE number 00378 * 00379 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE 00380 * 00381 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. 00382 * Validates the GpeBlock and the GpeNumber 00383 * 00384 * Should be called only when the GPE lists are semaphore locked 00385 * and not subject to change. 00386 * 00387 ******************************************************************************/ 00388 00389 ACPI_GPE_EVENT_INFO * 00390 AcpiEvGetGpeEventInfo ( 00391 ACPI_HANDLE GpeDevice, 00392 UINT32 GpeNumber) 00393 { 00394 ACPI_OPERAND_OBJECT *ObjDesc; 00395 ACPI_GPE_EVENT_INFO *GpeInfo; 00396 UINT32 i; 00397 00398 00399 ACPI_FUNCTION_ENTRY (); 00400 00401 00402 /* A NULL GpeDevice means use the FADT-defined GPE block(s) */ 00403 00404 if (!GpeDevice) 00405 { 00406 /* Examine GPE Block 0 and 1 (These blocks are permanent) */ 00407 00408 for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) 00409 { 00410 GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, 00411 AcpiGbl_GpeFadtBlocks[i]); 00412 if (GpeInfo) 00413 { 00414 return (GpeInfo); 00415 } 00416 } 00417 00418 /* The GpeNumber was not in the range of either FADT GPE block */ 00419 00420 return (NULL); 00421 } 00422 00423 /* A Non-NULL GpeDevice means this is a GPE Block Device */ 00424 00425 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); 00426 if (!ObjDesc || 00427 !ObjDesc->Device.GpeBlock) 00428 { 00429 return (NULL); 00430 } 00431 00432 return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); 00433 } 00434 00435 00436 /******************************************************************************* 00437 * 00438 * FUNCTION: AcpiEvGpeDetect 00439 * 00440 * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. 00441 * Can have multiple GPE blocks attached. 00442 * 00443 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 00444 * 00445 * DESCRIPTION: Detect if any GP events have occurred. This function is 00446 * executed at interrupt level. 00447 * 00448 ******************************************************************************/ 00449 00450 UINT32 00451 AcpiEvGpeDetect ( 00452 ACPI_GPE_XRUPT_INFO *GpeXruptList) 00453 { 00454 ACPI_STATUS Status; 00455 ACPI_GPE_BLOCK_INFO *GpeBlock; 00456 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 00457 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 00458 UINT8 EnabledStatusByte; 00459 UINT32 StatusReg; 00460 UINT32 EnableReg; 00461 ACPI_CPU_FLAGS Flags; 00462 UINT32 i; 00463 UINT32 j; 00464 00465 00466 ACPI_FUNCTION_NAME (EvGpeDetect); 00467 00468 /* Check for the case where there are no GPEs */ 00469 00470 if (!GpeXruptList) 00471 { 00472 return (IntStatus); 00473 } 00474 00475 /* 00476 * We need to obtain the GPE lock for both the data structs and registers 00477 * Note: Not necessary to obtain the hardware lock, since the GPE 00478 * registers are owned by the GpeLock. 00479 */ 00480 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 00481 00482 /* Examine all GPE blocks attached to this interrupt level */ 00483 00484 GpeBlock = GpeXruptList->GpeBlockListHead; 00485 while (GpeBlock) 00486 { 00487 /* 00488 * Read all of the 8-bit GPE status and enable registers in this GPE 00489 * block, saving all of them. Find all currently active GP events. 00490 */ 00491 for (i = 0; i < GpeBlock->RegisterCount; i++) 00492 { 00493 /* Get the next status/enable pair */ 00494 00495 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 00496 00497 /* 00498 * Optimization: If there are no GPEs enabled within this 00499 * register, we can safely ignore the entire register. 00500 */ 00501 if (!(GpeRegisterInfo->EnableForRun | 00502 GpeRegisterInfo->EnableForWake)) 00503 { 00504 continue; 00505 } 00506 00507 /* Read the Status Register */ 00508 00509 Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); 00510 if (ACPI_FAILURE (Status)) 00511 { 00512 goto UnlockAndExit; 00513 } 00514 00515 /* Read the Enable Register */ 00516 00517 Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); 00518 if (ACPI_FAILURE (Status)) 00519 { 00520 goto UnlockAndExit; 00521 } 00522 00523 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 00524 "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", 00525 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); 00526 00527 /* Check if there is anything active at all in this register */ 00528 00529 EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 00530 if (!EnabledStatusByte) 00531 { 00532 /* No active GPEs in this register, move on */ 00533 00534 continue; 00535 } 00536 00537 /* Now look at the individual GPEs in this byte register */ 00538 00539 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 00540 { 00541 /* Examine one GPE bit */ 00542 00543 if (EnabledStatusByte & (1 << j)) 00544 { 00545 /* 00546 * Found an active GPE. Dispatch the event to a handler 00547 * or method. 00548 */ 00549 IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, 00550 &GpeBlock->EventInfo[((ACPI_SIZE) i * 00551 ACPI_GPE_REGISTER_WIDTH) + j], 00552 j + GpeRegisterInfo->BaseGpeNumber); 00553 } 00554 } 00555 } 00556 00557 GpeBlock = GpeBlock->Next; 00558 } 00559 00560 UnlockAndExit: 00561 00562 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 00563 return (IntStatus); 00564 } 00565 00566 00567 /******************************************************************************* 00568 * 00569 * FUNCTION: AcpiEvAsynchExecuteGpeMethod 00570 * 00571 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 00572 * 00573 * RETURN: None 00574 * 00575 * DESCRIPTION: Perform the actual execution of a GPE control method. This 00576 * function is called from an invocation of AcpiOsExecute and 00577 * therefore does NOT execute at interrupt level - so that 00578 * the control method itself is not executed in the context of 00579 * an interrupt handler. 00580 * 00581 ******************************************************************************/ 00582 00583 static void ACPI_SYSTEM_XFACE 00584 AcpiEvAsynchExecuteGpeMethod ( 00585 void *Context) 00586 { 00587 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 00588 ACPI_STATUS Status; 00589 ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; 00590 ACPI_EVALUATE_INFO *Info; 00591 00592 00593 ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 00594 00595 00596 /* Allocate a local GPE block */ 00597 00598 LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); 00599 if (!LocalGpeEventInfo) 00600 { 00601 ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, 00602 "while handling a GPE")); 00603 return_VOID; 00604 } 00605 00606 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 00607 if (ACPI_FAILURE (Status)) 00608 { 00609 return_VOID; 00610 } 00611 00612 /* Must revalidate the GpeNumber/GpeBlock */ 00613 00614 if (!AcpiEvValidGpeEvent (GpeEventInfo)) 00615 { 00616 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 00617 return_VOID; 00618 } 00619 00620 /* 00621 * Take a snapshot of the GPE info for this level - we copy the info to 00622 * prevent a race condition with RemoveHandler/RemoveBlock. 00623 */ 00624 ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, 00625 sizeof (ACPI_GPE_EVENT_INFO)); 00626 00627 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 00628 if (ACPI_FAILURE (Status)) 00629 { 00630 return_VOID; 00631 } 00632 00633 /* Do the correct dispatch - normal method or implicit notify */ 00634 00635 switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 00636 { 00637 case ACPI_GPE_DISPATCH_NOTIFY: 00638 00639 /* 00640 * Implicit notify. 00641 * Dispatch a DEVICE_WAKE notify to the appropriate handler. 00642 * NOTE: the request is queued for execution after this method 00643 * completes. The notify handlers are NOT invoked synchronously 00644 * from this thread -- because handlers may in turn run other 00645 * control methods. 00646 */ 00647 Status = AcpiEvQueueNotifyRequest ( 00648 LocalGpeEventInfo->Dispatch.DeviceNode, 00649 ACPI_NOTIFY_DEVICE_WAKE); 00650 break; 00651 00652 case ACPI_GPE_DISPATCH_METHOD: 00653 00654 /* Allocate the evaluation information block */ 00655 00656 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 00657 if (!Info) 00658 { 00659 Status = AE_NO_MEMORY; 00660 } 00661 else 00662 { 00663 /* 00664 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the 00665 * _Lxx/_Exx control method that corresponds to this GPE 00666 */ 00667 Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; 00668 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 00669 00670 Status = AcpiNsEvaluate (Info); 00671 ACPI_FREE (Info); 00672 } 00673 00674 if (ACPI_FAILURE (Status)) 00675 { 00676 ACPI_EXCEPTION ((AE_INFO, Status, 00677 "while evaluating GPE method [%4.4s]", 00678 AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); 00679 } 00680 00681 break; 00682 00683 default: 00684 return_VOID; /* Should never happen */ 00685 } 00686 00687 /* Defer enabling of GPE until all notify handlers are done */ 00688 00689 Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, 00690 AcpiEvAsynchEnableGpe, LocalGpeEventInfo); 00691 if (ACPI_FAILURE (Status)) 00692 { 00693 ACPI_FREE (LocalGpeEventInfo); 00694 } 00695 return_VOID; 00696 } 00697 00698 00699 /******************************************************************************* 00700 * 00701 * FUNCTION: AcpiEvAsynchEnableGpe 00702 * 00703 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 00704 * Callback from AcpiOsExecute 00705 * 00706 * RETURN: None 00707 * 00708 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to 00709 * complete (i.e., finish execution of Notify) 00710 * 00711 ******************************************************************************/ 00712 00713 static void ACPI_SYSTEM_XFACE 00714 AcpiEvAsynchEnableGpe ( 00715 void *Context) 00716 { 00717 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 00718 00719 00720 (void) AcpiEvFinishGpe (GpeEventInfo); 00721 00722 ACPI_FREE (GpeEventInfo); 00723 return; 00724 } 00725 00726 00727 /******************************************************************************* 00728 * 00729 * FUNCTION: AcpiEvFinishGpe 00730 * 00731 * PARAMETERS: GpeEventInfo - Info for this GPE 00732 * 00733 * RETURN: Status 00734 * 00735 * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution 00736 * of a GPE method or a synchronous or asynchronous GPE handler. 00737 * 00738 ******************************************************************************/ 00739 00740 ACPI_STATUS 00741 AcpiEvFinishGpe ( 00742 ACPI_GPE_EVENT_INFO *GpeEventInfo) 00743 { 00744 ACPI_STATUS Status; 00745 00746 00747 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 00748 ACPI_GPE_LEVEL_TRIGGERED) 00749 { 00750 /* 00751 * GPE is level-triggered, we clear the GPE status bit after 00752 * handling the event. 00753 */ 00754 Status = AcpiHwClearGpe (GpeEventInfo); 00755 if (ACPI_FAILURE (Status)) 00756 { 00757 return (Status); 00758 } 00759 } 00760 00761 /* 00762 * Enable this GPE, conditionally. This means that the GPE will 00763 * only be physically enabled if the EnableForRun bit is set 00764 * in the EventInfo. 00765 */ 00766 (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); 00767 return (AE_OK); 00768 } 00769 00770 00771 /******************************************************************************* 00772 * 00773 * FUNCTION: AcpiEvGpeDispatch 00774 * 00775 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 00776 * GpeEventInfo - Info for this GPE 00777 * GpeNumber - Number relative to the parent GPE block 00778 * 00779 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 00780 * 00781 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) 00782 * or method (e.g. _Lxx/_Exx) handler. 00783 * 00784 * This function executes at interrupt level. 00785 * 00786 ******************************************************************************/ 00787 00788 UINT32 00789 AcpiEvGpeDispatch ( 00790 ACPI_NAMESPACE_NODE *GpeDevice, 00791 ACPI_GPE_EVENT_INFO *GpeEventInfo, 00792 UINT32 GpeNumber) 00793 { 00794 ACPI_STATUS Status; 00795 UINT32 ReturnValue; 00796 00797 00798 ACPI_FUNCTION_TRACE (EvGpeDispatch); 00799 00800 00801 /* Invoke global event handler if present */ 00802 00803 AcpiGpeCount++; 00804 if (AcpiGbl_GlobalEventHandler) 00805 { 00806 AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, 00807 GpeNumber, AcpiGbl_GlobalEventHandlerContext); 00808 } 00809 00810 /* 00811 * If edge-triggered, clear the GPE status bit now. Note that 00812 * level-triggered events are cleared after the GPE is serviced. 00813 */ 00814 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 00815 ACPI_GPE_EDGE_TRIGGERED) 00816 { 00817 Status = AcpiHwClearGpe (GpeEventInfo); 00818 if (ACPI_FAILURE (Status)) 00819 { 00820 ACPI_EXCEPTION ((AE_INFO, Status, 00821 "Unable to clear GPE%02X", GpeNumber)); 00822 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 00823 } 00824 } 00825 00826 /* 00827 * Always disable the GPE so that it does not keep firing before 00828 * any asynchronous activity completes (either from the execution 00829 * of a GPE method or an asynchronous GPE handler.) 00830 * 00831 * If there is no handler or method to run, just disable the 00832 * GPE and leave it disabled permanently to prevent further such 00833 * pointless events from firing. 00834 */ 00835 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 00836 if (ACPI_FAILURE (Status)) 00837 { 00838 ACPI_EXCEPTION ((AE_INFO, Status, 00839 "Unable to disable GPE%02X", GpeNumber)); 00840 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 00841 } 00842 00843 /* 00844 * Dispatch the GPE to either an installed handler or the control 00845 * method associated with this GPE (_Lxx or _Exx). If a handler 00846 * exists, we invoke it and do not attempt to run the method. 00847 * If there is neither a handler nor a method, leave the GPE 00848 * disabled. 00849 */ 00850 switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 00851 { 00852 case ACPI_GPE_DISPATCH_HANDLER: 00853 00854 /* Invoke the installed handler (at interrupt level) */ 00855 00856 ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( 00857 GpeDevice, GpeNumber, 00858 GpeEventInfo->Dispatch.Handler->Context); 00859 00860 /* If requested, clear (if level-triggered) and reenable the GPE */ 00861 00862 if (ReturnValue & ACPI_REENABLE_GPE) 00863 { 00864 (void) AcpiEvFinishGpe (GpeEventInfo); 00865 } 00866 break; 00867 00868 case ACPI_GPE_DISPATCH_METHOD: 00869 case ACPI_GPE_DISPATCH_NOTIFY: 00870 00871 /* 00872 * Execute the method associated with the GPE 00873 * NOTE: Level-triggered GPEs are cleared after the method completes. 00874 */ 00875 Status = AcpiOsExecute (OSL_GPE_HANDLER, 00876 AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 00877 if (ACPI_FAILURE (Status)) 00878 { 00879 ACPI_EXCEPTION ((AE_INFO, Status, 00880 "Unable to queue handler for GPE%02X - event disabled", 00881 GpeNumber)); 00882 } 00883 break; 00884 00885 default: 00886 00887 /* 00888 * No handler or method to run! 00889 * 03/2010: This case should no longer be possible. We will not allow 00890 * a GPE to be enabled if it has no handler or method. 00891 */ 00892 ACPI_ERROR ((AE_INFO, 00893 "No handler or method for GPE%02X, disabling event", 00894 GpeNumber)); 00895 break; 00896 } 00897 00898 return_UINT32 (ACPI_INTERRUPT_HANDLED); 00899 } 00900 Generated on Sat May 26 2012 04:25:45 for ReactOS by
1.7.6.1
|