void AcpiDbSendNotify ( char *Name, UINT32 Value) { ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; /* Translate name to an Named object */ Node = AcpiDbConvertToNode (Name); if (!Node) { return; } /* Dispatch the notify if legal */ if (AcpiEvIsNotifyObject (Node)) { Status = AcpiEvQueueNotifyRequest (Node, Value); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not queue notify\n"); } } else { AcpiOsPrintf ( "Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)); } }
ACPI_STATUS AcpiExOpcode_2A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_NAMESPACE_NODE *Node; UINT32 Value; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the opcode */ switch (WalkState->Opcode) { case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ /* The first operand is a namespace node */ Node = (ACPI_NAMESPACE_NODE *) Operand[0]; /* Second value is the notify value */ Value = (UINT32) Operand[1]->Integer.Value; /* Are notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { ACPI_ERROR ((AE_INFO, "Unexpected notify object type [%s]", AcpiUtGetTypeName (Node->Type))); Status = AE_AML_OPERAND_TYPE; break; } /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ Status = AcpiEvQueueNotifyRequest (Node, Value); break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerListHead = NULL; ACPI_GENERIC_STATE *Info; UINT8 HandlerListId = 0; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { return (AE_TYPE); } /* Get the correct notify list type (System or Device) */ if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerListId = ACPI_SYSTEM_HANDLER_LIST; } else { HandlerListId = ACPI_DEVICE_HANDLER_LIST; } /* Get the notify object attached to the namespace Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have an attached object, Get the correct handler list */ HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId]; } /* * If there is no notify handler (Global or Local) * for this object, just ignore the notify */ if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); return (AE_OK); } /* Setup notify info and schedule the notify dispatcher */ Info = AcpiUtCreateGenericState (); if (!Info) { return (AE_NO_MEMORY); } Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; Info->Notify.Node = Node; Info->Notify.Value = (UINT16) NotifyValue; Info->Notify.HandlerListId = HandlerListId; Info->Notify.HandlerListHead = HandlerListHead; Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId]; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), NotifyValue, AcpiUtGetNotifyName (NotifyValue, ACPI_TYPE_ANY), Node)); Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, Info); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (Info); } return (Status); }
ACPI_STATUS AcpiInstallNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler, void *Context) { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_STATUS Status; UINT32 i; ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (!HandlerType) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one global handler can be registered per notify type. * Ensure that a handler is not already installed. */ if (Device == ACPI_ROOT_OBJECT) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { if (AcpiGbl_GlobalNotify[i].Handler) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } AcpiGbl_GlobalNotify[i].Handler = Handler; AcpiGbl_GlobalNotify[i].Context = Context; } } goto UnlockAndExit; /* Global notify handler installed, all done */ } /* * All Other Objects: * Caller will only receive notifications specific to the target * object. Note that only certain object types are allowed to * receive notifications. */ /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { Status = AE_TYPE; goto UnlockAndExit; } /* Check for an existing internal object, might not exist */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* Create a new object */ ObjDesc = AcpiUtCreateInternalObject (Node->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Attach new object to the Node, remove local reference */ Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Ensure that the handler is not already installed in the lists */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; while (HandlerObj) { if (HandlerObj->Notify.Handler == Handler) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } HandlerObj = HandlerObj->Notify.Next[i]; } } } /* Create and populate a new notify handler object */ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); if (!HandlerObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } HandlerObj->Notify.Node = Node; HandlerObj->Notify.HandlerType = HandlerType; HandlerObj->Notify.Handler = Handler; HandlerObj->Notify.Context = Context; /* Install the handler at the list head(s) */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { HandlerObj->Notify.Next[i] = ObjDesc->CommonNotify.NotifyList[i]; ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; } } /* Add an extra reference if handler was installed in both lists */ if (HandlerType == ACPI_ALL_NOTIFY) { AcpiUtAddReference (HandlerObj); } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiRemoveNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler) { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *PreviousHandlerObj; ACPI_STATUS Status = AE_OK; UINT32 i; ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (!HandlerType) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Root Object. Global handlers are removed here */ if (Device == ACPI_ROOT_OBJECT) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (!AcpiGbl_GlobalNotify[i].Handler || (AcpiGbl_GlobalNotify[i].Handler != Handler)) { Status = AE_NOT_EXIST; goto UnlockAndExit; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing global notify handler\n")); AcpiGbl_GlobalNotify[i].Handler = NULL; AcpiGbl_GlobalNotify[i].Context = NULL; (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* Make sure all deferred notify tasks are completed */ AcpiOsWaitEventsComplete (); } } return_ACPI_STATUS (AE_OK); } /* All other objects: Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { return_ACPI_STATUS (AE_TYPE); } /* Must have an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return_ACPI_STATUS (AE_NOT_EXIST); } /* Internal object exists. Find the handler and remove it */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; PreviousHandlerObj = NULL; /* Attempt to find the handler in the handler list */ while (HandlerObj && (HandlerObj->Notify.Handler != Handler)) { PreviousHandlerObj = HandlerObj; HandlerObj = HandlerObj->Notify.Next[i]; } if (!HandlerObj) { Status = AE_NOT_EXIST; goto UnlockAndExit; } /* Remove the handler object from the list */ if (PreviousHandlerObj) /* Handler is not at the list head */ { PreviousHandlerObj->Notify.Next[i] = HandlerObj->Notify.Next[i]; } else /* Handler is at the list head */ { ObjDesc->CommonNotify.NotifyList[i] = HandlerObj->Notify.Next[i]; } (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* Make sure all deferred notify tasks are completed */ AcpiOsWaitEventsComplete (); AcpiUtRemoveReference (HandlerObj); } } return_ACPI_STATUS (Status); UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiRemoveNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler) { ACPI_OPERAND_OBJECT *NotifyObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Convert and validate the device handle */ Node = AcpiNsMapHandleToNode (Device); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Root Object */ if (Device == ACPI_ROOT_OBJECT) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for namespace root object\n")); if (((HandlerType & ACPI_SYSTEM_NOTIFY) && !AcpiGbl_SystemNotify.Handler) || ((HandlerType & ACPI_DEVICE_NOTIFY) && !AcpiGbl_DeviceNotify.Handler)) { Status = AE_NOT_EXIST; goto UnlockAndExit; } if (HandlerType & ACPI_SYSTEM_NOTIFY) { AcpiGbl_SystemNotify.Node = NULL; AcpiGbl_SystemNotify.Handler = NULL; AcpiGbl_SystemNotify.Context = NULL; } if (HandlerType & ACPI_DEVICE_NOTIFY) { AcpiGbl_DeviceNotify.Node = NULL; AcpiGbl_DeviceNotify.Handler = NULL; AcpiGbl_DeviceNotify.Context = NULL; } } /* All Other Objects */ else { /* Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { Status = AE_TYPE; goto UnlockAndExit; } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { Status = AE_NOT_EXIST; goto UnlockAndExit; } /* Object exists - make sure there's an existing handler */ if (HandlerType & ACPI_SYSTEM_NOTIFY) { NotifyObj = ObjDesc->CommonNotify.SystemNotify; if (!NotifyObj) { Status = AE_NOT_EXIST; goto UnlockAndExit; } if (NotifyObj->Notify.Handler != Handler) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Remove the handler */ ObjDesc->CommonNotify.SystemNotify = NULL; AcpiUtRemoveReference (NotifyObj); } if (HandlerType & ACPI_DEVICE_NOTIFY) { NotifyObj = ObjDesc->CommonNotify.DeviceNotify; if (!NotifyObj) { Status = AE_NOT_EXIST; goto UnlockAndExit; } if (NotifyObj->Notify.Handler != Handler) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Remove the handler */ ObjDesc->CommonNotify.DeviceNotify = NULL; AcpiUtRemoveReference (NotifyObj); } } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiInstallNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler, void *Context) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *NotifyObj; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Convert and validate the device handle */ Node = AcpiNsMapHandleToNode (Device); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one <external> global handler can be regsitered (per notify type). */ if (Device == ACPI_ROOT_OBJECT) { /* Make sure the handler is not already installed */ if (((HandlerType & ACPI_SYSTEM_NOTIFY) && AcpiGbl_SystemNotify.Handler) || ((HandlerType & ACPI_DEVICE_NOTIFY) && AcpiGbl_DeviceNotify.Handler)) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } if (HandlerType & ACPI_SYSTEM_NOTIFY) { AcpiGbl_SystemNotify.Node = Node; AcpiGbl_SystemNotify.Handler = Handler; AcpiGbl_SystemNotify.Context = Context; } if (HandlerType & ACPI_DEVICE_NOTIFY) { AcpiGbl_DeviceNotify.Node = Node; AcpiGbl_DeviceNotify.Handler = Handler; AcpiGbl_DeviceNotify.Context = Context; } /* Global notify handler installed */ } /* * All Other Objects: * Caller will only receive notifications specific to the target object. * Note that only certain object types can receive notifications. */ else { /* Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { Status = AE_TYPE; goto UnlockAndExit; } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Object exists - make sure there's no handler */ if (((HandlerType & ACPI_SYSTEM_NOTIFY) && ObjDesc->CommonNotify.SystemNotify) || ((HandlerType & ACPI_DEVICE_NOTIFY) && ObjDesc->CommonNotify.DeviceNotify)) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } } else { /* Create a new object */ ObjDesc = AcpiUtCreateInternalObject (Node->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Attach new object to the Node */ Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Install the handler */ NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); if (!NotifyObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } NotifyObj->Notify.Node = Node; NotifyObj->Notify.Handler = Handler; NotifyObj->Notify.Context = Context; if (HandlerType & ACPI_SYSTEM_NOTIFY) { ObjDesc->CommonNotify.SystemNotify = NotifyObj; } if (HandlerType & ACPI_DEVICE_NOTIFY) { ObjDesc->CommonNotify.DeviceNotify = NotifyObj; } if (HandlerType == ACPI_ALL_NOTIFY) { /* Extra ref if installed in both */ AcpiUtAddReference (NotifyObj); } } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_2A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_NAMESPACE_NODE *Node; UINT32 Value; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the opcode */ switch (WalkState->Opcode) { case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ /* The first operand is a namespace node */ Node = (ACPI_NAMESPACE_NODE *) Operand[0]; /* Second value is the notify value */ Value = (UINT32) Operand[1]->Integer.Value; /* Are notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { ACPI_ERROR ((AE_INFO, "Unexpected notify object type [%s]", 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 * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ Status = AcpiEvQueueNotifyRequest (Node, Value); break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; }