evxface.c revision 245582
167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: evxface - External interfaces for ACPI events 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 4467754Smsmith 4567754Smsmith#define __EVXFACE_C__ 4667754Smsmith 47193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 48193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 50193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 5267754Smsmith 5377424Smsmith#define _COMPONENT ACPI_EVENTS 5491116Smsmith ACPI_MODULE_NAME ("evxface") 5567754Smsmith 5667754Smsmith 5777424Smsmith/******************************************************************************* 5867754Smsmith * 5967754Smsmith * FUNCTION: AcpiInstallNotifyHandler 6067754Smsmith * 6167754Smsmith * PARAMETERS: Device - The device for which notifies will be handled 6267754Smsmith * HandlerType - The type of handler: 63234623Sjkim * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) 64234623Sjkim * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) 65234623Sjkim * ACPI_ALL_NOTIFY: Both System and Device 6667754Smsmith * Handler - Address of the handler 6767754Smsmith * Context - Value passed to the handler on each GPE 6867754Smsmith * 6967754Smsmith * RETURN: Status 7067754Smsmith * 71234623Sjkim * DESCRIPTION: Install a handler for notifications on an ACPI Device, 72234623Sjkim * ThermalZone, or Processor object. 7367754Smsmith * 74234623Sjkim * NOTES: The Root namespace object may have only one handler for each 75234623Sjkim * type of notify (System/Device). Device/Thermal/Processor objects 76234623Sjkim * may have one device notify handler, and multiple system notify 77234623Sjkim * handlers. 78234623Sjkim * 7967754Smsmith ******************************************************************************/ 8067754Smsmith 8167754SmsmithACPI_STATUS 8267754SmsmithAcpiInstallNotifyHandler ( 8367754Smsmith ACPI_HANDLE Device, 8467754Smsmith UINT32 HandlerType, 8577424Smsmith ACPI_NOTIFY_HANDLER Handler, 8667754Smsmith void *Context) 8767754Smsmith{ 88234623Sjkim ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); 8967754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 90234623Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 9191116Smsmith ACPI_STATUS Status; 92234623Sjkim UINT32 i; 9367754Smsmith 9467754Smsmith 95167802Sjkim ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); 9667754Smsmith 9767754Smsmith 9867754Smsmith /* Parameter validation */ 9967754Smsmith 100234623Sjkim if ((!Device) || (!Handler) || (!HandlerType) || 10167754Smsmith (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) 10267754Smsmith { 10367754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 10467754Smsmith } 10567754Smsmith 10691116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 10791116Smsmith if (ACPI_FAILURE (Status)) 10891116Smsmith { 10991116Smsmith return_ACPI_STATUS (Status); 11091116Smsmith } 11171867Smsmith 11267754Smsmith /* 11371867Smsmith * Root Object: 11471867Smsmith * Registering a notify handler on the root object indicates that the 115193267Sjkim * caller wishes to receive notifications for all objects. Note that 116234623Sjkim * only one global handler can be registered per notify type. 117234623Sjkim * Ensure that a handler is not already installed. 11867754Smsmith */ 11967754Smsmith if (Device == ACPI_ROOT_OBJECT) 12067754Smsmith { 121234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 12267754Smsmith { 123234623Sjkim if (HandlerType & (i+1)) 124234623Sjkim { 125234623Sjkim if (AcpiGbl_GlobalNotify[i].Handler) 126234623Sjkim { 127234623Sjkim Status = AE_ALREADY_EXISTS; 128234623Sjkim goto UnlockAndExit; 129234623Sjkim } 13067754Smsmith 131234623Sjkim AcpiGbl_GlobalNotify[i].Handler = Handler; 132234623Sjkim AcpiGbl_GlobalNotify[i].Context = Context; 133234623Sjkim } 13467754Smsmith } 135129684Snjl 136234623Sjkim goto UnlockAndExit; /* Global notify handler installed, all done */ 13767754Smsmith } 13867754Smsmith 13967754Smsmith /* 14085756Smsmith * All Other Objects: 141234623Sjkim * Caller will only receive notifications specific to the target 142234623Sjkim * object. Note that only certain object types are allowed to 143234623Sjkim * receive notifications. 14467754Smsmith */ 145234623Sjkim 146234623Sjkim /* Are Notifies allowed on this object? */ 147234623Sjkim 148234623Sjkim if (!AcpiEvIsNotifyObject (Node)) 14985756Smsmith { 150234623Sjkim Status = AE_TYPE; 151234623Sjkim goto UnlockAndExit; 152234623Sjkim } 15399146Siwasaki 154234623Sjkim /* Check for an existing internal object, might not exist */ 155234623Sjkim 156234623Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 157234623Sjkim if (!ObjDesc) 158234623Sjkim { 159234623Sjkim /* Create a new object */ 160234623Sjkim 161234623Sjkim ObjDesc = AcpiUtCreateInternalObject (Node->Type); 162234623Sjkim if (!ObjDesc) 16367754Smsmith { 164234623Sjkim Status = AE_NO_MEMORY; 16567754Smsmith goto UnlockAndExit; 16667754Smsmith } 16767754Smsmith 168234623Sjkim /* Attach new object to the Node, remove local reference */ 16967754Smsmith 170234623Sjkim Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); 171234623Sjkim AcpiUtRemoveReference (ObjDesc); 172234623Sjkim if (ACPI_FAILURE (Status)) 17367754Smsmith { 174234623Sjkim goto UnlockAndExit; 175234623Sjkim } 176234623Sjkim } 17771867Smsmith 178234623Sjkim /* Ensure that the handler is not already installed in the lists */ 179234623Sjkim 180234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 181234623Sjkim { 182234623Sjkim if (HandlerType & (i+1)) 18371867Smsmith { 184234623Sjkim HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; 185234623Sjkim while (HandlerObj) 18671867Smsmith { 187234623Sjkim if (HandlerObj->Notify.Handler == Handler) 188234623Sjkim { 189234623Sjkim Status = AE_ALREADY_EXISTS; 190234623Sjkim goto UnlockAndExit; 191234623Sjkim } 19267754Smsmith 193234623Sjkim HandlerObj = HandlerObj->Notify.Next[i]; 19471867Smsmith } 19571867Smsmith } 196234623Sjkim } 19771867Smsmith 198234623Sjkim /* Create and populate a new notify handler object */ 19971867Smsmith 200234623Sjkim HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); 201234623Sjkim if (!HandlerObj) 202234623Sjkim { 203234623Sjkim Status = AE_NO_MEMORY; 204234623Sjkim goto UnlockAndExit; 205234623Sjkim } 20667754Smsmith 207234623Sjkim HandlerObj->Notify.Node = Node; 208234623Sjkim HandlerObj->Notify.HandlerType = HandlerType; 209234623Sjkim HandlerObj->Notify.Handler = Handler; 210234623Sjkim HandlerObj->Notify.Context = Context; 21167754Smsmith 212234623Sjkim /* Install the handler at the list head(s) */ 213234623Sjkim 214234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 215234623Sjkim { 216234623Sjkim if (HandlerType & (i+1)) 21771867Smsmith { 218234623Sjkim HandlerObj->Notify.Next[i] = 219234623Sjkim ObjDesc->CommonNotify.NotifyList[i]; 220129684Snjl 221234623Sjkim ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; 22271867Smsmith } 223234623Sjkim } 224129684Snjl 225234623Sjkim /* Add an extra reference if handler was installed in both lists */ 226129684Snjl 227234623Sjkim if (HandlerType == ACPI_ALL_NOTIFY) 228234623Sjkim { 229234623Sjkim AcpiUtAddReference (HandlerObj); 23067754Smsmith } 23167754Smsmith 23285756Smsmith 23367754SmsmithUnlockAndExit: 23491116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 23567754Smsmith return_ACPI_STATUS (Status); 23667754Smsmith} 23767754Smsmith 238167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) 23967754Smsmith 240167802Sjkim 24177424Smsmith/******************************************************************************* 24267754Smsmith * 24367754Smsmith * FUNCTION: AcpiRemoveNotifyHandler 24467754Smsmith * 245234623Sjkim * PARAMETERS: Device - The device for which the handler is installed 24667754Smsmith * HandlerType - The type of handler: 247234623Sjkim * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) 248234623Sjkim * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) 249234623Sjkim * ACPI_ALL_NOTIFY: Both System and Device 25067754Smsmith * Handler - Address of the handler 251138287Smarks * 25267754Smsmith * RETURN: Status 25367754Smsmith * 25467754Smsmith * DESCRIPTION: Remove a handler for notifies on an ACPI device 25567754Smsmith * 25667754Smsmith ******************************************************************************/ 25767754Smsmith 25867754SmsmithACPI_STATUS 25967754SmsmithAcpiRemoveNotifyHandler ( 26067754Smsmith ACPI_HANDLE Device, 26167754Smsmith UINT32 HandlerType, 26277424Smsmith ACPI_NOTIFY_HANDLER Handler) 26367754Smsmith{ 264234623Sjkim ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); 26567754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 266234623Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 267234623Sjkim ACPI_OPERAND_OBJECT *PreviousHandlerObj; 26891116Smsmith ACPI_STATUS Status; 269234623Sjkim UINT32 i; 27067754Smsmith 27177424Smsmith 272167802Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); 27367754Smsmith 27477424Smsmith 27567754Smsmith /* Parameter validation */ 27667754Smsmith 277234623Sjkim if ((!Device) || (!Handler) || (!HandlerType) || 27867754Smsmith (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) 27967754Smsmith { 28067754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 28167754Smsmith } 28267754Smsmith 283235945Sjkim /* Make sure all deferred notify tasks are completed */ 284234623Sjkim 285235945Sjkim AcpiOsWaitEventsComplete (); 286234623Sjkim 28791116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 28891116Smsmith if (ACPI_FAILURE (Status)) 28991116Smsmith { 29091116Smsmith return_ACPI_STATUS (Status); 29191116Smsmith } 29267754Smsmith 293234623Sjkim /* Root Object. Global handlers are removed here */ 29467754Smsmith 29587031Smsmith if (Device == ACPI_ROOT_OBJECT) 29685756Smsmith { 297234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 29871867Smsmith { 299234623Sjkim if (HandlerType & (i+1)) 300234623Sjkim { 301234623Sjkim if (!AcpiGbl_GlobalNotify[i].Handler || 302234623Sjkim (AcpiGbl_GlobalNotify[i].Handler != Handler)) 303234623Sjkim { 304234623Sjkim Status = AE_NOT_EXIST; 305234623Sjkim goto UnlockAndExit; 306234623Sjkim } 30767754Smsmith 308234623Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 309234623Sjkim "Removing global notify handler\n")); 310234623Sjkim 311234623Sjkim AcpiGbl_GlobalNotify[i].Handler = NULL; 312234623Sjkim AcpiGbl_GlobalNotify[i].Context = NULL; 313234623Sjkim } 31471867Smsmith } 315129684Snjl 316234623Sjkim goto UnlockAndExit; 31767754Smsmith } 31867754Smsmith 319234623Sjkim /* All other objects: Are Notifies allowed on this object? */ 320138287Smarks 321234623Sjkim if (!AcpiEvIsNotifyObject (Node)) 32285756Smsmith { 323234623Sjkim Status = AE_TYPE; 324234623Sjkim goto UnlockAndExit; 325234623Sjkim } 32699146Siwasaki 327234623Sjkim /* Must have an existing internal object */ 32867754Smsmith 329234623Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 330234623Sjkim if (!ObjDesc) 331234623Sjkim { 332234623Sjkim Status = AE_NOT_EXIST; 333234623Sjkim goto UnlockAndExit; 334234623Sjkim } 33567754Smsmith 336234623Sjkim /* Internal object exists. Find the handler and remove it */ 337234623Sjkim 338234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 339234623Sjkim { 340234623Sjkim if (HandlerType & (i+1)) 34171867Smsmith { 342234623Sjkim HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; 343234623Sjkim PreviousHandlerObj = NULL; 34467754Smsmith 345234623Sjkim /* Attempt to find the handler in the handler list */ 34671867Smsmith 347234623Sjkim while (HandlerObj && 348234623Sjkim (HandlerObj->Notify.Handler != Handler)) 349129684Snjl { 350234623Sjkim PreviousHandlerObj = HandlerObj; 351234623Sjkim HandlerObj = HandlerObj->Notify.Next[i]; 352167802Sjkim } 353167802Sjkim 354234623Sjkim if (!HandlerObj) 355167802Sjkim { 356234623Sjkim Status = AE_NOT_EXIST; 357129684Snjl goto UnlockAndExit; 358129684Snjl } 359129684Snjl 360234623Sjkim /* Remove the handler object from the list */ 361129684Snjl 362234623Sjkim if (PreviousHandlerObj) /* Handler is not at the list head */ 363129684Snjl { 364234623Sjkim PreviousHandlerObj->Notify.Next[i] = 365234623Sjkim HandlerObj->Notify.Next[i]; 366167802Sjkim } 367234623Sjkim else /* Handler is at the list head */ 368167802Sjkim { 369234623Sjkim ObjDesc->CommonNotify.NotifyList[i] = 370234623Sjkim HandlerObj->Notify.Next[i]; 371129684Snjl } 37271867Smsmith 373234623Sjkim AcpiUtRemoveReference (HandlerObj); 37471867Smsmith } 37567754Smsmith } 37667754Smsmith 37767754Smsmith 37867754SmsmithUnlockAndExit: 37991116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 38067754Smsmith return_ACPI_STATUS (Status); 38167754Smsmith} 38267754Smsmith 383167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) 38471867Smsmith 385167802Sjkim 38677424Smsmith/******************************************************************************* 38767754Smsmith * 388231844Sjkim * FUNCTION: AcpiInstallExceptionHandler 389231844Sjkim * 390231844Sjkim * PARAMETERS: Handler - Pointer to the handler function for the 391231844Sjkim * event 392231844Sjkim * 393231844Sjkim * RETURN: Status 394231844Sjkim * 395231844Sjkim * DESCRIPTION: Saves the pointer to the handler function 396231844Sjkim * 397231844Sjkim ******************************************************************************/ 398231844Sjkim 399231844SjkimACPI_STATUS 400231844SjkimAcpiInstallExceptionHandler ( 401231844Sjkim ACPI_EXCEPTION_HANDLER Handler) 402231844Sjkim{ 403231844Sjkim ACPI_STATUS Status; 404231844Sjkim 405231844Sjkim 406231844Sjkim ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); 407231844Sjkim 408231844Sjkim 409231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 410231844Sjkim if (ACPI_FAILURE (Status)) 411231844Sjkim { 412231844Sjkim return_ACPI_STATUS (Status); 413231844Sjkim } 414231844Sjkim 415231844Sjkim /* Don't allow two handlers. */ 416231844Sjkim 417231844Sjkim if (AcpiGbl_ExceptionHandler) 418231844Sjkim { 419231844Sjkim Status = AE_ALREADY_EXISTS; 420231844Sjkim goto Cleanup; 421231844Sjkim } 422231844Sjkim 423231844Sjkim /* Install the handler */ 424231844Sjkim 425231844Sjkim AcpiGbl_ExceptionHandler = Handler; 426231844Sjkim 427231844SjkimCleanup: 428231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 429231844Sjkim return_ACPI_STATUS (Status); 430231844Sjkim} 431231844Sjkim 432231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) 433231844Sjkim 434231844Sjkim 435231844Sjkim#if (!ACPI_REDUCED_HARDWARE) 436231844Sjkim/******************************************************************************* 437231844Sjkim * 438231844Sjkim * FUNCTION: AcpiInstallGlobalEventHandler 439231844Sjkim * 440231844Sjkim * PARAMETERS: Handler - Pointer to the global event handler function 441231844Sjkim * Context - Value passed to the handler on each event 442231844Sjkim * 443231844Sjkim * RETURN: Status 444231844Sjkim * 445231844Sjkim * DESCRIPTION: Saves the pointer to the handler function. The global handler 446231844Sjkim * is invoked upon each incoming GPE and Fixed Event. It is 447231844Sjkim * invoked at interrupt level at the time of the event dispatch. 448231844Sjkim * Can be used to update event counters, etc. 449231844Sjkim * 450231844Sjkim ******************************************************************************/ 451231844Sjkim 452231844SjkimACPI_STATUS 453231844SjkimAcpiInstallGlobalEventHandler ( 454231844Sjkim ACPI_GBL_EVENT_HANDLER Handler, 455231844Sjkim void *Context) 456231844Sjkim{ 457231844Sjkim ACPI_STATUS Status; 458231844Sjkim 459231844Sjkim 460231844Sjkim ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); 461231844Sjkim 462231844Sjkim 463231844Sjkim /* Parameter validation */ 464231844Sjkim 465231844Sjkim if (!Handler) 466231844Sjkim { 467231844Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 468231844Sjkim } 469231844Sjkim 470231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 471231844Sjkim if (ACPI_FAILURE (Status)) 472231844Sjkim { 473231844Sjkim return_ACPI_STATUS (Status); 474231844Sjkim } 475231844Sjkim 476231844Sjkim /* Don't allow two handlers. */ 477231844Sjkim 478231844Sjkim if (AcpiGbl_GlobalEventHandler) 479231844Sjkim { 480231844Sjkim Status = AE_ALREADY_EXISTS; 481231844Sjkim goto Cleanup; 482231844Sjkim } 483231844Sjkim 484231844Sjkim AcpiGbl_GlobalEventHandler = Handler; 485231844Sjkim AcpiGbl_GlobalEventHandlerContext = Context; 486231844Sjkim 487231844Sjkim 488231844SjkimCleanup: 489231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 490231844Sjkim return_ACPI_STATUS (Status); 491231844Sjkim} 492231844Sjkim 493231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) 494231844Sjkim 495231844Sjkim 496231844Sjkim/******************************************************************************* 497231844Sjkim * 498231844Sjkim * FUNCTION: AcpiInstallFixedEventHandler 499231844Sjkim * 500231844Sjkim * PARAMETERS: Event - Event type to enable. 501231844Sjkim * Handler - Pointer to the handler function for the 502231844Sjkim * event 503231844Sjkim * Context - Value passed to the handler on each GPE 504231844Sjkim * 505231844Sjkim * RETURN: Status 506231844Sjkim * 507231844Sjkim * DESCRIPTION: Saves the pointer to the handler function and then enables the 508231844Sjkim * event. 509231844Sjkim * 510231844Sjkim ******************************************************************************/ 511231844Sjkim 512231844SjkimACPI_STATUS 513231844SjkimAcpiInstallFixedEventHandler ( 514231844Sjkim UINT32 Event, 515231844Sjkim ACPI_EVENT_HANDLER Handler, 516231844Sjkim void *Context) 517231844Sjkim{ 518231844Sjkim ACPI_STATUS Status; 519231844Sjkim 520231844Sjkim 521231844Sjkim ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); 522231844Sjkim 523231844Sjkim 524231844Sjkim /* Parameter validation */ 525231844Sjkim 526231844Sjkim if (Event > ACPI_EVENT_MAX) 527231844Sjkim { 528231844Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 529231844Sjkim } 530231844Sjkim 531231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 532231844Sjkim if (ACPI_FAILURE (Status)) 533231844Sjkim { 534231844Sjkim return_ACPI_STATUS (Status); 535231844Sjkim } 536231844Sjkim 537231844Sjkim /* Don't allow two handlers. */ 538231844Sjkim 539231844Sjkim if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) 540231844Sjkim { 541231844Sjkim Status = AE_ALREADY_EXISTS; 542231844Sjkim goto Cleanup; 543231844Sjkim } 544231844Sjkim 545231844Sjkim /* Install the handler before enabling the event */ 546231844Sjkim 547231844Sjkim AcpiGbl_FixedEventHandlers[Event].Handler = Handler; 548231844Sjkim AcpiGbl_FixedEventHandlers[Event].Context = Context; 549231844Sjkim 550231844Sjkim Status = AcpiEnableEvent (Event, 0); 551231844Sjkim if (ACPI_FAILURE (Status)) 552231844Sjkim { 553231844Sjkim ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event)); 554231844Sjkim 555231844Sjkim /* Remove the handler */ 556231844Sjkim 557231844Sjkim AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 558231844Sjkim AcpiGbl_FixedEventHandlers[Event].Context = NULL; 559231844Sjkim } 560231844Sjkim else 561231844Sjkim { 562231844Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 563231844Sjkim "Enabled fixed event %X, Handler=%p\n", Event, Handler)); 564231844Sjkim } 565231844Sjkim 566231844Sjkim 567231844SjkimCleanup: 568231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 569231844Sjkim return_ACPI_STATUS (Status); 570231844Sjkim} 571231844Sjkim 572231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) 573231844Sjkim 574231844Sjkim 575231844Sjkim/******************************************************************************* 576231844Sjkim * 577231844Sjkim * FUNCTION: AcpiRemoveFixedEventHandler 578231844Sjkim * 579231844Sjkim * PARAMETERS: Event - Event type to disable. 580231844Sjkim * Handler - Address of the handler 581231844Sjkim * 582231844Sjkim * RETURN: Status 583231844Sjkim * 584231844Sjkim * DESCRIPTION: Disables the event and unregisters the event handler. 585231844Sjkim * 586231844Sjkim ******************************************************************************/ 587231844Sjkim 588231844SjkimACPI_STATUS 589231844SjkimAcpiRemoveFixedEventHandler ( 590231844Sjkim UINT32 Event, 591231844Sjkim ACPI_EVENT_HANDLER Handler) 592231844Sjkim{ 593231844Sjkim ACPI_STATUS Status = AE_OK; 594231844Sjkim 595231844Sjkim 596231844Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); 597231844Sjkim 598231844Sjkim 599231844Sjkim /* Parameter validation */ 600231844Sjkim 601231844Sjkim if (Event > ACPI_EVENT_MAX) 602231844Sjkim { 603231844Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 604231844Sjkim } 605231844Sjkim 606231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 607231844Sjkim if (ACPI_FAILURE (Status)) 608231844Sjkim { 609231844Sjkim return_ACPI_STATUS (Status); 610231844Sjkim } 611231844Sjkim 612231844Sjkim /* Disable the event before removing the handler */ 613231844Sjkim 614231844Sjkim Status = AcpiDisableEvent (Event, 0); 615231844Sjkim 616231844Sjkim /* Always Remove the handler */ 617231844Sjkim 618231844Sjkim AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 619231844Sjkim AcpiGbl_FixedEventHandlers[Event].Context = NULL; 620231844Sjkim 621231844Sjkim if (ACPI_FAILURE (Status)) 622231844Sjkim { 623231844Sjkim ACPI_WARNING ((AE_INFO, 624231844Sjkim "Could not write to fixed event enable register 0x%X", Event)); 625231844Sjkim } 626231844Sjkim else 627231844Sjkim { 628231844Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); 629231844Sjkim } 630231844Sjkim 631231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 632231844Sjkim return_ACPI_STATUS (Status); 633231844Sjkim} 634231844Sjkim 635231844SjkimACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) 636231844Sjkim 637231844Sjkim 638231844Sjkim/******************************************************************************* 639231844Sjkim * 64067754Smsmith * FUNCTION: AcpiInstallGpeHandler 64167754Smsmith * 642151937Sjkim * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 643151937Sjkim * defined GPEs) 644151937Sjkim * GpeNumber - The GPE number within the GPE block 64567754Smsmith * Type - Whether this GPE should be treated as an 64667754Smsmith * edge- or level-triggered interrupt. 647129684Snjl * Address - Address of the handler 64867754Smsmith * Context - Value passed to the handler on each GPE 64967754Smsmith * 65067754Smsmith * RETURN: Status 65167754Smsmith * 65267754Smsmith * DESCRIPTION: Install a handler for a General Purpose Event. 65367754Smsmith * 65467754Smsmith ******************************************************************************/ 65567754Smsmith 65667754SmsmithACPI_STATUS 65767754SmsmithAcpiInstallGpeHandler ( 658117521Snjl ACPI_HANDLE GpeDevice, 65967754Smsmith UINT32 GpeNumber, 66067754Smsmith UINT32 Type, 661216471Sjkim ACPI_GPE_HANDLER Address, 66267754Smsmith void *Context) 66367754Smsmith{ 664129684Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo; 665216471Sjkim ACPI_GPE_HANDLER_INFO *Handler; 66691116Smsmith ACPI_STATUS Status; 667167802Sjkim ACPI_CPU_FLAGS Flags; 66867754Smsmith 66977424Smsmith 670167802Sjkim ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); 67167754Smsmith 67277424Smsmith 67367754Smsmith /* Parameter validation */ 67467754Smsmith 675206117Sjkim if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) 67667754Smsmith { 67767754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 67867754Smsmith } 67967754Smsmith 680117521Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 681117521Snjl if (ACPI_FAILURE (Status)) 682117521Snjl { 683117521Snjl return_ACPI_STATUS (Status); 684117521Snjl } 685117521Snjl 686216471Sjkim /* Allocate and init handler object (before lock) */ 687216471Sjkim 688216471Sjkim Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO)); 689216471Sjkim if (!Handler) 690216471Sjkim { 691216471Sjkim Status = AE_NO_MEMORY; 692216471Sjkim goto UnlockAndExit; 693216471Sjkim } 694216471Sjkim 695216471Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 696216471Sjkim 69767754Smsmith /* Ensure that we have a valid GPE number */ 69867754Smsmith 699117521Snjl GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 700114237Snjl if (!GpeEventInfo) 70167754Smsmith { 702117521Snjl Status = AE_BAD_PARAMETER; 703216471Sjkim goto FreeAndExit; 70467754Smsmith } 70567754Smsmith 70667754Smsmith /* Make sure that there isn't a handler there already */ 70767754Smsmith 708193267Sjkim if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 709193267Sjkim ACPI_GPE_DISPATCH_HANDLER) 71067754Smsmith { 71187031Smsmith Status = AE_ALREADY_EXISTS; 712216471Sjkim goto FreeAndExit; 71367754Smsmith } 71467754Smsmith 715216471Sjkim Handler->Address = Address; 716216471Sjkim Handler->Context = Context; 717216471Sjkim Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; 718216471Sjkim Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags & 719216471Sjkim (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK)); 72067754Smsmith 721216471Sjkim /* 722216471Sjkim * If the GPE is associated with a method, it may have been enabled 723216471Sjkim * automatically during initialization, in which case it has to be 724216471Sjkim * disabled now to avoid spurious execution of the handler. 725216471Sjkim */ 726216471Sjkim if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) || 727216471Sjkim (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) && 728216471Sjkim GpeEventInfo->RuntimeCount) 729129684Snjl { 730216471Sjkim Handler->OriginallyEnabled = TRUE; 731216471Sjkim (void) AcpiEvRemoveGpeReference (GpeEventInfo); 732216471Sjkim 733216471Sjkim /* Sanity check of original type against new type */ 734216471Sjkim 735216471Sjkim if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) 736216471Sjkim { 737216471Sjkim ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)")); 738216471Sjkim } 739129684Snjl } 74067754Smsmith 741129684Snjl /* Install the handler */ 74285756Smsmith 743129684Snjl GpeEventInfo->Dispatch.Handler = Handler; 74499679Siwasaki 745216471Sjkim /* Setup up dispatch flags to indicate handler (vs. method/notify) */ 746129684Snjl 747193267Sjkim GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 748129684Snjl GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); 749129684Snjl 750151937Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 751129684Snjl 752129684Snjl 753117521SnjlUnlockAndExit: 75491116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 75567754Smsmith return_ACPI_STATUS (Status); 756216471Sjkim 757216471SjkimFreeAndExit: 758216471Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 759216471Sjkim ACPI_FREE (Handler); 760216471Sjkim goto UnlockAndExit; 76167754Smsmith} 76267754Smsmith 763167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) 76467754Smsmith 765167802Sjkim 76677424Smsmith/******************************************************************************* 76767754Smsmith * 76867754Smsmith * FUNCTION: AcpiRemoveGpeHandler 76967754Smsmith * 770151937Sjkim * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 771151937Sjkim * defined GPEs) 772151937Sjkim * GpeNumber - The event to remove a handler 773129684Snjl * Address - Address of the handler 77467754Smsmith * 77567754Smsmith * RETURN: Status 77667754Smsmith * 77767754Smsmith * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. 77867754Smsmith * 77967754Smsmith ******************************************************************************/ 78067754Smsmith 78167754SmsmithACPI_STATUS 78267754SmsmithAcpiRemoveGpeHandler ( 783117521Snjl ACPI_HANDLE GpeDevice, 78467754Smsmith UINT32 GpeNumber, 785216471Sjkim ACPI_GPE_HANDLER Address) 78667754Smsmith{ 787129684Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo; 788216471Sjkim ACPI_GPE_HANDLER_INFO *Handler; 78991116Smsmith ACPI_STATUS Status; 790167802Sjkim ACPI_CPU_FLAGS Flags; 79167754Smsmith 79267754Smsmith 793167802Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); 79467754Smsmith 79567754Smsmith 79667754Smsmith /* Parameter validation */ 79767754Smsmith 798129684Snjl if (!Address) 79967754Smsmith { 80067754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 80167754Smsmith } 80267754Smsmith 803235945Sjkim /* Make sure all deferred GPE tasks are completed */ 804235945Sjkim 805235945Sjkim AcpiOsWaitEventsComplete (); 806235945Sjkim 807117521Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 808117521Snjl if (ACPI_FAILURE (Status)) 809117521Snjl { 810117521Snjl return_ACPI_STATUS (Status); 811117521Snjl } 812117521Snjl 813216471Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 814216471Sjkim 81567754Smsmith /* Ensure that we have a valid GPE number */ 81667754Smsmith 817117521Snjl GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 818114237Snjl if (!GpeEventInfo) 81967754Smsmith { 820117521Snjl Status = AE_BAD_PARAMETER; 821117521Snjl goto UnlockAndExit; 82267754Smsmith } 82367754Smsmith 824129684Snjl /* Make sure that a handler is indeed installed */ 82567754Smsmith 826193267Sjkim if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != 827193267Sjkim ACPI_GPE_DISPATCH_HANDLER) 82899679Siwasaki { 829129684Snjl Status = AE_NOT_EXIST; 830117521Snjl goto UnlockAndExit; 83199679Siwasaki } 83267754Smsmith 83367754Smsmith /* Make sure that the installed handler is the same */ 83467754Smsmith 835129684Snjl if (GpeEventInfo->Dispatch.Handler->Address != Address) 83667754Smsmith { 83767754Smsmith Status = AE_BAD_PARAMETER; 838117521Snjl goto UnlockAndExit; 83967754Smsmith } 84067754Smsmith 84167754Smsmith /* Remove the handler */ 84267754Smsmith 843129684Snjl Handler = GpeEventInfo->Dispatch.Handler; 844129684Snjl 845129684Snjl /* Restore Method node (if any), set dispatch flags */ 846129684Snjl 847129684Snjl GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; 848216471Sjkim GpeEventInfo->Flags &= 849216471Sjkim ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 850216471Sjkim GpeEventInfo->Flags |= Handler->OriginalFlags; 851216471Sjkim 852216471Sjkim /* 853216471Sjkim * If the GPE was previously associated with a method and it was 854216471Sjkim * enabled, it should be enabled at this point to restore the 855216471Sjkim * post-initialization configuration. 856216471Sjkim */ 857216471Sjkim if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) && 858216471Sjkim Handler->OriginallyEnabled) 859129684Snjl { 860216471Sjkim (void) AcpiEvAddGpeReference (GpeEventInfo); 861129684Snjl } 86267754Smsmith 863129684Snjl /* Now we can free the handler object */ 86485756Smsmith 865167802Sjkim ACPI_FREE (Handler); 866129684Snjl 867129684Snjl 868117521SnjlUnlockAndExit: 869216471Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 87091116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 87167754Smsmith return_ACPI_STATUS (Status); 87267754Smsmith} 87367754Smsmith 874167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) 87567754Smsmith 876167802Sjkim 87777424Smsmith/******************************************************************************* 87867754Smsmith * 87967754Smsmith * FUNCTION: AcpiAcquireGlobalLock 88067754Smsmith * 88167754Smsmith * PARAMETERS: Timeout - How long the caller is willing to wait 882151937Sjkim * Handle - Where the handle to the lock is returned 883151937Sjkim * (if acquired) 88467754Smsmith * 88567754Smsmith * RETURN: Status 88667754Smsmith * 88767754Smsmith * DESCRIPTION: Acquire the ACPI Global Lock 88867754Smsmith * 889167802Sjkim * Note: Allows callers with the same thread ID to acquire the global lock 890167802Sjkim * multiple times. In other words, externally, the behavior of the global lock 891167802Sjkim * is identical to an AML mutex. On the first acquire, a new handle is 892167802Sjkim * returned. On any subsequent calls to acquire by the same thread, the same 893167802Sjkim * handle is returned. 894167802Sjkim * 89567754Smsmith ******************************************************************************/ 89685756Smsmith 89767754SmsmithACPI_STATUS 89867754SmsmithAcpiAcquireGlobalLock ( 899107325Siwasaki UINT16 Timeout, 90091116Smsmith UINT32 *Handle) 90167754Smsmith{ 90267754Smsmith ACPI_STATUS Status; 90367754Smsmith 90467754Smsmith 90591116Smsmith if (!Handle) 90691116Smsmith { 90791116Smsmith return (AE_BAD_PARAMETER); 90891116Smsmith } 90991116Smsmith 910167802Sjkim /* Must lock interpreter to prevent race conditions */ 91177424Smsmith 912167802Sjkim AcpiExEnterInterpreter (); 91367754Smsmith 914167802Sjkim Status = AcpiExAcquireMutexObject (Timeout, 915167802Sjkim AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); 916167802Sjkim 91791116Smsmith if (ACPI_SUCCESS (Status)) 91891116Smsmith { 919172314Sjkim /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ 920167802Sjkim 92191116Smsmith *Handle = AcpiGbl_GlobalLockHandle; 92291116Smsmith } 92391116Smsmith 924167802Sjkim AcpiExExitInterpreter (); 92567754Smsmith return (Status); 92667754Smsmith} 92767754Smsmith 928167802SjkimACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) 92967754Smsmith 930167802Sjkim 93177424Smsmith/******************************************************************************* 93267754Smsmith * 93367754Smsmith * FUNCTION: AcpiReleaseGlobalLock 93467754Smsmith * 93567754Smsmith * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock 93667754Smsmith * 93767754Smsmith * RETURN: Status 93867754Smsmith * 939151937Sjkim * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. 94067754Smsmith * 94167754Smsmith ******************************************************************************/ 94267754Smsmith 94367754SmsmithACPI_STATUS 94467754SmsmithAcpiReleaseGlobalLock ( 94591116Smsmith UINT32 Handle) 94667754Smsmith{ 94799679Siwasaki ACPI_STATUS Status; 94885756Smsmith 94999679Siwasaki 950167802Sjkim if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) 95191116Smsmith { 95291116Smsmith return (AE_NOT_ACQUIRED); 95391116Smsmith } 95491116Smsmith 955167802Sjkim Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); 95699679Siwasaki return (Status); 95767754Smsmith} 95867754Smsmith 959167802SjkimACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) 96067754Smsmith 961231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 962