evevent.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 875 行 · 第 1/2 页
C
875 行
/****************************************************************************** * * Module Name: evevent - Fixed and General Purpose Even handling and dispatch * $Revision: 78 $ * *****************************************************************************//* * Copyright (C) 2000 - 2002, R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "acpi.h"#include "achware.h"#include "acevents.h"#include "acnamesp.h"#define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evevent")/******************************************************************************* * * FUNCTION: Acpi_ev_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Initialize global data structures for events. * ******************************************************************************/acpi_statusacpi_ev_initialize ( void){ acpi_status status; ACPI_FUNCTION_TRACE ("Ev_initialize"); /* Make sure we have ACPI tables */ if (!acpi_gbl_DSDT) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* * Initialize the Fixed and General Purpose Acpi_events prior. This is * done prior to enabling SCIs to prevent interrupts from occuring * before handers are installed. */ status = acpi_ev_fixed_event_initialize (); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize fixed events, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } status = acpi_ev_gpe_initialize (); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize general purpose events, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: Acpi_ev_handler_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Install handlers for the SCI, Global Lock, and GPEs. * ******************************************************************************/acpi_statusacpi_ev_handler_initialize ( void){ acpi_status status; ACPI_FUNCTION_TRACE ("Ev_initialize"); /* Install the SCI handler */ status = acpi_ev_install_sci_handler (); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to install System Control Interrupt Handler, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ status = acpi_ev_init_gpe_control_methods (); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize GPE control methods, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } /* Install the handler for the Global Lock */ status = acpi_ev_init_global_lock_handler (); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Global Lock handler, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: Acpi_ev_fixed_event_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Install the fixed event handlers and enable the fixed events. * ******************************************************************************/acpi_statusacpi_ev_fixed_event_initialize ( void){ NATIVE_UINT i; /* * Initialize the structure that keeps track of fixed event handlers * and enable the fixed events. */ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { acpi_gbl_fixed_event_handlers[i].handler = NULL; acpi_gbl_fixed_event_handlers[i].context = NULL; /* Enable the fixed event */ if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[i].enable_register_id, 0, ACPI_MTX_LOCK); } } return (AE_OK);}/******************************************************************************* * * FUNCTION: Acpi_ev_fixed_event_detect * * PARAMETERS: None * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Checks the PM status register for fixed events * ******************************************************************************/u32acpi_ev_fixed_event_detect ( void){ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u32 gpe_status; u32 gpe_enable; NATIVE_UINT i; ACPI_FUNCTION_NAME ("Ev_fixed_event_detect"); /* * Read the fixed feature status and enable registers, as all the cases * depend on their values. */ gpe_status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS); gpe_enable = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE); ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Fixed Acpi_event Block: Enable %08X Status %08X\n", gpe_enable, gpe_status)); /* * 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 ((gpe_status & acpi_gbl_fixed_event_info[i].status_bit_mask) && (gpe_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) { /* Found an active (signalled) event */ int_status |= acpi_ev_fixed_event_dispatch (i); } } return (int_status);}/******************************************************************************* * * FUNCTION: Acpi_ev_fixed_event_dispatch * * 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. * ******************************************************************************/u32acpi_ev_fixed_event_dispatch ( u32 event){ ACPI_FUNCTION_ENTRY (); /* Clear the status bit */ acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].status_register_id, 1, ACPI_MTX_DO_NOT_LOCK); /* * Make sure we've got a handler. If not, report an error. * The event is disabled to prevent further interrupts. */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].enable_register_id, 0, ACPI_MTX_DO_NOT_LOCK); ACPI_REPORT_ERROR ( ("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n", event)); return (ACPI_INTERRUPT_NOT_HANDLED); } /* Invoke the Fixed Event handler */ return ((acpi_gbl_fixed_event_handlers[event].handler)( acpi_gbl_fixed_event_handlers[event].context));}/******************************************************************************* * * FUNCTION: Acpi_ev_gpe_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Initialize the GPE data structures * ******************************************************************************/acpi_statusacpi_ev_gpe_initialize (void){ NATIVE_UINT i; NATIVE_UINT j; NATIVE_UINT gpe_block; u32 gpe_register; u32 gpe_number_index; u32 gpe_number; ACPI_GPE_REGISTER_INFO *gpe_register_info; ACPI_FUNCTION_TRACE ("Ev_gpe_initialize"); /* * Initialize the GPE Block globals * * Why the GPE register block lengths divided by 2: From the ACPI Spec, * section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN * The length of the GPE1_STS and GPE1_EN registers is equal to * half the GPE1_LEN. If a generic register block is not supported * then its respective block pointer and block length values in the * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need * to be the same size." */ acpi_gbl_gpe_block_info[0].address_space_id = acpi_gbl_FADT->Xgpe0_blk.address_space_id; acpi_gbl_gpe_block_info[1].address_space_id = acpi_gbl_FADT->Xgpe1_blk.address_space_id; acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width); acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width); acpi_gbl_gpe_block_info[0].block_address = &acpi_gbl_FADT->Xgpe0_blk; acpi_gbl_gpe_block_info[1].block_address = &acpi_gbl_FADT->Xgpe1_blk; acpi_gbl_gpe_block_info[0].block_base_number = 0; acpi_gbl_gpe_block_info[1].block_base_number = acpi_gbl_FADT->gpe1_base; acpi_gbl_gpe_register_count = acpi_gbl_gpe_block_info[0].register_count + acpi_gbl_gpe_block_info[1].register_count; if (!acpi_gbl_gpe_register_count) { ACPI_REPORT_WARNING (("Zero GPEs are defined in the FADT\n")); return_ACPI_STATUS (AE_OK); } /* Determine the maximum GPE number for this machine */ acpi_gbl_gpe_number_max = ACPI_MUL_8 (acpi_gbl_gpe_block_info[0].register_count) - 1; if (acpi_gbl_gpe_block_info[1].register_count) { /* Check for GPE0/GPE1 overlap */ if (acpi_gbl_gpe_number_max >= acpi_gbl_FADT->gpe1_base) { ACPI_REPORT_ERROR (("GPE0 block overlaps the GPE1 block\n")); return_ACPI_STATUS (AE_BAD_VALUE); } /* GPE0 and GPE1 do not have to be contiguous in the GPE number space */ acpi_gbl_gpe_number_max = acpi_gbl_FADT->gpe1_base + (ACPI_MUL_8 (acpi_gbl_gpe_block_info[1].register_count) - 1); } /* Check for Max GPE number out-of-range */ if (acpi_gbl_gpe_number_max > ACPI_GPE_MAX) { ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n", acpi_gbl_gpe_number_max)); return_ACPI_STATUS (AE_BAD_VALUE); } /* * Allocate the GPE number-to-index translation table */ acpi_gbl_gpe_number_to_index = ACPI_MEM_CALLOCATE (sizeof (ACPI_GPE_INDEX_INFO) * (acpi_gbl_gpe_number_max + 1)); if (!acpi_gbl_gpe_number_to_index) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_number_to_index table\n")); return_ACPI_STATUS (AE_NO_MEMORY); } /* Set the Gpe index table to GPE_INVALID */ ACPI_MEMSET (acpi_gbl_gpe_number_to_index, (int) ACPI_GPE_INVALID, sizeof (ACPI_GPE_INDEX_INFO) * (acpi_gbl_gpe_number_max + 1)); /* * Allocate the GPE register information block */ acpi_gbl_gpe_register_info = ACPI_MEM_CALLOCATE (acpi_gbl_gpe_register_count * sizeof (ACPI_GPE_REGISTER_INFO)); if (!acpi_gbl_gpe_register_info) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_register_info table\n")); goto error_exit1; } /* * Allocate the GPE dispatch handler block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ acpi_gbl_gpe_number_info = ACPI_MEM_CALLOCATE (ACPI_MUL_8 (acpi_gbl_gpe_register_count) * sizeof (ACPI_GPE_NUMBER_INFO)); if (!acpi_gbl_gpe_number_info) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_number_info table\n")); goto error_exit2; } /* * Initialize the GPE information and validation tables. A goal of these * tables is to hide the fact that there are two separate GPE register sets * in a given gpe hardware block, the status registers occupy the first half, * and the enable registers occupy the second half. Another goal is to hide * the fact that there may be multiple GPE hardware blocks. */ gpe_register = 0; gpe_number_index = 0; for (gpe_block = 0; gpe_block < ACPI_MAX_GPE_BLOCKS; gpe_block++) { for (i = 0; i < acpi_gbl_gpe_block_info[gpe_block].register_count; i++) { gpe_register_info = &acpi_gbl_gpe_register_info[gpe_register]; /* Init the Register info for this entire GPE register (8 GPEs) */ gpe_register_info->base_gpe_number = (u8) (acpi_gbl_gpe_block_info[gpe_block].block_base_number + (ACPI_MUL_8 (i))); ACPI_STORE_ADDRESS (gpe_register_info->status_address.address, (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + i)); ACPI_STORE_ADDRESS (gpe_register_info->enable_address.address, (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + i + acpi_gbl_gpe_block_info[gpe_block].register_count)); gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; gpe_register_info->status_address.register_bit_width = 8; gpe_register_info->enable_address.register_bit_width = 8;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?