patch-2.4.22 linux-2.4.22/drivers/acpi/events/evevent.c

Next file: linux-2.4.22/drivers/acpi/events/evgpe.c
Previous file: linux-2.4.22/drivers/acpi/events/Makefile
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/drivers/acpi/events/evevent.c linux-2.4.22/drivers/acpi/events/evevent.c
@@ -1,49 +1,62 @@
 /******************************************************************************
  *
- * Module Name: evevent - Fixed and General Purpose Acpi_event
- *                          handling and dispatch
- *              $Revision: 51 $
+ * Module Name: evevent - Fixed Event handling and dispatch
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000, 2001 R. Byron Moore
+ * Copyright (C) 2000 - 2003, R. Byron Moore
+ * All rights reserved.
  *
- *  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
+ * 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 "acpi.h"
-#include "achware.h"
-#include "acevents.h"
-#include "acnamesp.h"
+#include <acpi/acpi.h>
+#include <acpi/acevents.h>
 
 #define _COMPONENT          ACPI_EVENTS
-	 MODULE_NAME         ("evevent")
+	 ACPI_MODULE_NAME    ("evevent")
 
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ev_initialize
+ * 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
+ * DESCRIPTION: Initialize global data structures for events.
  *
  ******************************************************************************/
 
@@ -51,10 +64,10 @@
 acpi_ev_initialize (
 	void)
 {
-	acpi_status             status;
+	acpi_status                     status;
 
 
-	FUNCTION_TRACE ("Ev_initialize");
+	ACPI_FUNCTION_TRACE ("ev_initialize");
 
 
 	/* Make sure we have ACPI tables */
@@ -64,48 +77,60 @@
 		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 	}
 
-
-	/* Make sure the BIOS supports ACPI mode */
-
-	if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "ACPI Mode is not supported!\n"));
-		return_ACPI_STATUS (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.
+	 * Initialize the Fixed and General Purpose Events. This is
+	 * done prior to enabling SCIs to prevent interrupts from
+	 * occurring 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.\n"));
+		ACPI_REPORT_ERROR ((
+				"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.\n"));
+		ACPI_REPORT_ERROR ((
+				"Unable to initialize general purpose events, %s\n",
+				acpi_format_exception (status)));
 		return_ACPI_STATUS (status);
 	}
 
-	/* Install the SCI handler */
+	return_ACPI_STATUS (status);
+}
 
-	status = acpi_ev_install_sci_handler ();
-	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to install System Control Interrupt Handler\n"));
-		return_ACPI_STATUS (status);
-	}
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_handler_initialize
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_handler_initialize (
+	void)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_handler_initialize");
 
-	/* Install handlers for control method GPE handlers (_Lxx, _Exx) */
 
-	status = acpi_ev_init_gpe_control_methods ();
+	/* Install the SCI handler */
+
+	status = acpi_ev_install_sci_handler ();
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Gpe control methods\n"));
+		ACPI_REPORT_ERROR ((
+				"Unable to install System Control Interrupt Handler, %s\n",
+				acpi_format_exception (status)));
 		return_ACPI_STATUS (status);
 	}
 
@@ -113,44 +138,55 @@
 
 	status = acpi_ev_init_global_lock_handler ();
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Global Lock handler\n"));
+		ACPI_REPORT_ERROR ((
+				"Unable to initialize Global Lock handler, %s\n",
+				acpi_format_exception (status)));
 		return_ACPI_STATUS (status);
 	}
 
-
+	acpi_gbl_events_initialized = TRUE;
 	return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ev_fixed_event_initialize
+ * FUNCTION:    acpi_ev_fixed_event_initialize
  *
  * PARAMETERS:  None
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Initialize the Fixed Acpi_event data structures
+ * DESCRIPTION: Install the fixed event handlers and enable the fixed events.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_ev_fixed_event_initialize(void)
+acpi_ev_fixed_event_initialize (
+	void)
 {
-	int                     i = 0;
+	acpi_native_uint                i;
+	acpi_status                     status;
 
-	/* Initialize the structure that keeps track of fixed event handlers */
 
+	/*
+	 * 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;
-	}
 
-	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);
+		/* Enable the fixed event */
+
+		if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
+			status = acpi_set_register (acpi_gbl_fixed_event_info[i].enable_register_id,
+					 0, ACPI_MTX_LOCK);
+			if (ACPI_FAILURE (status)) {
+				return (status);
+			}
+		}
+	}
 
 	return (AE_OK);
 }
@@ -158,7 +194,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ev_fixed_event_detect
+ * FUNCTION:    acpi_ev_fixed_event_detect
  *
  * PARAMETERS:  None
  *
@@ -169,54 +205,41 @@
  ******************************************************************************/
 
 u32
-acpi_ev_fixed_event_detect (void)
+acpi_ev_fixed_event_detect (
+	void)
 {
-	u32                     int_status = INTERRUPT_NOT_HANDLED;
-	u32                     status_register;
-	u32                     enable_register;
+	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
+	u32                             fixed_status;
+	u32                             fixed_enable;
+	acpi_native_uint                i;
 
 
-	PROC_NAME ("Ev_fixed_event_detect");
+	ACPI_FUNCTION_NAME ("ev_fixed_event_detect");
 
 
 	/*
 	 * Read the fixed feature status and enable registers, as all the cases
-	 * depend on their values.
+	 * depend on their values.  Ignore errors here.
 	 */
-	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);
+	(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &fixed_status);
+	(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
-		"Fixed Acpi_event Block: Enable %08X Status %08X\n",
-		enable_register, status_register));
-
+		"Fixed Event Block: Enable %08X Status %08X\n",
+		fixed_enable, fixed_status));
 
-	/* 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 wants 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);
-	}
+	/*
+	 * 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 */
 
-	/* sleep button event */
+		if ((fixed_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
+			(fixed_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
+			/* Found an active (signalled) 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);
+			int_status |= acpi_ev_fixed_event_dispatch ((u32) i);
+		}
 	}
 
 	return (int_status);
@@ -225,7 +248,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ev_fixed_event_dispatch
+ * FUNCTION:    acpi_ev_fixed_event_dispatch
  *
  * PARAMETERS:  Event               - Event type
  *
@@ -238,590 +261,37 @@
 
 u32
 acpi_ev_fixed_event_dispatch (
-	u32                     event)
+	u32                             event)
 {
-	u32                     register_id;
 
 
-	FUNCTION_ENTRY ();
+	ACPI_FUNCTION_ENTRY ();
 
 
 	/* 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);
+	(void) acpi_set_register (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) {
-		register_id = (PM1_EN | REGISTER_BIT_ID(register_id));
+		(void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+				0, ACPI_MTX_DO_NOT_LOCK);
 
-		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",
+		ACPI_REPORT_ERROR (
+			("No installed handler for fixed event [%08X]\n",
 			event));
 
-		return (INTERRUPT_NOT_HANDLED);
+		return (ACPI_INTERRUPT_NOT_HANDLED);
 	}
 
-	/* Invoke the handler */
+	/* 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_status
-acpi_ev_gpe_initialize (void)
-{
-	u32                     i;
-	u32                     j;
-	u32                     register_index;
-	u32                     gpe_number;
-	u16                     gpe0register_count;
-	u16                     gpe1_register_count;
-
-
-	FUNCTION_TRACE ("Ev_gpe_initialize");
-
-	/*
-	 * 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_ACPI_STATUS (AE_OK);
-	}
-
-	/*
-	 * Allocate the Gpe information block
-	 */
-	acpi_gbl_gpe_registers = ACPI_MEM_CALLOCATE (acpi_gbl_gpe_register_count *
-			  sizeof (acpi_gpe_registers));
-	if (!acpi_gbl_gpe_registers) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Could not allocate the Gpe_registers block\n"));
-		return_ACPI_STATUS (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_MEM_CALLOCATE (MUL_8 (acpi_gbl_gpe_register_count) *
-			  sizeof (acpi_gpe_level_info));
-	if (!acpi_gbl_gpe_info) {
-		ACPI_MEM_FREE (acpi_gbl_gpe_registers);
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_info block\n"));
-		return_ACPI_STATUS (AE_NO_MEMORY);
-	}
-
-	/* Set the Gpe validation table to GPE_INVALID */
-
-	MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, ACPI_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
-		 * by writing a '0'.
-		 */
-		acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00, 8);
-		acpi_os_write_port (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF, 8);
-
-		register_index++;
-	}
-
-	/* GPE Block 1 */
-
-	for (i = 0; i < gpe1_register_count; i++) {
-		acpi_gbl_gpe_registers[register_index].status_addr =
-				 (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i);
-
-		acpi_gbl_gpe_registers[register_index].enable_addr =
-				 (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i + gpe1_register_count);
-
-		acpi_gbl_gpe_registers[register_index].gpe_base =
-				 (u8) (acpi_gbl_FADT->gpe1_base + 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
-		 * by writing a '0'.
-		 */
-		acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00, 8);
-		acpi_os_write_port (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF, 8);
-
-		register_index++;
-	}
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE registers: %X@%8.8X%8.8X (Blk0) %X@%8.8X%8.8X (Blk1)\n",
-		gpe0register_count, HIDWORD(acpi_gbl_FADT->Xgpe0blk.address), LODWORD(acpi_gbl_FADT->Xgpe0blk.address),
-		gpe1_register_count, HIDWORD(acpi_gbl_FADT->Xgpe1_blk.address), LODWORD(acpi_gbl_FADT->Xgpe1_blk.address)));
-
-	return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_ev_save_method_info
- *
- * PARAMETERS:  None
- *
- * RETURN:      None
- *
- * DESCRIPTION: Called from Acpi_walk_namespace. Expects each object to be a
- *              control method under the _GPE portion of the namespace.
- *              Extract the name and GPE type from the object, saving this
- *              information for quick lookup during GPE dispatch
- *
- *              The name of each GPE control method is of the form:
- *                  "_Lnn" or "_Enn"
- *              Where:
- *                  L      - means that the GPE is level triggered
- *                  E      - means that the GPE is edge triggered
- *                  nn     - is the GPE number
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ev_save_method_info (
-	acpi_handle             obj_handle,
-	u32                     level,
-	void                    *obj_desc,
-	void                    **return_value)
-{
-	u32                     gpe_number;
-	NATIVE_CHAR             name[ACPI_NAME_SIZE + 1];
-	u8                      type;
-
-
-	PROC_NAME ("Ev_save_method_info");
-
-
-	/* Extract the name from the object and convert to a string */
-
-	MOVE_UNALIGNED32_TO_32 (name, &((acpi_namespace_node *) obj_handle)->name);
-	name[ACPI_NAME_SIZE] = 0;
-
-	/*
-	 * Edge/Level determination is based on the 2nd s8 of the method name
-	 */
-	if (name[1] == 'L') {
-		type = ACPI_EVENT_LEVEL_TRIGGERED;
-	}
-	else if (name[1] == 'E') {
-		type = ACPI_EVENT_EDGE_TRIGGERED;
-	}
-	else {
-		/* Unknown method type, just ignore it! */
-
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
-			name));
-		return (AE_OK);
-	}
-
-	/* Convert the last two characters of the name to the Gpe Number */
-
-	gpe_number = STRTOUL (&name[2], NULL, 16);
-	if (gpe_number == ACPI_UINT32_MAX) {
-		/* Conversion failed; invalid method, just ignore it */
-
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n",
-			name));
-		return (AE_OK);
-	}
-
-	/* Ensure that we have a valid GPE number */
-
-	if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
-		/* Not valid, all we can do here is ignore it */
-
-		return (AE_OK);
-	}
-
-	/*
-	 * Now we can add this information to the Gpe_info block
-	 * for use during dispatch of this GPE.
-	 */
-	acpi_gbl_gpe_info [gpe_number].type         = type;
-	acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle;
-
-
-	/*
-	 * Enable the GPE (SCIs should be disabled at this point)
-	 */
-	acpi_hw_enable_gpe (gpe_number);
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n",
-		name, gpe_number));
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_ev_init_gpe_control_methods
- *
- * PARAMETERS:  None
- *
- * RETURN:      None
- *
- * DESCRIPTION: Obtain the control methods associated with the GPEs.
- *
- *              NOTE: Must be called AFTER namespace initialization!
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ev_init_gpe_control_methods (void)
-{
-	acpi_status             status;
-
-
-	FUNCTION_TRACE ("Ev_init_gpe_control_methods");
-
-
-	/* Get a permanent handle to the _GPE object */
-
-	status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
-
-	/* Traverse the namespace under \_GPE to find all methods there */
-
-	status = acpi_walk_namespace (ACPI_TYPE_METHOD, acpi_gbl_gpe_obj_handle,
-			  ACPI_UINT32_MAX, acpi_ev_save_method_info,
-			  NULL, NULL);
-
-	return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_ev_gpe_detect
- *
- * PARAMETERS:  None
- *
- * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
- *
- * DESCRIPTION: Detect if any GP events have occurred
- *
- ******************************************************************************/
-
-u32
-acpi_ev_gpe_detect (void)
-{
-	u32                     int_status = INTERRUPT_NOT_HANDLED;
-	u32                     i;
-	u32                     j;
-	u8                      enabled_status_byte;
-	u8                      bit_mask;
-
-
-	PROC_NAME ("Ev_gpe_detect");
-
-
-	/*
-	 * Read all of the 8-bit GPE status and enable registers
-	 * in both of the register blocks, saving all of it.
-	 * Find all currently active GP events.
-	 */
-	for (i = 0; i < acpi_gbl_gpe_register_count; i++) {
-		acpi_os_read_port (acpi_gbl_gpe_registers[i].status_addr,
-				&acpi_gbl_gpe_registers[i].status, 8);
-
-		acpi_os_read_port (acpi_gbl_gpe_registers[i].enable_addr,
-				&acpi_gbl_gpe_registers[i].enable, 8);
-
-		ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
-			"GPE block at %X - Enable %08X Status %08X\n",
-			acpi_gbl_gpe_registers[i].enable_addr,
-			acpi_gbl_gpe_registers[i].status,
-			acpi_gbl_gpe_registers[i].enable));
-
-		/* First check if there is anything active at all in this register */
-
-		enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status &
-				   acpi_gbl_gpe_registers[i].enable);
-
-		if (!enabled_status_byte) {
-			/* No active GPEs in this register, move on */
-
-			continue;
-		}
-
-		/* Now look at the individual GPEs in this byte register */
-
-		for (j = 0, bit_mask = 1; j < 8; j++, bit_mask <<= 1) {
-			/* Examine one GPE bit */
-
-			if (enabled_status_byte & bit_mask) {
-				/*
-				 * Found an active GPE.  Dispatch the event to a handler
-				 * or method.
-				 */
-				int_status |= acpi_ev_gpe_dispatch (
-						  acpi_gbl_gpe_registers[i].gpe_base + j);
-			}
-		}
-	}
-
-	return (int_status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_ev_asynch_execute_gpe_method
- *
- * PARAMETERS:  Gpe_number      - The 0-based Gpe number
- *
- * RETURN:      None
- *
- * DESCRIPTION: Perform the actual execution of a GPE control method.  This
- *              function is called from an invocation of Acpi_os_queue_for_execution
- *              (and therefore does NOT execute at interrupt level) so that
- *              the control method itself is not executed in the context of
- *              the SCI interrupt handler.
- *
- ******************************************************************************/
-
-static void
-acpi_ev_asynch_execute_gpe_method (
-	void                    *context)
-{
-	unsigned long           gpe_number = (unsigned long) context;
-	acpi_gpe_level_info     gpe_info;
-
-
-	FUNCTION_TRACE ("Ev_asynch_execute_gpe_method");
-
-	/*
-	 * Take a snapshot of the GPE info for this level
-	 */
-	acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
-	gpe_info = acpi_gbl_gpe_info [gpe_number];
-	acpi_ut_release_mutex (ACPI_MTX_EVENTS);
-
-	/*
-	 * Method Handler (_Lxx, _Exx):
-	 * ----------------------------
-	 * Evaluate the _Lxx/_Exx control method that corresponds to this GPE.
-	 */
-	if (gpe_info.method_handle) {
-		acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL);
-	}
-
-	/*
-	 * Level-Triggered?
-	 * ----------------
-	 * If level-triggered we clear the GPE status bit after handling the event.
-	 */
-	if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
-		acpi_hw_clear_gpe (gpe_number);
-	}
-
-	/*
-	 * Enable the GPE.
-	 */
-	acpi_hw_enable_gpe (gpe_number);
-
-	return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_ev_gpe_dispatch
- *
- * PARAMETERS:  Gpe_number      - The 0-based Gpe number
- *
- * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
- *
- * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event.
- *              Clears the status bit for the requested event.
- *
- * TBD: [Investigate] is this still valid or necessary:
- * The Gpe handler differs from the fixed events in that it clears the enable
- * bit rather than the status bit to clear the interrupt.  This allows
- * software outside of interrupt context to determine what caused the SCI and
- * dispatch the correct AML.
- *
- ******************************************************************************/
-
-u32
-acpi_ev_gpe_dispatch (
-	u32                     gpe_number)
-{
-	acpi_gpe_level_info     gpe_info;
-
-
-	FUNCTION_TRACE ("Ev_gpe_dispatch");
-
-
-	/*
-	 * Valid GPE number?
-	 */
-	if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid GPE bit [%X].\n", gpe_number));
-		return_VALUE (INTERRUPT_NOT_HANDLED);
-	}
-
-	/*
-	 * Disable the GPE.
-	 */
-	acpi_hw_disable_gpe (gpe_number);
-
-	gpe_info = acpi_gbl_gpe_info [gpe_number];
-
-	/*
-	 * Edge-Triggered?
-	 * ---------------
-	 * If edge-triggered, clear the GPE status bit now.  Note that
-	 * level-triggered events are cleared after the GPE is serviced.
-	 */
-	if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) {
-		acpi_hw_clear_gpe (gpe_number);
-	}
-		/*
-		 * Function Handler (e.g. EC)?
-		 */
-	if (gpe_info.handler) {
-		/* Invoke function handler (at interrupt level). */
-
-		gpe_info.handler (gpe_info.context);
-
-		/* Level-Triggered? */
-
-		if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
-			acpi_hw_clear_gpe (gpe_number);
-		}
-
-		/* Enable GPE */
-
-		acpi_hw_enable_gpe (gpe_number);
-	}
-
-	/*
-	 * Method Handler (e.g. _Exx/_Lxx)?
-	 */
-	else if (gpe_info.method_handle) {
-		if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
-			acpi_ev_asynch_execute_gpe_method, (void*) (u64)gpe_number))) {
-			/*
-			 * Shoudn't occur, but if it does report an error. Note that
-			 * the GPE will remain disabled until the ACPI Core Subsystem
-			 * is restarted, or the handler is removed/reinstalled.
-			 */
-			REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number));
-		}
-	}
-
-	/*
-	 * No Handler? Report an error and leave the GPE disabled.
-	 */
-	else {
-		REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number));
-
-		/* Level-Triggered? */
-
-		if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
-			acpi_hw_clear_gpe (gpe_number);
-		}
-	}
-
-	return_VALUE (INTERRUPT_HANDLED);
-}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)