예제 #1
0
ACPI_STATUS
AcpiRemoveAddressSpaceHandler (
    ACPI_HANDLE             Device,
    ACPI_ADR_SPACE_TYPE     SpaceId,
    ACPI_ADR_SPACE_HANDLER  Handler)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_OPERAND_OBJECT     *RegionObj;
    ACPI_OPERAND_OBJECT     **LastObjPtr;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler);


    /* Parameter validation */

    if (!Device)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

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

    /* Convert and validate the device handle */

    Node = AcpiNsValidateHandle (Device);
    if (!Node ||
            ((Node->Type != ACPI_TYPE_DEVICE)    &&
             (Node->Type != ACPI_TYPE_PROCESSOR) &&
             (Node->Type != ACPI_TYPE_THERMAL)   &&
             (Node != AcpiGbl_RootNode)))
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    /* Make sure the internal object exists */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        Status = AE_NOT_EXIST;
        goto UnlockAndExit;
    }

    /* Find the address handler the user requested */

    HandlerObj = ObjDesc->Device.Handler;
    LastObjPtr = &ObjDesc->Device.Handler;
    while (HandlerObj)
    {
        /* We have a handler, see if user requested this one */

        if (HandlerObj->AddressSpace.SpaceId == SpaceId)
        {
            /* Handler must be the same as the installed handler */

            if (HandlerObj->AddressSpace.Handler != Handler)
            {
                Status = AE_BAD_PARAMETER;
                goto UnlockAndExit;
            }

            /* Matched SpaceId, first dereference this in the Regions */

            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                               "Removing address handler %p(%p) for region %s "
                               "on Device %p(%p)\n",
                               HandlerObj, Handler, AcpiUtGetRegionName (SpaceId),
                               Node, ObjDesc));

            RegionObj = HandlerObj->AddressSpace.RegionList;

            /* Walk the handler's region list */

            while (RegionObj)
            {
                /*
                 * First disassociate the handler from the region.
                 *
                 * NOTE: this doesn't mean that the region goes away
                 * The region is just inaccessible as indicated to
                 * the _REG method
                 */
                AcpiEvDetachRegion (RegionObj, TRUE);

                /*
                 * Walk the list: Just grab the head because the
                 * DetachRegion removed the previous head.
                 */
                RegionObj = HandlerObj->AddressSpace.RegionList;

            }

            /* Remove this Handler object from the list */

            *LastObjPtr = HandlerObj->AddressSpace.Next;

            /* Now we can delete the handler object */

            AcpiUtRemoveReference (HandlerObj);
            goto UnlockAndExit;
        }

        /* Walk the linked list of handlers */

        LastObjPtr = &HandlerObj->AddressSpace.Next;
        HandlerObj = HandlerObj->AddressSpace.Next;
    }

    /* The handler does not exist */

    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                       "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
                       Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc));

    Status = AE_NOT_EXIST;

UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
예제 #2
0
ACPI_STATUS
AcpiRemoveAddressSpaceHandler (
    ACPI_HANDLE             Device,
    ACPI_ADR_SPACE_TYPE     SpaceId,
    ACPI_ADR_SPACE_HANDLER  Handler)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_OPERAND_OBJECT     *RegionObj;
    ACPI_OPERAND_OBJECT     **LastObjPtr;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE ("AcpiRemoveAddressSpaceHandler");


    /* Parameter validation */

    if (!Device)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

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

    /* Convert and validate the device handle */

    Node = AcpiNsMapHandleToNode (Device);
    if (!Node)
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    /* Make sure the internal object exists */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        Status = AE_NOT_EXIST;
        goto UnlockAndExit;
    }

    /*
     * find the address handler the user requested
     */
    HandlerObj = ObjDesc->Device.AddrHandler;
    LastObjPtr = &ObjDesc->Device.AddrHandler;
    while (HandlerObj)
    {
        /*
         * We have a handler, see if user requested this one
         */
        if (HandlerObj->AddrHandler.SpaceId == SpaceId)
        {
            /*
             * Got it, first dereference this in the Regions
             */
            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                "Removing address handler %p(%p) for region %s on Device %p(%p)\n",
                HandlerObj, Handler, AcpiUtGetRegionName (SpaceId),
                Node, ObjDesc));

            RegionObj = HandlerObj->AddrHandler.RegionList;

            /* Walk the handler's region list */

            while (RegionObj)
            {
                /*
                 * First disassociate the handler from the region.
                 *
                 * NOTE: this doesn't mean that the region goes away
                 * The region is just inaccessible as indicated to
                 * the _REG method
                 */
                AcpiEvDetachRegion (RegionObj, TRUE);

                /*
                 * Walk the list, since we took the first region and it
                 * was removed from the list by the dissassociate call
                 * we just get the first item on the list again
                 */
                RegionObj = HandlerObj->AddrHandler.RegionList;

            }

            /*
             * Remove this Handler object from the list
             */
            *LastObjPtr = HandlerObj->AddrHandler.Next;

            /*
             * Now we can delete the handler object
             */
            AcpiUtRemoveReference (HandlerObj);
            AcpiUtRemoveReference (HandlerObj);

            goto UnlockAndExit;
        }

        /*
         * Move through the linked list of handlers
         */
        LastObjPtr = &HandlerObj->AddrHandler.Next;
        HandlerObj = HandlerObj->AddrHandler.Next;
    }


    /*
     * The handler does not exist
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
        Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc));

    Status = AE_NOT_EXIST;


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
예제 #3
0
파일: evhandler.c 프로젝트: tomtor/freebsd
static ACPI_STATUS
AcpiEvInstallHandler (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_OPERAND_OBJECT     *NextHandlerObj;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_NAME (EvInstallHandler);


    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;

    /* Parameter validation */

    if (!HandlerObj)
    {
        return (AE_OK);
    }

    /* Convert and validate the device handle */

    Node = AcpiNsValidateHandle (ObjHandle);
    if (!Node)
    {
        return (AE_BAD_PARAMETER);
    }

    /*
     * We only care about regions and objects that are allowed to have
     * address space handlers
     */
    if ((Node->Type != ACPI_TYPE_DEVICE) &&
            (Node->Type != ACPI_TYPE_REGION) &&
            (Node != AcpiGbl_RootNode))
    {
        return (AE_OK);
    }

    /* Check for an existing internal object */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        /* No object, just exit */

        return (AE_OK);
    }

    /* Devices are handled different than regions */

    if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
    {
        /* Check if this Device already has a handler for this address space */

        NextHandlerObj = AcpiEvFindRegionHandler (
                             HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler);
        if (NextHandlerObj)
        {
            /* Found a handler, is it for the same address space? */

            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                               "Found handler for region [%s] in device %p(%p) handler %p\n",
                               AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
                               ObjDesc, NextHandlerObj, HandlerObj));

            /*
             * Since the object we found it on was a device, then it means
             * that someone has already installed a handler for the branch
             * of the namespace from this device on. Just bail out telling
             * the walk routine to not traverse this branch. This preserves
             * the scoping rule for handlers.
             */
            return (AE_CTRL_DEPTH);
        }

        /*
         * As long as the device didn't have a handler for this space we
         * don't care about it. We just ignore it and proceed.
         */
        return (AE_OK);
    }

    /* Object is a Region */

    if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
    {
        /* This region is for a different address space, just ignore it */

        return (AE_OK);
    }

    /*
     * Now we have a region and it is for the handler's address space type.
     *
     * First disconnect region for any previous handler (if any)
     */
    AcpiEvDetachRegion (ObjDesc, FALSE);

    /* Connect the region to the new handler */

    Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
    return (Status);
}
예제 #4
0
ACPI_STATUS
AcpiEvAddrHandlerHelper (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_OPERAND_OBJECT     *TmpObj;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_NAME ("EvAddrHandlerHelper");


    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;

    /* Parameter validation */

    if (!HandlerObj)
    {
        return (AE_OK);
    }

    /* Convert and validate the device handle */

    Node = AcpiNsMapHandleToNode (ObjHandle);
    if (!Node)
    {
        return (AE_BAD_PARAMETER);
    }

    /*
     *  We only care about regions.and objects
     *  that can have address handlers
     */
    if ((Node->Type != ACPI_TYPE_DEVICE) &&
        (Node->Type != ACPI_TYPE_REGION) &&
        (Node != AcpiGbl_RootNode))
    {
        return (AE_OK);
    }

    /* Check for an existing internal object */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        /*
         *  The object DNE, we don't care about it
         */
        return (AE_OK);
    }

    /*
     *  Devices are handled different than regions
     */
    if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_DEVICE)
    {
        /*
         *  See if this guy has any handlers
         */
        TmpObj = ObjDesc->Device.AddrHandler;
        while (TmpObj)
        {
            /*
             *  Now let's see if it's for the same address space.
             */
            if (TmpObj->AddrHandler.SpaceId == HandlerObj->AddrHandler.SpaceId)
            {
                /*
                 *  It's for the same address space
                 */
                ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                    "Found handler for region [%s] in device %p(%p) handler %p\n",
                    AcpiUtGetRegionName (HandlerObj->AddrHandler.SpaceId),
                    ObjDesc, TmpObj, HandlerObj));

                /*
                 *  Since the object we found it on was a device, then it
                 *  means that someone has already installed a handler for
                 *  the branch of the namespace from this device on.  Just
                 *  bail out telling the walk routine to not traverse this
                 *  branch.  This preserves the scoping rule for handlers.
                 */
                return (AE_CTRL_DEPTH);
            }

            /*
             *  Move through the linked list of handlers
             */
            TmpObj = TmpObj->AddrHandler.Next;
        }

        /*
         *  As long as the device didn't have a handler for this
         *  space we don't care about it.  We just ignore it and
         *  proceed.
         */
        return (AE_OK);
    }

    /*
     *  Only here if it was a region
     */
    if (ObjDesc->Region.SpaceId != HandlerObj->AddrHandler.SpaceId)
    {
        /*
         *  This region is for a different address space
         *  ignore it
         */
        return (AE_OK);
    }

    /*
     *  Now we have a region and it is for the handler's address
     *  space type.
     *
     *  First disconnect region for any previous handler (if any)
     */
    AcpiEvDetachRegion (ObjDesc, FALSE);

    /*
     *  Then connect the region to the new handler
     */
    Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);

    return (Status);
}