src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evhandler.c
/*******************************************************************************
 *
 * FUNCTION:    AcpiEvInstallSpaceHandler
 *
 * PARAMETERS:  Node            - Namespace node for the device
 *              SpaceId         - The address space ID
 *              Handler         - Address of the handler
 *              Setup           - Address of the setup function
 *              Context         - Value passed to the handler on each access
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
 *              Assumes namespace is locked
 *
 ******************************************************************************/


Status

Install a handler for all OpRegions of a given SpaceId.
Assumes namespace is locked
Status Install a handler for all OpRegions of a given SpaceId . Assumes namespace is locked
ACPI_STATUS
AcpiEvInstallSpaceHandler (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_ADR_SPACE_TYPE     SpaceId,
    ACPI_ADR_SPACE_HANDLER  Handler,
    ACPI_ADR_SPACE_SETUP    Setup,
    void                    *Context)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_STATUS             Status = AE_OK;
    ACPI_OBJECT_TYPE        Type;
    UINT8                   Flags = 0;
    ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
    if ((Node->Type != ACPI_TYPE_DEVICE)     &&
        (Node->Type != ACPI_TYPE_PROCESSOR)  &&
        (Node->Type != ACPI_TYPE_THERMAL)    &&
        (Node != AcpiGbl_RootNode))
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }
    if (Handler == ACPI_DEFAULT_HANDLER)
    {
        Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
        switch (SpaceId)
        {
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
            Handler = AcpiExSystemMemorySpaceHandler;
            Setup   = AcpiEvSystemMemoryRegionSetup;
            break;
        case ACPI_ADR_SPACE_SYSTEM_IO:
            Handler = AcpiExSystemIoSpaceHandler;
            Setup   = AcpiEvIoSpaceRegionSetup;
            break;
        case ACPI_ADR_SPACE_PCI_CONFIG:
            Handler = AcpiExPciConfigSpaceHandler;
            Setup   = AcpiEvPciConfigRegionSetup;
            break;
        case ACPI_ADR_SPACE_CMOS:
            Handler = AcpiExCmosSpaceHandler;
            Setup   = AcpiEvCmosRegionSetup;
            break;
        case ACPI_ADR_SPACE_PCI_BAR_TARGET:
            Handler = AcpiExPciBarSpaceHandler;
            Setup   = AcpiEvPciBarRegionSetup;
            break;
        case ACPI_ADR_SPACE_DATA_TABLE:
            Handler = AcpiExDataTableSpaceHandler;
            Setup   = NULL;
            break;
        default:
            Status = AE_BAD_PARAMETER;
            goto UnlockAndExit;
        }
    }
    if (!Setup)
    {
        Setup = AcpiEvDefaultRegionSetup;
    }
    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (ObjDesc)
    {
        HandlerObj = AcpiEvFindRegionHandler (SpaceId,
            ObjDesc->CommonNotify.Handler);
        if (HandlerObj)
        {
            if (HandlerObj->AddressSpace.Handler == Handler)
            {
                Status = AE_SAME_HANDLER;
                goto UnlockAndExit;
            }
            else
            {
                Status = AE_ALREADY_EXISTS;
            }
            goto UnlockAndExit;
        }
    }
    else
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
            "Creating object on Device %p while installing handler\n",
            Node));
        if (Node->Type == ACPI_TYPE_ANY)
        {
            Type = ACPI_TYPE_DEVICE;
        }
        else
        {
            Type = Node->Type;
        }
        ObjDesc = AcpiUtCreateInternalObject (Type);
        if (!ObjDesc)
        {
            Status = AE_NO_MEMORY;
            goto UnlockAndExit;
        }
        ObjDesc->Common.Type = (UINT8) Type;
        Status = AcpiNsAttachObject (Node, ObjDesc, Type);
        AcpiUtRemoveReference (ObjDesc);
        if (ACPI_FAILURE (Status))
        {
            goto UnlockAndExit;
        }
    }
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Installing address handler for region %s(%X) "
        "on Device %4.4s %p(%p)\n",
        AcpiUtGetRegionName (SpaceId), SpaceId,
        AcpiUtGetNodeName (Node), Node, ObjDesc));
    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
    if (!HandlerObj)
    {
        Status = AE_NO_MEMORY;
        goto UnlockAndExit;
    }
    HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
    HandlerObj->AddressSpace.HandlerFlags = Flags;
    HandlerObj->AddressSpace.RegionList = NULL;
    HandlerObj->AddressSpace.Node = Node;
    HandlerObj->AddressSpace.Handler = Handler;
    HandlerObj->AddressSpace.Context = Context;
    HandlerObj->AddressSpace.Setup = Setup;
    HandlerObj->AddressSpace.Next = ObjDesc->CommonNotify.Handler;
    ObjDesc->CommonNotify.Handler = HandlerObj;
    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node,
        ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
        AcpiEvInstallHandler, NULL, HandlerObj, NULL);
