⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evgpe.c

📁 acpi tools for linux include acpiexec and acpixtract
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    /* A Non-NULL GpeDevice means this is a GPE Block Device */    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);    if (!ObjDesc ||        !ObjDesc->Device.GpeBlock)    {        return (NULL);    }    GpeBlock = ObjDesc->Device.GpeBlock;    if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&        (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))    {        return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);    }    return (NULL);}/******************************************************************************* * * FUNCTION:    AcpiEvGpeDetect * * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt. *                                    Can have multiple GPE blocks attached. * * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Detect if any GP events have occurred.  This function is *              executed at interrupt level. * ******************************************************************************/UINT32AcpiEvGpeDetect (    ACPI_GPE_XRUPT_INFO     *GpeXruptList){    ACPI_STATUS             Status;    ACPI_GPE_BLOCK_INFO     *GpeBlock;    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;    UINT8                   EnabledStatusByte;    UINT32                  StatusReg;    UINT32                  EnableReg;    ACPI_CPU_FLAGS          Flags;    ACPI_NATIVE_UINT        i;    ACPI_NATIVE_UINT        j;    ACPI_FUNCTION_NAME (EvGpeDetect);    /* Check for the case where there are no GPEs */    if (!GpeXruptList)    {        return (IntStatus);    }    /*     * We need to obtain the GPE lock for both the data structs and registers     * Note: Not necessary to obtain the hardware lock, since the GPE registers     * are owned by the GpeLock.     */    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);    /* Examine all GPE blocks attached to this interrupt level */    GpeBlock = GpeXruptList->GpeBlockListHead;    while (GpeBlock)    {        /*         * Read all of the 8-bit GPE status and enable registers         * in this GPE block, saving all of them.         * Find all currently active GP events.         */        for (i = 0; i < GpeBlock->RegisterCount; i++)        {            /* Get the next status/enable pair */            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];            /* Read the Status Register */            Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &StatusReg,                        &GpeRegisterInfo->StatusAddress);            if (ACPI_FAILURE (Status))            {                goto UnlockAndExit;            }            /* Read the Enable Register */            Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &EnableReg,                        &GpeRegisterInfo->EnableAddress);            if (ACPI_FAILURE (Status))            {                goto UnlockAndExit;            }            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,                "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",                GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));            /* Check if there is anything active at all in this register */            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);            if (!EnabledStatusByte)            {                /* No active GPEs in this register, move on */                continue;            }            /* Now look at the individual GPEs in this byte register */            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)            {                /* Examine one GPE bit */                if (EnabledStatusByte & (1 << j))                {                    /*                     * Found an active GPE. Dispatch the event to a handler                     * or method.                     */                    IntStatus |= AcpiEvGpeDispatch (                        &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j],                        (UINT32) j + GpeRegisterInfo->BaseGpeNumber);                }            }        }        GpeBlock = GpeBlock->Next;    }UnlockAndExit:    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);    return (IntStatus);}/******************************************************************************* * * FUNCTION:    AcpiEvAsynchExecuteGpeMethod * * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE * * RETURN:      None * * DESCRIPTION: Perform the actual execution of a GPE control method. This *              function is called from an invocation of AcpiOsExecute and *              therefore does NOT execute at interrupt level - so that *              the control method itself is not executed in the context of *              an interrupt handler. * ******************************************************************************/static void ACPI_SYSTEM_XFACEAcpiEvAsynchExecuteGpeMethod (    void                    *Context){    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;    ACPI_STATUS             Status;    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;    ACPI_EVALUATE_INFO      *Info;    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);    /* Allocate a local GPE block */    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));    if (!LocalGpeEventInfo)    {        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,            "while handling a GPE"));        return_VOID;    }    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);    if (ACPI_FAILURE (Status))    {        return_VOID;    }    /* Must revalidate the GpeNumber/GpeBlock */    if (!AcpiEvValidGpeEvent (GpeEventInfo))    {        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);        return_VOID;    }    /* Set the GPE flags for return to enabled state */    (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);    /*     * Take a snapshot of the GPE info for this level - we copy the     * info to prevent a race condition with RemoveHandler/RemoveBlock.     */    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,        sizeof (ACPI_GPE_EVENT_INFO));    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);    if (ACPI_FAILURE (Status))    {        return_VOID;    }    /*     * Must check for control method type dispatch one more     * time to avoid race with EvGpeInstallHandler     */    if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==            ACPI_GPE_DISPATCH_METHOD)    {        /* Allocate the evaluation information block */        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));        if (!Info)        {            Status = AE_NO_MEMORY;        }        else        {            /*             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx             * control method that corresponds to this GPE             */            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;            Info->Parameters = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT *, LocalGpeEventInfo);            Info->ParameterType = ACPI_PARAM_GPE;            Info->Flags = ACPI_IGNORE_RETURN_VALUE;            Status = AcpiNsEvaluate (Info);            ACPI_FREE (Info);        }        if (ACPI_FAILURE (Status))        {            ACPI_EXCEPTION ((AE_INFO, Status,                "while evaluating GPE method [%4.4s]",                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));        }    }    /* Defer enabling of GPE until all notify handlers are done */    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);    if (ACPI_FAILURE (Status))    {        ACPI_FREE (LocalGpeEventInfo);    }    return_VOID;}/******************************************************************************* * * FUNCTION:    AcpiEvAsynchEnableGpe * * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE * * RETURN:      None * * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to *              complete (i.e., finish execution of Notify) * ******************************************************************************/static void ACPI_SYSTEM_XFACEAcpiEvAsynchEnableGpe (    void                    *Context){    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;    ACPI_STATUS             Status;    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==            ACPI_GPE_LEVEL_TRIGGERED)    {        /*         * GPE is level-triggered, we clear the GPE status bit after         * handling the event.         */        Status = AcpiHwClearGpe (GpeEventInfo);        if (ACPI_FAILURE (Status))        {            goto Exit;        }    }    /* Enable this GPE */    (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);Exit:    ACPI_FREE (GpeEventInfo);    return;}/******************************************************************************* * * FUNCTION:    AcpiEvGpeDispatch * * PARAMETERS:  GpeEventInfo    - Info for this GPE *              GpeNumber       - Number relative to the parent GPE block * * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) *              or method (e.g. _Lxx/_Exx) handler. * *              This function executes at interrupt level. * ******************************************************************************/UINT32AcpiEvGpeDispatch (    ACPI_GPE_EVENT_INFO     *GpeEventInfo,    UINT32                  GpeNumber){    ACPI_STATUS             Status;    ACPI_FUNCTION_TRACE (EvGpeDispatch);    AcpiGpeCount++;    /*     * If edge-triggered, clear the GPE status bit now.  Note that     * level-triggered events are cleared after the GPE is serviced.     */    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==            ACPI_GPE_EDGE_TRIGGERED)    {        Status = AcpiHwClearGpe (GpeEventInfo);        if (ACPI_FAILURE (Status))        {            ACPI_EXCEPTION ((AE_INFO, Status,                "Unable to clear GPE[%2X]", GpeNumber));            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);        }    }    if (!AcpiGbl_SystemAwakeAndRunning)    {        /*         * We just woke up because of a wake GPE. Disable any further GPEs         * until we are fully up and running (Only wake GPEs should be enabled         * at this time, but we just brute-force disable them all.)         * 1) We must disable this particular wake GPE so it won't fire again         * 2) We want to disable all wake GPEs, since we are now awake         */        (void) AcpiHwDisableAllGpes ();    }    /*     * Dispatch the GPE to either an installed handler, or the control method     * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke     * it and do not attempt to run the method. If there is neither a handler     * nor a method, we disable this GPE to prevent further such pointless     * events from firing.     */    switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)    {    case ACPI_GPE_DISPATCH_HANDLER:        /*         * Invoke the installed handler (at interrupt level)         * Ignore return status for now.  TBD: leave GPE disabled on error?         */        (void) GpeEventInfo->Dispatch.Handler->Address (                        GpeEventInfo->Dispatch.Handler->Context);        /* It is now safe to clear level-triggered events. */        if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==                ACPI_GPE_LEVEL_TRIGGERED)        {            Status = AcpiHwClearGpe (GpeEventInfo);            if (ACPI_FAILURE (Status))            {                ACPI_EXCEPTION ((AE_INFO, Status,                    "Unable to clear GPE[%2X]", GpeNumber));                return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);            }        }        break;    case ACPI_GPE_DISPATCH_METHOD:        /*         * Disable the GPE, so it doesn't keep firing before the method has a         * chance to run (it runs asynchronously with interrupts enabled).         */        Status = AcpiEvDisableGpe (GpeEventInfo);        if (ACPI_FAILURE (Status))        {            ACPI_EXCEPTION ((AE_INFO, Status,                "Unable to disable GPE[%2X]", GpeNumber));            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);        }        /*         * Execute the method associated with the GPE         * NOTE: Level-triggered GPEs are cleared after the method completes.         */        Status = AcpiOsExecute (OSL_GPE_HANDLER,                    AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);        if (ACPI_FAILURE (Status))        {            ACPI_EXCEPTION ((AE_INFO, Status,                "Unable to queue handler for GPE[%2X] - event disabled",                GpeNumber));        }        break;    default:        /* No handler or method to run! */        ACPI_ERROR ((AE_INFO,            "No handler or method for GPE[%2X], disabling event",            GpeNumber));        /*         * Disable the GPE. The GPE will remain disabled until the ACPI         * Core Subsystem is restarted, or a handler is installed.         */        Status = AcpiEvDisableGpe (GpeEventInfo);        if (ACPI_FAILURE (Status))        {            ACPI_EXCEPTION ((AE_INFO, Status,                "Unable to disable GPE[%2X]", GpeNumber));            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);        }        break;    }    return_UINT32 (ACPI_INTERRUPT_HANDLED);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -