diff options
Diffstat (limited to 'sys/contrib/dev/acpica/evmisc.c')
-rw-r--r-- | sys/contrib/dev/acpica/evmisc.c | 233 |
1 files changed, 164 insertions, 69 deletions
diff --git a/sys/contrib/dev/acpica/evmisc.c b/sys/contrib/dev/acpica/evmisc.c index 516774e..afa7b2d 100644 --- a/sys/contrib/dev/acpica/evmisc.c +++ b/sys/contrib/dev/acpica/evmisc.c @@ -2,7 +2,7 @@ * * Module Name: evmisc - ACPI device notification handler dispatch * and ACPI Global Lock support - * $Revision: 22 $ + * $Revision: 31 $ * *****************************************************************************/ @@ -121,13 +121,13 @@ #include "acinterp.h" #include "achware.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evmisc") -/************************************************************************** +/******************************************************************************* * - * FUNCTION: AcpiEvNotifyDispatch + * FUNCTION: AcpiEvQueueNotifyRequest * * PARAMETERS: * @@ -136,16 +136,20 @@ * DESCRIPTION: Dispatch a device notification event to a previously * installed handler. * - *************************************************************************/ + ******************************************************************************/ -void -AcpiEvNotifyDispatch ( - ACPI_HANDLE Device, +ACPI_STATUS +AcpiEvQueueNotifyRequest ( + ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; - ACPI_OPERAND_OBJECT *HandlerObj; - NOTIFY_HANDLER Handler; + ACPI_OPERAND_OBJECT *HandlerObj = NULL; + ACPI_GENERIC_STATE *NotifyInfo; + ACPI_STATUS Status = AE_OK; + + + PROC_NAME ("EvQueueNotifyRequest"); /* @@ -155,108 +159,181 @@ AcpiEvNotifyDispatch ( * initiate soft-off or sleep operation? */ - - DEBUG_PRINT (ACPI_INFO, - ("Dispatching Notify(%X) on device %p\n", NotifyValue, Device)); + DEBUG_PRINTP (ACPI_INFO, + ("Dispatching Notify(%X) on node %p\n", NotifyValue, Node)); switch (NotifyValue) { case 0: - DEBUG_PRINT (ACPI_INFO, ("Notify value: Re-enumerate Devices\n")); + DEBUG_PRINTP (ACPI_INFO, ("Notify value: Re-enumerate Devices\n")); break; case 1: - DEBUG_PRINT (ACPI_INFO, ("Notify value: Ejection Request\n")); + DEBUG_PRINTP (ACPI_INFO, ("Notify value: Ejection Request\n")); break; case 2: - DEBUG_PRINT (ACPI_INFO, ("Notify value: Device Wake\n")); + DEBUG_PRINTP (ACPI_INFO, ("Notify value: Device Wake\n")); break; case 0x80: - DEBUG_PRINT (ACPI_INFO, ("Notify value: Status Change\n")); + DEBUG_PRINTP (ACPI_INFO, ("Notify value: Status Change\n")); break; default: - DEBUG_PRINT (ACPI_INFO, ("Unknown Notify Value: %lx \n", NotifyValue)); + DEBUG_PRINTP (ACPI_INFO, ("Unknown Notify Value: %lx \n", NotifyValue)); break; } /* - * Invoke a global notify handler if installed. - * This is done _before_ we invoke the per-device handler attached to the device. + * Get the notify object attached to the device Node */ - if (NotifyValue <= MAX_SYS_NOTIFY) + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) { - /* Global system notification handler */ - if (AcpiGbl_SysNotify.Handler) + /* We have the notify object, Get the right handler */ + + switch (Node->Type) { - AcpiGbl_SysNotify.Handler (Device, NotifyValue, - AcpiGbl_SysNotify.Context); + case ACPI_TYPE_DEVICE: + if (NotifyValue <= MAX_SYS_NOTIFY) + { + HandlerObj = ObjDesc->Device.SysHandler; + } + else + { + HandlerObj = ObjDesc->Device.DrvHandler; + } + break; + + case ACPI_TYPE_THERMAL: + if (NotifyValue <= MAX_SYS_NOTIFY) + { + HandlerObj = ObjDesc->ThermalZone.SysHandler; + } + else + { + HandlerObj = ObjDesc->ThermalZone.DrvHandler; + } + break; } } - else + + /* If there is any handler to run, schedule the dispatcher */ + + if ((AcpiGbl_SysNotify.Handler && (NotifyValue <= MAX_SYS_NOTIFY)) || + (AcpiGbl_DrvNotify.Handler && (NotifyValue > MAX_SYS_NOTIFY)) || + HandlerObj) { - /* Global driver notification handler */ - if (AcpiGbl_DrvNotify.Handler) + NotifyInfo = AcpiUtCreateGenericState (); + if (!NotifyInfo) { - AcpiGbl_DrvNotify.Handler (Device, NotifyValue, - AcpiGbl_DrvNotify.Context); + return (AE_NO_MEMORY); } - } + NotifyInfo->Notify.Node = Node; + NotifyInfo->Notify.Value = (UINT16) NotifyValue; + NotifyInfo->Notify.HandlerObj = HandlerObj; - /* - * Get the notify object which must be attached to the device Node - */ + Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH, + AcpiEvNotifyDispatch, NotifyInfo); + if (ACPI_FAILURE (Status)) + { + AcpiUtDeleteGenericState (NotifyInfo); + } + } - ObjDesc = AcpiNsGetAttachedObject ((ACPI_HANDLE) Device); - if (!ObjDesc) + if (!HandlerObj) { - /* There can be no notify handler for this device */ + /* There is no per-device notify handler for this device */ - DEBUG_PRINT (ACPI_INFO, - ("No notify handler for device %p \n", Device)); - return; + DEBUG_PRINTP (ACPI_INFO, ("No notify handler for node %p \n", Node)); } + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvNotifyDispatch + * + * PARAMETERS: + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + ******************************************************************************/ + +void +AcpiEvNotifyDispatch ( + void *Context) +{ + ACPI_GENERIC_STATE *NotifyInfo = (ACPI_GENERIC_STATE *) Context; + ACPI_NOTIFY_HANDLER GlobalHandler = NULL; + void *GlobalContext = NULL; + ACPI_OPERAND_OBJECT *HandlerObj; + - /* We have the notify object, Get the right handler */ + /* + * We will invoke a global notify handler if installed. + * This is done _before_ we invoke the per-device handler attached to the device. + */ - if (NotifyValue <= MAX_SYS_NOTIFY) + if (NotifyInfo->Notify.Value <= MAX_SYS_NOTIFY) { - HandlerObj = ObjDesc->Device.SysHandler; + /* Global system notification handler */ + + if (AcpiGbl_SysNotify.Handler) + { + GlobalHandler = AcpiGbl_SysNotify.Handler; + GlobalContext = AcpiGbl_SysNotify.Context; + } } + else { - HandlerObj = ObjDesc->Device.DrvHandler; + /* Global driver notification handler */ + + if (AcpiGbl_DrvNotify.Handler) + { + GlobalHandler = AcpiGbl_DrvNotify.Handler; + GlobalContext = AcpiGbl_DrvNotify.Context; + } } - /* Validate the handler */ - if (!HandlerObj) + /* Invoke the system handler first, if present */ + + if (GlobalHandler) { - /* There is no notify handler for this device */ + GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, GlobalContext); + } - DEBUG_PRINT (ACPI_INFO, - ("No notify handler for device %p \n", Device)); - return; + /* Now invoke the per-device handler, if present */ + + HandlerObj = NotifyInfo->Notify.HandlerObj; + if (HandlerObj) + { + HandlerObj->NotifyHandler.Handler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, + HandlerObj->NotifyHandler.Context); } - /* There is a handler, invoke it */ - Handler = HandlerObj->NotifyHandler.Handler; - Handler (Device, NotifyValue, HandlerObj->NotifyHandler.Context); + /* All done with the info object */ + AcpiUtDeleteGenericState (NotifyInfo); } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: AcpiEvGlobalLockThread * @@ -266,7 +343,7 @@ AcpiEvNotifyDispatch ( * Global Lock. Simply signal all threads that are waiting * for the lock. * - **************************************************************************/ + ******************************************************************************/ static void AcpiEvGlobalLockThread ( @@ -285,7 +362,7 @@ AcpiEvGlobalLockThread ( } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: AcpiEvGlobalLockHandler * @@ -295,7 +372,7 @@ AcpiEvGlobalLockThread ( * release interrupt occurs. Grab the global lock and queue * the global lock thread for execution * - **************************************************************************/ + ******************************************************************************/ static UINT32 AcpiEvGlobalLockHandler ( @@ -329,7 +406,7 @@ AcpiEvGlobalLockHandler ( } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: AcpiEvInitGlobalLockHandler * @@ -337,7 +414,7 @@ AcpiEvGlobalLockHandler ( * * DESCRIPTION: Install a handler for the global lock release event * - **************************************************************************/ + ******************************************************************************/ ACPI_STATUS AcpiEvInitGlobalLockHandler (void) @@ -348,14 +425,28 @@ AcpiEvInitGlobalLockHandler (void) FUNCTION_TRACE ("EvInitGlobalLockHandler"); + AcpiGbl_GlobalLockPresent = TRUE; Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AcpiEvGlobalLockHandler, NULL); + /* + * If the global lock does not exist on this platform, the attempt + * to enable GBL_STS will fail (the GBL_EN bit will not stick) + * Map to AE_OK, but mark global lock as not present. + * Any attempt to actually use the global lock will be flagged + * with an error. + */ + if (Status == AE_NO_HARDWARE_RESPONSE) + { + AcpiGbl_GlobalLockPresent = FALSE; + Status = AE_OK; + } + return_ACPI_STATUS (Status); } -/*************************************************************************** +/****************************************************************************** * * FUNCTION: AcpiEvAcquireGlobalLock * @@ -363,7 +454,7 @@ AcpiEvInitGlobalLockHandler (void) * * DESCRIPTION: Attempt to gain ownership of the Global Lock. * - **************************************************************************/ + *****************************************************************************/ ACPI_STATUS AcpiEvAcquireGlobalLock(void) @@ -375,6 +466,12 @@ AcpiEvAcquireGlobalLock(void) FUNCTION_TRACE ("EvAcquireGlobalLock"); + /* Make sure that we actually have a global lock */ + + if (!AcpiGbl_GlobalLockPresent) + { + return_ACPI_STATUS (AE_NO_GLOBAL_LOCK); + } /* One more thread wants the global lock */ @@ -404,10 +501,9 @@ AcpiEvAcquireGlobalLock(void) { /* We got the lock */ - DEBUG_PRINT (ACPI_INFO, ("Acquired the HW Global Lock\n")); + DEBUG_PRINTP (ACPI_INFO, ("Acquired the Global Lock\n")); AcpiGbl_GlobalLockAcquired = TRUE; - return_ACPI_STATUS (AE_OK); } @@ -417,27 +513,26 @@ AcpiEvAcquireGlobalLock(void) * wait until we get the global lock released interrupt. */ - DEBUG_PRINT (ACPI_INFO, ("Waiting for the HW Global Lock\n")); + DEBUG_PRINTP (ACPI_INFO, ("Waiting for the HW Global Lock\n")); /* * Acquire the global lock semaphore first. * Since this wait will block, we must release the interpreter */ - Status = AcpiAmlSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, + Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, ACPI_UINT32_MAX); - return_ACPI_STATUS (Status); } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: AcpiEvReleaseGlobalLock * * DESCRIPTION: Releases ownership of the Global Lock. * - **************************************************************************/ + ******************************************************************************/ void AcpiEvReleaseGlobalLock (void) @@ -450,7 +545,7 @@ AcpiEvReleaseGlobalLock (void) if (!AcpiGbl_GlobalLockThreadCount) { - REPORT_WARNING(("Releasing a non-acquired Global Lock\n")); + REPORT_WARNING(("Global Lock has not be acquired, cannot release\n")); return_VOID; } |