Exemple #1
0
ACPI_STATUS
AcpiDisableGpe (
    ACPI_HANDLE             GpeDevice,
    UINT32                  GpeNumber)
{
    ACPI_STATUS             Status = AE_BAD_PARAMETER;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_CPU_FLAGS          Flags;


    ACPI_FUNCTION_TRACE (AcpiDisableGpe);


    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);

    /* Ensure that we have a valid GPE number */

    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    if (GpeEventInfo)
    {
        Status = AcpiEvRemoveGpeReference (GpeEventInfo);
    }

    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    return_ACPI_STATUS (Status);
}
Exemple #2
0
static ACPI_STATUS
AcpiEvInstallGpeHandler (
    ACPI_HANDLE             GpeDevice,
    UINT32                  GpeNumber,
    UINT32                  Type,
    BOOLEAN                 IsRawHandler,
    ACPI_GPE_HANDLER        Address,
    void                    *Context)
{
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_GPE_HANDLER_INFO   *Handler;
    ACPI_STATUS             Status;
    ACPI_CPU_FLAGS          Flags;


    ACPI_FUNCTION_TRACE (EvInstallGpeHandler);


    /* Parameter validation */

    if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Allocate and init handler object (before lock) */

    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
    if (!Handler)
    {
        Status = AE_NO_MEMORY;
        goto UnlockAndExit;
    }

    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);

    /* Ensure that we have a valid GPE number */

    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    if (!GpeEventInfo)
    {
        Status = AE_BAD_PARAMETER;
        goto FreeAndExit;
    }

    /* Make sure that there isn't a handler there already */

    if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
            ACPI_GPE_DISPATCH_HANDLER) ||
        (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
            ACPI_GPE_DISPATCH_RAW_HANDLER))
    {
        Status = AE_ALREADY_EXISTS;
        goto FreeAndExit;
    }

    Handler->Address = Address;
    Handler->Context = Context;
    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
    Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
        (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));

    /*
     * If the GPE is associated with a method, it may have been enabled
     * automatically during initialization, in which case it has to be
     * disabled now to avoid spurious execution of the handler.
     */
    if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
            ACPI_GPE_DISPATCH_METHOD) ||
         (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
            ACPI_GPE_DISPATCH_NOTIFY)) &&
        GpeEventInfo->RuntimeCount)
    {
        Handler->OriginallyEnabled = TRUE;
        (void) AcpiEvRemoveGpeReference (GpeEventInfo);

        /* Sanity check of original type against new type */

        if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
        {
            ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
        }
    }

    /* Install the handler */

    GpeEventInfo->Dispatch.Handler = Handler;

    /* Setup up dispatch flags to indicate handler (vs. method/notify) */

    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
    GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ?
        ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER));

    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    return_ACPI_STATUS (Status);

FreeAndExit:
    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    ACPI_FREE (Handler);
    goto UnlockAndExit;
}
Exemple #3
0
ACPI_STATUS
AcpiSetupGpeForWake (
    ACPI_HANDLE             WakeDevice,
    ACPI_HANDLE             GpeDevice,
    UINT32                  GpeNumber)
{
    ACPI_STATUS             Status;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_NAMESPACE_NODE     *DeviceNode;
    ACPI_GPE_NOTIFY_INFO    *Notify;
    ACPI_GPE_NOTIFY_INFO    *NewNotify;
    ACPI_CPU_FLAGS          Flags;


    ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);


    /* Parameter Validation */

    if (!WakeDevice)
    {
        /*
         * By forcing WakeDevice to be valid, we automatically enable the
         * implicit notify feature on all hosts.
         */
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Handle root object case */

    if (WakeDevice == ACPI_ROOT_OBJECT)
    {
        DeviceNode = AcpiGbl_RootNode;
    }
    else
    {
        DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
    }

    /* Validate WakeDevice is of type Device */

    if (DeviceNode->Type != ACPI_TYPE_DEVICE)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /*
     * Allocate a new notify object up front, in case it is needed.
     * Memory allocation while holding a spinlock is a big no-no
     * on some hosts.
     */
    NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
    if (!NewNotify)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);

    /* Ensure that we have a valid GPE number */

    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    if (!GpeEventInfo)
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    /*
     * If there is no method or handler for this GPE, then the
     * WakeDevice will be notified whenever this GPE fires. This is
     * known as an "implicit notify". Note: The GPE is assumed to be
     * level-triggered (for windows compatibility).
     */
    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
        ACPI_GPE_DISPATCH_NONE)
    {
        /*
         * This is the first device for implicit notify on this GPE.
         * Just set the flags here, and enter the NOTIFY block below.
         */
        GpeEventInfo->Flags =
            (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
    }
    else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)
    {
        /*
         * A reference to this GPE has been added during the GPE block
         * initialization, so drop it now to prevent the GPE from being
         * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
         */
        (void) AcpiEvRemoveGpeReference (GpeEventInfo);
        GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED;
    }

    /*
     * If we already have an implicit notify on this GPE, add
     * this device to the notify list.
     */
    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
        ACPI_GPE_DISPATCH_NOTIFY)
    {
        /* Ensure that the device is not already in the list */

        Notify = GpeEventInfo->Dispatch.NotifyList;
        while (Notify)
        {
            if (Notify->DeviceNode == DeviceNode)
            {
                Status = AE_ALREADY_EXISTS;
                goto UnlockAndExit;
            }
            Notify = Notify->Next;
        }

        /* Add this device to the notify list for this GPE */

        NewNotify->DeviceNode = DeviceNode;
        NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
        GpeEventInfo->Dispatch.NotifyList = NewNotify;
        NewNotify = NULL;
    }

    /* Mark the GPE as a possible wake event */

    GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
    Status = AE_OK;


UnlockAndExit:
    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);

    /* Delete the notify object if it was not used above */

    if (NewNotify)
    {
        ACPI_FREE (NewNotify);
    }
    return_ACPI_STATUS (Status);
}