version 1.11, 2020/03/28 19:49:26 |
version 1.11.4.2, 2021/04/03 22:28:54 |
|
|
*****************************************************************************/ |
*****************************************************************************/ |
|
|
/* |
/* |
* Copyright (C) 2000 - 2020, Intel Corp. |
* Copyright (C) 2000 - 2021, Intel Corp. |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
|
|
* NO WARRANTY |
* NO WARRANTY |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
Line 56 extern UINT8 AcpiGbl_DefaultAddre |
|
Line 56 extern UINT8 AcpiGbl_DefaultAddre |
|
/* Local prototypes */ |
/* Local prototypes */ |
|
|
static void |
static void |
AcpiEvOrphanEcRegMethod ( |
AcpiEvExecuteOrphanRegMethod ( |
ACPI_NAMESPACE_NODE *EcDeviceNode); |
ACPI_NAMESPACE_NODE *DeviceNode, |
|
ACPI_ADR_SPACE_TYPE SpaceId); |
|
|
|
|
static ACPI_STATUS |
static ACPI_STATUS |
AcpiEvRegRun ( |
AcpiEvRegRun ( |
Line 160 AcpiEvAddressSpaceDispatch ( |
|
Line 162 AcpiEvAddressSpaceDispatch ( |
|
ACPI_OPERAND_OBJECT *RegionObj2; |
ACPI_OPERAND_OBJECT *RegionObj2; |
void *RegionContext = NULL; |
void *RegionContext = NULL; |
ACPI_CONNECTION_INFO *Context; |
ACPI_CONNECTION_INFO *Context; |
|
ACPI_MUTEX ContextMutex; |
|
BOOLEAN ContextLocked; |
ACPI_PHYSICAL_ADDRESS Address; |
ACPI_PHYSICAL_ADDRESS Address; |
|
|
|
|
Line 186 AcpiEvAddressSpaceDispatch ( |
|
Line 190 AcpiEvAddressSpaceDispatch ( |
|
} |
} |
|
|
Context = HandlerDesc->AddressSpace.Context; |
Context = HandlerDesc->AddressSpace.Context; |
|
ContextMutex = HandlerDesc->AddressSpace.ContextMutex; |
|
ContextLocked = FALSE; |
|
|
/* |
/* |
* It may be the case that the region has never been initialized. |
* It may be the case that the region has never been initialized. |
Line 252 AcpiEvAddressSpaceDispatch ( |
|
Line 258 AcpiEvAddressSpaceDispatch ( |
|
Handler = HandlerDesc->AddressSpace.Handler; |
Handler = HandlerDesc->AddressSpace.Handler; |
Address = (RegionObj->Region.Address + RegionOffset); |
Address = (RegionObj->Region.Address + RegionOffset); |
|
|
|
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
|
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n", |
|
&RegionObj->Region.Handler->AddressSpace, Handler, |
|
ACPI_FORMAT_UINT64 (Address), |
|
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
|
|
|
if (!(HandlerDesc->AddressSpace.HandlerFlags & |
|
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) |
|
{ |
|
/* |
|
* For handlers other than the default (supplied) handlers, we must |
|
* exit the interpreter because the handler *might* block -- we don't |
|
* know what it will do, so we can't hold the lock on the interpreter. |
|
*/ |
|
AcpiExExitInterpreter(); |
|
} |
|
|
/* |
/* |
* Special handling for GenericSerialBus and GeneralPurposeIo: |
* Special handling for GenericSerialBus and GeneralPurposeIo: |
* There are three extra parameters that must be passed to the |
* There are three extra parameters that must be passed to the |
Line 260 AcpiEvAddressSpaceDispatch ( |
|
Line 283 AcpiEvAddressSpaceDispatch ( |
|
* 2) Length of the above buffer |
* 2) Length of the above buffer |
* 3) Actual access length from the AccessAs() op |
* 3) Actual access length from the AccessAs() op |
* |
* |
|
* Since we pass these extra parameters via the context, which is |
|
* shared between threads, we must lock the context to avoid these |
|
* parameters being changed from another thread before the handler |
|
* has completed running. |
|
* |
* In addition, for GeneralPurposeIo, the Address and BitWidth fields |
* In addition, for GeneralPurposeIo, the Address and BitWidth fields |
* are defined as follows: |
* are defined as follows: |
* 1) Address is the pin number index of the field (bit offset from |
* 1) Address is the pin number index of the field (bit offset from |
* the previous Connection) |
* the previous Connection) |
* 2) BitWidth is the actual bit length of the field (number of pins) |
* 2) BitWidth is the actual bit length of the field (number of pins) |
*/ |
*/ |
if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) && |
if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || |
|
RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) && |
Context && |
Context && |
FieldObj) |
FieldObj) |
{ |
{ |
/* Get the Connection (ResourceTemplate) buffer */ |
|
|
|
Context->Connection = FieldObj->Field.ResourceBuffer; |
Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER); |
Context->Length = FieldObj->Field.ResourceLength; |
if (ACPI_FAILURE (Status)) |
Context->AccessLength = FieldObj->Field.AccessLength; |
{ |
} |
goto ReEnterInterpreter; |
if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) && |
} |
Context && |
|
FieldObj) |
ContextLocked = TRUE; |
{ |
|
/* Get the Connection (ResourceTemplate) buffer */ |
/* Get the Connection (ResourceTemplate) buffer */ |
|
|
Context->Connection = FieldObj->Field.ResourceBuffer; |
Context->Connection = FieldObj->Field.ResourceBuffer; |
Context->Length = FieldObj->Field.ResourceLength; |
Context->Length = FieldObj->Field.ResourceLength; |
Context->AccessLength = FieldObj->Field.AccessLength; |
Context->AccessLength = FieldObj->Field.AccessLength; |
Address = FieldObj->Field.PinNumberIndex; |
|
BitWidth = FieldObj->Field.BitLength; |
|
} |
|
|
|
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
|
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n", |
|
&RegionObj->Region.Handler->AddressSpace, Handler, |
|
ACPI_FORMAT_UINT64 (Address), |
|
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
|
|
|
if (!(HandlerDesc->AddressSpace.HandlerFlags & |
if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) |
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) |
{ |
{ |
Address = FieldObj->Field.PinNumberIndex; |
/* |
BitWidth = FieldObj->Field.BitLength; |
* For handlers other than the default (supplied) handlers, we must |
} |
* exit the interpreter because the handler *might* block -- we don't |
|
* know what it will do, so we can't hold the lock on the interpreter. |
|
*/ |
|
AcpiExExitInterpreter(); |
|
} |
} |
|
|
/* Call the handler */ |
/* Call the handler */ |
Line 311 AcpiEvAddressSpaceDispatch ( |
|
Line 326 AcpiEvAddressSpaceDispatch ( |
|
Status = Handler (Function, Address, BitWidth, Value, Context, |
Status = Handler (Function, Address, BitWidth, Value, Context, |
RegionObj2->Extra.RegionContext); |
RegionObj2->Extra.RegionContext); |
|
|
|
if (ContextLocked) |
|
{ |
|
AcpiOsReleaseMutex (ContextMutex); |
|
} |
|
|
if (ACPI_FAILURE (Status)) |
if (ACPI_FAILURE (Status)) |
{ |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", |
ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", |
Line 328 AcpiEvAddressSpaceDispatch ( |
|
Line 348 AcpiEvAddressSpaceDispatch ( |
|
} |
} |
} |
} |
|
|
|
ReEnterInterpreter: |
if (!(HandlerDesc->AddressSpace.HandlerFlags & |
if (!(HandlerDesc->AddressSpace.HandlerFlags & |
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) |
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) |
{ |
{ |
Line 761 AcpiEvExecuteRegMethods ( |
|
Line 782 AcpiEvExecuteRegMethods ( |
|
(void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, |
(void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, |
ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL); |
ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL); |
|
|
/* Special case for EC: handle "orphan" _REG methods with no region */ |
/* |
|
* Special case for EC and GPIO: handle "orphan" _REG methods with |
if (SpaceId == ACPI_ADR_SPACE_EC) |
* no region. |
|
*/ |
|
if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO) |
{ |
{ |
AcpiEvOrphanEcRegMethod (Node); |
AcpiEvExecuteOrphanRegMethod (Node, SpaceId); |
} |
} |
|
|
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, |
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, |
|
|
|
|
/******************************************************************************* |
/******************************************************************************* |
* |
* |
* FUNCTION: AcpiEvOrphanEcRegMethod |
* FUNCTION: AcpiEvExecuteOrphanRegMethod |
* |
* |
* PARAMETERS: EcDeviceNode - Namespace node for an EC device |
* PARAMETERS: DeviceNode - Namespace node for an ACPI device |
|
* SpaceId - The address space ID |
* |
* |
* RETURN: None |
* RETURN: None |
* |
* |
* DESCRIPTION: Execute an "orphan" _REG method that appears under the EC |
* DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI |
* device. This is a _REG method that has no corresponding region |
* device. This is a _REG method that has no corresponding region |
* within the EC device scope. The orphan _REG method appears to |
* within the device's scope. ACPI tables depending on these |
* have been enabled by the description of the ECDT in the ACPI |
* "orphan" _REG methods have been seen for both EC and GPIO |
* specification: "The availability of the region space can be |
* Operation Regions. Presumably the Windows ACPI implementation |
* detected by providing a _REG method object underneath the |
* always calls the _REG method independent of the presence of |
* Embedded Controller device." |
* an actual Operation Region with the correct address space ID. |
* |
|
* To quickly access the EC device, we use the EcDeviceNode used |
|
* during EC handler installation. Otherwise, we would need to |
|
* perform a time consuming namespace walk, executing _HID |
|
* methods to find the EC device. |
|
* |
* |
* MUTEX: Assumes the namespace is locked |
* MUTEX: Assumes the namespace is locked |
* |
* |
******************************************************************************/ |
******************************************************************************/ |
|
|
static void |
static void |
AcpiEvOrphanEcRegMethod ( |
AcpiEvExecuteOrphanRegMethod ( |
ACPI_NAMESPACE_NODE *EcDeviceNode) |
ACPI_NAMESPACE_NODE *DeviceNode, |
|
ACPI_ADR_SPACE_TYPE SpaceId) |
{ |
{ |
ACPI_HANDLE RegMethod; |
ACPI_HANDLE RegMethod; |
ACPI_NAMESPACE_NODE *NextNode; |
ACPI_NAMESPACE_NODE *NextNode; |
Line 880 AcpiEvOrphanEcRegMethod ( |
|
Line 900 AcpiEvOrphanEcRegMethod ( |
|
ACPI_OBJECT Objects[2]; |
ACPI_OBJECT Objects[2]; |
|
|
|
|
ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); |
ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod); |
|
|
|
|
if (!EcDeviceNode) |
if (!DeviceNode) |
{ |
{ |
return_VOID; |
return_VOID; |
} |
} |
Line 894 AcpiEvOrphanEcRegMethod ( |
|
Line 914 AcpiEvOrphanEcRegMethod ( |
|
|
|
/* Get a handle to a _REG method immediately under the EC device */ |
/* Get a handle to a _REG method immediately under the EC device */ |
|
|
Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); |
Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod); |
if (ACPI_FAILURE (Status)) |
if (ACPI_FAILURE (Status)) |
{ |
{ |
goto Exit; /* There is no _REG method present */ |
goto Exit; /* There is no _REG method present */ |
Line 907 AcpiEvOrphanEcRegMethod ( |
|
Line 927 AcpiEvOrphanEcRegMethod ( |
|
* with other space IDs to be present; but the code below will then |
* with other space IDs to be present; but the code below will then |
* execute the _REG method with the EmbeddedControl SpaceID argument. |
* execute the _REG method with the EmbeddedControl SpaceID argument. |
*/ |
*/ |
NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); |
NextNode = AcpiNsGetNextNode (DeviceNode, NULL); |
while (NextNode) |
while (NextNode) |
{ |
{ |
if ((NextNode->Type == ACPI_TYPE_REGION) && |
if ((NextNode->Type == ACPI_TYPE_REGION) && |
(NextNode->Object) && |
(NextNode->Object) && |
(NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) |
(NextNode->Object->Region.SpaceId == SpaceId)) |
{ |
{ |
goto Exit; /* Do not execute the _REG */ |
goto Exit; /* Do not execute the _REG */ |
} |
} |
|
|
NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); |
NextNode = AcpiNsGetNextNode (DeviceNode, NextNode); |
} |
} |
|
|
/* Evaluate the _REG(EmbeddedControl,Connect) method */ |
/* Evaluate the _REG(SpaceId,Connect) method */ |
|
|
Args.Count = 2; |
Args.Count = 2; |
Args.Pointer = Objects; |
Args.Pointer = Objects; |
Objects[0].Type = ACPI_TYPE_INTEGER; |
Objects[0].Type = ACPI_TYPE_INTEGER; |
Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; |
Objects[0].Integer.Value = SpaceId; |
Objects[1].Type = ACPI_TYPE_INTEGER; |
Objects[1].Type = ACPI_TYPE_INTEGER; |
Objects[1].Integer.Value = ACPI_REG_CONNECT; |
Objects[1].Integer.Value = ACPI_REG_CONNECT; |
|
|