UnlockAndExit:
    return_ACPI_STATUS (Status);
}
ACPI_STATUS AcpiEvInstallSpaceHandler ( ACPI_NAMESPACE_NODE * Node , ACPI_ADR_SPACE_TYPE SpaceId , ACPI_ADR_SPACE_HANDLER Handler , ACPI_ADR_SPACE_SETUP Setup , void * Context ) { ACPI_OPERAND_OBJECT * ObjDesc ; ACPI_OPERAND_OBJECT * HandlerObj ; ACPI_STATUS Status = AE_OK ; ACPI_OBJECT_TYPE Type ; UINT8 Flags = 0 ; ACPI_FUNCTION_TRACE ( EvInstallSpaceHandler ) ; if ( ( Node -> Type != ACPI_TYPE_DEVICE ) && ( Node -> Type != ACPI_TYPE_PROCESSOR ) && ( Node -> Type != ACPI_TYPE_THERMAL ) && ( Node != AcpiGbl_RootNode ) ) { Status = AE_BAD_PARAMETER ; goto UnlockAndExit ; } if ( Handler == ACPI_DEFAULT_HANDLER ) { Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED ; switch ( SpaceId ) { case ACPI_ADR_SPACE_SYSTEM_MEMORY : Handler = AcpiExSystemMemorySpaceHandler ; Setup = AcpiEvSystemMemoryRegionSetup ; break ; case ACPI_ADR_SPACE_SYSTEM_IO : Handler = AcpiExSystemIoSpaceHandler ; Setup = AcpiEvIoSpaceRegionSetup ; break ; case ACPI_ADR_SPACE_PCI_CONFIG : Handler = AcpiExPciConfigSpaceHandler ; Setup = AcpiEvPciConfigRegionSetup ; break ; case ACPI_ADR_SPACE_CMOS : Handler = AcpiExCmosSpaceHandler ; Setup = AcpiEvCmosRegionSetup ; break ; case ACPI_ADR_SPACE_PCI_BAR_TARGET : Handler = AcpiExPciBarSpaceHandler ; Setup = AcpiEvPciBarRegionSetup ; break ; case ACPI_ADR_SPACE_DATA_TABLE : Handler = AcpiExDataTableSpaceHandler ; Setup = NULL ; break ; default : Status = AE_BAD_PARAMETER ; goto UnlockAndExit ; } } if ( ! Setup ) { Setup = AcpiEvDefaultRegionSetup ; } ObjDesc = AcpiNsGetAttachedObject ( Node ) ; if ( ObjDesc ) { HandlerObj = AcpiEvFindRegionHandler ( SpaceId , ObjDesc -> CommonNotify . Handler ) ; if ( HandlerObj ) { if ( HandlerObj -> AddressSpace . Handler == Handler ) { Status = AE_SAME_HANDLER ; goto UnlockAndExit ; } else { Status = AE_ALREADY_EXISTS ; } goto UnlockAndExit ; } } else { ACPI_DEBUG_PRINT ( ( ACPI_DB_OPREGION , " \n " , Node ) ) ; if ( Node -> Type == ACPI_TYPE_ANY ) { Type = ACPI_TYPE_DEVICE ; } else { Type = Node -> Type ; } ObjDesc = AcpiUtCreateInternalObject ( Type ) ; if ( ! ObjDesc ) { Status = AE_NO_MEMORY ; goto UnlockAndExit ; } ObjDesc -> Common . Type = ( UINT8 ) Type ; Status = AcpiNsAttachObject ( Node , ObjDesc , Type ) ; AcpiUtRemoveReference ( ObjDesc ) ; if ( ACPI_FAILURE ( Status ) ) { goto UnlockAndExit ; } } ACPI_DEBUG_PRINT ( ( ACPI_DB_OPREGION , " " " \n " , AcpiUtGetRegionName ( SpaceId ) , SpaceId , AcpiUtGetNodeName ( Node ) , Node , ObjDesc ) ) ; HandlerObj = AcpiUtCreateInternalObject ( ACPI_TYPE_LOCAL_ADDRESS_HANDLER ) ; if ( ! HandlerObj ) { Status = AE_NO_MEMORY ; goto UnlockAndExit ; } HandlerObj -> AddressSpace . SpaceId = ( UINT8 ) SpaceId ; HandlerObj -> AddressSpace . HandlerFlags = Flags ; HandlerObj -> AddressSpace . RegionList = NULL ; HandlerObj -> AddressSpace . Node = Node ; HandlerObj -> AddressSpace . Handler = Handler ; HandlerObj -> AddressSpace . Context = Context ; HandlerObj -> AddressSpace . Setup = Setup ; HandlerObj -> AddressSpace . Next = ObjDesc -> CommonNotify . Handler ; ObjDesc -> CommonNotify . Handler = HandlerObj ; Status = AcpiNsWalkNamespace ( ACPI_TYPE_ANY , Node , ACPI_UINT32_MAX , ACPI_NS_WALK_UNLOCK , AcpiEvInstallHandler , NULL , HandlerObj , NULL ) ; UnlockAndExit : return_ACPI_STATUS ( Status ) ; }
FUNCTION:    AcpiEvInstallSpaceHandler
 PARAMETERS:  Node            - Namespace node for the device
              SpaceId         - The address space ID
              Handler         - Address of the handler
              Setup           - Address of the setup function
              Context         - Value passed to the handler on each access
