⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evevent.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 *
 * Module Name: evevent - Fixed and General Purpose Acpi_event
 *                          handling and dispatch
 *              $Revision: 1.1 $
 *
 *****************************************************************************/

/*
 *  Copyright (C) 2000, 2001 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>

#define _COMPONENT          ACPI_EVENTS
	 MODULE_NAME         ("evevent")


/**************************************************************************
 *
 * FUNCTION:    Acpi_ev_initialize
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly
 *              configured, disables SCI event sources, installs the SCI
 *              handler
 *
 *************************************************************************/

ACPI_STATUS
acpi_ev_initialize (
	void)
{
	ACPI_STATUS             status;


	/* Make sure we have ACPI tables */

	if (!acpi_gbl_DSDT) {
		return (AE_NO_ACPI_TABLES);
	}


	/* Make sure the BIOS supports ACPI mode */

	if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) {
		return (AE_ERROR);
	}


	acpi_gbl_original_mode = acpi_hw_get_mode();

	/*
	 * 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)) {
		return (status);
	}

	status = acpi_ev_gpe_initialize ();
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* Install the SCI handler */

	status = acpi_ev_install_sci_handler ();
	if (ACPI_FAILURE (status)) {
		return (status);
	}


	/* Install handlers for control method GPE handlers (_Lxx, _Exx) */

	status = acpi_ev_init_gpe_control_methods ();
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* Install the handler for the Global Lock */

	status = acpi_ev_init_global_lock_handler ();
	if (ACPI_FAILURE (status)) {
		return (status);
	}


	return (status);
}


/******************************************************************************
 *
 * FUNCTION:    Acpi_ev_fixed_event_initialize
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Initialize the Fixed Acpi_event data structures
 *
 ******************************************************************************/

ACPI_STATUS
acpi_ev_fixed_event_initialize(void)
{
	int                     i = 0;

	/* Initialize the structure that keeps track of fixed event handlers */

	for (i = 0; i < NUM_FIXED_EVENTS; i++) {
		acpi_gbl_fixed_event_handlers[i].handler = NULL;
		acpi_gbl_fixed_event_handlers[i].context = NULL;
	}

	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0);
	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0);
	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0);
	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0);
	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0);

	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
 *
 ******************************************************************************/

u32
acpi_ev_fixed_event_detect(void)
{
	u32                     int_status = INTERRUPT_NOT_HANDLED;
	u32                     status_register;
	u32                     enable_register;

	/*
	 * Read the fixed feature status and enable registers, as all the cases
	 * depend on their values.
	 */

	status_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
	enable_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);


	/* power management timer roll over */

	if ((status_register & ACPI_STATUS_PMTIMER) &&
		(enable_register & ACPI_ENABLE_PMTIMER)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER);
	}

	/* global event (BIOS want's the global lock) */

	if ((status_register & ACPI_STATUS_GLOBAL) &&
		(enable_register & ACPI_ENABLE_GLOBAL)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL);
	}

	/* power button event */

	if ((status_register & ACPI_STATUS_POWER_BUTTON) &&
		(enable_register & ACPI_ENABLE_POWER_BUTTON)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON);
	}

	/* sleep button event */

	if ((status_register & ACPI_STATUS_SLEEP_BUTTON) &&
		(enable_register & ACPI_ENABLE_SLEEP_BUTTON)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON);
	}

	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.
 *
 ******************************************************************************/

u32
acpi_ev_fixed_event_dispatch (
	u32                     event)
{
	u32 register_id;

	/* Clear the status bit */

	switch (event) {
	case ACPI_EVENT_PMTIMER:
		register_id = TMR_STS;
		break;

	case ACPI_EVENT_GLOBAL:
		register_id = GBL_STS;
		break;

	case ACPI_EVENT_POWER_BUTTON:
		register_id = PWRBTN_STS;
		break;

	case ACPI_EVENT_SLEEP_BUTTON:
		register_id = SLPBTN_STS;
		break;

	case ACPI_EVENT_RTC:
		register_id = RTC_STS;
		break;

	default:
		return 0;
		break;
	}

	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 1);

	/*
	 * 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) {
		register_id = (PM1_EN | REGISTER_BIT_ID(register_id));

		acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,
				 register_id, 0);

		REPORT_ERROR (
			("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n",
			event));

		return (INTERRUPT_NOT_HANDLED);
	}

	/* Invoke the 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_STATUS
acpi_ev_gpe_initialize (void)
{
	u32                     i;
	u32                     j;
	u32                     register_index;
	u32                     gpe_number;
	u16                     gpe0register_count;
	u16                     gpe1_register_count;


	/*
	 * Set up various GPE counts
	 *
	 * You may ask,why are the GPE register block lengths divided by 2?
	 * From the ACPI 2.0 Spec, section, 4.7.1.6 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."
	 */

	gpe0register_count          = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
	gpe1_register_count         = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
	acpi_gbl_gpe_register_count = gpe0register_count + gpe1_register_count;

	if (!acpi_gbl_gpe_register_count) {
		REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
		return (AE_OK);
	}

	/*
	 * Allocate the Gpe information block
	 */

	acpi_gbl_gpe_registers = acpi_cm_callocate (acpi_gbl_gpe_register_count *
			 sizeof (ACPI_GPE_REGISTERS));
	if (!acpi_gbl_gpe_registers) {
		return (AE_NO_MEMORY);
	}

	/*
	 * Allocate the Gpe dispatch handler block
	 * There are eight distinct GP events per register.
	 * Initialization to zeros is sufficient
	 */

	acpi_gbl_gpe_info = acpi_cm_callocate (MUL_8 (acpi_gbl_gpe_register_count) *
			 sizeof (ACPI_GPE_LEVEL_INFO));
	if (!acpi_gbl_gpe_info) {
		acpi_cm_free (acpi_gbl_gpe_registers);
		return (AE_NO_MEMORY);
	}

	/* Set the Gpe validation table to GPE_INVALID */

	MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, NUM_GPE);

	/*
	 * Initialize the Gpe information and validation blocks.  A goal of these
	 * blocks is to hide the fact that there are two separate GPE register sets
	 * In a given block, the status registers occupy the first half, and
	 * the enable registers occupy the second half.
	 */

	/* GPE Block 0 */

	register_index = 0;

	for (i = 0; i < gpe0register_count; i++) {
		acpi_gbl_gpe_registers[register_index].status_addr =
				 (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i);

		acpi_gbl_gpe_registers[register_index].enable_addr =
				 (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i + gpe0register_count);

		acpi_gbl_gpe_registers[register_index].gpe_base = (u8) MUL_8 (i);

		for (j = 0; j < 8; j++) {
			gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j;
			acpi_gbl_gpe_valid[gpe_number] = (u8) register_index;
		}

		/*
		 * Clear the status/enable registers.  Note that status registers
		 * are cleared by writing a '1', while enable registers are cleared

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -