167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: evxface - External interfaces for ACPI events 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, 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 44281075Sdim#define EXPORT_ACPI_INTERFACES 4567754Smsmith 46193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 47193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 48193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 49193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 50193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 5167754Smsmith 5277424Smsmith#define _COMPONENT ACPI_EVENTS 5391116Smsmith ACPI_MODULE_NAME ("evxface") 5467754Smsmith 55281075Sdim#if (!ACPI_REDUCED_HARDWARE) 5667754Smsmith 57281075Sdim/* Local prototypes */ 58281075Sdim 59281075Sdimstatic ACPI_STATUS 60281075SdimAcpiEvInstallGpeHandler ( 61281075Sdim ACPI_HANDLE GpeDevice, 62281075Sdim UINT32 GpeNumber, 63281075Sdim UINT32 Type, 64281075Sdim BOOLEAN IsRawHandler, 65281075Sdim ACPI_GPE_HANDLER Address, 66281075Sdim void *Context); 67281075Sdim 68281075Sdim#endif 69281075Sdim 70281075Sdim 7177424Smsmith/******************************************************************************* 7267754Smsmith * 7367754Smsmith * FUNCTION: AcpiInstallNotifyHandler 7467754Smsmith * 7567754Smsmith * PARAMETERS: Device - The device for which notifies will be handled 7667754Smsmith * HandlerType - The type of handler: 77234623Sjkim * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) 78234623Sjkim * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) 79234623Sjkim * ACPI_ALL_NOTIFY: Both System and Device 8067754Smsmith * Handler - Address of the handler 8167754Smsmith * Context - Value passed to the handler on each GPE 8267754Smsmith * 8367754Smsmith * RETURN: Status 8467754Smsmith * 85234623Sjkim * DESCRIPTION: Install a handler for notifications on an ACPI Device, 86234623Sjkim * ThermalZone, or Processor object. 8767754Smsmith * 88234623Sjkim * NOTES: The Root namespace object may have only one handler for each 89234623Sjkim * type of notify (System/Device). Device/Thermal/Processor objects 90234623Sjkim * may have one device notify handler, and multiple system notify 91234623Sjkim * handlers. 92234623Sjkim * 9367754Smsmith ******************************************************************************/ 9467754Smsmith 9567754SmsmithACPI_STATUS 9667754SmsmithAcpiInstallNotifyHandler ( 9767754Smsmith ACPI_HANDLE Device, 9867754Smsmith UINT32 HandlerType, 9977424Smsmith ACPI_NOTIFY_HANDLER Handler, 10067754Smsmith void *Context) 10167754Smsmith{ 102234623Sjkim ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); 10367754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 104234623Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 10591116Smsmith ACPI_STATUS Status; 106234623Sjkim UINT32 i; 10767754Smsmith 10867754Smsmith 109167802Sjkim ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); 11067754Smsmith 11167754Smsmith 11267754Smsmith /* Parameter validation */ 11367754Smsmith 114234623Sjkim if ((!Device) || (!Handler) || (!HandlerType) || 11567754Smsmith (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) 11667754Smsmith { 11767754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 11867754Smsmith } 11967754Smsmith 12091116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 12191116Smsmith if (ACPI_FAILURE (Status)) 12291116Smsmith { 12391116Smsmith return_ACPI_STATUS (Status); 12491116Smsmith } 12571867Smsmith 12667754Smsmith /* 12771867Smsmith * Root Object: 12871867Smsmith * Registering a notify handler on the root object indicates that the 129193267Sjkim * caller wishes to receive notifications for all objects. Note that 130234623Sjkim * only one global handler can be registered per notify type. 131234623Sjkim * Ensure that a handler is not already installed. 13267754Smsmith */ 13367754Smsmith if (Device == ACPI_ROOT_OBJECT) 13467754Smsmith { 135234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 13667754Smsmith { 137234623Sjkim if (HandlerType & (i+1)) 138234623Sjkim { 139234623Sjkim if (AcpiGbl_GlobalNotify[i].Handler) 140234623Sjkim { 141234623Sjkim Status = AE_ALREADY_EXISTS; 142234623Sjkim goto UnlockAndExit; 143234623Sjkim } 14467754Smsmith 145234623Sjkim AcpiGbl_GlobalNotify[i].Handler = Handler; 146234623Sjkim AcpiGbl_GlobalNotify[i].Context = Context; 147234623Sjkim } 14867754Smsmith } 149129684Snjl 150234623Sjkim goto UnlockAndExit; /* Global notify handler installed, all done */ 15167754Smsmith } 15267754Smsmith 15367754Smsmith /* 15485756Smsmith * All Other Objects: 155234623Sjkim * Caller will only receive notifications specific to the target 156234623Sjkim * object. Note that only certain object types are allowed to 157234623Sjkim * receive notifications. 15867754Smsmith */ 159234623Sjkim 160234623Sjkim /* Are Notifies allowed on this object? */ 161234623Sjkim 162234623Sjkim if (!AcpiEvIsNotifyObject (Node)) 16385756Smsmith { 164234623Sjkim Status = AE_TYPE; 165234623Sjkim goto UnlockAndExit; 166234623Sjkim } 16799146Siwasaki 168234623Sjkim /* Check for an existing internal object, might not exist */ 169234623Sjkim 170234623Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 171234623Sjkim if (!ObjDesc) 172234623Sjkim { 173234623Sjkim /* Create a new object */ 174234623Sjkim 175234623Sjkim ObjDesc = AcpiUtCreateInternalObject (Node->Type); 176234623Sjkim if (!ObjDesc) 17767754Smsmith { 178234623Sjkim Status = AE_NO_MEMORY; 17967754Smsmith goto UnlockAndExit; 18067754Smsmith } 18167754Smsmith 182234623Sjkim /* Attach new object to the Node, remove local reference */ 18367754Smsmith 184234623Sjkim Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); 185234623Sjkim AcpiUtRemoveReference (ObjDesc); 186234623Sjkim if (ACPI_FAILURE (Status)) 18767754Smsmith { 188234623Sjkim goto UnlockAndExit; 189234623Sjkim } 190234623Sjkim } 19171867Smsmith 192234623Sjkim /* Ensure that the handler is not already installed in the lists */ 193234623Sjkim 194234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 195234623Sjkim { 196234623Sjkim if (HandlerType & (i+1)) 19771867Smsmith { 198234623Sjkim HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; 199234623Sjkim while (HandlerObj) 20071867Smsmith { 201234623Sjkim if (HandlerObj->Notify.Handler == Handler) 202234623Sjkim { 203234623Sjkim Status = AE_ALREADY_EXISTS; 204234623Sjkim goto UnlockAndExit; 205234623Sjkim } 20667754Smsmith 207234623Sjkim HandlerObj = HandlerObj->Notify.Next[i]; 20871867Smsmith } 20971867Smsmith } 210234623Sjkim } 21171867Smsmith 212234623Sjkim /* Create and populate a new notify handler object */ 21371867Smsmith 214234623Sjkim HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); 215234623Sjkim if (!HandlerObj) 216234623Sjkim { 217234623Sjkim Status = AE_NO_MEMORY; 218234623Sjkim goto UnlockAndExit; 219234623Sjkim } 22067754Smsmith 221234623Sjkim HandlerObj->Notify.Node = Node; 222234623Sjkim HandlerObj->Notify.HandlerType = HandlerType; 223234623Sjkim HandlerObj->Notify.Handler = Handler; 224234623Sjkim HandlerObj->Notify.Context = Context; 22567754Smsmith 226234623Sjkim /* Install the handler at the list head(s) */ 227234623Sjkim 228234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 229234623Sjkim { 230234623Sjkim if (HandlerType & (i+1)) 23171867Smsmith { 232234623Sjkim HandlerObj->Notify.Next[i] = 233234623Sjkim ObjDesc->CommonNotify.NotifyList[i]; 234129684Snjl 235234623Sjkim ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; 23671867Smsmith } 237234623Sjkim } 238129684Snjl 239234623Sjkim /* Add an extra reference if handler was installed in both lists */ 240129684Snjl 241234623Sjkim if (HandlerType == ACPI_ALL_NOTIFY) 242234623Sjkim { 243234623Sjkim AcpiUtAddReference (HandlerObj); 24467754Smsmith } 24567754Smsmith 24685756Smsmith 24767754SmsmithUnlockAndExit: 24891116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 24967754Smsmith return_ACPI_STATUS (Status); 25067754Smsmith} 25167754Smsmith 252167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) 25367754Smsmith 254167802Sjkim 25577424Smsmith/******************************************************************************* 25667754Smsmith * 25767754Smsmith * FUNCTION: AcpiRemoveNotifyHandler 25867754Smsmith * 259234623Sjkim * PARAMETERS: Device - The device for which the handler is installed 26067754Smsmith * HandlerType - The type of handler: 261234623Sjkim * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) 262234623Sjkim * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) 263234623Sjkim * ACPI_ALL_NOTIFY: Both System and Device 26467754Smsmith * Handler - Address of the handler 265138287Smarks * 26667754Smsmith * RETURN: Status 26767754Smsmith * 26867754Smsmith * DESCRIPTION: Remove a handler for notifies on an ACPI device 26967754Smsmith * 27067754Smsmith ******************************************************************************/ 27167754Smsmith 27267754SmsmithACPI_STATUS 27367754SmsmithAcpiRemoveNotifyHandler ( 27467754Smsmith ACPI_HANDLE Device, 27567754Smsmith UINT32 HandlerType, 27677424Smsmith ACPI_NOTIFY_HANDLER Handler) 27767754Smsmith{ 278234623Sjkim ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); 27967754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 280234623Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 281234623Sjkim ACPI_OPERAND_OBJECT *PreviousHandlerObj; 282281075Sdim ACPI_STATUS Status = AE_OK; 283234623Sjkim UINT32 i; 28467754Smsmith 28577424Smsmith 286167802Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); 28767754Smsmith 28877424Smsmith 28967754Smsmith /* Parameter validation */ 29067754Smsmith 291234623Sjkim if ((!Device) || (!Handler) || (!HandlerType) || 29267754Smsmith (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) 29367754Smsmith { 29467754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 29567754Smsmith } 29667754Smsmith 297234623Sjkim /* Root Object. Global handlers are removed here */ 29867754Smsmith 29987031Smsmith if (Device == ACPI_ROOT_OBJECT) 30085756Smsmith { 301234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 30271867Smsmith { 303234623Sjkim if (HandlerType & (i+1)) 304234623Sjkim { 305281075Sdim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 306281075Sdim if (ACPI_FAILURE (Status)) 307281075Sdim { 308281075Sdim return_ACPI_STATUS (Status); 309281075Sdim } 310281075Sdim 311234623Sjkim if (!AcpiGbl_GlobalNotify[i].Handler || 312234623Sjkim (AcpiGbl_GlobalNotify[i].Handler != Handler)) 313234623Sjkim { 314234623Sjkim Status = AE_NOT_EXIST; 315234623Sjkim goto UnlockAndExit; 316234623Sjkim } 31767754Smsmith 318234623Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 319234623Sjkim "Removing global notify handler\n")); 320234623Sjkim 321234623Sjkim AcpiGbl_GlobalNotify[i].Handler = NULL; 322234623Sjkim AcpiGbl_GlobalNotify[i].Context = NULL; 323281075Sdim 324281075Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 325281075Sdim 326281075Sdim /* Make sure all deferred notify tasks are completed */ 327281075Sdim 328281075Sdim AcpiOsWaitEventsComplete (); 329234623Sjkim } 33071867Smsmith } 331129684Snjl 332281075Sdim return_ACPI_STATUS (AE_OK); 33367754Smsmith } 33467754Smsmith 335234623Sjkim /* All other objects: Are Notifies allowed on this object? */ 336138287Smarks 337234623Sjkim if (!AcpiEvIsNotifyObject (Node)) 33885756Smsmith { 339281075Sdim return_ACPI_STATUS (AE_TYPE); 340234623Sjkim } 34199146Siwasaki 342234623Sjkim /* Must have an existing internal object */ 34367754Smsmith 344234623Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 345234623Sjkim if (!ObjDesc) 346234623Sjkim { 347281075Sdim return_ACPI_STATUS (AE_NOT_EXIST); 348234623Sjkim } 34967754Smsmith 350234623Sjkim /* Internal object exists. Find the handler and remove it */ 351234623Sjkim 352234623Sjkim for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 353234623Sjkim { 354234623Sjkim if (HandlerType & (i+1)) 35571867Smsmith { 356281075Sdim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 357281075Sdim if (ACPI_FAILURE (Status)) 358281075Sdim { 359281075Sdim return_ACPI_STATUS (Status); 360281075Sdim } 361281075Sdim 362234623Sjkim HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; 363234623Sjkim PreviousHandlerObj = NULL; 36467754Smsmith 365234623Sjkim /* Attempt to find the handler in the handler list */ 36671867Smsmith 367234623Sjkim while (HandlerObj && 368234623Sjkim (HandlerObj->Notify.Handler != Handler)) 369129684Snjl { 370234623Sjkim PreviousHandlerObj = HandlerObj; 371234623Sjkim HandlerObj = HandlerObj->Notify.Next[i]; 372167802Sjkim } 373167802Sjkim 374234623Sjkim if (!HandlerObj) 375167802Sjkim { 376234623Sjkim Status = AE_NOT_EXIST; 377129684Snjl goto UnlockAndExit; 378129684Snjl } 379129684Snjl 380234623Sjkim /* Remove the handler object from the list */ 381129684Snjl 382234623Sjkim if (PreviousHandlerObj) /* Handler is not at the list head */ 383129684Snjl { 384234623Sjkim PreviousHandlerObj->Notify.Next[i] = 385234623Sjkim HandlerObj->Notify.Next[i]; 386167802Sjkim } 387234623Sjkim else /* Handler is at the list head */ 388167802Sjkim { 389234623Sjkim ObjDesc->CommonNotify.NotifyList[i] = 390234623Sjkim HandlerObj->Notify.Next[i]; 391129684Snjl } 39271867Smsmith 393281075Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 394281075Sdim 395281075Sdim /* Make sure all deferred notify tasks are completed */ 396281075Sdim 397281075Sdim AcpiOsWaitEventsComplete (); 398234623Sjkim AcpiUtRemoveReference (HandlerObj); 39971867Smsmith } 40067754Smsmith } 40167754Smsmith 402281075Sdim return_ACPI_STATUS (Status); 40367754Smsmith 404281075Sdim 40567754SmsmithUnlockAndExit: 40691116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 40767754Smsmith return_ACPI_STATUS (Status); 40867754Smsmith} 40967754Smsmith 410167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) 41171867Smsmith 412167802Sjkim 41377424Smsmith/******************************************************************************* 41467754Smsmith * 415231844Sjkim * FUNCTION: AcpiInstallExceptionHandler 416231844Sjkim * 417231844Sjkim * PARAMETERS: Handler - Pointer to the handler function for the 418231844Sjkim * event 419231844Sjkim * 420231844Sjkim * RETURN: Status 421231844Sjkim * 422231844Sjkim * DESCRIPTION: Saves the pointer to the handler function 423231844Sjkim * 424231844Sjkim ******************************************************************************/ 425231844Sjkim 426231844SjkimACPI_STATUS 427231844SjkimAcpiInstallExceptionHandler ( 428231844Sjkim ACPI_EXCEPTION_HANDLER Handler) 429231844Sjkim{ 430231844Sjkim ACPI_STATUS Status; 431231844Sjkim 432231844Sjkim 433231844Sjkim ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); 434231844Sjkim 435231844Sjkim 436231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 437231844Sjkim if (ACPI_FAILURE (Status)) 438231844Sjkim { 439231844Sjkim return_ACPI_STATUS (Status); 440231844Sjkim } 441231844Sjkim 442231844Sjkim /* Don't allow two handlers. */ 443231844Sjkim 444231844Sjkim if (AcpiGbl_ExceptionHandler) 445231844Sjkim { 446231844Sjkim Status = AE_ALREADY_EXISTS; 447231844Sjkim goto Cleanup; 448231844Sjkim } 449231844Sjkim 450231844Sjkim /* Install the handler */ 451231844Sjkim 452231844Sjkim AcpiGbl_ExceptionHandler = Handler; 453231844Sjkim 454231844SjkimCleanup: 455231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 456231844Sjkim return_ACPI_STATUS (Status); 457231844Sjkim} 458231844Sjkim 459231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) 460231844Sjkim 461231844Sjkim 462231844Sjkim#if (!ACPI_REDUCED_HARDWARE) 463231844Sjkim/******************************************************************************* 464231844Sjkim * 465254745Sjkim * FUNCTION: AcpiInstallSciHandler 466254745Sjkim * 467254745Sjkim * PARAMETERS: Address - Address of the handler 468254745Sjkim * Context - Value passed to the handler on each SCI 469254745Sjkim * 470254745Sjkim * RETURN: Status 471254745Sjkim * 472254745Sjkim * DESCRIPTION: Install a handler for a System Control Interrupt. 473254745Sjkim * 474254745Sjkim ******************************************************************************/ 475254745Sjkim 476254745SjkimACPI_STATUS 477254745SjkimAcpiInstallSciHandler ( 478254745Sjkim ACPI_SCI_HANDLER Address, 479254745Sjkim void *Context) 480254745Sjkim{ 481254745Sjkim ACPI_SCI_HANDLER_INFO *NewSciHandler; 482254745Sjkim ACPI_SCI_HANDLER_INFO *SciHandler; 483254745Sjkim ACPI_CPU_FLAGS Flags; 484254745Sjkim ACPI_STATUS Status; 485254745Sjkim 486254745Sjkim 487254745Sjkim ACPI_FUNCTION_TRACE (AcpiInstallSciHandler); 488254745Sjkim 489254745Sjkim 490254745Sjkim if (!Address) 491254745Sjkim { 492254745Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 493254745Sjkim } 494254745Sjkim 495254745Sjkim /* Allocate and init a handler object */ 496254745Sjkim 497254745Sjkim NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO)); 498254745Sjkim if (!NewSciHandler) 499254745Sjkim { 500254745Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 501254745Sjkim } 502254745Sjkim 503254745Sjkim NewSciHandler->Address = Address; 504254745Sjkim NewSciHandler->Context = Context; 505254745Sjkim 506254745Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 507254745Sjkim if (ACPI_FAILURE (Status)) 508254745Sjkim { 509254745Sjkim goto Exit; 510254745Sjkim } 511254745Sjkim 512254745Sjkim /* Lock list during installation */ 513254745Sjkim 514254745Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 515254745Sjkim SciHandler = AcpiGbl_SciHandlerList; 516254745Sjkim 517254745Sjkim /* Ensure handler does not already exist */ 518254745Sjkim 519254745Sjkim while (SciHandler) 520254745Sjkim { 521254745Sjkim if (Address == SciHandler->Address) 522254745Sjkim { 523254745Sjkim Status = AE_ALREADY_EXISTS; 524254745Sjkim goto UnlockAndExit; 525254745Sjkim } 526254745Sjkim 527254745Sjkim SciHandler = SciHandler->Next; 528254745Sjkim } 529254745Sjkim 530254745Sjkim /* Install the new handler into the global list (at head) */ 531254745Sjkim 532254745Sjkim NewSciHandler->Next = AcpiGbl_SciHandlerList; 533254745Sjkim AcpiGbl_SciHandlerList = NewSciHandler; 534254745Sjkim 535254745Sjkim 536254745SjkimUnlockAndExit: 537254745Sjkim 538254745Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 539254745Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 540254745Sjkim 541254745SjkimExit: 542254745Sjkim if (ACPI_FAILURE (Status)) 543254745Sjkim { 544254745Sjkim ACPI_FREE (NewSciHandler); 545254745Sjkim } 546254745Sjkim return_ACPI_STATUS (Status); 547254745Sjkim} 548254745Sjkim 549281075SdimACPI_EXPORT_SYMBOL (AcpiInstallSciHandler) 550254745Sjkim 551281075Sdim 552254745Sjkim/******************************************************************************* 553254745Sjkim * 554254745Sjkim * FUNCTION: AcpiRemoveSciHandler 555254745Sjkim * 556254745Sjkim * PARAMETERS: Address - Address of the handler 557254745Sjkim * 558254745Sjkim * RETURN: Status 559254745Sjkim * 560254745Sjkim * DESCRIPTION: Remove a handler for a System Control Interrupt. 561254745Sjkim * 562254745Sjkim ******************************************************************************/ 563254745Sjkim 564254745SjkimACPI_STATUS 565254745SjkimAcpiRemoveSciHandler ( 566254745Sjkim ACPI_SCI_HANDLER Address) 567254745Sjkim{ 568254745Sjkim ACPI_SCI_HANDLER_INFO *PrevSciHandler; 569254745Sjkim ACPI_SCI_HANDLER_INFO *NextSciHandler; 570254745Sjkim ACPI_CPU_FLAGS Flags; 571254745Sjkim ACPI_STATUS Status; 572254745Sjkim 573254745Sjkim 574254745Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler); 575254745Sjkim 576254745Sjkim 577254745Sjkim if (!Address) 578254745Sjkim { 579254745Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 580254745Sjkim } 581254745Sjkim 582254745Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 583254745Sjkim if (ACPI_FAILURE (Status)) 584254745Sjkim { 585254745Sjkim return_ACPI_STATUS (Status); 586254745Sjkim } 587254745Sjkim 588254745Sjkim /* Remove the SCI handler with lock */ 589254745Sjkim 590254745Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 591254745Sjkim 592254745Sjkim PrevSciHandler = NULL; 593254745Sjkim NextSciHandler = AcpiGbl_SciHandlerList; 594254745Sjkim while (NextSciHandler) 595254745Sjkim { 596254745Sjkim if (NextSciHandler->Address == Address) 597254745Sjkim { 598254745Sjkim /* Unlink and free the SCI handler info block */ 599254745Sjkim 600254745Sjkim if (PrevSciHandler) 601254745Sjkim { 602254745Sjkim PrevSciHandler->Next = NextSciHandler->Next; 603254745Sjkim } 604254745Sjkim else 605254745Sjkim { 606254745Sjkim AcpiGbl_SciHandlerList = NextSciHandler->Next; 607254745Sjkim } 608254745Sjkim 609254745Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 610254745Sjkim ACPI_FREE (NextSciHandler); 611254745Sjkim goto UnlockAndExit; 612254745Sjkim } 613254745Sjkim 614254745Sjkim PrevSciHandler = NextSciHandler; 615254745Sjkim NextSciHandler = NextSciHandler->Next; 616254745Sjkim } 617254745Sjkim 618254745Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 619254745Sjkim Status = AE_NOT_EXIST; 620254745Sjkim 621254745Sjkim 622254745SjkimUnlockAndExit: 623254745Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 624254745Sjkim return_ACPI_STATUS (Status); 625254745Sjkim} 626254745Sjkim 627281075SdimACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler) 628254745Sjkim 629281075Sdim 630254745Sjkim/******************************************************************************* 631254745Sjkim * 632231844Sjkim * FUNCTION: AcpiInstallGlobalEventHandler 633231844Sjkim * 634231844Sjkim * PARAMETERS: Handler - Pointer to the global event handler function 635231844Sjkim * Context - Value passed to the handler on each event 636231844Sjkim * 637231844Sjkim * RETURN: Status 638231844Sjkim * 639231844Sjkim * DESCRIPTION: Saves the pointer to the handler function. The global handler 640231844Sjkim * is invoked upon each incoming GPE and Fixed Event. It is 641231844Sjkim * invoked at interrupt level at the time of the event dispatch. 642231844Sjkim * Can be used to update event counters, etc. 643231844Sjkim * 644231844Sjkim ******************************************************************************/ 645231844Sjkim 646231844SjkimACPI_STATUS 647231844SjkimAcpiInstallGlobalEventHandler ( 648231844Sjkim ACPI_GBL_EVENT_HANDLER Handler, 649231844Sjkim void *Context) 650231844Sjkim{ 651231844Sjkim ACPI_STATUS Status; 652231844Sjkim 653231844Sjkim 654231844Sjkim ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); 655231844Sjkim 656231844Sjkim 657231844Sjkim /* Parameter validation */ 658231844Sjkim 659231844Sjkim if (!Handler) 660231844Sjkim { 661231844Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 662231844Sjkim } 663231844Sjkim 664231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 665231844Sjkim if (ACPI_FAILURE (Status)) 666231844Sjkim { 667231844Sjkim return_ACPI_STATUS (Status); 668231844Sjkim } 669231844Sjkim 670231844Sjkim /* Don't allow two handlers. */ 671231844Sjkim 672231844Sjkim if (AcpiGbl_GlobalEventHandler) 673231844Sjkim { 674231844Sjkim Status = AE_ALREADY_EXISTS; 675231844Sjkim goto Cleanup; 676231844Sjkim } 677231844Sjkim 678231844Sjkim AcpiGbl_GlobalEventHandler = Handler; 679231844Sjkim AcpiGbl_GlobalEventHandlerContext = Context; 680231844Sjkim 681231844Sjkim 682231844SjkimCleanup: 683231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 684231844Sjkim return_ACPI_STATUS (Status); 685231844Sjkim} 686231844Sjkim 687231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) 688231844Sjkim 689231844Sjkim 690231844Sjkim/******************************************************************************* 691231844Sjkim * 692231844Sjkim * FUNCTION: AcpiInstallFixedEventHandler 693231844Sjkim * 694231844Sjkim * PARAMETERS: Event - Event type to enable. 695231844Sjkim * Handler - Pointer to the handler function for the 696231844Sjkim * event 697231844Sjkim * Context - Value passed to the handler on each GPE 698231844Sjkim * 699231844Sjkim * RETURN: Status 700231844Sjkim * 701231844Sjkim * DESCRIPTION: Saves the pointer to the handler function and then enables the 702231844Sjkim * event. 703231844Sjkim * 704231844Sjkim ******************************************************************************/ 705231844Sjkim 706231844SjkimACPI_STATUS 707231844SjkimAcpiInstallFixedEventHandler ( 708231844Sjkim UINT32 Event, 709231844Sjkim ACPI_EVENT_HANDLER Handler, 710231844Sjkim void *Context) 711231844Sjkim{ 712231844Sjkim ACPI_STATUS Status; 713231844Sjkim 714231844Sjkim 715231844Sjkim ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); 716231844Sjkim 717231844Sjkim 718231844Sjkim /* Parameter validation */ 719231844Sjkim 720231844Sjkim if (Event > ACPI_EVENT_MAX) 721231844Sjkim { 722231844Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 723231844Sjkim } 724231844Sjkim 725231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 726231844Sjkim if (ACPI_FAILURE (Status)) 727231844Sjkim { 728231844Sjkim return_ACPI_STATUS (Status); 729231844Sjkim } 730231844Sjkim 731246849Sjkim /* Do not allow multiple handlers */ 732231844Sjkim 733246849Sjkim if (AcpiGbl_FixedEventHandlers[Event].Handler) 734231844Sjkim { 735231844Sjkim Status = AE_ALREADY_EXISTS; 736231844Sjkim goto Cleanup; 737231844Sjkim } 738231844Sjkim 739231844Sjkim /* Install the handler before enabling the event */ 740231844Sjkim 741231844Sjkim AcpiGbl_FixedEventHandlers[Event].Handler = Handler; 742231844Sjkim AcpiGbl_FixedEventHandlers[Event].Context = Context; 743231844Sjkim 744231844Sjkim Status = AcpiEnableEvent (Event, 0); 745231844Sjkim if (ACPI_FAILURE (Status)) 746231844Sjkim { 747246849Sjkim ACPI_WARNING ((AE_INFO, 748246849Sjkim "Could not enable fixed event - %s (%u)", 749246849Sjkim AcpiUtGetEventName (Event), Event)); 750231844Sjkim 751231844Sjkim /* Remove the handler */ 752231844Sjkim 753231844Sjkim AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 754231844Sjkim AcpiGbl_FixedEventHandlers[Event].Context = NULL; 755231844Sjkim } 756231844Sjkim else 757231844Sjkim { 758231844Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 759246849Sjkim "Enabled fixed event %s (%X), Handler=%p\n", 760246849Sjkim AcpiUtGetEventName (Event), Event, Handler)); 761231844Sjkim } 762231844Sjkim 763231844Sjkim 764231844SjkimCleanup: 765231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 766231844Sjkim return_ACPI_STATUS (Status); 767231844Sjkim} 768231844Sjkim 769231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) 770231844Sjkim 771231844Sjkim 772231844Sjkim/******************************************************************************* 773231844Sjkim * 774231844Sjkim * FUNCTION: AcpiRemoveFixedEventHandler 775231844Sjkim * 776231844Sjkim * PARAMETERS: Event - Event type to disable. 777231844Sjkim * Handler - Address of the handler 778231844Sjkim * 779231844Sjkim * RETURN: Status 780231844Sjkim * 781231844Sjkim * DESCRIPTION: Disables the event and unregisters the event handler. 782231844Sjkim * 783231844Sjkim ******************************************************************************/ 784231844Sjkim 785231844SjkimACPI_STATUS 786231844SjkimAcpiRemoveFixedEventHandler ( 787231844Sjkim UINT32 Event, 788231844Sjkim ACPI_EVENT_HANDLER Handler) 789231844Sjkim{ 790231844Sjkim ACPI_STATUS Status = AE_OK; 791231844Sjkim 792231844Sjkim 793231844Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); 794231844Sjkim 795231844Sjkim 796231844Sjkim /* Parameter validation */ 797231844Sjkim 798231844Sjkim if (Event > ACPI_EVENT_MAX) 799231844Sjkim { 800231844Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 801231844Sjkim } 802231844Sjkim 803231844Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 804231844Sjkim if (ACPI_FAILURE (Status)) 805231844Sjkim { 806231844Sjkim return_ACPI_STATUS (Status); 807231844Sjkim } 808231844Sjkim 809231844Sjkim /* Disable the event before removing the handler */ 810231844Sjkim 811231844Sjkim Status = AcpiDisableEvent (Event, 0); 812231844Sjkim 813231844Sjkim /* Always Remove the handler */ 814231844Sjkim 815231844Sjkim AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 816231844Sjkim AcpiGbl_FixedEventHandlers[Event].Context = NULL; 817231844Sjkim 818231844Sjkim if (ACPI_FAILURE (Status)) 819231844Sjkim { 820231844Sjkim ACPI_WARNING ((AE_INFO, 821246849Sjkim "Could not disable fixed event - %s (%u)", 822246849Sjkim AcpiUtGetEventName (Event), Event)); 823231844Sjkim } 824231844Sjkim else 825231844Sjkim { 826246849Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 827246849Sjkim "Disabled fixed event - %s (%X)\n", 828246849Sjkim AcpiUtGetEventName (Event), Event)); 829231844Sjkim } 830231844Sjkim 831231844Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 832231844Sjkim return_ACPI_STATUS (Status); 833231844Sjkim} 834231844Sjkim 835231844SjkimACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) 836231844Sjkim 837231844Sjkim 838231844Sjkim/******************************************************************************* 839231844Sjkim * 840281075Sdim * FUNCTION: AcpiEvInstallGpeHandler 84167754Smsmith * 842151937Sjkim * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 843151937Sjkim * defined GPEs) 844151937Sjkim * GpeNumber - The GPE number within the GPE block 84567754Smsmith * Type - Whether this GPE should be treated as an 84667754Smsmith * edge- or level-triggered interrupt. 847281075Sdim * IsRawHandler - Whether this GPE should be handled using 848281075Sdim * the special GPE handler mode. 849129684Snjl * Address - Address of the handler 85067754Smsmith * Context - Value passed to the handler on each GPE 85167754Smsmith * 85267754Smsmith * RETURN: Status 85367754Smsmith * 854281075Sdim * DESCRIPTION: Internal function to install a handler for a General Purpose 855281075Sdim * Event. 85667754Smsmith * 85767754Smsmith ******************************************************************************/ 85867754Smsmith 859281075Sdimstatic ACPI_STATUS 860281075SdimAcpiEvInstallGpeHandler ( 861117521Snjl ACPI_HANDLE GpeDevice, 86267754Smsmith UINT32 GpeNumber, 86367754Smsmith UINT32 Type, 864281075Sdim BOOLEAN IsRawHandler, 865216471Sjkim ACPI_GPE_HANDLER Address, 86667754Smsmith void *Context) 86767754Smsmith{ 868129684Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo; 869216471Sjkim ACPI_GPE_HANDLER_INFO *Handler; 87091116Smsmith ACPI_STATUS Status; 871167802Sjkim ACPI_CPU_FLAGS Flags; 87267754Smsmith 87377424Smsmith 874281075Sdim ACPI_FUNCTION_TRACE (EvInstallGpeHandler); 87567754Smsmith 87677424Smsmith 87767754Smsmith /* Parameter validation */ 87867754Smsmith 879206117Sjkim if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) 88067754Smsmith { 88167754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 88267754Smsmith } 88367754Smsmith 884117521Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 885117521Snjl if (ACPI_FAILURE (Status)) 886117521Snjl { 887117521Snjl return_ACPI_STATUS (Status); 888117521Snjl } 889117521Snjl 890216471Sjkim /* Allocate and init handler object (before lock) */ 891216471Sjkim 892216471Sjkim Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO)); 893216471Sjkim if (!Handler) 894216471Sjkim { 895216471Sjkim Status = AE_NO_MEMORY; 896216471Sjkim goto UnlockAndExit; 897216471Sjkim } 898216471Sjkim 899216471Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 900216471Sjkim 90167754Smsmith /* Ensure that we have a valid GPE number */ 90267754Smsmith 903117521Snjl GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 904114237Snjl if (!GpeEventInfo) 90567754Smsmith { 906117521Snjl Status = AE_BAD_PARAMETER; 907216471Sjkim goto FreeAndExit; 90867754Smsmith } 90967754Smsmith 91067754Smsmith /* Make sure that there isn't a handler there already */ 91167754Smsmith 912281075Sdim if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 913281075Sdim ACPI_GPE_DISPATCH_HANDLER) || 914281075Sdim (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 915281075Sdim ACPI_GPE_DISPATCH_RAW_HANDLER)) 91667754Smsmith { 91787031Smsmith Status = AE_ALREADY_EXISTS; 918216471Sjkim goto FreeAndExit; 91967754Smsmith } 92067754Smsmith 921216471Sjkim Handler->Address = Address; 922216471Sjkim Handler->Context = Context; 923216471Sjkim Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; 924216471Sjkim Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags & 925216471Sjkim (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK)); 92667754Smsmith 927216471Sjkim /* 928216471Sjkim * If the GPE is associated with a method, it may have been enabled 929216471Sjkim * automatically during initialization, in which case it has to be 930216471Sjkim * disabled now to avoid spurious execution of the handler. 931216471Sjkim */ 932281075Sdim if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == 933281075Sdim ACPI_GPE_DISPATCH_METHOD) || 934281075Sdim (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == 935281075Sdim ACPI_GPE_DISPATCH_NOTIFY)) && 936216471Sjkim GpeEventInfo->RuntimeCount) 937129684Snjl { 938216471Sjkim Handler->OriginallyEnabled = TRUE; 939216471Sjkim (void) AcpiEvRemoveGpeReference (GpeEventInfo); 940216471Sjkim 941216471Sjkim /* Sanity check of original type against new type */ 942216471Sjkim 943216471Sjkim if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) 944216471Sjkim { 945216471Sjkim ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)")); 946216471Sjkim } 947129684Snjl } 94867754Smsmith 949129684Snjl /* Install the handler */ 95085756Smsmith 951129684Snjl GpeEventInfo->Dispatch.Handler = Handler; 95299679Siwasaki 953216471Sjkim /* Setup up dispatch flags to indicate handler (vs. method/notify) */ 954129684Snjl 955193267Sjkim GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 956281075Sdim GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ? 957281075Sdim ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER)); 958129684Snjl 959151937Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 960129684Snjl 961129684Snjl 962117521SnjlUnlockAndExit: 96391116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 96467754Smsmith return_ACPI_STATUS (Status); 965216471Sjkim 966216471SjkimFreeAndExit: 967216471Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 968216471Sjkim ACPI_FREE (Handler); 969216471Sjkim goto UnlockAndExit; 97067754Smsmith} 97167754Smsmith 972281075Sdim 973281075Sdim/******************************************************************************* 974281075Sdim * 975281075Sdim * FUNCTION: AcpiInstallGpeHandler 976281075Sdim * 977281075Sdim * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 978281075Sdim * defined GPEs) 979281075Sdim * GpeNumber - The GPE number within the GPE block 980281075Sdim * Type - Whether this GPE should be treated as an 981281075Sdim * edge- or level-triggered interrupt. 982281075Sdim * Address - Address of the handler 983281075Sdim * Context - Value passed to the handler on each GPE 984281075Sdim * 985281075Sdim * RETURN: Status 986281075Sdim * 987281075Sdim * DESCRIPTION: Install a handler for a General Purpose Event. 988281075Sdim * 989281075Sdim ******************************************************************************/ 990281075Sdim 991281075SdimACPI_STATUS 992281075SdimAcpiInstallGpeHandler ( 993281075Sdim ACPI_HANDLE GpeDevice, 994281075Sdim UINT32 GpeNumber, 995281075Sdim UINT32 Type, 996281075Sdim ACPI_GPE_HANDLER Address, 997281075Sdim void *Context) 998281075Sdim{ 999281075Sdim ACPI_STATUS Status; 1000281075Sdim 1001281075Sdim 1002281075Sdim ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); 1003281075Sdim 1004281075Sdim 1005281075Sdim Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type, FALSE, 1006281075Sdim Address, Context); 1007281075Sdim 1008281075Sdim return_ACPI_STATUS (Status); 1009281075Sdim} 1010281075Sdim 1011167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) 101267754Smsmith 1013167802Sjkim 101477424Smsmith/******************************************************************************* 101567754Smsmith * 1016281075Sdim * FUNCTION: AcpiInstallGpeRawHandler 1017281075Sdim * 1018281075Sdim * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 1019281075Sdim * defined GPEs) 1020281075Sdim * GpeNumber - The GPE number within the GPE block 1021281075Sdim * Type - Whether this GPE should be treated as an 1022281075Sdim * edge- or level-triggered interrupt. 1023281075Sdim * Address - Address of the handler 1024281075Sdim * Context - Value passed to the handler on each GPE 1025281075Sdim * 1026281075Sdim * RETURN: Status 1027281075Sdim * 1028281075Sdim * DESCRIPTION: Install a handler for a General Purpose Event. 1029281075Sdim * 1030281075Sdim ******************************************************************************/ 1031281075Sdim 1032281075SdimACPI_STATUS 1033281075SdimAcpiInstallGpeRawHandler ( 1034281075Sdim ACPI_HANDLE GpeDevice, 1035281075Sdim UINT32 GpeNumber, 1036281075Sdim UINT32 Type, 1037281075Sdim ACPI_GPE_HANDLER Address, 1038281075Sdim void *Context) 1039281075Sdim{ 1040281075Sdim ACPI_STATUS Status; 1041281075Sdim 1042281075Sdim 1043281075Sdim ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler); 1044281075Sdim 1045281075Sdim 1046281075Sdim Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type, TRUE, 1047281075Sdim Address, Context); 1048281075Sdim 1049281075Sdim return_ACPI_STATUS (Status); 1050281075Sdim} 1051281075Sdim 1052281075SdimACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler) 1053281075Sdim 1054281075Sdim 1055281075Sdim/******************************************************************************* 1056281075Sdim * 105767754Smsmith * FUNCTION: AcpiRemoveGpeHandler 105867754Smsmith * 1059151937Sjkim * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 1060151937Sjkim * defined GPEs) 1061151937Sjkim * GpeNumber - The event to remove a handler 1062129684Snjl * Address - Address of the handler 106367754Smsmith * 106467754Smsmith * RETURN: Status 106567754Smsmith * 106667754Smsmith * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. 106767754Smsmith * 106867754Smsmith ******************************************************************************/ 106967754Smsmith 107067754SmsmithACPI_STATUS 107167754SmsmithAcpiRemoveGpeHandler ( 1072117521Snjl ACPI_HANDLE GpeDevice, 107367754Smsmith UINT32 GpeNumber, 1074216471Sjkim ACPI_GPE_HANDLER Address) 107567754Smsmith{ 1076129684Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo; 1077216471Sjkim ACPI_GPE_HANDLER_INFO *Handler; 107891116Smsmith ACPI_STATUS Status; 1079167802Sjkim ACPI_CPU_FLAGS Flags; 108067754Smsmith 108167754Smsmith 1082167802Sjkim ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); 108367754Smsmith 108467754Smsmith 108567754Smsmith /* Parameter validation */ 108667754Smsmith 1087129684Snjl if (!Address) 108867754Smsmith { 108967754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 109067754Smsmith } 109167754Smsmith 1092117521Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 1093117521Snjl if (ACPI_FAILURE (Status)) 1094117521Snjl { 1095117521Snjl return_ACPI_STATUS (Status); 1096117521Snjl } 1097117521Snjl 1098216471Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 1099216471Sjkim 110067754Smsmith /* Ensure that we have a valid GPE number */ 110167754Smsmith 1102117521Snjl GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 1103114237Snjl if (!GpeEventInfo) 110467754Smsmith { 1105117521Snjl Status = AE_BAD_PARAMETER; 1106117521Snjl goto UnlockAndExit; 110767754Smsmith } 110867754Smsmith 1109129684Snjl /* Make sure that a handler is indeed installed */ 111067754Smsmith 1111281075Sdim if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != 1112281075Sdim ACPI_GPE_DISPATCH_HANDLER) && 1113281075Sdim (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != 1114281075Sdim ACPI_GPE_DISPATCH_RAW_HANDLER)) 111599679Siwasaki { 1116129684Snjl Status = AE_NOT_EXIST; 1117117521Snjl goto UnlockAndExit; 111899679Siwasaki } 111967754Smsmith 112067754Smsmith /* Make sure that the installed handler is the same */ 112167754Smsmith 1122129684Snjl if (GpeEventInfo->Dispatch.Handler->Address != Address) 112367754Smsmith { 112467754Smsmith Status = AE_BAD_PARAMETER; 1125117521Snjl goto UnlockAndExit; 112667754Smsmith } 112767754Smsmith 112867754Smsmith /* Remove the handler */ 112967754Smsmith 1130129684Snjl Handler = GpeEventInfo->Dispatch.Handler; 1131281075Sdim GpeEventInfo->Dispatch.Handler = NULL; 1132129684Snjl 1133129684Snjl /* Restore Method node (if any), set dispatch flags */ 1134129684Snjl 1135129684Snjl GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; 1136216471Sjkim GpeEventInfo->Flags &= 1137216471Sjkim ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 1138216471Sjkim GpeEventInfo->Flags |= Handler->OriginalFlags; 1139216471Sjkim 1140216471Sjkim /* 1141216471Sjkim * If the GPE was previously associated with a method and it was 1142216471Sjkim * enabled, it should be enabled at this point to restore the 1143216471Sjkim * post-initialization configuration. 1144216471Sjkim */ 1145281075Sdim if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == 1146281075Sdim ACPI_GPE_DISPATCH_METHOD) || 1147281075Sdim (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == 1148281075Sdim ACPI_GPE_DISPATCH_NOTIFY)) && 1149216471Sjkim Handler->OriginallyEnabled) 1150129684Snjl { 1151216471Sjkim (void) AcpiEvAddGpeReference (GpeEventInfo); 1152129684Snjl } 115367754Smsmith 1154281075Sdim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 1155281075Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 1156281075Sdim 1157281075Sdim /* Make sure all deferred GPE tasks are completed */ 1158281075Sdim 1159281075Sdim AcpiOsWaitEventsComplete (); 1160281075Sdim 1161129684Snjl /* Now we can free the handler object */ 116285756Smsmith 1163167802Sjkim ACPI_FREE (Handler); 1164281075Sdim return_ACPI_STATUS (Status); 1165129684Snjl 1166117521SnjlUnlockAndExit: 1167216471Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 116891116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 116967754Smsmith return_ACPI_STATUS (Status); 117067754Smsmith} 117167754Smsmith 1172167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) 117367754Smsmith 1174167802Sjkim 117577424Smsmith/******************************************************************************* 117667754Smsmith * 117767754Smsmith * FUNCTION: AcpiAcquireGlobalLock 117867754Smsmith * 117967754Smsmith * PARAMETERS: Timeout - How long the caller is willing to wait 1180151937Sjkim * Handle - Where the handle to the lock is returned 1181151937Sjkim * (if acquired) 118267754Smsmith * 118367754Smsmith * RETURN: Status 118467754Smsmith * 118567754Smsmith * DESCRIPTION: Acquire the ACPI Global Lock 118667754Smsmith * 1187167802Sjkim * Note: Allows callers with the same thread ID to acquire the global lock 1188167802Sjkim * multiple times. In other words, externally, the behavior of the global lock 1189167802Sjkim * is identical to an AML mutex. On the first acquire, a new handle is 1190167802Sjkim * returned. On any subsequent calls to acquire by the same thread, the same 1191167802Sjkim * handle is returned. 1192167802Sjkim * 119367754Smsmith ******************************************************************************/ 119485756Smsmith 119567754SmsmithACPI_STATUS 119667754SmsmithAcpiAcquireGlobalLock ( 1197107325Siwasaki UINT16 Timeout, 119891116Smsmith UINT32 *Handle) 119967754Smsmith{ 120067754Smsmith ACPI_STATUS Status; 120167754Smsmith 120267754Smsmith 120391116Smsmith if (!Handle) 120491116Smsmith { 120591116Smsmith return (AE_BAD_PARAMETER); 120691116Smsmith } 120791116Smsmith 1208167802Sjkim /* Must lock interpreter to prevent race conditions */ 120977424Smsmith 1210167802Sjkim AcpiExEnterInterpreter (); 121167754Smsmith 1212167802Sjkim Status = AcpiExAcquireMutexObject (Timeout, 1213167802Sjkim AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); 1214167802Sjkim 121591116Smsmith if (ACPI_SUCCESS (Status)) 121691116Smsmith { 1217172314Sjkim /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ 1218167802Sjkim 121991116Smsmith *Handle = AcpiGbl_GlobalLockHandle; 122091116Smsmith } 122191116Smsmith 1222167802Sjkim AcpiExExitInterpreter (); 122367754Smsmith return (Status); 122467754Smsmith} 122567754Smsmith 1226167802SjkimACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) 122767754Smsmith 1228167802Sjkim 122977424Smsmith/******************************************************************************* 123067754Smsmith * 123167754Smsmith * FUNCTION: AcpiReleaseGlobalLock 123267754Smsmith * 123367754Smsmith * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock 123467754Smsmith * 123567754Smsmith * RETURN: Status 123667754Smsmith * 1237151937Sjkim * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. 123867754Smsmith * 123967754Smsmith ******************************************************************************/ 124067754Smsmith 124167754SmsmithACPI_STATUS 124267754SmsmithAcpiReleaseGlobalLock ( 124391116Smsmith UINT32 Handle) 124467754Smsmith{ 124599679Siwasaki ACPI_STATUS Status; 124685756Smsmith 124799679Siwasaki 1248167802Sjkim if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) 124991116Smsmith { 125091116Smsmith return (AE_NOT_ACQUIRED); 125191116Smsmith } 125291116Smsmith 1253167802Sjkim Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); 125499679Siwasaki return (Status); 125567754Smsmith} 125667754Smsmith 1257167802SjkimACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) 125867754Smsmith 1259231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 1260