text: /******************************************************************************
   *
   * Module Name: evevent - Fixed Event handling and dispatch
   *
   *****************************************************************************/
  
  /*
   * Copyright (C) 2000 - 2011, Intel Corp.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   *    substantially similar to the "NO WARRANTY" disclaimer below
   *    ("Disclaimer") and any redistribution must be conditioned upon
   *    including a substantially similar Disclaimer requirement for further
   *    binary redistribution.
   * 3. Neither the names of the above-listed copyright holders nor the names
   *    of any contributors may be used to endorse or promote products derived
   *    from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * NO WARRANTY
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   */
  
  #include <contrib/dev/acpica/include/acpi.h>
  #include <contrib/dev/acpica/include/accommon.h>
  #include <contrib/dev/acpica/include/acevents.h>
  
  #define _COMPONENT          ACPI_EVENTS
          ACPI_MODULE_NAME    ("evevent")
  
  /* Local prototypes */
  
  static ACPI_STATUS
  AcpiEvFixedEventInitialize (
      void);
  
  static UINT32
  AcpiEvFixedEventDispatch (
      UINT32                  Event);
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiEvInitializeEvents
   *
   * PARAMETERS:  None
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
   *
   ******************************************************************************/
  
  ACPI_STATUS
  AcpiEvInitializeEvents (
      void)
  {
      ACPI_STATUS             Status;
  
  
      ACPI_FUNCTION_TRACE (EvInitializeEvents);
  
  
      /*
       * Initialize the Fixed and General Purpose Events. This is done prior to
       * enabling SCIs to prevent interrupts from occurring before the handlers
       * are installed.
       */
      Status = AcpiEvFixedEventInitialize ();
      if (ACPI_FAILURE (Status))
      {
          ACPI_EXCEPTION ((AE_INFO, Status,
              "Unable to initialize fixed events"));
          return_ACPI_STATUS (Status);
      }
  
      Status = AcpiEvGpeInitialize ();
      if (ACPI_FAILURE (Status))
      {
          ACPI_EXCEPTION ((AE_INFO, Status,
              "Unable to initialize general purpose events"));
          return_ACPI_STATUS (Status);
      }
  
      return_ACPI_STATUS (Status);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiEvInstallXruptHandlers
   *
   * PARAMETERS:  None
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
   *
   ******************************************************************************/
  
  ACPI_STATUS
  AcpiEvInstallXruptHandlers (
      void)
  {
      ACPI_STATUS             Status;
  
  
      ACPI_FUNCTION_TRACE (EvInstallXruptHandlers);
  
  
      /* Install the SCI handler */
  
      Status = AcpiEvInstallSciHandler ();
      if (ACPI_FAILURE (Status))
      {
          ACPI_EXCEPTION ((AE_INFO, Status,
              "Unable to install System Control Interrupt handler"));
          return_ACPI_STATUS (Status);
      }
  
      /* Install the handler for the Global Lock */
  
      Status = AcpiEvInitGlobalLockHandler ();
      if (ACPI_FAILURE (Status))
      {
          ACPI_EXCEPTION ((AE_INFO, Status,
              "Unable to initialize Global Lock handler"));
          return_ACPI_STATUS (Status);
      }
  
      AcpiGbl_EventsInitialized = TRUE;
      return_ACPI_STATUS (Status);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiEvFixedEventInitialize
   *
   * PARAMETERS:  None
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Install the fixed event handlers and disable all fixed events.
   *
   ******************************************************************************/
  
  static ACPI_STATUS
  AcpiEvFixedEventInitialize (
      void)
  {
      UINT32                  i;
      ACPI_STATUS             Status;
  
  
      /*
       * Initialize the structure that keeps track of fixed event handlers and
       * enable the fixed events.
       */
      for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
      {
          AcpiGbl_FixedEventHandlers[i].Handler = NULL;
          AcpiGbl_FixedEventHandlers[i].Context = NULL;
  
          /* Disable the fixed event */
  
          if (AcpiGbl_FixedEventInfo[i].EnableRegisterId != 0xFF)
          {
              Status = AcpiWriteBitRegister (
                          AcpiGbl_FixedEventInfo[i].EnableRegisterId,
                          ACPI_DISABLE_EVENT);
              if (ACPI_FAILURE (Status))
              {
                  return (Status);
              }
          }
      }
  
      return (AE_OK);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiEvFixedEventDetect
   *
   * PARAMETERS:  None
   *
   * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
   *
   * DESCRIPTION: Checks the PM status register for active fixed events
   *
   ******************************************************************************/
  
  UINT32
  AcpiEvFixedEventDetect (
      void)
  {
      UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
      UINT32                  FixedStatus;
      UINT32                  FixedEnable;
      UINT32                  i;
  
  
      ACPI_FUNCTION_NAME (EvFixedEventDetect);
  
  
      /*
       * Read the fixed feature status and enable registers, as all the cases
       * depend on their values. Ignore errors here.
       */
      (void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, &FixedStatus);
      (void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_ENABLE, &FixedEnable);
  
      ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
          "Fixed Event Block: Enable %08X Status %08X\n",
          FixedEnable, FixedStatus));
  
      /*
       * Check for all possible Fixed Events and dispatch those that are active
       */
      for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
      {
          /* Both the status and enable bits must be on for this event */
  
          if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) &&
              (FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask))
          {
              /*
               * Found an active (signalled) event. Invoke global event
               * handler if present.
               */
              AcpiFixedEventCount[i]++;
              if (AcpiGbl_GlobalEventHandler)
              {
                  AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_FIXED, NULL,
                       i, AcpiGbl_GlobalEventHandlerContext);
              }
  
              IntStatus |= AcpiEvFixedEventDispatch (i);
          }
      }
  
      return (IntStatus);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiEvFixedEventDispatch
   *
   * PARAMETERS:  Event               - Event type
   *
   * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
   *
   * DESCRIPTION: Clears the status bit for the requested event, calls the
   *              handler that previously registered for the event.
   *
   ******************************************************************************/
  
  static UINT32
  AcpiEvFixedEventDispatch (
      UINT32                  Event)
  {
  
      ACPI_FUNCTION_ENTRY ();
  
  
      /* Clear the status bit */
  
      (void) AcpiWriteBitRegister (
              AcpiGbl_FixedEventInfo[Event].StatusRegisterId,
              ACPI_CLEAR_STATUS);
  
      /*
       * Make sure we've got a handler. If not, report an error. The event is
       * disabled to prevent further interrupts.
       */
      if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler)
      {
          (void) AcpiWriteBitRegister (
                  AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
                  ACPI_DISABLE_EVENT);
  
          ACPI_ERROR ((AE_INFO,
              "No installed handler for fixed event [0x%08X]",
              Event));
  
          return (ACPI_INTERRUPT_NOT_HANDLED);
      }
  
      /* Invoke the Fixed Event handler */
  
      return ((AcpiGbl_FixedEventHandlers[Event].Handler)(
                  AcpiGbl_FixedEventHandlers[Event].Context));
  }
  
  
  