Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/acpi/acpica/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 8 kB image not shown  

Quelle  evgpeutil.c   Sprache: C

 
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/******************************************************************************
 *
 * Module Name: evgpeutil - GPE utilities
 *
 * Copyright (C) 2000 - 2025, Intel Corp.
 *
 *****************************************************************************/


#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"

#define _COMPONENT          ACPI_EVENTS
ACPI_MODULE_NAME("evgpeutil")

#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_walk_gpe_list
 *
 * PARAMETERS:  gpe_walk_callback   - Routine called for each GPE block
 *              context             - Value passed to callback
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Walk the GPE lists.
 *
 ******************************************************************************/

acpi_status
acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context)
{
 struct acpi_gpe_block_info *gpe_block;
 struct acpi_gpe_xrupt_info *gpe_xrupt_info;
 acpi_status status = AE_OK;
 acpi_cpu_flags flags;

 ACPI_FUNCTION_TRACE(ev_walk_gpe_list);

 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);

 /* Walk the interrupt level descriptor list */

 gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
 while (gpe_xrupt_info) {

  /* Walk all Gpe Blocks attached to this interrupt level */

  gpe_block = gpe_xrupt_info->gpe_block_list_head;
  while (gpe_block) {

   /* One callback per GPE block */

   status =
       gpe_walk_callback(gpe_xrupt_info, gpe_block,
           context);
   if (ACPI_FAILURE(status)) {
    if (status == AE_CTRL_END) { /* Callback abort */
     status = AE_OK;
    }
    goto unlock_and_exit;
   }

   gpe_block = gpe_block->next;
  }

  gpe_xrupt_info = gpe_xrupt_info->next;
 }

unlock_and_exit:
 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 return_ACPI_STATUS(status);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_get_gpe_device
 *
 * PARAMETERS:  GPE_WALK_CALLBACK
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
 *              block device. NULL if the GPE is one of the FADT-defined GPEs.
 *
 ******************************************************************************/


acpi_status
acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
         struct acpi_gpe_block_info *gpe_block, void *context)
{
 struct acpi_gpe_device_info *info = context;

 /* Increment Index by the number of GPEs in this block */

 info->next_block_base_index += gpe_block->gpe_count;

 if (info->index < info->next_block_base_index) {
  /*
 * The GPE index is within this block, get the node. Leave the node
 * NULL for the FADT-defined GPEs
 */

  if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
   info->gpe_device = gpe_block->node;
  }

  info->status = AE_OK;
  return (AE_CTRL_END);
 }

 return (AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_get_gpe_xrupt_block
 *
 * PARAMETERS:  interrupt_number            - Interrupt for a GPE block
 *              gpe_xrupt_block             - Where the block is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
 *              block per unique interrupt level used for GPEs. Should be
 *              called only when the GPE lists are semaphore locked and not
 *              subject to change.
 *
 ******************************************************************************/


acpi_status
acpi_ev_get_gpe_xrupt_block(u32 interrupt_number,
       struct acpi_gpe_xrupt_info **gpe_xrupt_block)
{
 struct acpi_gpe_xrupt_info *next_gpe_xrupt;
 struct acpi_gpe_xrupt_info *gpe_xrupt;
 acpi_status status;
 acpi_cpu_flags flags;

 ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block);

 /* No need for lock since we are not changing any list elements here */

 next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
 while (next_gpe_xrupt) {
  if (next_gpe_xrupt->interrupt_number == interrupt_number) {
   *gpe_xrupt_block = next_gpe_xrupt;
   return_ACPI_STATUS(AE_OK);
  }

  next_gpe_xrupt = next_gpe_xrupt->next;
 }

 /* Not found, must allocate a new xrupt descriptor */

 gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info));
 if (!gpe_xrupt) {
  return_ACPI_STATUS(AE_NO_MEMORY);
 }

 gpe_xrupt->interrupt_number = interrupt_number;

 /* Install new interrupt descriptor with spin lock */

 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 if (acpi_gbl_gpe_xrupt_list_head) {
  next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
  while (next_gpe_xrupt->next) {
   next_gpe_xrupt = next_gpe_xrupt->next;
  }

  next_gpe_xrupt->next = gpe_xrupt;
  gpe_xrupt->previous = next_gpe_xrupt;
 } else {
  acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
 }

 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);

 /* Install new interrupt handler if not SCI_INT */

 if (interrupt_number != acpi_gbl_FADT.sci_interrupt) {
  status = acpi_os_install_interrupt_handler(interrupt_number,
          acpi_ev_gpe_xrupt_handler,
          gpe_xrupt);
  if (ACPI_FAILURE(status)) {
   ACPI_EXCEPTION((AE_INFO, status,
     "Could not install GPE interrupt handler at level 0x%X",
     interrupt_number));
   return_ACPI_STATUS(status);
  }
 }

 *gpe_xrupt_block = gpe_xrupt;
 return_ACPI_STATUS(AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_delete_gpe_xrupt
 *
 * PARAMETERS:  gpe_xrupt       - A GPE interrupt info block
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated
 *              interrupt handler if not the SCI interrupt.
 *
 ******************************************************************************/


acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
{
 acpi_status status;
 acpi_cpu_flags flags;

 ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt);

 /* We never want to remove the SCI interrupt handler */

 if (gpe_xrupt->interrupt_number == acpi_gbl_FADT.sci_interrupt) {
  gpe_xrupt->gpe_block_list_head = NULL;
  return_ACPI_STATUS(AE_OK);
 }

 /* Disable this interrupt */

 status =
     acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
          acpi_ev_gpe_xrupt_handler);
 if (ACPI_FAILURE(status)) {
  return_ACPI_STATUS(status);
 }

 /* Unlink the interrupt block with lock */

 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 if (gpe_xrupt->previous) {
  gpe_xrupt->previous->next = gpe_xrupt->next;
 } else {
  /* No previous, update list head */

  acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next;
 }

 if (gpe_xrupt->next) {
  gpe_xrupt->next->previous = gpe_xrupt->previous;
 }
 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);

 /* Free the block */

 ACPI_FREE(gpe_xrupt);
 return_ACPI_STATUS(AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_delete_gpe_handlers
 *
 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 *              gpe_block           - Gpe Block info
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
 *              Used only prior to termination.
 *
 ******************************************************************************/


acpi_status
acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
       struct acpi_gpe_block_info *gpe_block,
       void *context)
{
 struct acpi_gpe_event_info *gpe_event_info;
 struct acpi_gpe_notify_info *notify;
 struct acpi_gpe_notify_info *next;
 u32 i;
 u32 j;

 ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers);

 /* Examine each GPE Register within the block */

 for (i = 0; i < gpe_block->register_count; i++) {

  /* Now look at the individual GPEs in this byte register */

  for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
   gpe_event_info = &gpe_block->event_info[((acpi_size)i *
         ACPI_GPE_REGISTER_WIDTH)
        + j];

   if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
        ACPI_GPE_DISPATCH_HANDLER) ||
       (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
        ACPI_GPE_DISPATCH_RAW_HANDLER)) {

    /* Delete an installed handler block */

    ACPI_FREE(gpe_event_info->dispatch.handler);
    gpe_event_info->dispatch.handler = NULL;
    gpe_event_info->flags &=
        ~ACPI_GPE_DISPATCH_MASK;
   } else if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags)
       == ACPI_GPE_DISPATCH_NOTIFY) {

    /* Delete the implicit notification device list */

    notify = gpe_event_info->dispatch.notify_list;
    while (notify) {
     next = notify->next;
     ACPI_FREE(notify);
     notify = next;
    }

    gpe_event_info->dispatch.notify_list = NULL;
    gpe_event_info->flags &=
        ~ACPI_GPE_DISPATCH_MASK;
   }
  }
 }

 return_ACPI_STATUS(AE_OK);
}

#endif    /* !ACPI_REDUCED_HARDWARE */

Messung V0.5
C=95 H=88 G=91

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.