FUNCTION : AcpiEvInstallSpaceHandler PARAMETERS : Node - Namespace node for the device SpaceId - The address space ID Handler - Address of the handler Setup - Address of the setup function Context - Value passed to the handler on each access
/*
     * This registration is valid for only the types below and the root.
     * The root node is where the default handlers get installed.
     */ /* If the caller hasn't specified a setup routine, use the default */ /* Check for an existing internal object */ /*
         * The attached device object already exists. Now make sure
         * the handler is not already installed.
         */ /*
                 * It is (relatively) OK to attempt to install the SAME
                 * handler twice. This can easily happen with the
                 * PCI_Config space.
                 */ /* A handler is already installed */ /* ObjDesc does not exist, create one */ /* Init new descriptor */ /* Attach the new object to the Node */ /* Remove local reference to the object */ /*
     * Install the handler
     *
     * At this point there is no existing handler. Just allocate the object
     * for the handler and link it into the list.
     */ /* Init handler obj */ /* Install at head of Device.AddressSpace list */ /*
     * The Device object is the first reference on the HandlerObj.
     * Each region that uses the handler adds a reference.
     */ /*
     * Walk the namespace finding all of the regions this handler will
     * manage.
     *
     * Start at the device and search the branch toward the leaf nodes
     * until either the leaf is encountered or a device is detected that
     * has an address handler of the same type.
     *
     * In either case, back up and search down the remainder of the branch
     */