summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/acpica/evregion.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/evregion.c')
-rw-r--r--sys/contrib/dev/acpica/evregion.c359
1 files changed, 174 insertions, 185 deletions
diff --git a/sys/contrib/dev/acpica/evregion.c b/sys/contrib/dev/acpica/evregion.c
index db1ab85..1404b31 100644
--- a/sys/contrib/dev/acpica/evregion.c
+++ b/sys/contrib/dev/acpica/evregion.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
- * $Revision: 137 $
+ * $Revision: 141 $
*
*****************************************************************************/
@@ -125,16 +125,24 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME ("evregion")
+#define ACPI_NUM_DEFAULT_SPACES 4
+
+UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = {
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE};
+
/*******************************************************************************
*
* FUNCTION: AcpiEvInitAddressSpaces
*
- * PARAMETERS:
+ * PARAMETERS: None
*
* RETURN: Status
*
- * DESCRIPTION: Installs the core subsystem address space handlers.
+ * DESCRIPTION: Installs the core subsystem default address space handlers.
*
******************************************************************************/
@@ -143,6 +151,7 @@ AcpiEvInitAddressSpaces (
void)
{
ACPI_STATUS Status;
+ ACPI_NATIVE_UINT i;
ACPI_FUNCTION_TRACE ("EvInitAddressSpaces");
@@ -150,9 +159,11 @@ AcpiEvInitAddressSpaces (
/*
* All address spaces (PCI Config, EC, SMBus) are scope dependent
- * and registration must occur for a specific device. In the case
- * system memory and IO address spaces there is currently no device
- * associated with the address space. For these we use the root.
+ * and registration must occur for a specific device.
+ *
+ * In the case of the system memory and IO address spaces there is currently
+ * no device associated with the address space. For these we use the root.
+ *
* We install the default PCI config space handler at the root so
* that this space is immediately available even though the we have
* not enumerated all the PCI Root Buses yet. This is to conform
@@ -161,43 +172,29 @@ AcpiEvInitAddressSpaces (
* near ready to find the PCI root buses at this point.
*
* NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
- * has already been installed (via AcpiInstallAddressSpaceHandler)
+ * has already been installed (via AcpiInstallAddressSpaceHandler).
+ * Similar for AE_SAME_HANDLER.
*/
- Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- if ((ACPI_FAILURE (Status)) &&
- (Status != AE_ALREADY_EXISTS))
+ for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
{
- return_ACPI_STATUS (Status);
- }
+ Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
+ AcpiGbl_DefaultAddressSpaces[i],
+ ACPI_DEFAULT_HANDLER, NULL, NULL);
+ switch (Status)
+ {
+ case AE_OK:
+ case AE_SAME_HANDLER:
+ case AE_ALREADY_EXISTS:
- Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- if ((ACPI_FAILURE (Status)) &&
- (Status != AE_ALREADY_EXISTS))
- {
- return_ACPI_STATUS (Status);
- }
+ /* These exceptions are all OK */
- Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- if ((ACPI_FAILURE (Status)) &&
- (Status != AE_ALREADY_EXISTS))
- {
- return_ACPI_STATUS (Status);
- }
+ break;
- Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
- ACPI_ADR_SPACE_DATA_TABLE,
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- if ((ACPI_FAILURE (Status)) &&
- (Status != AE_ALREADY_EXISTS))
- {
- return_ACPI_STATUS (Status);
+ default:
+
+ return_ACPI_STATUS (Status);
+ }
}
return_ACPI_STATUS (AE_OK);
@@ -242,10 +239,10 @@ AcpiEvExecuteRegMethod (
}
/*
- * _REG method has two arguments
- * Arg0: Integer: Operation region space ID
+ * _REG method has two arguments
+ * Arg0: Integer: Operation region space ID
* Same value as RegionObj->Region.SpaceId
- * Arg1: Integer: connection status
+ * Arg1: Integer: connection status
* 1 for connecting the handler,
* 0 for disconnecting the handler
* Passed as a parameter
@@ -263,16 +260,14 @@ AcpiEvExecuteRegMethod (
goto Cleanup;
}
- /*
- * Set up the parameter objects
- */
+ /* Set up the parameter objects */
+
Params[0]->Integer.Value = RegionObj->Region.SpaceId;
Params[1]->Integer.Value = Function;
Params[2] = NULL;
- /*
- * Execute the method, no return value
- */
+ /* Execute the method, no return value */
+
ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, RegionObj2->Extra.Method_REG, NULL));
Status = AcpiNsEvaluateByHandle (RegionObj2->Extra.Method_REG, Params, NULL);
@@ -329,10 +324,9 @@ AcpiEvAddressSpaceDispatch (
return_ACPI_STATUS (AE_NOT_EXIST);
}
- /*
- * Ensure that there is a handler associated with this region
- */
- HandlerDesc = RegionObj->Region.AddrHandler;
+ /* Ensure that there is a handler associated with this region */
+
+ HandlerDesc = RegionObj->Region.AddressSpace;
if (!HandlerDesc)
{
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n",
@@ -350,25 +344,24 @@ AcpiEvAddressSpaceDispatch (
/*
* This region has not been initialized yet, do it
*/
- RegionSetup = HandlerDesc->AddrHandler.Setup;
+ RegionSetup = HandlerDesc->AddressSpace.Setup;
if (!RegionSetup)
{
- /*
- * Bad news, no init routine and not init'd
- */
+ /* No initialization routine, exit with error */
+
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
- return_ACPI_STATUS (AE_UNKNOWN_STATUS);
+ return_ACPI_STATUS (AE_NOT_EXIST);
}
/*
* We must exit the interpreter because the region setup will potentially
- * execute control methods
+ * execute control methods (e.g., _REG method for this region)
*/
AcpiExExitInterpreter ();
Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
- HandlerDesc->AddrHandler.Context, &RegionContext);
+ HandlerDesc->AddressSpace.Context, &RegionContext);
/* Re-enter the interpreter */
@@ -378,9 +371,8 @@ AcpiEvAddressSpaceDispatch (
return_ACPI_STATUS (Status2);
}
- /*
- * Init routine may fail
- */
+ /* Check for failure of the Region Setup */
+
if (ACPI_FAILURE (Status))
{
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
@@ -389,40 +381,54 @@ AcpiEvAddressSpaceDispatch (
return_ACPI_STATUS (Status);
}
- RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
-
/*
- * Save the returned context for use in all accesses to
- * this particular region.
+ * Region initialization may have been completed by RegionSetup
*/
- RegionObj2->Extra.RegionContext = RegionContext;
+ if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
+ {
+ RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
+
+ if (RegionObj2->Extra.RegionContext)
+ {
+ /* The handler for this region was already installed */
+
+ ACPI_MEM_FREE (RegionContext);
+ }
+ else
+ {
+ /*
+ * Save the returned context for use in all accesses to
+ * this particular region
+ */
+ RegionObj2->Extra.RegionContext = RegionContext;
+ }
+ }
}
- /*
- * We have everything we need, begin the process
- */
- Handler = HandlerDesc->AddrHandler.Handler;
+ /* We have everything we need, we can invoke the address space handler */
+
+ Handler = HandlerDesc->AddressSpace.Handler;
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Addrhandler %p (%p), Address %8.8X%8.8X\n",
- &RegionObj->Region.AddrHandler->AddrHandler, Handler,
- ACPI_HIDWORD (Address), ACPI_LODWORD (Address)));
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ &RegionObj->Region.AddressSpace->AddressSpace, Handler,
+ ACPI_HIDWORD (Address), ACPI_LODWORD (Address),
+ AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
- if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
+ if (!(HandlerDesc->AddressSpace.Flags & 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 intepreter.
+ * 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 intepreter.
*/
AcpiExExitInterpreter();
}
- /*
- * Invoke the handler.
- */
+ /* Call the handler */
+
Status = Handler (Function, Address, BitWidth, Value,
- HandlerDesc->AddrHandler.Context,
+ HandlerDesc->AddressSpace.Context,
RegionObj2->Extra.RegionContext);
if (ACPI_FAILURE (Status))
@@ -432,7 +438,7 @@ AcpiEvAddressSpaceDispatch (
AcpiFormatException (Status)));
}
- if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
+ if (!(HandlerDesc->AddressSpace.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* We just returned from a non-default handler, we must re-enter the
@@ -486,38 +492,33 @@ AcpiEvDetachRegion(
}
RegionContext = RegionObj2->Extra.RegionContext;
- /*
- * Get the address handler from the region object
- */
- HandlerObj = RegionObj->Region.AddrHandler;
+ /* Get the address handler from the region object */
+
+ HandlerObj = RegionObj->Region.AddressSpace;
if (!HandlerObj)
{
- /*
- * This region has no handler, all done
- */
+ /* This region has no handler, all done */
+
return_VOID;
}
+ /* Find this region in the handler's list */
- /*
- * Find this region in the handler's list
- */
- ObjDesc = HandlerObj->AddrHandler.RegionList;
- LastObjPtr = &HandlerObj->AddrHandler.RegionList;
+ ObjDesc = HandlerObj->AddressSpace.RegionList;
+ LastObjPtr = &HandlerObj->AddressSpace.RegionList;
while (ObjDesc)
{
- /*
- * See if this is the one
- */
+ /* Is this the correct Region? */
+
if (ObjDesc == RegionObj)
{
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Removing Region %p from address handler %p\n",
RegionObj, HandlerObj));
- /*
- * This is it, remove it from the handler's list
- */
+
+ /* This is it, remove it from the handler's list */
+
*LastObjPtr = ObjDesc->Region.Next;
ObjDesc->Region.Next = NULL; /* Must clear field */
@@ -530,9 +531,8 @@ AcpiEvDetachRegion(
}
}
- /*
- * Now stop region accesses by executing the _REG method
- */
+ /* Now stop region accesses by executing the _REG method */
+
Status = AcpiEvExecuteRegMethod (RegionObj, 0);
if (ACPI_FAILURE (Status))
{
@@ -550,16 +550,14 @@ AcpiEvDetachRegion(
}
}
- /*
- * Call the setup handler with the deactivate notification
- */
- RegionSetup = HandlerObj->AddrHandler.Setup;
+ /* Call the setup handler with the deactivate notification */
+
+ RegionSetup = HandlerObj->AddressSpace.Setup;
Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
- HandlerObj->AddrHandler.Context, &RegionContext);
+ HandlerObj->AddressSpace.Context, &RegionContext);
+
+ /* Init routine may fail, Just ignore errors */
- /*
- * Init routine may fail, Just ignore errors
- */
if (ACPI_FAILURE (Status))
{
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
@@ -570,31 +568,29 @@ AcpiEvDetachRegion(
RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
/*
- * Remove handler reference in the region
+ * Remove handler reference in the region
*
- * NOTE: this doesn't mean that the region goes away
- * The region is just inaccessible as indicated to
- * the _REG method
+ * NOTE: this doesn't mean that the region goes away
+ * The region is just inaccessible as indicated to
+ * the _REG method
*
- * If the region is on the handler's list
- * this better be the region's handler
+ * If the region is on the handler's list
+ * this better be the region's handler
*/
- RegionObj->Region.AddrHandler = NULL;
+ RegionObj->Region.AddressSpace = NULL;
+ AcpiUtRemoveReference (HandlerObj);
return_VOID;
+ }
- } /* found the right handler */
+ /* Walk the linked list of handlers */
- /*
- * Move through the linked list of handlers
- */
LastObjPtr = &ObjDesc->Region.Next;
ObjDesc = ObjDesc->Region.Next;
}
- /*
- * If we get here, the region was not in the handler's region list
- */
+ /* If we get here, the region was not in the handler's region list */
+
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Cannot remove region %p from address handler %p\n",
RegionObj, HandlerObj));
@@ -636,16 +632,20 @@ AcpiEvAttachRegion (
RegionObj, HandlerObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
- /*
- * Link this region to the front of the handler's list
- */
- RegionObj->Region.Next = HandlerObj->AddrHandler.RegionList;
- HandlerObj->AddrHandler.RegionList = RegionObj;
+ /* Link this region to the front of the handler's list */
- /*
- * Set the region's handler
- */
- RegionObj->Region.AddrHandler = HandlerObj;
+ RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
+ HandlerObj->AddressSpace.RegionList = RegionObj;
+
+ /* Install the region's handler */
+
+ if (RegionObj->Region.AddressSpace)
+ {
+ return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ }
+
+ RegionObj->Region.AddressSpace = HandlerObj;
+ AcpiUtAddReference (HandlerObj);
/*
* Tell all users that this region is usable by running the _REG
@@ -677,14 +677,14 @@ AcpiEvAttachRegion (
/*******************************************************************************
*
- * FUNCTION: AcpiEvAddrHandlerHelper
+ * FUNCTION: AcpiEvInstallHandler
*
* PARAMETERS: Handle - Node to be dumped
* Level - Nesting level of the handle
* Context - Passed into AcpiNsWalkNamespace
*
* DESCRIPTION: This routine installs an address handler into objects that are
- * of type Region.
+ * of type Region or Device.
*
* If the Object is a Device, and the device has a handler of
* the same type then the search is terminated in that branch.
@@ -695,20 +695,20 @@ AcpiEvAttachRegion (
******************************************************************************/
ACPI_STATUS
-AcpiEvAddrHandlerHelper (
+AcpiEvInstallHandler (
ACPI_HANDLE ObjHandle,
UINT32 Level,
void *Context,
void **ReturnValue)
{
ACPI_OPERAND_OBJECT *HandlerObj;
- ACPI_OPERAND_OBJECT *TmpObj;
+ ACPI_OPERAND_OBJECT *NextHandlerObj;
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_NAMESPACE_NODE *Node;
ACPI_STATUS Status;
- ACPI_FUNCTION_NAME ("EvAddrHandlerHelper");
+ ACPI_FUNCTION_NAME ("EvInstallHandler");
HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
@@ -729,8 +729,8 @@ AcpiEvAddrHandlerHelper (
}
/*
- * We only care about regions.and objects
- * that can have address handlers
+ * 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) &&
@@ -744,85 +744,74 @@ AcpiEvAddrHandlerHelper (
ObjDesc = AcpiNsGetAttachedObject (Node);
if (!ObjDesc)
{
- /*
- * The object DNE, we don't care about it
- */
+ /* No object, just exit */
+
return (AE_OK);
}
- /*
- * Devices are handled different than regions
- */
+ /* 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)
+ /* Check if this Device already has a handler for this address space */
+
+ NextHandlerObj = ObjDesc->Device.AddressSpace;
+ while (NextHandlerObj)
{
- /*
- * Now let's see if it's for the same address space.
- */
- if (TmpObj->AddrHandler.SpaceId == HandlerObj->AddrHandler.SpaceId)
+ /* Found a handler, is it for the same address space? */
+
+ if (NextHandlerObj->AddressSpace.SpaceId == HandlerObj->AddressSpace.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));
+ 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.
+ * 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;
+ /* 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.
+ * 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)
+ /* Object is a Region */
+
+ if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
{
/*
- * This region is for a different address space
- * ignore it
+ * 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.
+ * Now we have a region and it is for the handler's address
+ * space type.
*
- * First disconnect region for any previous handler (if any)
+ * 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);
+ /* Connect the region to the new handler */
+ Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
return (Status);
}
OpenPOWER on IntegriCloud