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 + -
显示快捷键?