/*
- * Ensure that the globals are actually defined only once.
+ * Ensure that the globals are actually defined and initialized only once.
*
- * The use of these defines allows a single list of globals (here) in order
+ * The use of these macros allows a single list of globals (here) in order
* to simplify maintenance of the code.
*/
#ifdef DEFINE_ACPI_GLOBALS
#define ACPI_EXTERN
+#define ACPI_INIT_GLOBAL(a,b) a=b
#else
#define ACPI_EXTERN extern
+#define ACPI_INIT_GLOBAL(a,b) a
#endif
+/*
+ * Keep local copies of these FADT-based registers. NOTE: These globals
+ * are first in this file for alignment reasons on 64-bit systems.
+ */
+ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1aEnable;
+ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1bEnable;
+
/*****************************************************************************
*
+ * Runtime configuration (static defaults that can be overriden at runtime)
+ *
+ ****************************************************************************/
+
+/*
+ * Create the predefined _OSI method in the namespace? Default is TRUE
+ * because ACPI CA is fully compatible with other ACPI implementations.
+ * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
+ */
+ACPI_EXTERN UINT8 ACPI_INIT_GLOBAL (AcpiGbl_CreateOsiMethod, TRUE);
+
+/*
+ * Automatically serialize ALL control methods? Default is FALSE, meaning
+ * to use the Serialized/NotSerialized method flags on a per method basis.
+ * Only change this if the ASL code is poorly written and cannot handle
+ * reentrancy even though methods are marked "NotSerialized".
+ */
+ACPI_EXTERN UINT8 ACPI_INIT_GLOBAL (AcpiGbl_AllMethodsSerialized, FALSE);
+
+/*
+ * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
+ * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
+ * be enabled just before going to sleep.
+ */
+ACPI_EXTERN UINT8 ACPI_INIT_GLOBAL (AcpiGbl_LeaveWakeGpesDisabled, TRUE);
+
+
+/*****************************************************************************
+ *
* ACPI Table globals
*
****************************************************************************/
@@ -160,7 +198,6 @@
*
* These tables are single-table only; meaning that there can be at most one
* of each in the system. Each global points to the actual table.
- *
*/
ACPI_EXTERN UINT32 AcpiGbl_TableFlags;
ACPI_EXTERN UINT32 AcpiGbl_RsdtTableCount;
@@ -170,6 +207,11 @@
ACPI_EXTERN ACPI_TABLE_HEADER *AcpiGbl_DSDT;
ACPI_EXTERN FACS_DESCRIPTOR *AcpiGbl_FACS;
ACPI_EXTERN ACPI_COMMON_FACS AcpiGbl_CommonFACS;
+/*
+ * Since there may be multiple SSDTs and PSDTS, a single pointer is not
+ * sufficient; Therefore, there isn't one!
+ */
+
-/* Keep local copies of these FADT-based registers */
-
-ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1aEnable;
-ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1bEnable;
-
-/*
- * Since there may be multiple SSDTs and PSDTS, a single pointer is not
- * sufficient; Therefore, there isn't one!
- */
-
-
/*
* ACPI Table info arrays
*/
@@ -234,13 +265,16 @@
ACPI_EXTERN BOOLEAN AcpiGbl_AcpiHardwarePresent;
ACPI_EXTERN BOOLEAN AcpiGbl_GlobalLockPresent;
ACPI_EXTERN BOOLEAN AcpiGbl_EventsInitialized;
+ACPI_EXTERN BOOLEAN AcpiGbl_SystemAwakeAndRunning;
@@ -264,8 +264,6 @@
UINT8 Type; /* Type associated with this name */
UINT16 OwnerId;
ACPI_NAME_UNION Name; /* ACPI Name, always 4 chars per ACPI spec */
-
-
union acpi_operand_object *Object; /* Pointer to attached ACPI object (optional) */
struct acpi_namespace_node *Child; /* First child */
struct acpi_namespace_node *Peer; /* Next peer*/
@@ -287,10 +285,8 @@
#define ANOBJ_METHOD_LOCAL 0x10
#define ANOBJ_METHOD_NO_RETVAL 0x20
#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40
-
#define ANOBJ_IS_BIT_OFFSET 0x80
-
/*
* ACPI Table Descriptor. One per ACPI table
*/
@@ -392,16 +388,33 @@
*
****************************************************************************/
-/* Information about a GPE, one per each GPE in an array */
+/* Dispatch info for each GPE -- either a method or handler, cannot be both */
-typedef struct acpi_gpe_event_info
+typedef struct acpi_handler_info
{
- ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level */
- ACPI_GPE_HANDLER Handler; /* Address of handler, if any */
+ ACPI_EVENT_HANDLER Address; /* Address of handler, if any */
void *Context; /* Context to be passed to handler */
+ ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level (saved) */
+
+} ACPI_HANDLER_INFO;
+
+typedef union acpi_gpe_dispatch_info
+{
+ ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level */
+ struct acpi_handler_info *Handler;
+
+} ACPI_GPE_DISPATCH_INFO;
+
+/*
+ * Information about a GPE, one per each GPE in an array.
+ * NOTE: Important to keep this struct as small as possible.
+ */
+typedef struct acpi_gpe_event_info
+{
+ union acpi_gpe_dispatch_info Dispatch; /* Either Method or Handler */
struct acpi_gpe_register_info *RegisterInfo; /* Backpointer to register info */
- UINT8 Flags; /* Level or Edge */
- UINT8 BitMask; /* This GPE within the register */
+ UINT8 Flags; /* Misc info about this GPE */
+ UINT8 RegisterBit; /* This GPE bit within the register */
} ACPI_GPE_EVENT_INFO;
@@ -411,9 +424,8 @@
{
ACPI_GENERIC_ADDRESS StatusAddress; /* Address of status reg */
ACPI_GENERIC_ADDRESS EnableAddress; /* Address of enable reg */
- UINT8 Status; /* Current value of status reg */
- UINT8 Enable; /* Current value of enable reg */
- UINT8 WakeEnable; /* Mask of bits to keep enabled when sleeping */
+ UINT8 EnableForWake; /* GPEs to keep enabled when sleeping */
+ UINT8 EnableForRun; /* GPEs to keep enabled when running */
UINT8 BaseGpeNumber; /* Base GPE number for this register */
@@ -122,9 +122,9 @@
* XXX this is technically correct, but will cause problems with some ASL
* which only works if the string names a Microsoft operating system.
*/
-#define ACPI_OS_NAME "NetBSD"
+#define ACPI_OS_NAME "NetBSD"
#else
-#define ACPI_OS_NAME "Microsoft Windows NT"
+#define ACPI_OS_NAME "Microsoft Windows NT"
#endif
@@ -142,13 +142,14 @@
typedef struct acpi_walk_state
{
UINT8 DataType; /* To differentiate various internal objs MUST BE FIRST!*/\
+ UINT8 WalkType;
ACPI_OWNER_ID OwnerId; /* Owner of objects created during the walk */
BOOLEAN LastPredicate; /* Result of last predicate */
+ UINT8 Reserved; /* For alignment */
UINT8 CurrentResult; /* */
UINT8 NextOpInfo; /* Info about NextOp */
UINT8 NumOperands; /* Stack pointer for Operands[] array */
UINT8 ReturnUsed;
- UINT8 WalkType;
UINT16 Opcode; /* Current AML opcode */
UINT8 ScopeDepth;
UINT8 Reserved1;
@@ -164,7 +165,8 @@
struct acpi_namespace_node Arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
union acpi_operand_object **CallerReturnDesc;
ACPI_GENERIC_STATE *ControlState; /* List of control states (nested IFs) */
- struct acpi_namespace_node *DeferredNode; /* Used when executing deferred opcodes */
+ struct acpi_namespace_node *DeferredNode; /* Used when executing deferred opcodes */
+ struct acpi_gpe_event_info *GpeEventInfo; /* Info for GPE (_Lxx/_Exx methods only */
struct acpi_namespace_node LocalVariables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *MethodCallNode; /* Called method Node*/
ACPI_PARSE_OBJECT *MethodCallOp; /* MethodCall Op if running a method */
@@ -279,4 +281,22 @@
} ACPI_AML_OPERANDS;
-
/*
* Table types. These values are passed to the table related APIs
*/
@@ -488,14 +486,13 @@
#define ACPI_TABLE_MAX 6
#define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1)
-
/*
* Types associated with ACPI names and objects. The first group of
* values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition
* of the ACPI ObjectType() operator (See the ACPI Spec). Therefore,
* only add to the first group if the spec changes.
*
- * Types must be kept in sync with the global AcpiNsProperties
+ * NOTE: Types must be kept in sync with the global AcpiNsProperties
* and AcpiNsTypeNames arrays.
*/
typedef UINT32 ACPI_OBJECT_TYPE;
@@ -532,26 +529,27 @@
#define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13
#define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, RefOf, Index */
#define ACPI_TYPE_LOCAL_ALIAS 0x15
-#define ACPI_TYPE_LOCAL_NOTIFY 0x16
-#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x17
-#define ACPI_TYPE_LOCAL_RESOURCE 0x18
-#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x19
-#define ACPI_TYPE_LOCAL_SCOPE 0x1A /* 1 Name, multiple ObjectList Nodes */
+#define ACPI_TYPE_LOCAL_METHOD_ALIAS 0x16
+#define ACPI_TYPE_LOCAL_NOTIFY 0x17
+#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x18
+#define ACPI_TYPE_LOCAL_RESOURCE 0x19
+#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x1A
+#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple ObjectList Nodes */
-#define ACPI_TYPE_NS_NODE_MAX 0x1A /* Last typecode used within a NS Node */
+#define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */
/*
* These are special object types that never appear in
* a Namespace node, only in an ACPI_OPERAND_OBJECT
*/
-#define ACPI_TYPE_LOCAL_EXTRA 0x1B
-#define ACPI_TYPE_LOCAL_DATA 0x1C
+#define ACPI_TYPE_LOCAL_EXTRA 0x1C
+#define ACPI_TYPE_LOCAL_DATA 0x1D
- UINT32 Valid; /* Indicates which fields are valid */
+ UINT32 Valid; /* Indicates which fields below are valid */
UINT32 CurrentStatus; /* _STA value */
ACPI_INTEGER Address; /* _ADR value if any */
ACPI_DEVICE_ID HardwareId; /* _HID value if any */
ACPI_DEVICE_ID UniqueId; /* _UID value if any */
+ UINT8 HighestDstates[4]; /* _SxD values: 0xFF indicates not valid */
ACPI_COMPATIBLE_ID_LIST CompatibilityId; /* List of _CIDs if any */
- /* 1) Parse: Create a new walk state for the preempting walk */
-
- NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId,
- Op, ObjDesc, NULL);
- if (!NextWalkState)
+ if (!(ObjDesc->Method.MethodFlags & AML_METHOD_INTERNAL_ONLY))
{
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
+ /* 1) Parse: Create a new walk state for the preempting walk */
- /* Create and init a Root Node */
+ NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId,
+ Op, ObjDesc, NULL);
+ if (!NextWalkState)
+ {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
- Op = AcpiPsCreateScopeOp ();
- if (!Op)
- {
- Status = AE_NO_MEMORY;
- goto Cleanup;
- }
+ /* Create and init a Root Node */
- Status = AcpiPsParseAml (NextWalkState);
- AcpiPsDeleteParseTree (Op);
+ Status = AcpiPsParseAml (NextWalkState);
+ AcpiPsDeleteParseTree (Op);
+ }
/* 2) Execute: Create a new state for the preempting walk */
@@ -433,7 +438,6 @@
Status = AE_NO_MEMORY;
goto Cleanup;
}
-
/*
* The resolved arguments were put on the previous walk state's operand
* stack. Operands on the previous walk state stack always
@@ -442,9 +446,12 @@
*/
ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
+ if (ObjDesc->Method.MethodFlags & AML_METHOD_INTERNAL_ONLY)
+ {
+ Status = ObjDesc->Method.Implementation (NextWalkState);
+ return_ACPI_STATUS (Status);
+ }
+
return_ACPI_STATUS (AE_OK);
/* On error, we must delete the new walk state */
Cleanup:
+ if (NextWalkState->MethodDesc)
+ {
+ /* Decrement the thread count on the method parse tree */
+
+ NextWalkState->MethodDesc->Method.ThreadCount--;
+ }
(void) AcpiDsTerminateControlMethod (NextWalkState);
AcpiDsDeleteWalkState (NextWalkState);
return_ACPI_STATUS (Status);
-
}
@@ -607,12 +625,34 @@
}
}
- /* Decrement the thread count on the method parse tree */
+ if (WalkState->MethodDesc->Method.ThreadCount)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "*** Not deleting method namespace, there are still %d threads\n",
+ WalkState->MethodDesc->Method.ThreadCount));
+ }
- WalkState->MethodDesc->Method.ThreadCount--;
if (!WalkState->MethodDesc->Method.ThreadCount)
{
/*
+ * Support to dynamically change a method from NotSerialized to
+ * Serialized if it appears that the method is written foolishly and
+ * does not support multiple thread execution. The best example of this
+ * is if such a method creates namespace objects and blocks. A second
+ * thread will fail with an AE_ALREADY_EXISTS exception
+ *
+ * This code is here because we must wait until the last thread exits
+ * before creating the synchronization semaphore.
+ */
+ if ((WalkState->MethodDesc->Method.Concurrency == 1) &&
+ (!WalkState->MethodDesc->Method.Semaphore))
+ {
+ Status = AcpiOsCreateSemaphore (1,
+ 1,
+ &WalkState->MethodDesc->Method.Semaphore);
+ }
+
+ /*
* There are no more threads executing this method. Perform
* additional cleanup.
*
Index: sys/dev/acpi/acpica/Subsystem/dsmthdat.c
===================================================================
RCS file: /cvsroot/src/sys/dev/acpi/acpica/Subsystem/dsmthdat.c,v
retrieving revision 1.11
diff -u -r1.11 dsmthdat.c
--- sys/dev/acpi/acpica/Subsystem/dsmthdat.c 14 Feb 2004 16:57:24 -0000 1.11
+++ sys/dev/acpi/acpica/Subsystem/dsmthdat.c 8 May 2004 03:05:57 -0000
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: dsmthdat - control method arguments and local variables
- * xRevision: 77 $
+ * xRevision: 78 $
*
******************************************************************************/
/*
- * Store this object to the Node
- * (perform the indirect store)
+ * Store this object to the Node (perform the indirect store)
+ * NOTE: No implicit conversion is performed, as per the ACPI
+ * specification rules on storing to Locals/Args.
*/
Status = AcpiExStoreObjectToNode (NewObjDesc,
- CurrentObjDesc->Reference.Object, WalkState);
+ CurrentObjDesc->Reference.Object, WalkState,
+ ACPI_NO_IMPLICIT_CONVERSION);
/* Remove local reference if we copied the object above */
Index: sys/dev/acpi/acpica/Subsystem/dsopcode.c
===================================================================
RCS file: /cvsroot/src/sys/dev/acpi/acpica/Subsystem/dsopcode.c,v
retrieving revision 1.10
diff -u -r1.10 dsopcode.c
--- sys/dev/acpi/acpica/Subsystem/dsopcode.c 14 Feb 2004 16:57:24 -0000 1.10
+++ sys/dev/acpi/acpica/Subsystem/dsopcode.c 8 May 2004 03:05:57 -0000
@@ -2,7 +2,7 @@
*
* Module Name: dsopcode - Dispatcher Op Region support and handling of
* "control" opcodes
- * xRevision: 93 $
+ * xRevision: 94 $
*
*****************************************************************************/
@@ -184,7 +184,7 @@
}
Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart,
- AmlLength, NULL, NULL, 1);
+ AmlLength, NULL, 1);
if (ACPI_FAILURE (Status))
{
AcpiDsDeleteWalkState (WalkState);
@@ -233,7 +233,7 @@
/* Execute the opcode and arguments */
- if (LocalGpeEventInfo.MethodNode)
+ /*
+ * Must check for control method type dispatch one more
+ * time to avoid race with EvGpeInstallHandler
+ */
+ if ((LocalGpeEventInfo.Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD)
{
/*
- * Invoke the GPE Method (_Lxx, _Exx):
- * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
+ * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+ * control method that corresponds to this GPE
*/
- Status = AcpiNsEvaluateByHandle (LocalGpeEventInfo.MethodNode, NULL, NULL);
+ Info.Node = LocalGpeEventInfo.Dispatch.MethodNode;
+ Info.Parameters = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT *, GpeEventInfo);
+ Info.ParameterType = ACPI_PARAM_GPE;
+
+ Status = AcpiNsEvaluateByHandle (&Info);
if (ACPI_FAILURE (Status))
{
- ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
+ ACPI_REPORT_ERROR ((
+ "%s while evaluating method [%4.4s] for GPE[%2X]\n",
AcpiFormatException (Status),
- AcpiUtGetNodeName (LocalGpeEventInfo.MethodNode), GpeNumber));
+ AcpiUtGetNodeName (LocalGpeEventInfo.Dispatch.MethodNode),
+ GpeNumber));
}
}
- if (LocalGpeEventInfo.Flags & ACPI_EVENT_LEVEL_TRIGGERED)
+ if ((LocalGpeEventInfo.Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED)
{
/*
- * GPE is level-triggered, we clear the GPE status bit after handling
- * the event.
+ * GPE is level-triggered, we clear the GPE status bit after
+ * handling the event.
*/
Status = AcpiHwClearGpe (&LocalGpeEventInfo);
if (ACPI_FAILURE (Status))
@@ -437,7 +702,7 @@
* If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced.
*/
- if (GpeEventInfo->Flags & ACPI_EVENT_EDGE_TRIGGERED)
+ if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED)
{
Status = AcpiHwClearGpe (GpeEventInfo);
if (ACPI_FAILURE (Status))
@@ -448,6 +713,17 @@
}
}
+ /* Save current system state */
+
+ if (AcpiGbl_SystemAwakeAndRunning)
+ {
+ GpeEventInfo->Flags |= ACPI_GPE_SYSTEM_RUNNING;
+ }
+ else
+ {
+ GpeEventInfo->Flags &= ~ACPI_GPE_SYSTEM_RUNNING;
+ }
+
/*
* Dispatch the GPE to either an installed handler, or the control
* method associated with this GPE (_Lxx or _Exx).
@@ -455,15 +731,18 @@
* If there is neither a handler nor a method, we disable the level to
* prevent further events from coming in here.
*/
- if (GpeEventInfo->Handler)
+ switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
{
+ case ACPI_GPE_DISPATCH_HANDLER:
+
/* Invoke the installed handler (at interrupt level) */
+
+#ifdef ACPI_GPE_NOTIFY_CHECK
+
+/*******************************************************************************
+ * NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
+ *
+ * FUNCTION: AcpiEvCheckForWakeOnlyGpe
+ *
+ * PARAMETERS: GpeEventInfo - info for this GPE
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Determine if a a GPE is "wake-only".
+ *
+ * Called from Notify() code in interpreter when a "DeviceWake"
+ * Notify comes in.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvCheckForWakeOnlyGpe (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE ("EvCheckForWakeOnlyGpe");
+
+
+ if ((GpeEventInfo) && /* Only >0 for _Lxx/_Exx */
+ ((GpeEventInfo->Flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */
+ {
+ /* This must be a wake-only GPE, disable it */
+
+ Status = AcpiHwDisableGpe (GpeEventInfo);
+
+ /* Set GPE to wake-only. Do not change wake disabled/enabled status */
+
+ AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE);
+
+ ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
+ GpeEventInfo));
+
+ /* This was a wake-only GPE */
+
+ return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+#endif
+
+
Index: sys/dev/acpi/acpica/Subsystem/evgpeblk.c
===================================================================
RCS file: /cvsroot/src/sys/dev/acpi/acpica/Subsystem/evgpeblk.c,v
retrieving revision 1.7
diff -u -r1.7 evgpeblk.c
--- sys/dev/acpi/acpica/Subsystem/evgpeblk.c 14 Feb 2004 16:57:24 -0000 1.7
+++ sys/dev/acpi/acpica/Subsystem/evgpeblk.c 8 May 2004 03:05:59 -0000
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: evgpeblk - GPE block creation and initialization.
- * xRevision: 27 $
+ * xRevision: 32 $
*
*****************************************************************************/
@@ -129,7 +129,7 @@
*
* FUNCTION: AcpiEvValidGpeEvent
*
- * PARAMETERS: GpeEventInfo - Info for this GPE
+ * PARAMETERS: GpeEventInfo - Info for this GPE
*
* RETURN: TRUE if the GpeEvent is valid
*
@@ -236,6 +236,53 @@
}
+/******************************************************************************
+ *
+ * FUNCTION: AcpiEvDeleteGpeHandlers
+ *
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
+ * Used only prior to termination.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvDeleteGpeHandlers (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock)
+{
+ ACPI_GPE_EVENT_INFO *GpeEventInfo;
+ UINT32 i;
+ UINT32 j;
+
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ /* Now look at the individual GPEs in this byte register */
+
+ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
+ {
+ GpeEventInfo = &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+
+ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER)
+ {
+ ACPI_MEM_FREE (GpeEventInfo->Dispatch.Handler);
+ GpeEventInfo->Dispatch.Handler = NULL;
+ GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
+ }
+ }
+ }
+
+ return (AE_OK);
+}
+
+
/*******************************************************************************
*
* FUNCTION: AcpiEvSaveMethodInfo
@@ -250,11 +297,11 @@
* information for quick lookup during GPE dispatch
*
* The name of each GPE control method is of the form:
- * "_Lnn" or "_Enn"
- * Where:
- * L - means that the GPE is level triggered
- * E - means that the GPE is edge triggered
- * nn - is the GPE number [in HEX]
+ * "_Lxx" or "_Exx"
+ * Where:
+ * L - means that the GPE is level triggered
+ * E - means that the GPE is edge triggered
+ * xx - is the GPE number [in HEX]
*
******************************************************************************/
- /* Extract the name from the object and convert to a string */
-
+ /*
+ * _Lxx and _Exx GPE method support
+ *
+ * 1) Extract the name from the object and convert to a string
+ */
ACPI_MOVE_32_TO_32 (Name,
&((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer);
Name[ACPI_NAME_SIZE] = 0;
/*
- * Edge/Level determination is based on the 2nd character
- * of the method name
+ * 2) Edge/Level determination is based on the 2nd character
+ * of the method name
+ *
+ * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
+ * if a _PRW object is found that points to this GPE.
*/
switch (Name[1])
{
case 'L':
- Type = ACPI_EVENT_LEVEL_TRIGGERED;
+ Type = ACPI_GPE_LEVEL_TRIGGERED;
break;
case 'E':
- Type = ACPI_EVENT_EDGE_TRIGGERED;
+ Type = ACPI_GPE_EDGE_TRIGGERED;
break;
default:
/* Unknown method type, just ignore it! */
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
+ "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
Name));
return_ACPI_STATUS (AE_OK);
}
@@ -313,7 +365,7 @@
/* Conversion failed; invalid method, just ignore it */
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not extract GPE number from name: %s (name is not of form _Lnn or _Enn)\n",
+ "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
Name));
return_ACPI_STATUS (AE_OK);
}
@@ -333,20 +385,19 @@
/*
* Now we can add this information to the GpeEventInfo block
- * for use during dispatch of this GPE.
+ * for use during dispatch of this GPE. Default type is RUNTIME, although
+ * this may change when the _PRW methods are executed later.
*/
GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber];
+ /* Find all GPE methods (_Lxx, _Exx) for this block */
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, AcpiEvSaveMethodInfo,
+ GpeBlock, NULL);
+
+ /*
+ * Runtime option: Should Wake GPEs be enabled at runtime? The default
+ * is No,they should only be enabled just as the machine goes to sleep.
+ */
+ if (AcpiGbl_LeaveWakeGpesDisabled)
+ {
+ /*
+ * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
+ * (Each GPE that has one or more _PRWs that reference it is by
+ * definition a WAKE GPE and will not be enabled while the machine
+ * is running.)
+ */
+ GpeInfo.GpeBlock = GpeBlock;
+ GpeInfo.GpeDevice = GpeDevice;
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, AcpiEvMatchPrwAndGpe,
+ &GpeInfo, NULL);
+ }
+
+ /*
+ * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
+ * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must
+ * be enabled via the AcpiEnableGpe() external interface.
+ */
+ WakeGpeCount = 0;
+ GpeEnabledCount = 0;
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ /* Get the info block for this particular GPE */
+
+ GpeEventInfo = &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+
+ if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
+ (GpeEventInfo->Flags & ACPI_GPE_TYPE_RUNTIME))
+ {
+ GpeEnabledCount++;
+ }
+
+ if (GpeEventInfo->Flags & ACPI_GPE_TYPE_WAKE)
+ {
+ WakeGpeCount++;
+ }
+ }
+ }
+
/* Dump info about this GPE block */
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+ "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
GpeBlock->BlockBaseNumber,
(UINT32) (GpeBlock->BlockBaseNumber +
((GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH) -1)),
@@ -868,11 +1106,14 @@
ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (GpeBlock->BlockAddress.Address)),
InterruptLevel));
- /* Find all GPE methods (_Lxx, _Exx) for this block */
- Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
- ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, AcpiEvSaveMethodInfo,
- GpeBlock, NULL);
+ /* Enable all valid GPEs found above */
+
+ Status = AcpiHwEnableRuntimeGpeBlock (NULL, GpeBlock);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+ "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
+ WakeGpeCount, GpeEnabledCount));
- /* Get a handle to the predefined _GPE object */
-
- Status = AcpiGetHandle (NULL, "\\_GPE", &GpeDevice);
+ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
/*
- * Initialize the GPE Blocks defined in the FADT
+ * Initialize the GPE Block(s) defined in the FADT
*
* Why the GPE register block lengths are divided by 2: From the ACPI Spec,
* section "General-Purpose Event Registers", we have:
@@ -954,8 +1193,9 @@
- Status = AcpiEvCreateGpeBlock (GpeDevice, &AcpiGbl_FADT->XGpe1Blk,
+ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, &AcpiGbl_FADT->XGpe1Blk,
RegisterCount1, AcpiGbl_FADT->Gpe1Base,
AcpiGbl_FADT->SciInt, &AcpiGbl_GpeFadtBlocks[1]);
+
if (ACPI_FAILURE (Status))
{
ACPI_REPORT_ERROR ((
@@ -1015,8 +1256,10 @@
{
/* GPEs are not required by ACPI, this is OK */
- ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+ "There are no GPE blocks defined in the FADT\n"));
+ Status = AE_OK;
+ goto Cleanup;
}
/* Check for Max GPE number out-of-range */
@@ -1025,9 +1268,12 @@
{
ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
GpeNumberMax));
- return_ACPI_STATUS (AE_BAD_VALUE);
+ Status = AE_BAD_VALUE;
+ goto Cleanup;
}
/*
- * For value 1 (Ejection Request), some device method may need to be run.
+ * For value 3 (Ejection Request), some device method may need to be run.
* For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
* For value 0x80 (Status Change) on the power button or sleep button,
* initiate soft-off or sleep operation?
@@ -197,27 +211,15 @@
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"Dispatching Notify(%X) on node %p\n", NotifyValue, Node));
+ /* Deallocate all handler objects installed within GPE info structs */
+
+ Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers);
+
/* Return to original mode if necessary */
+ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
/*
* All address spaces (PCI Config, EC, SMBus) are scope dependent
* and registration must occur for a specific device.
@@ -178,10 +184,9 @@
* has already been installed (via AcpiInstallAddressSpaceHandler).
* Similar for AE_SAME_HANDLER.
*/
-
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
{
- Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
+ Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
AcpiGbl_DefaultAddressSpaces[i],
ACPI_DEFAULT_HANDLER, NULL, NULL);
switch (Status)
@@ -192,15 +197,65 @@
/*
- * _REG method has two arguments
- * Arg0: Integer: Operation region space ID
+ * The _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
@@ -269,10 +326,15 @@
Params[1]->Integer.Value = Function;
Params[2] = NULL;
+ Info.Node = RegionObj2->Extra.Method_REG;
+ Info.Parameters = Params;
+ Info.ParameterType = ACPI_PARAM_ARGS;
+
/* Execute the method, no return value */
- if (!(HandlerDesc->AddressSpace.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
+ if (!(HandlerDesc->AddressSpace.Hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* For handlers other than the default (supplied) handlers, we must
@@ -443,7 +505,7 @@
AcpiFormatException (Status)));
}
- if (!(HandlerDesc->AddressSpace.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
+ if (!(HandlerDesc->AddressSpace.Hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* We just returned from a non-default handler, we must re-enter the
@@ -793,6 +855,288 @@
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_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;
+ ACPI_OBJECT_TYPE Type;
+ UINT16 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.Hflags = 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 _REG methods for the Space ID;
+ * Note: assumes namespace is locked, or system init time.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvExecuteRegMethods (
+ 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
@@ -810,20 +1154,13 @@
void *Context,
void **ReturnValue)
{
- ACPI_OPERAND_OBJECT *HandlerObj;
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_NAMESPACE_NODE *Node;
+ ACPI_ADR_SPACE_TYPE SpaceId;
ACPI_STATUS Status;
/*******************************************************************************
*
- * FUNCTION: AcpiEnableGpe
+ * FUNCTION: AcpiSetGpeType
*
* PARAMETERS: GpeDevice - Parent GPE Device
* GpeNumber - GPE level within the GPE block
- * Flags - Just enable, or also wake enable?
- * Called from ISR or not
+ * Type - New GPE type
*
* RETURN: Status
*
@@ -308,28 +307,17 @@
******************************************************************************/
- /* Decode the Fixed Event */
+ /* Use semaphore lock if not executing at interrupt level */
- if (Event > ACPI_EVENT_MAX)
+ if (Flags & ACPI_NOT_ISR)
{
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
}
- /*
- * Disable the requested fixed event (by writing a zero to the
- * enable register bit)
- */
- Status = AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
- 0, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
+ /* Ensure that we have a valid GPE number */
- Status = AcpiGetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
- &Value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (Status))
+ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
+ if (!GpeEventInfo)
{
- return_ACPI_STATUS (Status);
+ Status = AE_BAD_PARAMETER;
+ goto UnlockAndExit;
}
- if (Value != 0)
+ /* Perform the enable */
+
+ Status = AcpiEvEnableGpe (GpeEventInfo, TRUE);
+
+UnlockAndExit:
+ if (Flags & ACPI_NOT_ISR)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not disable %s events\n", AcpiUtGetEventName (Event)));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
}
-
return_ACPI_STATUS (Status);
}
@@ -429,7 +417,7 @@
*
* PARAMETERS: GpeDevice - Parent GPE Device
* GpeNumber - GPE level within the GPE block
- * Flags - Just enable, or also wake enable?
+ * Flags - Just disable, or also wake disable?
* Called from ISR or not
*
* RETURN: Status
@@ -471,24 +459,74 @@
goto UnlockAndExit;
}
+ Status = AcpiEvDisableGpe (GpeEventInfo);
+
+UnlockAndExit:
+ if (Flags & ACPI_NOT_ISR)
+ {
+ (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
+ }
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDisableEvent
+ *
+ * PARAMETERS: Event - The fixed eventto be enabled
+ * Flags - Reserved
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Disable an ACPI event (fixed)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDisableEvent (
+ UINT32 Event,
+ UINT32 Flags)
+{
+ ACPI_STATUS Status = AE_OK;
+ UINT32 Value;
+
+
+ ACPI_FUNCTION_TRACE ("AcpiDisableEvent");
+
+
+ /* Decode the Fixed Event */
+
+ if (Event > ACPI_EVENT_MAX)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
/*
- * Only disable the requested GPE number for wake if specified.
- * Otherwise, turn it totally off
+ * Disable the requested fixed event (by writing a zero to the
+ * enable register bit)
*/
- if (Flags & ACPI_EVENT_WAKE_DISABLE)
+ Status = AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
+ 0, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE (Status))
{
- AcpiHwDisableGpeForWakeup (GpeEventInfo);
+ return_ACPI_STATUS (Status);
}
- else
+
+ Status = AcpiGetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
+ &Value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE (Status))
{
- Status = AcpiHwDisableGpe (GpeEventInfo);
+ return_ACPI_STATUS (Status);
}
- /*
- * 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);
+ /* Install the handler for all Regions for this Space ID */
- 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 = AcpiEvInstallSpaceHandler (Node, SpaceId, Handler, Setup, Context);
+ if (ACPI_FAILURE (Status))
{
- Status = AE_NO_MEMORY;
goto UnlockAndExit;
}
- /* Init handler obj */
+ /* Run all _REG methods for this address space */
- HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
- HandlerObj->AddressSpace.Hflags = 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, Device, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler,
- HandlerObj, NULL);
-
- /*
- * Now we can run the _REG methods for all 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, Device, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, AcpiEvRegRun,
- HandlerObj, NULL);
+ Status = AcpiEvExecuteRegMethods (Node, SpaceId);
@@ -394,13 +395,30 @@
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
ObjDesc, AcpiUtGetObjectTypeName (ObjDesc)));
- /* Get the table header */
+ /*
+ * If the Region Address and Length have not been previously evaluated,
+ * evaluate them now and save the results.
+ */
+ if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
+ {
+ Status = AcpiDsGetRegionArguments (ObjDesc);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ /* Get the base physical address of the region */
+
+ Address = ObjDesc->Region.Address;
+
+ /* Get the table length from the table header */
TableHeader.Length = 0;
- for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++)
+ for (i = 0; i < 8; i++)
{
Status = AcpiEvAddressSpaceDispatch (ObjDesc, ACPI_READ,
- (ACPI_PHYSICAL_ADDRESS) i, 8,
+ (ACPI_PHYSICAL_ADDRESS) i + Address, 8,
((UINT8 *) &TableHeader) + i);
if (ACPI_FAILURE (Status))
{
@@ -408,6 +426,13 @@
}
}
+ /* Sanity check the table length */
+
+ if (TableHeader.Length < sizeof (ACPI_TABLE_HEADER))
+ {
+ return_ACPI_STATUS (AE_BAD_HEADER);
+ }
+
/* Allocate a buffer for the entire table */
- /* Copy the header to the buffer */
-
- ACPI_MEMCPY (TablePtr, &TableHeader, sizeof (ACPI_TABLE_HEADER));
- TableDataPtr = ACPI_PTR_ADD (UINT8, TablePtr, sizeof (ACPI_TABLE_HEADER));
-
- /* Get the table from the op region */
+ /* Get the entire table from the op region */
for (i = 0; i < TableHeader.Length; i++)
{
Status = AcpiEvAddressSpaceDispatch (ObjDesc, ACPI_READ,
- (ACPI_PHYSICAL_ADDRESS) i, 8,
- ((UINT8 *) TableDataPtr + i));
+ (ACPI_PHYSICAL_ADDRESS) i + Address, 8,
+ ((UINT8 *) TablePtr + i));
if (ACPI_FAILURE (Status))
{
goto Cleanup;
@@ -455,6 +475,13 @@
}
- if (TargetNode->Type == ACPI_TYPE_LOCAL_ALIAS)
+ if ((TargetNode->Type == ACPI_TYPE_LOCAL_ALIAS) ||
+ (TargetNode->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS))
{
/*
* Dereference an existing alias so that we don't create a chain
@@ -170,7 +171,7 @@
* always exactly one level of indirection away from the
* actual aliased name.
*/
- TargetNode = (ACPI_NAMESPACE_NODE *) TargetNode->Object;
+ TargetNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, TargetNode->Object);
}
+ case ACPI_TYPE_METHOD:
+
+ /*
+ * The new alias has the type ALIAS and points to the original
+ * NS node, not the object itself. This is because for these
+ * types, the object can change dynamically via a Store.
+ */
+ AliasNode->Type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
+ AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
+ break;
+
default:
/* Attach the original source object to the new Alias Node */
@@ -684,29 +696,36 @@
ObjDesc->Method.AmlStart = AmlStart;
ObjDesc->Method.AmlLength = AmlLength;
- /* disassemble the method flags */
-
+ /*
+ * Disassemble the method flags. Split off the Arg Count
+ * for efficiency
+ */
MethodFlags = (UINT8) Operand[1]->Integer.Value;
@@ -131,7 +131,7 @@
*
* FUNCTION: AcpiExUnlinkMutex
*
- * PARAMETERS: *ObjDesc - The mutex to be unlinked
+ * PARAMETERS: ObjDesc - The mutex to be unlinked
*
* RETURN: Status
*
@@ -151,6 +151,8 @@
return;
}
+ /* Doubly linked list */
+
if (ObjDesc->Mutex.Next)
{
(ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev;
@@ -171,8 +173,8 @@
*
* FUNCTION: AcpiExLinkMutex
*
- * PARAMETERS: *ObjDesc - The mutex to be linked
- * *ListHead - head of the "AcquiredMutex" list
+ * PARAMETERS: ObjDesc - The mutex to be linked
+ * ListHead - head of the "AcquiredMutex" list
*
* RETURN: Status
*
@@ -212,8 +214,8 @@
*
* FUNCTION: AcpiExAcquireMutex
*
- * PARAMETERS: *TimeDesc - The 'time to delay' object descriptor
- * *ObjDesc - The object descriptor for this op
+ * PARAMETERS: TimeDesc - The 'time to delay' object descriptor
+ * ObjDesc - The object descriptor for this op
*
* RETURN: Status
*
@@ -258,19 +260,22 @@
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
}
- /*
- * Support for multiple acquires by the owning thread
- */
+ /* Support for multiple acquires by the owning thread */
- if ((ObjDesc->Mutex.OwnerThread) &&
- (ObjDesc->Mutex.OwnerThread->ThreadId == WalkState->Thread->ThreadId))
+ if (ObjDesc->Mutex.OwnerThread)
{
- /*
- * The mutex is already owned by this thread,
- * just increment the acquisition depth
- */
- ObjDesc->Mutex.AcquisitionDepth++;
- return_ACPI_STATUS (AE_OK);
+ /* Special case for Global Lock, allow all threads */
+
+ if ((ObjDesc->Mutex.OwnerThread->ThreadId == WalkState->Thread->ThreadId) ||
+ (ObjDesc->Mutex.Semaphore == AcpiGbl_GlobalLockSemaphore))
+ {
+ /*
+ * The mutex is already owned by this thread,
+ * just increment the acquisition depth
+ */
+ ObjDesc->Mutex.AcquisitionDepth++;
+ return_ACPI_STATUS (AE_OK);
+ }
}
/* Acquire the mutex, wait if necessary */
@@ -283,12 +288,12 @@
return_ACPI_STATUS (Status);
}
- /* Have the mutex, update mutex and walk info */
+ /* Have the mutex: update mutex and walk info and save the SyncLevel */
/* Link the mutex to the current thread for force-unlock at method exit */
@@ -303,7 +308,7 @@
*
* FUNCTION: AcpiExReleaseMutex
*
- * PARAMETERS: *ObjDesc - The object descriptor for this op
+ * PARAMETERS: ObjDesc - The object descriptor for this op
*
* RETURN: Status
*
@@ -345,9 +350,12 @@
return_ACPI_STATUS (AE_AML_INTERNAL);
}
- /* The Mutex is owned, but this thread must be the owner */
-
- if (ObjDesc->Mutex.OwnerThread->ThreadId != WalkState->Thread->ThreadId)
+ /*
+ * The Mutex is owned, but this thread must be the owner.
+ * Special case for Global Lock, any thread can release
+ */
+ if ((ObjDesc->Mutex.OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
+ (ObjDesc->Mutex.Semaphore != AcpiGbl_GlobalLockSemaphore))
{
ACPI_REPORT_ERROR ((
"Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
@@ -368,9 +376,8 @@
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
}
- /*
- * Match multiple Acquires with multiple Releases
- */
+ /* Match multiple Acquires with multiple Releases */
+
ObjDesc->Mutex.AcquisitionDepth--;
if (ObjDesc->Mutex.AcquisitionDepth != 0)
{
@@ -387,10 +394,10 @@
Status = AcpiExSystemReleaseMutex (ObjDesc);
- /* Update the mutex and walk state */
+ /* Update the mutex and walk state, restore SyncLevel before acquire */
return_ACPI_STATUS (Status);
}
@@ -400,7 +407,7 @@
*
* FUNCTION: AcpiExReleaseAllMutexes
*
- * PARAMETERS: *MutexList - Head of the mutex list
+ * PARAMETERS: MutexList - Head of the mutex list
*
* RETURN: Status
*
@@ -420,9 +427,8 @@
ACPI_FUNCTION_ENTRY ();
- /*
- * Traverse the list of owned mutexes, releasing each one.
- */
+ /* Traverse the list of owned mutexes, releasing each one */
+
while (Next)
{
This = Next;
@@ -442,7 +448,11 @@
/* Mark mutex unowned */
- This->Mutex.OwnerThread = NULL;
+ This->Mutex.OwnerThread = NULL;
+
+ /* Update Thread SyncLevel (Last mutex is the important one) */
+
+ Thread->CurrentSyncLevel = This->Mutex.OriginalSyncLevel;
}
}
+ /* Second value is the notify value */
+
+ Value = (UINT32) Operand[1]->Integer.Value;
+
/* Notifies allowed on this object? */
if (!AcpiEvIsNotifyObject (Node))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Unexpected notify object type [%s]\n",
AcpiUtGetTypeName (Node->Type)));
Status = AE_AML_OPERAND_TYPE;
break;
}
+#ifdef ACPI_GPE_NOTIFY_CHECK
+ /*
+ * GPE method wake/notify check. Here, we want to ensure that we
+ * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx
+ * GPE method during system runtime. If we do, the GPE is marked
+ * as "wake-only" and disabled.
+ *
+ * 1) Is the Notify() value == DeviceWake?
+ * 2) Is this a GPE deferred method? (An _Lxx or _Exx method)
+ * 3) Did the original GPE happen at system runtime?
+ * (versus during wake)
+ *
+ * If all three cases are true, this is a wake-only GPE that should
+ * be disabled at runtime.
+ */
+ if (Value == 2) /* DeviceWake */
+ {
+ Status = AcpiEvCheckForWakeOnlyGpe (WalkState->GpeEventInfo);
+ if (ACPI_FAILURE (Status))
+ {
+ /* AE_WAKE_ONLY_GPE only error, means ignore this notify */
+
+ return_ACPI_STATUS (AE_OK)
+ }
+ }
+#endif
+
/*
* Dispatch the notify to the appropriate handler
* NOTE: the request is queued for execution after this method
@@ -210,8 +243,7 @@
* from this thread -- because handlers may in turn run other
* control methods.
*/
- Status = AcpiEvQueueNotifyRequest (Node,
- (UINT32) Operand[1]->Integer.Value);
+ Status = AcpiEvQueueNotifyRequest (Node, Value);
break;
- if (EntryType == ACPI_TYPE_LOCAL_ALIAS)
+ if ((EntryType == ACPI_TYPE_LOCAL_ALIAS) ||
+ (EntryType == ACPI_TYPE_LOCAL_METHOD_ALIAS))
{
/* There is always exactly one level of indirection */
@@ -129,11 +129,12 @@
*
* FUNCTION: AcpiHwEnableGpe
*
- * PARAMETERS: GpeNumber - The GPE
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to be enabled
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Enable a single GPE.
+ * DESCRIPTION: Enable a single GPE. Note: The bit for this GPE must already
+ * be set in the parent register EnableForRun mask.
*
******************************************************************************/
@@ -141,51 +142,8 @@
AcpiHwEnableGpe (
ACPI_GPE_EVENT_INFO *GpeEventInfo)
{
- UINT32 InByte;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- /*
- * Read the current value of the register, set the appropriate bit
- * to enable the GPE, and write out the new register.
- */
- Status = AcpiHwLowLevelRead (8, &InByte,
- &GpeEventInfo->RegisterInfo->EnableAddress);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Write with the new GPE bit enabled */
-
- Status = AcpiHwLowLevelWrite (8, (InByte | GpeEventInfo->BitMask),
- &GpeEventInfo->RegisterInfo->EnableAddress);
-
- return (Status);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION: AcpiHwEnableGpeForWakeup
- *
- * PARAMETERS: GpeNumber - The GPE
- *
- * RETURN: None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- * disabled when going to sleep.
- *
- ******************************************************************************/
-
-void
-AcpiHwEnableGpeForWakeup (
- ACPI_GPE_EVENT_INFO *GpeEventInfo)
-{
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+ ACPI_STATUS Status;
- /*
- * Set the bit so we will not disable this when sleeping
- */
- GpeRegisterInfo->WakeEnable |= GpeEventInfo->BitMask;
+ /* Write GPE enable register with the new GPE bit enabled */
+
+ Status = AcpiHwLowLevelWrite (8, GpeRegisterInfo->EnableForRun,
+ &GpeRegisterInfo->EnableAddress);
+
+ return (Status);
}
@@ -210,9 +170,9 @@
*
* FUNCTION: AcpiHwDisableGpe
*
- * PARAMETERS: GpeNumber - The GPE
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Disable a single GPE.
*
@@ -222,9 +182,8 @@
AcpiHwDisableGpe (
ACPI_GPE_EVENT_INFO *GpeEventInfo)
{
- UINT32 InByte;
- ACPI_STATUS Status;
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+ ACPI_STATUS Status;
ACPI_FUNCTION_ENTRY ();
@@ -235,69 +194,14 @@
GpeRegisterInfo = GpeEventInfo->RegisterInfo;
if (!GpeRegisterInfo)
{
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * Read the current value of the register, clear the appropriate bit,
- * and write out the new register value to disable the GPE.
- */
- Status = AcpiHwLowLevelRead (8, &InByte,
- &GpeRegisterInfo->EnableAddress);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
+ return (AE_NOT_EXIST);
}
- /* Write the byte with this GPE bit cleared */
+ /* Write the GPE enable register with this GPE bit cleared */
- Status = AcpiHwLowLevelWrite (8, (InByte & ~(GpeEventInfo->BitMask)),
+ Status = AcpiHwLowLevelWrite (8, GpeRegisterInfo->EnableForRun,
&GpeRegisterInfo->EnableAddress);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- AcpiHwDisableGpeForWakeup (GpeEventInfo);
- return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION: AcpiHwDisableGpeForWakeup
- *
- * PARAMETERS: GpeNumber - The GPE
- *
- * RETURN: None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- * disabled when going to sleep.
- *
- ******************************************************************************/
-
-void
-AcpiHwDisableGpeForWakeup (
- ACPI_GPE_EVENT_INFO *GpeEventInfo)
-{
- ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- /* Get the info block for the entire GPE register */
-
- GpeRegisterInfo = GpeEventInfo->RegisterInfo;
- if (!GpeRegisterInfo)
- {
- return;
- }
-
- /*
- * Clear the bit so we will disable this when sleeping
- */
- GpeRegisterInfo->WakeEnable &= ~(GpeEventInfo->BitMask);
+ return (Status);
}
@@ -305,11 +209,11 @@
*
* FUNCTION: AcpiHwClearGpe
*
- * PARAMETERS: GpeNumber - The GPE
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared
*
- * RETURN: None
+ * RETURN: StatusStatus
*
- * DESCRIPTION: Clear a single GPE.
+ * DESCRIPTION: Clear the status bit for a single GPE.
*
******************************************************************************/
@@ -327,7 +231,7 @@
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
- Status = AcpiHwLowLevelWrite (8, GpeEventInfo->BitMask,
+ Status = AcpiHwLowLevelWrite (8, GpeEventInfo->RegisterBit,
&GpeEventInfo->RegisterInfo->StatusAddress);
return (Status);
@@ -338,9 +242,10 @@
*
* FUNCTION: AcpiHwGetGpeStatus
*
- * PARAMETERS: GpeNumber - The GPE
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to queried
+ * EventStatus - Where the GPE status is returned
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Return the status of a single GPE.
*
@@ -352,7 +257,7 @@
ACPI_EVENT_STATUS *EventStatus)
{
UINT32 InByte;
- UINT8 BitMask;
+ UINT8 RegisterBit;
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
ACPI_STATUS Status;
ACPI_EVENT_STATUS LocalEventStatus = 0;
@@ -372,29 +277,23 @@
- /* GPE Enabled? */
-
- Status = AcpiHwLowLevelRead (8, &InByte, &GpeRegisterInfo->EnableAddress);
- if (ACPI_FAILURE (Status))
- {
- goto UnlockAndExit;
- }
+ /* GPE currently enabled? (enabled for runtime?) */
- if (BitMask & InByte)
+ if (RegisterBit & GpeRegisterInfo->EnableForRun)
{
LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
}
- /* GPE Enabled for wake? */
+ /* GPE enabled for wake? */
- if (BitMask & GpeRegisterInfo->WakeEnable)
+ if (RegisterBit & GpeRegisterInfo->EnableForWake)
{
LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
}
- /* GPE active (set)? */
+ /* GPE currently active (status bit == 1)? */
Status = AcpiHwLowLevelRead (8, &InByte, &GpeRegisterInfo->StatusAddress);
if (ACPI_FAILURE (Status))
@@ -402,7 +301,7 @@
goto UnlockAndExit;
}
- if (BitMask & InByte)
+ if (RegisterBit & InByte)
{
LocalEventStatus |= ACPI_EVENT_FLAG_SET;
}
@@ -466,7 +365,7 @@
*
* RETURN: Status
*
- * DESCRIPTION: Clear all GPEs within a GPE block
+ * DESCRIPTION: Clear status bits for all GPEs within a GPE block
*
******************************************************************************/
@@ -483,7 +382,7 @@
for (i = 0; i < GpeBlock->RegisterCount; i++)
{
- /* Clear all GPEs in this register */
+ /* Clear status on all GPEs in this register */
Status = AcpiHwLowLevelWrite (8, 0xFF,
&GpeBlock->RegisterInfo[i].StatusAddress);
@@ -499,60 +398,46 @@
/******************************************************************************
*
- * FUNCTION: AcpiHwDisableNonWakeupGpeBlock
+ * FUNCTION: AcpiHwEnableRuntimeGpeBlock
*
* PARAMETERS: GpeXruptInfo - GPE Interrupt info
* GpeBlock - Gpe Block info
*
* RETURN: Status
*
- * DESCRIPTION: Disable all GPEs except wakeup GPEs in a GPE block
+ * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
+ * combination wake/run GPEs.)
*
******************************************************************************/
- /* Get the register info for the entire GPE block */
-
- GpeRegisterInfo = GpeBlock->RegisterInfo;
+ /* NOTE: assumes that all GPEs are currently disabled */
/* Examine each GPE Register within the block */
for (i = 0; i < GpeBlock->RegisterCount; i++)
{
- /*
- * Read the enabled status of all GPEs. We
- * will be using it to restore all the GPEs later.
- */
- Status = AcpiHwLowLevelRead (8, &InValue,
- &GpeRegisterInfo->EnableAddress);
- if (ACPI_FAILURE (Status))
+ if (!GpeBlock->RegisterInfo[i].EnableForRun)
{
- return (Status);
+ continue;
}
- GpeRegisterInfo->Enable = (UINT8) InValue;
+ /* Enable all "runtime" GPEs in this register */
- /*
- * Disable all GPEs except wakeup GPEs.
- */
- Status = AcpiHwLowLevelWrite (8, GpeRegisterInfo->WakeEnable,
- &GpeRegisterInfo->EnableAddress);
+ Status = AcpiHwLowLevelWrite (8, GpeBlock->RegisterInfo[i].EnableForRun,
+ &GpeBlock->RegisterInfo[i].EnableAddress);
if (ACPI_FAILURE (Status))
{
return (Status);
}
-
- GpeRegisterInfo++;
}
return (AE_OK);
@@ -561,102 +446,115 @@
/******************************************************************************
*
- * FUNCTION: AcpiHwDisableNonWakeupGpes
+ * FUNCTION: AcpiHwEnableWakeupGpeBlock
*
- * PARAMETERS: None
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Disable all non-wakeup GPEs
- * Called with interrupts disabled. The interrupt handler also
- * modifies GpeRegisterInfo->Enable, so it should not be
- * given the chance to run until after non-wake GPEs are
- * re-enabled.
+ * DESCRIPTION: Enable all "wake" GPEs within a GPE block. (Includes
+ * combination wake/run GPEs.)
*
******************************************************************************/
- /* This callback processes one entire GPE block */
+ ACPI_FUNCTION_ENTRY ();
- /* Get the register info for the entire GPE block */
- GpeRegisterInfo = GpeBlock->RegisterInfo;
+ Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock);
+ Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
+ return (Status);
+}
- /* Examine each GPE register within the block */
- for (i = 0; i < GpeBlock->RegisterCount; i++)
- {
- /*
- * We previously stored the enabled status of all GPEs.
- * Blast them back in.
- */
- Status = AcpiHwLowLevelWrite (8, GpeRegisterInfo->Enable,
- &GpeRegisterInfo->EnableAddress);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwEnableAllRuntimeGpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all GPEs of the given type
+ *
+ ******************************************************************************/
ACPI_FUNCTION_TRACE ("AcpiGetSleepTypeData");
@@ -236,19 +236,20 @@
/*
* Evaluate the namespace object containing the values for this state
*/
- Status = AcpiNsEvaluateByName ((char *) AcpiGbl_DbSleepStates[SleepState],
- NULL, &ObjDesc);
+ Info.Parameters = NULL;
+ Status = AcpiNsEvaluateByName ((char *) AcpiGbl_SleepStateNames[SleepState],
+ &Info);
if (ACPI_FAILURE (Status))
{
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating SleepState [%s]\n",
- AcpiFormatException (Status), AcpiGbl_DbSleepStates[SleepState]));
+ AcpiFormatException (Status), AcpiGbl_SleepStateNames[SleepState]));
return_ACPI_STATUS (Status);
}
/* Must have a return object */
- if (!ObjDesc)
+ if (!Info.ReturnObject)
{
ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
Status = AE_NOT_EXIST;
@@ -256,7 +257,7 @@
/* It must be of type Package */
- else if (ACPI_GET_OBJECT_TYPE (ObjDesc) != ACPI_TYPE_PACKAGE)
+ else if (ACPI_GET_OBJECT_TYPE (Info.ReturnObject) != ACPI_TYPE_PACKAGE)
{
ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
Status = AE_AML_OPERAND_TYPE;
@@ -264,7 +265,7 @@
/* The package must have at least two elements */
- else if (ObjDesc->Package.Count < 2)
+ else if (Info.ReturnObject->Package.Count < 2)
{
ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
Status = AE_AML_NO_OPERAND;
@@ -272,12 +273,12 @@
/* The first two elements must both be of type Integer */
- else if ((ACPI_GET_OBJECT_TYPE (ObjDesc->Package.Elements[0]) != ACPI_TYPE_INTEGER) ||
- (ACPI_GET_OBJECT_TYPE (ObjDesc->Package.Elements[1]) != ACPI_TYPE_INTEGER))
+ else if ((ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[0]) != ACPI_TYPE_INTEGER) ||
+ (ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[1]) != ACPI_TYPE_INTEGER))
{
ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
- AcpiUtGetObjectTypeName (ObjDesc->Package.Elements[0]),
- AcpiUtGetObjectTypeName (ObjDesc->Package.Elements[1])));
+ AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[0]),
+ AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[1])));
Status = AE_AML_OPERAND_TYPE;
}
else
@@ -285,17 +286,19 @@
/*
* Valid _Sx_ package size, type, and value
*/
- *SleepTypeA = (UINT8) (ObjDesc->Package.Elements[0])->Integer.Value;
- *SleepTypeB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.Value;
+ *SleepTypeA = (UINT8) (Info.ReturnObject->Package.Elements[0])->Integer.Value;
+ *SleepTypeB = (UINT8) (Info.ReturnObject->Package.Elements[1])->Integer.Value;
}
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating SleepState [%s], bad Sleep object %p type %s\n",
- AcpiGbl_DbSleepStates[SleepState], ObjDesc, AcpiUtGetObjectTypeName (ObjDesc)));
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "While evaluating SleepState [%s], bad Sleep object %p type %s\n",
+ AcpiGbl_SleepStateNames[SleepState], Info.ReturnObject,
+ AcpiUtGetObjectTypeName (Info.ReturnObject)));
}
- Status = AcpiEvaluateObject (NULL, "\\_PTS", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
return_ACPI_STATUS (Status);
}
- Status = AcpiEvaluateObject (NULL, "\\_GTS", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
return_ACPI_STATUS (Status);
}
- /* Set the system indicators to show the desired sleep state. */
+ /* Setup the argument to _SST */
switch (SleepState)
{
case ACPI_STATE_S0:
- /* _SST 1: Working */
- Arg.Integer.Value = 1;
+ Arg.Integer.Value = ACPI_SST_WORKING;
break;
+
case ACPI_STATE_S1:
case ACPI_STATE_S2:
case ACPI_STATE_S3:
- /* _SST 3: Sleeping. Used to indicate system state S1, S2 or S3. */
- Arg.Integer.Value = 3;
+ Arg.Integer.Value = ACPI_SST_SLEEPING;
break;
+
case ACPI_STATE_S4:
- /* _SST 4: Sleeping with context saved to non-volatile storage. */
- Arg.Integer.Value = 4;
+ Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
break;
- case ACPI_STATE_S5:
- /* _SST 0: No system state indication. Indicator off. */
- Arg.Integer.Value = 0;
+
+ default:
+ Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
break;
}
- Status = AcpiEvaluateObject (NULL, "\\_SI._SST", &ArgList, NULL);
+ /* Set the system indicators to show the desired sleep state. */
+
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
@@ -339,22 +353,24 @@
SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
- if (SleepState != ACPI_STATE_S5)
+ /* Clear wake status */
+
+ Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (Status))
{
- /* Clear wake status */
+ return_ACPI_STATUS (Status);
+ }
- Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
+ /* Clear all fixed and general purpose status bits */
- Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
+ Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
{
+ /* _OSI is optional for now, will be permanent later */
+
+ if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
+ {
+ continue;
+ }
+
Status = AcpiNsLookup (NULL, InitVal->Name, InitVal->Type,
- ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &NewNode);
+ ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
+ NULL, &NewNode);
if (ACPI_FAILURE (Status) || (!NewNode)) /* Must be on same line for code converter */
{
@@ -205,7 +213,8 @@
Status = AcpiOsPredefinedOverride (InitVal, &Val);
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n",
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Could not override predefined %s\n",
InitVal->Name));
}
-#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
+#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_APP)
- /* Compiler cheats by putting parameter count in the OwnerID */
+ /* iASL Compiler cheats by putting parameter count in the OwnerID */
NewNode->OwnerId = ObjDesc->Method.ParamCount;
+#else
+ /* Mark this as a very SPECIAL method */
+
+ ObjDesc->Method.MethodFlags = AML_METHOD_INTERNAL_ONLY;
+ ObjDesc->Method.Implementation = AcpiUtOsiImplementation;
#endif
break;
@@ -305,9 +310,9 @@
* to evaluate it.
*/
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
- Pathname, Node, AcpiNsGetAttachedObject (Node)));
+ Pathname, Info->Node, AcpiNsGetAttachedObject (Info->Node)));
- Status = AcpiNsEvaluateByHandle (Node, Params, ReturnObject);
+ Status = AcpiNsEvaluateByHandle (Info);
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
Pathname));
@@ -334,6 +339,7 @@
* Params - List of parameters to pass to the method,
* terminated by NULL. Params itself may be
* NULL if no parameters are being passed.
+ * ParamType - Type of Parameter list
* ReturnObject - Where to put method's return value (if
* any). If NULL, no value is returned.
*
@@ -347,13 +353,9 @@
/*
+ * For a method alias, we must grab the actual method node
+ * so that proper scoping context will be established
+ * before execution.
+ */
+ if (AcpiNsGetType (Info->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS)
+ {
+ Info->Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Info->Node->Object);
+ }
+
+ /*
* Two major cases here:
* 1) The object is an actual control method -- execute it.
* 2) The object is not a method -- just return it's current
@@ -404,13 +413,12 @@
* In both cases, the namespace is unlocked by the
* AcpiNs* procedure
*/
- if (AcpiNsGetType (Node) == ACPI_TYPE_METHOD)
+ if (AcpiNsGetType (Info->Node) == ACPI_TYPE_METHOD)
{
/*
* Case 1) We have an actual control method to execute
*/
- Status = AcpiNsExecuteControlMethod (Node, Params,
- &LocalReturnObject);
+ Status = AcpiNsExecuteControlMethod (Info);
}
else
{
@@ -418,7 +426,7 @@
* Case 2) Object is NOT a method, just return its
* current value
*/
- Status = AcpiNsGetObjectValue (Node, &LocalReturnObject);
+ Status = AcpiNsGetObjectValue (Info);
}
/*
@@ -427,21 +435,6 @@
*/
if (Status == AE_CTRL_RETURN_VALUE)
{
- /*
- * If the Method returned a value and the caller
- * provided a place to store a returned value, Copy
- * the returned value to the object descriptor provided
- * by the caller.
- */
- if (ReturnObject)
- {
- /*
- * Valid return object, copy the pointer to
- * the returned object
- */
- *ReturnObject = LocalReturnObject;
- }
-
/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
- Node = AcpiNsMapHandleToNode (ObjHandle);
- if (!Node)
+ Pinfo.Parameters = NULL;
+ Pinfo.ParameterType = ACPI_PARAM_ARGS;
+
+ Pinfo.Node = AcpiNsMapHandleToNode (ObjHandle);
+ if (!Pinfo.Node)
{
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
@@ -443,8 +446,8 @@
/*
* We will run _STA/_INI on Devices and Processors only
*/
- if ((Node->Type != ACPI_TYPE_DEVICE) &&
- (Node->Type != ACPI_TYPE_PROCESSOR))
+ if ((Pinfo.Node->Type != ACPI_TYPE_DEVICE) &&
+ (Pinfo.Node->Type != ACPI_TYPE_PROCESSOR))
{
return_ACPI_STATUS (AE_OK);
}
@@ -459,12 +462,12 @@
/*
* Run _STA to determine if we can run _INI on the device.
*/
- ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Node, "_STA"));
- Status = AcpiUtExecute_STA (Node, &Flags);
+ ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Pinfo.Node, "_STA"));
+ Status = AcpiUtExecute_STA (Pinfo.Node, &Flags);
if (ACPI_FAILURE (Status))
{
- if (Node->Type == ACPI_TYPE_DEVICE)
+ if (Pinfo.Node->Type == ACPI_TYPE_DEVICE)
{
/* Ignore error and move on to next device */
@@ -488,8 +491,8 @@
/*
* The device is present. Run _INI.
*/
- ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, ObjHandle, "_INI"));
- Status = AcpiNsEvaluateRelative (ObjHandle, "_INI", NULL, NULL);
+ ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Pinfo.Node, "_INI"));
+ Status = AcpiNsEvaluateRelative ("_INI", &Pinfo);
if (ACPI_FAILURE (Status))
{
/* No _INI (AE_NOT_FOUND) means device requires no initialization */
@@ -499,7 +502,7 @@
/* Ignore error and move on to next device */
#define _COMPONENT ACPI_NAMESPACE
@@ -234,11 +235,11 @@
* FUNCTION: AcpiEvaluateObject
*
* PARAMETERS: Handle - Object handle (optional)
- * *Pathname - Object pathname (optional)
- * **ExternalParams - List of parameters to pass to method,
+ * Pathname - Object pathname (optional)
+ * ExternalParams - List of parameters to pass to method,
* terminated by NULL. May be NULL
* if no parameters are being passed.
- * *ReturnBuffer - Where to put method's return value (if
+ * ReturnBuffer - Where to put method's return value (if
* any). If NULL, no value is returned.
*
* RETURN: Status
@@ -257,8 +258,8 @@
ACPI_BUFFER *ReturnBuffer)
{
ACPI_STATUS Status;
- ACPI_OPERAND_OBJECT **InternalParams = NULL;
- ACPI_OPERAND_OBJECT *InternalReturnObj = NULL;
+ ACPI_STATUS Status2;
+ ACPI_PARAMETER_INFO Info;
ACPI_SIZE BufferSpaceNeeded;
UINT32 i;
+ Info.Node = Handle;
+ Info.Parameters = NULL;
+ Info.ReturnObject = NULL;
+ Info.ParameterType = ACPI_PARAM_ARGS;
+
/*
* If there are parameters to be passed to the object
* (which must be a control method), the external objects
@@ -277,9 +283,10 @@
* Allocate a new parameter block for the internal objects
* Add 1 to count to allow for null terminated internal list
*/
- InternalParams = ACPI_MEM_CALLOCATE (((ACPI_SIZE) ExternalParams->Count + 1) *
- sizeof (void *));
- if (!InternalParams)
+ Info.Parameters = ACPI_MEM_CALLOCATE (
+ ((ACPI_SIZE) ExternalParams->Count + 1) *
+ sizeof (void *));
+ if (!Info.Parameters)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
@@ -291,16 +298,17 @@
for (i = 0; i < ExternalParams->Count; i++)
{
Status = AcpiUtCopyEobjectToIobject (&ExternalParams->Pointer[i],
- &InternalParams[i]);
+ &Info.Parameters[i]);
if (ACPI_FAILURE (Status))
{
- AcpiUtDeleteInternalObjectList (InternalParams);
+ AcpiUtDeleteInternalObjectList (Info.Parameters);
return_ACPI_STATUS (Status);
}
}
- InternalParams[ExternalParams->Count] = NULL;
+ Info.Parameters[ExternalParams->Count] = NULL;
}
+
/*
* Three major cases:
* 1) Fully qualified pathname
@@ -313,8 +321,7 @@
/*
* The path is fully qualified, just evaluate by name
*/
- Status = AcpiNsEvaluateByName (Pathname, InternalParams,
- &InternalReturnObj);
+ Status = AcpiNsEvaluateByName (Pathname, &Info);
}
else if (!Handle)
{
@@ -349,16 +356,14 @@
* The null pathname case means the handle is for
* the actual object to be evaluated
*/
- Status = AcpiNsEvaluateByHandle (Handle, InternalParams,
- &InternalReturnObj);
+ Status = AcpiNsEvaluateByHandle (&Info);
}
else
{
/*
* Both a Handle and a relative Pathname
*/
- Status = AcpiNsEvaluateRelative (Handle, Pathname, InternalParams,
- &InternalReturnObj);
+ Status = AcpiNsEvaluateRelative (Pathname, &Info);
}
}
@@ -369,13 +374,13 @@
*/
if (ReturnBuffer)
{
- if (!InternalReturnObj)
+ if (!Info.ReturnObject)
{
ReturnBuffer->Length = 0;
}
else
{
- if (ACPI_GET_DESCRIPTOR_TYPE (InternalReturnObj) == ACPI_DESC_TYPE_NAMED)
+ if (ACPI_GET_DESCRIPTOR_TYPE (Info.ReturnObject) == ACPI_DESC_TYPE_NAMED)
{
/*
* If we received a NS Node as a return object, this means that
@@ -386,7 +391,7 @@
* support for various types at a later date if necessary.
*/
Status = AE_TYPE;
- InternalReturnObj = NULL; /* No need to delete a NS Node */
+ Info.ReturnObject = NULL; /* No need to delete a NS Node */
ReturnBuffer->Length = 0;
}
@@ -396,7 +401,7 @@
* Find out how large a buffer is needed
* to contain the returned object
*/
- Status = AcpiUtGetObjectSize (InternalReturnObj,
+ Status = AcpiUtGetObjectSize (Info.ReturnObject,
&BufferSpaceNeeded);
if (ACPI_SUCCESS (Status))
{
@@ -410,14 +415,15 @@
*/
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"Needed buffer size %X, %s\n",
- (UINT32) BufferSpaceNeeded, AcpiFormatException (Status)));
+ (UINT32) BufferSpaceNeeded,
+ AcpiFormatException (Status)));
}
else
{
/*
* We have enough space for the object, build it
*/
- Status = AcpiUtCopyIobjectToEobject (InternalReturnObj,
+ Status = AcpiUtCopyIobjectToEobject (Info.ReturnObject,
ReturnBuffer);
}
}
@@ -425,25 +431,32 @@
}
}
- /* Delete the return and parameter objects */
-
- if (InternalReturnObj)
+ if (Info.ReturnObject)
{
/*
- * Delete the internal return object. (Or at least
- * decrement the reference count by one)
+ * Delete the internal return object. NOTE: Interpreter
+ * must be locked to avoid race condition.
*/
- AcpiUtRemoveReference (InternalReturnObj);
+ Status2 = AcpiExEnterInterpreter ();
+ if (ACPI_SUCCESS (Status2))
+ {
+ /*
+ * Delete the internal return object. (Or at least
+ * decrement the reference count by one)
+ */
+ AcpiUtRemoveReference (Info.ReturnObject);
+ AcpiExExitInterpreter ();
+ }
}
/*
* Free the input parameter list (if we created one),
*/
- if (InternalParams)
+ if (Info.Parameters)
{
/* Free the allocated parameter block */
@@ -377,7 +377,7 @@
{
/*
* Get extra info for ACPI Devices objects only:
- * Run the Device _HID, _UID, _CID, _STA, and _ADR methods.
+ * Run the Device _HID, _UID, _CID, _STA, _ADR and _SxD methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info.Valid bitfield is used
@@ -427,6 +427,14 @@
Info.Valid |= ACPI_VALID_ADR;
}
+ /* Execute the Device._SxD methods */
+
+ Status = AcpiUtExecute_Sxds (Node, Info.HighestDstates);
+ if (ACPI_SUCCESS (Status))
+ {
+ Info.Valid |= ACPI_VALID_SXDS;
+ }
+
Status = AE_OK;
}
if (Op->Common.AmlOpcode == AML_REGION_OP)
@@ -996,6 +1007,11 @@
AcpiPsCompleteThisOp (WalkState, Op);
Op = NULL;
+ if (PreOp)
+ {
+ AcpiPsFreeOp (PreOp);
+ PreOp = NULL;
+ }
switch (Status)
{
@@ -1288,6 +1304,30 @@
{
ACPI_REPORT_METHOD_ERROR ("Method execution failed",
WalkState->MethodNode, NULL, Status);
+
+ /* Check for possible multi-thread reentrancy problem */
+
+ if ((Status == AE_ALREADY_EXISTS) &&
+ (!WalkState->MethodDesc->Method.Semaphore))
+ {
+ /*
+ * This method is marked NotSerialized, but it tried to create a named
+ * object, causing the second thread entrance to fail. We will workaround
+ * this by marking the method permanently as Serialized.
+ */
+ WalkState->MethodDesc->Method.MethodFlags |= AML_METHOD_SERIALIZED;
+ WalkState->MethodDesc->Method.Concurrency = 1;
+ }
+ }
+
+ if (WalkState->MethodDesc)
+ {
+ /* Decrement the thread count on the method parse tree */
+
+ if (WalkState->MethodDesc->Method.ThreadCount)
+ {
+ WalkState->MethodDesc->Method.ThreadCount--;
+ }
}
/* We are done with this walk, move on to the parent if any */
Index: sys/dev/acpi/acpica/Subsystem/psscope.c
===================================================================
RCS file: /cvsroot/src/sys/dev/acpi/acpica/Subsystem/psscope.c,v
retrieving revision 1.10
diff -u -r1.10 psscope.c
--- sys/dev/acpi/acpica/Subsystem/psscope.c 14 Feb 2004 16:57:25 -0000 1.10
+++ sys/dev/acpi/acpica/Subsystem/psscope.c 8 May 2004 03:06:06 -0000
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: psscope - Parser scope stack management routines
- * xRevision: 37 $
+ * xRevision: 38 $
*
*****************************************************************************/
@@ -134,7 +134,7 @@
*
* FUNCTION: AcpiPsxExecute
*
- * PARAMETERS: MethodNode - A method object containing both the AML
+ * PARAMETERS: Info->Node - A method object containing both the AML
* address and length.
* **Params - List of parameters to pass to method,
* terminated by NULL. Params itself may be
@@ -150,9 +150,7 @@
/* Init for new method, wait on concurrency semaphore */
- Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, NULL);
+ Status = AcpiDsBeginMethodExecution (Info->Node, ObjDesc, NULL);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
- if (Params)
+ if (Info &&
+ (Info->ParameterType == ACPI_PARAM_ARGS) &&
+ (Info->Parameters))
{
/*
* The caller "owns" the parameters, so give each one an extra
* reference
*/
- for (i = 0; Params[i]; i++)
+ for (i = 0; Info->Parameters[i]; i++)
{
- AcpiUtAddReference (Params[i]);
+ AcpiUtAddReference (Info->Parameters[i]);
}
}
Cleanup1:
- if (Params)
+ if ((Info->ParameterType == ACPI_PARAM_ARGS) &&
+ (Info->Parameters))
{
/* Take away the extra reference that we gave the parameters above */
- for (i = 0; Params[i]; i++)
+ for (i = 0; Info->Parameters[i]; i++)
{
/* Ignore errors, just do them all */
@@ -320,11 +322,11 @@
* If the method has returned an object, signal this to the caller with
* a control exception code
*/
- if (*ReturnObjDesc)
+ if (Info->ReturnObject)
{
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
- *ReturnObjDesc));
- ACPI_DUMP_STACK_ENTRY (*ReturnObjDesc);
+ Info->ReturnObject));
+ ACPI_DUMP_STACK_ENTRY (Info->ReturnObject);
/******************************************************************************
@@ -273,14 +300,10 @@
/*
* Predefined ACPI Names (Built-in to the Interpreter)
*
- * Initial values are currently supported only for types String and Number.
- * Both are specified as strings in this table.
- *
* NOTES:
- * 1) _SB_ is defined to be a device to allow _SB_/_INI to be run
+ * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
* during the initialization sequence.
*/
-
const ACPI_PREDEFINED_NAMES AcpiGbl_PreDefinedNames[] =
{
{"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
@@ -292,7 +315,7 @@
{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
{"_GL_", ACPI_TYPE_MUTEX, "0"},
-
ACPI_TABLE_SUPPORT AcpiGbl_TableData[NUM_ACPI_TABLE_TYPES] =
{
/*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */
@@ -549,9 +570,8 @@
*
* The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; when
* stored in a table it really means that we have thus far seen no evidence to
- * indicatewhat type is actually going to be stored for this entry.
+ * indicate what type is actually going to be stored for this entry.
*/
-
static const char AcpiGbl_BadType[] = "UNDEFINED";
#define TYPE_NAME_LENGTH 12 /* Maximum length of each string */
/*
- * Initialize ACPI Event handling
+ * Install the default OpRegion handlers. These are installed unless
+ * other handlers have already been installed via the
+ * InstallAddressSpaceHandler interface.
+ */
+ if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+
+ Status = AcpiEvInstallRegionHandlers ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ /*
+ * Initialize ACPI Event handling (Fixed and General Purpose)
*
* NOTE: We must have the hardware AND events initialized before we can execute
* ANY control methods SAFELY. Any control method can require ACPI hardware
@@ -268,20 +283,20 @@
{
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n"));
- Status = AcpiEvInitialize ();
+ Status = AcpiEvInitializeEvents ();
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
}
- /* Install the SCI handler, Global Lock handler, and GPE handlers */
+ /* Install the SCI handler and Global Lock handler */
- Status = AcpiEvHandlerInitialize ();
+ Status = AcpiEvInstallXruptHandlers ();
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
@@ -315,19 +330,17 @@
/*
- * Install the default OpRegion handlers. These are installed unless
- * other handlers have already been installed via the
- * InstallAddressSpaceHandler interface.
+ * Run all _REG methods
*
- * NOTE: This will cause _REG methods to be run. Any objects accessed
+ * NOTE: Any objects accessed
* by the _REG methods will be automatically initialized, even if they
* contain executable AML (see call to AcpiNsInitializeObjects below).
*/
if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG OpRegion methods\n"));
- Status = AcpiEvInitAddressSpaces ();
+ Status = AcpiEvInitializeOpRegions ();
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
@@ -341,7 +354,7 @@
*/
if (!(Flags & ACPI_NO_OBJECT_INIT))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n"));
Status = AcpiNsInitializeObjects ();
if (ACPI_FAILURE (Status))