📄 evregion.c
字号:
while (NextHandlerObj) { /* Found a handler, is it for the same address space? */ if (NextHandlerObj->AddressSpace.SpaceId == HandlerObj->AddressSpace.SpaceId) { 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); } /* Walk the linked list of handlers attached to this device */ NextHandlerObj = NextHandlerObj->AddressSpace.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); } /* 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);}/******************************************************************************* * * 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 * ******************************************************************************/ACPI_STATUSAcpiEvInstallSpaceHandler ( 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; ACPI_OBJECT_TYPE Type; UINT8 Flags = 0; ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); /* * This registration is valid for only the types below * and the root. This is where the default handlers * get placed. */ 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 the caller hasn't specified a setup routine, use the default */ if (!Setup) { Setup = AcpiEvDefaultRegionSetup; } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* * The attached device object already exists. * Make sure the handler is not already installed. */ HandlerObj = ObjDesc->Device.Handler; /* Walk the handler list for this device */ while (HandlerObj) { /* Same SpaceId indicates a handler already installed */ if (HandlerObj->AddressSpace.SpaceId == SpaceId) { if (HandlerObj->AddressSpace.Handler == Handler) { /* * It is (relatively) OK to attempt to install the SAME * handler twice. This can easily happen * with PCI_Config space. */ Status = AE_SAME_HANDLER; goto UnlockAndExit; } else { /* A handler is already installed */ Status = AE_ALREADY_EXISTS; } goto UnlockAndExit; } /* Walk the linked list of handlers */ HandlerObj = HandlerObj->AddressSpace.Next; } } else { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Creating object on Device %p while installing handler\n", Node)); /* ObjDesc does not exist, create one */ 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; } /* Init new descriptor */ ObjDesc->Common.Type = (UINT8) Type; /* Attach the new object to the Node */ Status = AcpiNsAttachObject (Node, ObjDesc, Type); /* Remove local reference to the object */ 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)); /* * Install the handler * * At this point there is no existing handler. * Just allocate the object for the handler and link it * into the list. */ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); if (!HandlerObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Init handler obj */ 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; /* Install at head of Device.AddressSpace list */ HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; /* * The Device object is the first reference on the HandlerObj. * Each region that uses the handler adds a reference. */ ObjDesc->Device.Handler = HandlerObj; /* * 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 */ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, HandlerObj, NULL);UnlockAndExit: return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiEvExecuteRegMethods * * PARAMETERS: Node - Namespace node for the device * SpaceId - The address space ID * * RETURN: Status * * DESCRIPTION: Run all _REG methods for the input Space ID; * Note: assumes namespace is locked, or system init time. * ******************************************************************************/ACPI_STATUSAcpiEvExecuteRegMethods ( ACPI_NAMESPACE_NODE *Node, ACPI_ADR_SPACE_TYPE SpaceId){ ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvExecuteRegMethods); /* * Run all _REG methods for all Operation Regions for this * space ID. This is a separate walk in order to handle any * interdependencies between regions and _REG methods. (i.e. handlers * must be installed for all regions of this Space ID before we * can run any _REG methods) */ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, &SpaceId, NULL); return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiEvRegRun * * PARAMETERS: WalkNamespace callback * * DESCRIPTION: Run _REG method for region objects of the requested spaceID * ******************************************************************************/static ACPI_STATUSAcpiEvRegRun ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue){ ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_ADR_SPACE_TYPE SpaceId; ACPI_STATUS Status; SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); /* Convert and validate the device handle */ Node = AcpiNsMapHandleToNode (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_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); } /* Object is a Region */ if (ObjDesc->Region.SpaceId != SpaceId) { /* * This region is for a different address space * -- just ignore it */ return (AE_OK); } Status = AcpiEvExecuteRegMethod (ObjDesc, 1); return (Status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -