patch-2.4.22 linux-2.4.22/drivers/acpi/hardware/hwacpi.c

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

diff -urN linux-2.4.21/drivers/acpi/hardware/hwacpi.c linux-2.4.22/drivers/acpi/hardware/hwacpi.c
@@ -2,40 +2,57 @@
 /******************************************************************************
  *
  * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
- *              $Revision: 46 $
  *
  *****************************************************************************/
 
 /*
- *  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 <acpi/acpi.h>
 
 
 #define _COMPONENT          ACPI_HARDWARE
-	 MODULE_NAME         ("hwacpi")
+	 ACPI_MODULE_NAME    ("hwacpi")
 
 
 /******************************************************************************
  *
- * FUNCTION:    Acpi_hw_initialize
+ * FUNCTION:    acpi_hw_initialize
  *
  * PARAMETERS:  None
  *
@@ -49,182 +66,120 @@
 acpi_hw_initialize (
 	void)
 {
-	acpi_status             status = AE_OK;
-	u32                     index;
+	acpi_status                     status;
 
 
-	FUNCTION_TRACE ("Hw_initialize");
+	ACPI_FUNCTION_TRACE ("hw_initialize");
 
 
 	/* We must have the ACPI tables by the time we get here */
 
 	if (!acpi_gbl_FADT) {
-		acpi_gbl_restore_acpi_chipset = FALSE;
-
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "A FADT is not loaded\n"));
 
 		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 	}
 
-	/* Identify current ACPI/legacy mode   */
-
-	switch (acpi_gbl_system_flags & SYS_MODES_MASK) {
-	case (SYS_MODE_ACPI):
-
-		acpi_gbl_original_mode = SYS_MODE_ACPI;
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.\n"));
-		break;
-
-
-	case (SYS_MODE_LEGACY):
-
-		acpi_gbl_original_mode = SYS_MODE_LEGACY;
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-			"Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n"));
-		break;
-
+	/* Sanity check the FADT for valid values */
 
-	case (SYS_MODE_ACPI | SYS_MODE_LEGACY):
-
-		if (acpi_hw_get_mode () == SYS_MODE_ACPI) {
-			acpi_gbl_original_mode = SYS_MODE_ACPI;
-		}
-		else {
-			acpi_gbl_original_mode = SYS_MODE_LEGACY;
-		}
-
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-			"System supports both ACPI and LEGACY modes.\n"));
-
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-			"System is currently in %s mode.\n",
-			(acpi_gbl_original_mode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY"));
-		break;
+	status = acpi_ut_validate_fadt ();
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
 
-
-	if (acpi_gbl_system_flags & SYS_MODE_ACPI) {
-		/* Target system supports ACPI mode */
-
-		/*
-		 * The purpose of this code is to save the initial state
-		 * of the ACPI event enable registers. An exit function will be
-		 * registered which will restore this state when the application
-		 * exits. The exit function will also clear all of the ACPI event
-		 * status bits prior to restoring the original mode.
-		 *
-		 * The location of the PM1a_evt_blk enable registers is defined as the
-		 * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further
-		 * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset
-		 * for the enable registers is always 2 from the base. It is hard
-		 * coded here. If this changes in the spec, this code will need to
-		 * be modified. The PM1b_evt_blk behaves as expected.
-		 */
-		acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read (
-				   ACPI_MTX_LOCK, PM1_EN);
-
-
-		/*
-		 * The GPEs behave similarly, except that the length of the register
-		 * block is not fixed, so the buffer must be allocated with malloc
-		 */
-		if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
-			acpi_gbl_FADT->gpe0blk_len) {
-			/* GPE0 specified in FADT  */
-
-			acpi_gbl_gpe0enable_register_save = ACPI_MEM_ALLOCATE (
-					   DIV_2 (acpi_gbl_FADT->gpe0blk_len));
-			if (!acpi_gbl_gpe0enable_register_save) {
-				return_ACPI_STATUS (AE_NO_MEMORY);
-			}
-
-			/* Save state of GPE0 enable bits */
-
-			for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
-				acpi_gbl_gpe0enable_register_save[index] =
-					(u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index);
-			}
-		}
-
-		else {
-			acpi_gbl_gpe0enable_register_save = NULL;
-		}
-
-		if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
-			acpi_gbl_FADT->gpe1_blk_len) {
-			/* GPE1 defined */
-
-			acpi_gbl_gpe1_enable_register_save = ACPI_MEM_ALLOCATE (
-					   DIV_2 (acpi_gbl_FADT->gpe1_blk_len));
-			if (!acpi_gbl_gpe1_enable_register_save) {
-				return_ACPI_STATUS (AE_NO_MEMORY);
-			}
-
-			/* save state of GPE1 enable bits */
-
-			for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
-				acpi_gbl_gpe1_enable_register_save[index] =
-					(u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index);
-			}
-		}
-
-		else {
-			acpi_gbl_gpe1_enable_register_save = NULL;
-		}
-	}
-
-	return_ACPI_STATUS (status);
+	return_ACPI_STATUS (AE_OK);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    Acpi_hw_set_mode
+ * FUNCTION:    acpi_hw_set_mode
  *
  * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Transitions the system into the requested mode or does nothing
- *              if the system is already in that mode.
+ * DESCRIPTION: Transitions the system into the requested mode.
  *
  ******************************************************************************/
 
 acpi_status
 acpi_hw_set_mode (
-	u32                     mode)
+	u32                             mode)
 {
 
-	acpi_status             status = AE_NO_HARDWARE_RESPONSE;
+	acpi_status                     status;
+	u32                             retry;
+
 
+	ACPI_FUNCTION_TRACE ("hw_set_mode");
 
-	FUNCTION_TRACE ("Hw_set_mode");
+	/*
+	 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
+	 * system does not support mode transition.
+	 */
+	if (!acpi_gbl_FADT->smi_cmd) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No SMI_CMD in FADT, mode transition failed.\n"));
+		return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+	}
+
+	/*
+	 * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
+	 * in FADT: If it is zero, enabling or disabling is not supported.
+	 * As old systems may have used zero for mode transition,
+	 * we make sure both the numbers are zero to determine these
+	 * transitions are not supported.
+	 */
+	if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No mode transition supported in this system.\n"));
+		return_ACPI_STATUS (AE_OK);
+	}
 
+	switch (mode) {
+	case ACPI_SYS_MODE_ACPI:
 
-	if (mode == SYS_MODE_ACPI) {
 		/* BIOS should have disabled ALL fixed and GP events */
 
-		acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable, 8);
+		status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
+				  (u32) acpi_gbl_FADT->acpi_enable, 8);
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
-	}
+		break;
+
+	case ACPI_SYS_MODE_LEGACY:
 
-	else if (mode == SYS_MODE_LEGACY) {
 		/*
 		 * BIOS should clear all fixed status bits and restore fixed event
 		 * enable bits to default
 		 */
-		acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable, 8);
+		status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
+				 (u32) acpi_gbl_FADT->acpi_disable, 8);
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 				 "Attempting to enable Legacy (non-ACPI) mode\n"));
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	/* Give the platform some time to react */
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
 
-	acpi_os_stall (20000);
+	/*
+	 * Some hardware takes a LONG time to switch modes. Give them 3 sec to
+	 * do so, but allow faster systems to proceed more quickly.
+	 */
+	retry = 3000;
+	while (retry) {
+		status = AE_NO_HARDWARE_RESPONSE;
 
-	if (acpi_hw_get_mode () == mode) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode));
-		status = AE_OK;
+		if (acpi_hw_get_mode() == mode) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode));
+			status = AE_OK;
+			break;
+		}
+		acpi_os_stall(1000);
+		retry--;
 	}
 
 	return_ACPI_STATUS (status);
@@ -233,7 +188,7 @@
 
 /******************************************************************************
  *
- * FUNCTION:    Acpi_hw_get_mode
+ * FUNCTION:    acpi_hw_get_mode
  *
  * PARAMETERS:  none
  *
@@ -247,74 +202,25 @@
 u32
 acpi_hw_get_mode (void)
 {
+	acpi_status                     status;
+	u32                             value;
 
-	FUNCTION_TRACE ("Hw_get_mode");
 
+	ACPI_FUNCTION_TRACE ("hw_get_mode");
 
-	if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) {
-		return_VALUE (SYS_MODE_ACPI);
-	}
-	else {
-		return_VALUE (SYS_MODE_LEGACY);
-	}
-}
-
+	/* If there's no smi_cmd port, then it's ACPI only hw */
+	if (!acpi_gbl_FADT->smi_cmd)
+		return_VALUE (ACPI_SYS_MODE_ACPI);
 
-/******************************************************************************
- *
- * FUNCTION:    Acpi_hw_get_mode_capabilities
- *
- * PARAMETERS:  none
- *
- * RETURN:      logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
- *              system state.
- *
- * DESCRIPTION: Returns capablities of system
- *
- ******************************************************************************/
-
-u32
-acpi_hw_get_mode_capabilities (void)
-{
-
-	FUNCTION_TRACE ("Hw_get_mode_capabilities");
-
-
-	if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) {
-		if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
-			/*
-			 * Assume that if this call is being made, Acpi_init has been called
-			 * and ACPI support has been established by the presence of the
-			 * tables.  Therefore since we're in SYS_MODE_LEGACY, the system
-			 * must support both modes
-			 */
-			acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
-		}
-
-		else {
-			/* TBD: [Investigate] !!! this may be unsafe... */
-			/*
-			 * system is is ACPI mode, so try to switch back to LEGACY to see if
-			 * it is supported
-			 */
-			acpi_hw_set_mode (SYS_MODE_LEGACY);
-
-			if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
-				/* Now in SYS_MODE_LEGACY, so both are supported */
-
-				acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
-				acpi_hw_set_mode (SYS_MODE_ACPI);
-			}
-
-			else {
-				/* Still in SYS_MODE_ACPI so this must be an ACPI only system */
-
-				acpi_gbl_system_flags |= SYS_MODE_ACPI;
-			}
-		}
+	status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_VALUE (ACPI_SYS_MODE_LEGACY);
 	}
 
-	return_VALUE (acpi_gbl_system_flags & SYS_MODES_MASK);
+	if (value) {
+		return_VALUE (ACPI_SYS_MODE_ACPI);
+	}
+	else {
+		return_VALUE (ACPI_SYS_MODE_LEGACY);
+	}
 }
-
-

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